From 5810ce616bf813bcdebe9a91124f76774db58ce1 Mon Sep 17 00:00:00 2001 From: Peter Amstutz Date: Mon, 7 Mar 2022 16:33:05 -0500 Subject: [PATCH 1/2] Fix spurious validation error #1639 Typing related to conditionals should be part of the computed output signature of the step, not added in by the checker. Arvados-DCO-1.1-Signed-off-by: Peter Amstutz --- cwltool/checker.py | 21 --------------------- cwltool/workflow.py | 13 ++++++++++++- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/cwltool/checker.py b/cwltool/checker.py index f4c2b87a3..0cca2635d 100644 --- a/cwltool/checker.py +++ b/cwltool/checker.py @@ -407,27 +407,6 @@ def check_all_types( ) ) - if is_conditional_step(param_to_step, parm_id): - src_typ = aslist(srcs_of_sink[0]["type"]) - snk_typ = sink["type"] - - if "null" not in src_typ: - src_typ = ["null"] + cast(List[Any], src_typ) - - if "null" not in cast( - Union[List[str], CWLObjectType], snk_typ - ): # Given our type names this works even if not a list - validation["warning"].append( - SrcSink( - src_dict[parm_id], - sink, - linkMerge, - message="Source is from conditional step and may produce `null`", - ) - ) - - srcs_of_sink[0]["type"] = src_typ - for src in srcs_of_sink: check_result = check_types(src, sink, linkMerge, valueFrom) if check_result == "warning": diff --git a/cwltool/workflow.py b/cwltool/workflow.py index 986db5b99..06720378d 100644 --- a/cwltool/workflow.py +++ b/cwltool/workflow.py @@ -359,6 +359,8 @@ def __init__( "SubworkflowFeatureRequirement not in requirements" ) + conditional = self.tool.get("when") + if "scatter" in self.tool: (feature, _) = self.get_requirement("ScatterFeatureRequirement") if not feature: @@ -398,11 +400,20 @@ def __init__( else: nesting = 1 - for _ in range(0, nesting): + for n in range(0, nesting): for oparam in outputparms: + if conditional and n == 0: + oparam["type"] = ["null"] + aslist(oparam["type"]) oparam["type"] = {"type": "array", "items": oparam["type"]} self.tool["inputs"] = inputparms self.tool["outputs"] = outputparms + elif conditional: + # No scatter, but conditional + outputparms = copy.deepcopy(self.tool["outputs"]) + for oparam in outputparms: + oparam["type"] = ["null"] + aslist(oparam["type"]) + self.tool["outputs"] = outputparms + self.prov_obj = None # type: Optional[ProvenanceProfile] if loadingContext.research_obj is not None: self.prov_obj = parentworkflowProv From 21da544d8794d612ff7d4fb2383343be281bd025 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Tue, 8 Mar 2022 13:19:32 +0100 Subject: [PATCH 2/2] fix typing --- cwltool/workflow.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cwltool/workflow.py b/cwltool/workflow.py index 06720378d..7250b1ef4 100644 --- a/cwltool/workflow.py +++ b/cwltool/workflow.py @@ -403,7 +403,9 @@ def __init__( for n in range(0, nesting): for oparam in outputparms: if conditional and n == 0: - oparam["type"] = ["null"] + aslist(oparam["type"]) + oparam["type"] = ["null"] + cast( + List[str], aslist(oparam["type"]) + ) oparam["type"] = {"type": "array", "items": oparam["type"]} self.tool["inputs"] = inputparms self.tool["outputs"] = outputparms @@ -411,7 +413,7 @@ def __init__( # No scatter, but conditional outputparms = copy.deepcopy(self.tool["outputs"]) for oparam in outputparms: - oparam["type"] = ["null"] + aslist(oparam["type"]) + oparam["type"] = ["null"] + cast(List[str], aslist(oparam["type"])) self.tool["outputs"] = outputparms self.prov_obj = None # type: Optional[ProvenanceProfile]