diff --git a/cwltool/utils.py b/cwltool/utils.py index ec33cadf1..d764d9011 100644 --- a/cwltool/utils.py +++ b/cwltool/utils.py @@ -16,3 +16,7 @@ def get_feature(self, feature): # type: (Any, Any) -> Tuple[Any, bool] if t["class"] == feature: return (t, False) return (None, None) + +class HashableDict(dict): + def __hash__(self): + return hash(tuple(sorted(self.items()))) diff --git a/cwltool/workflow.py b/cwltool/workflow.py index c2ffad113..3c54ee682 100644 --- a/cwltool/workflow.py +++ b/cwltool/workflow.py @@ -1,6 +1,6 @@ from . import job from . import draft2tool -from .utils import aslist +from .utils import aslist, HashableDict from .process import Process, get_feature, empty_subtree, shortname, uniquename from .errors import WorkflowException import copy @@ -88,21 +88,28 @@ def match_types(sinktype, src, iid, inputobj, linkMerge, valueFrom): return True return False + def are_same_type(src, sink): # type: (Any, Any) -> bool """Check for identical type specifications, ignoring extra keys like inputBinding. """ if isinstance(src, dict) and isinstance(sink, dict): if src["type"] == "array" and sink["type"] == "array": - if 'null' in sink["items"]: - return are_same_type([src["items"]], [it for it in sink["items"] if it != 'null']) - return are_same_type(src["items"], sink["items"]) - elif src["type"] == sink["type"]: - return True + src_items = src["items"] + sink_items = sink["items"] + if not isinstance(src_items, list): + src_items = [src_items] + if not isinstance(sink_items, list): + sink_items = [sink_items] + src_items = [HashableDict(s) if isinstance(s, dict) else s for s in src_items] + sink_items = [HashableDict(s) if isinstance(s, dict) else s for s in sink_items] + return are_same_type(src_items, sink_items) else: - return False + return src["type"] == sink["type"] else: - return src == sink - + try: + return src == sink or len(set(src).intersection(set(sink))) > 0 + except TypeError: + return False def object_from_state(state, parms, frag_only, supportsMultipleInput): # type: (Dict[str,WorkflowStateItem], List[Dict[str, Any]], bool, bool) -> Dict[str, str]