Skip to content

Commit 81ff56f

Browse files
authored
Merge pull request #106 from common-workflow-language/typecheck-assignable
Fix type checking that a source port is assignable to a sink port
2 parents c9dd7e4 + 0b86748 commit 81ff56f

File tree

2 files changed

+31
-11
lines changed

2 files changed

+31
-11
lines changed

cwltool/workflow.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,27 +82,29 @@ def match_types(sinktype, src, iid, inputobj, linkMerge, valueFrom):
8282
else:
8383
raise WorkflowException(u"Unrecognized linkMerge enum '%s'" % linkMerge)
8484
return True
85-
elif valueFrom is not None or are_same_type(src.parameter["type"], sinktype) or sinktype == "Any":
85+
elif valueFrom is not None or can_assign_src_to_sink(src.parameter["type"], sinktype) or sinktype == "Any":
8686
# simply assign the value from state to input
8787
inputobj[iid] = copy.deepcopy(src.value)
8888
return True
8989
return False
9090

91-
def are_same_type(src, sink): # type: (Any, Any) -> bool
91+
def can_assign_src_to_sink(src, sink): # type: (Any, Any) -> bool
9292
"""Check for identical type specifications, ignoring extra keys like inputBinding.
9393
"""
9494
if isinstance(src, dict) and isinstance(sink, dict):
9595
if src["type"] == "array" and sink["type"] == "array":
96-
if 'null' in sink["items"]:
97-
return are_same_type([src["items"]], [it for it in sink["items"] if it != 'null'])
98-
return are_same_type(src["items"], sink["items"])
99-
elif src["type"] == sink["type"]:
100-
return True
101-
else:
102-
return False
96+
return can_assign_src_to_sink(src["items"], sink["items"])
97+
elif isinstance(src, list):
98+
for t in src:
99+
if can_assign_src_to_sink(t, sink):
100+
return True
101+
elif isinstance(sink, list):
102+
for t in sink:
103+
if can_assign_src_to_sink(src, t):
104+
return True
103105
else:
104106
return src == sink
105-
107+
return False
106108

107109
def object_from_state(state, parms, frag_only, supportsMultipleInput, sourceField):
108110
# type: (Dict[unicode, WorkflowStateItem], List[Dict[unicode, Any]], bool, bool, unicode) -> Dict[unicode, Any]

tests/test_examples.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import cwltool.expression as expr
55
import cwltool.factory
66
import cwltool.process
7-
7+
import cwltool.workflow
88

99
class TestParamMatching(unittest.TestCase):
1010

@@ -150,6 +150,24 @@ def loadref(base, p):
150150
set(("$include", "$schemas", "path")),
151151
loadref), indent=4)
152152

153+
class TestTypeCompare(unittest.TestCase):
154+
def test_typecompare(self):
155+
self.assertTrue(cwltool.workflow.can_assign_src_to_sink(
156+
{'items': ['string', 'null'], 'type': 'array'},
157+
{'items': ['string', 'null'], 'type': 'array'}))
158+
159+
self.assertTrue(cwltool.workflow.can_assign_src_to_sink(
160+
{'items': ['string'], 'type': 'array'},
161+
{'items': ['string', 'null'], 'type': 'array'}))
162+
163+
self.assertTrue(cwltool.workflow.can_assign_src_to_sink(
164+
{'items': ['string', 'null'], 'type': 'array'},
165+
{'items': ['string'], 'type': 'array'}))
166+
167+
self.assertFalse(cwltool.workflow.can_assign_src_to_sink(
168+
{'items': ['string'], 'type': 'array'},
169+
{'items': ['int'], 'type': 'array'}))
170+
153171

154172
if __name__ == '__main__':
155173
unittest.main()

0 commit comments

Comments
 (0)