Skip to content

Commit 1314aef

Browse files
committed
structural pattern matching
1 parent 5c381a7 commit 1314aef

14 files changed

+1205
-1156
lines changed

cwl_utils/cwl_v1_0_expression_refactor.py

Lines changed: 138 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -208,89 +208,91 @@ def traverse(
208208
skip_command_line2: bool,
209209
) -> tuple[cwl.CommandLineTool | cwl.ExpressionTool | cwl.Workflow, bool]:
210210
"""Convert the given process and any subprocesses."""
211-
if not inside and isinstance(process, cwl.CommandLineTool):
212-
process = expand_stream_shortcuts(process)
213-
wf_inputs = []
214-
wf_outputs = []
215-
step_inputs = []
216-
step_outputs = []
217-
if process.inputs:
218-
for inp in process.inputs:
219-
inp_id = inp.id.split("#")[-1]
220-
step_inputs.append(
221-
cwl.WorkflowStepInput(
222-
id=inp_id,
223-
source=inp_id,
224-
extension_fields=inp.extension_fields,
225-
loadingOptions=inp.loadingOptions,
211+
match process:
212+
case cwl.CommandLineTool() if not inside:
213+
process = expand_stream_shortcuts(process)
214+
wf_inputs = []
215+
wf_outputs = []
216+
step_inputs = []
217+
step_outputs = []
218+
if process.inputs:
219+
for inp in process.inputs:
220+
inp_id = inp.id.split("#")[-1]
221+
step_inputs.append(
222+
cwl.WorkflowStepInput(
223+
id=inp_id,
224+
source=inp_id,
225+
extension_fields=inp.extension_fields,
226+
loadingOptions=inp.loadingOptions,
227+
)
226228
)
227-
)
228-
wf_inputs.append(
229-
cwl.InputParameter(
230-
id=inp_id,
231-
label=inp.label,
232-
secondaryFiles=inp.secondaryFiles,
233-
streamable=inp.streamable,
234-
doc=inp.doc,
235-
format=inp.format,
236-
default=inp.default,
237-
type_=inp.type_,
238-
extension_fields=inp.extension_fields,
239-
loadingOptions=inp.loadingOptions,
229+
wf_inputs.append(
230+
cwl.InputParameter(
231+
id=inp_id,
232+
label=inp.label,
233+
secondaryFiles=inp.secondaryFiles,
234+
streamable=inp.streamable,
235+
doc=inp.doc,
236+
format=inp.format,
237+
default=inp.default,
238+
type_=inp.type_,
239+
extension_fields=inp.extension_fields,
240+
loadingOptions=inp.loadingOptions,
241+
)
240242
)
241-
)
242-
if process.outputs:
243-
for outp in process.outputs:
244-
outp_id = outp.id.split("#")[-1]
245-
step_outputs.append(outp_id)
246-
wf_outputs.append(
247-
cwl.WorkflowOutputParameter(
248-
id=outp_id,
249-
label=outp.label,
250-
secondaryFiles=outp.secondaryFiles,
251-
streamable=outp.streamable,
252-
doc=outp.doc,
253-
format=outp.format,
254-
outputSource=f"main/{outp_id}",
255-
type_=outp.type_,
256-
extension_fields=outp.extension_fields,
257-
loadingOptions=outp.loadingOptions,
243+
if process.outputs:
244+
for outp in process.outputs:
245+
outp_id = outp.id.split("#")[-1]
246+
step_outputs.append(outp_id)
247+
wf_outputs.append(
248+
cwl.WorkflowOutputParameter(
249+
id=outp_id,
250+
label=outp.label,
251+
secondaryFiles=outp.secondaryFiles,
252+
streamable=outp.streamable,
253+
doc=outp.doc,
254+
format=outp.format,
255+
outputSource=f"main/{outp_id}",
256+
type_=outp.type_,
257+
extension_fields=outp.extension_fields,
258+
loadingOptions=outp.loadingOptions,
259+
)
258260
)
259-
)
260-
step = cwl.WorkflowStep(
261-
id="#main",
262-
in_=step_inputs,
263-
out=step_outputs,
264-
run=copy.deepcopy(process),
265-
)
266-
workflow = cwl.Workflow(
267-
inputs=wf_inputs,
268-
outputs=wf_outputs,
269-
steps=[step],
270-
cwlVersion=process.cwlVersion,
271-
)
272-
result, modified = traverse_workflow(
273-
workflow, replace_etool, skip_command_line1, skip_command_line2
274-
)
275-
if modified:
276-
return result, True
277-
else:
261+
step = cwl.WorkflowStep(
262+
id="#main",
263+
in_=step_inputs,
264+
out=step_outputs,
265+
run=copy.deepcopy(process),
266+
)
267+
workflow = cwl.Workflow(
268+
inputs=wf_inputs,
269+
outputs=wf_outputs,
270+
steps=[step],
271+
cwlVersion=process.cwlVersion,
272+
)
273+
result, modified = traverse_workflow(
274+
workflow, replace_etool, skip_command_line1, skip_command_line2
275+
)
276+
if modified:
277+
return result, True
278+
else:
279+
return process, False
280+
case cwl.ExpressionTool() if replace_etool:
281+
expression = get_expression(process.expression, empty_inputs(process), None)
282+
# Why call get_expression on an ExpressionTool?
283+
# It normalizes the form of $() CWL expressions into the ${} style
284+
if expression:
285+
process2 = copy.deepcopy(process)
286+
process2.expression = expression
287+
else:
288+
process2 = process
289+
return etool_to_cltool(process2), True
290+
case cwl.Workflow():
291+
return traverse_workflow(
292+
process, replace_etool, skip_command_line1, skip_command_line2
293+
)
294+
case _:
278295
return process, False
279-
if isinstance(process, cwl.ExpressionTool) and replace_etool:
280-
expression = get_expression(process.expression, empty_inputs(process), None)
281-
# Why call get_expression on an ExpressionTool?
282-
# It normalizes the form of $() CWL expressions into the ${} style
283-
if expression:
284-
process2 = copy.deepcopy(process)
285-
process2.expression = expression
286-
else:
287-
process2 = process
288-
return etool_to_cltool(process2), True
289-
if isinstance(process, cwl.Workflow):
290-
return traverse_workflow(
291-
process, replace_etool, skip_command_line1, skip_command_line2
292-
)
293-
return process, False
294296

295297

296298
def load_step(
@@ -668,8 +670,8 @@ def process_workflow_reqs_and_hints(
668670
iwdr: cwl.InitialWorkDirRequirement | None = None
669671
if workflow.requirements is not None:
670672
for req in cast(list[cwl.ProcessRequirement], workflow.requirements):
671-
if req and isinstance(req, cwl.EnvVarRequirement):
672-
if req.envDef:
673+
match req:
674+
case cwl.EnvVarRequirement() if req.envDef:
673675
for index, envDef in enumerate(req.envDef):
674676
if envDef.envValue:
675677
expression = get_expression(envDef.envValue, inputs, None)
@@ -699,36 +701,33 @@ def process_workflow_reqs_and_hints(
699701
newEnvDef.envValue = f"$(inputs._envDef{index})"
700702
envVarReq.envDef[index] = newEnvDef
701703
generated_envVar_reqs.append((etool_id, index))
702-
if req and isinstance(req, cwl.ResourceRequirement):
703-
for attr in cwl.ResourceRequirement.attrs:
704-
this_attr = getattr(req, attr, None)
705-
if this_attr:
706-
expression = get_expression(this_attr, inputs, None)
707-
if expression:
708-
modified = True
709-
target = cwl.InputParameter(id=None, type_="long")
710-
etool_id = (
711-
"_expression_workflow_ResourceRequirement_{}".format(
704+
case cwl.ResourceRequirement():
705+
for attr in cwl.ResourceRequirement.attrs:
706+
this_attr = getattr(req, attr, None)
707+
if this_attr:
708+
expression = get_expression(this_attr, inputs, None)
709+
if expression:
710+
modified = True
711+
target = cwl.InputParameter(id=None, type_="long")
712+
etool_id = "_expression_workflow_ResourceRequirement_{}".format(
712713
attr
713714
)
714-
)
715-
replace_expr_with_etool(
716-
expression,
717-
etool_id,
718-
workflow,
719-
target,
720-
None,
721-
replace_etool,
722-
)
723-
if not resourceReq:
724-
resourceReq = cwl.ResourceRequirement(
725-
loadingOptions=workflow.loadingOptions,
715+
replace_expr_with_etool(
716+
expression,
717+
etool_id,
718+
workflow,
719+
target,
720+
None,
721+
replace_etool,
726722
)
727-
prop_reqs += (cwl.ResourceRequirement,)
728-
setattr(resourceReq, attr, f"$(inputs._{attr})")
729-
generated_res_reqs.append((etool_id, attr))
730-
if req and isinstance(req, cwl.InitialWorkDirRequirement):
731-
if req.listing:
723+
if not resourceReq:
724+
resourceReq = cwl.ResourceRequirement(
725+
loadingOptions=workflow.loadingOptions,
726+
)
727+
prop_reqs += (cwl.ResourceRequirement,)
728+
setattr(resourceReq, attr, f"$(inputs._{attr})")
729+
generated_res_reqs.append((etool_id, attr))
730+
case cwl.InitialWorkDirRequirement() if req.listing:
732731
if isinstance(req.listing, str):
733732
expression = get_expression(req.listing, inputs, None)
734733
if expression:
@@ -991,8 +990,8 @@ def process_level_reqs(
991990
return False
992991
step_name = step.id.split("#", 1)[-1]
993992
for req_index, req in enumerate(process.requirements):
994-
if req and isinstance(req, cwl.EnvVarRequirement):
995-
if req.envDef:
993+
match req:
994+
case cwl.EnvVarRequirement() if req.envDef:
996995
for env_index, envDef in enumerate(req.envDef):
997996
if envDef.envValue:
998997
expression = get_expression(envDef.envValue, inputs, None)
@@ -1015,33 +1014,35 @@ def process_level_reqs(
10151014
env_index
10161015
].envValue = f"$(inputs._envDef{env_index})"
10171016
generated_envVar_reqs.append((etool_id, env_index))
1018-
if req and isinstance(req, cwl.ResourceRequirement):
1019-
for attr in cwl.ResourceRequirement.attrs:
1020-
this_attr = getattr(req, attr, None)
1021-
if this_attr:
1022-
expression = get_expression(this_attr, inputs, None)
1023-
if expression:
1024-
modified = True
1025-
target = cwl.InputParameter(id=None, type_="long")
1026-
etool_id = "_expression_{}_ResourceRequirement_{}".format(
1027-
step_name, attr
1028-
)
1029-
replace_clt_hintreq_expr_with_etool(
1030-
expression, etool_id, parent, target, step, replace_etool
1031-
)
1032-
setattr(
1033-
target_process.requirements[req_index],
1034-
attr,
1035-
f"$(inputs._{attr})",
1036-
)
1037-
generated_res_reqs.append((etool_id, attr))
1038-
1039-
if (
1040-
not skip_command_line2
1041-
and req
1042-
and isinstance(req, cwl.InitialWorkDirRequirement)
1043-
):
1044-
if req.listing:
1017+
case cwl.ResourceRequirement():
1018+
for attr in cwl.ResourceRequirement.attrs:
1019+
this_attr = getattr(req, attr, None)
1020+
if this_attr:
1021+
expression = get_expression(this_attr, inputs, None)
1022+
if expression:
1023+
modified = True
1024+
target = cwl.InputParameter(id=None, type_="long")
1025+
etool_id = "_expression_{}_ResourceRequirement_{}".format(
1026+
step_name, attr
1027+
)
1028+
replace_clt_hintreq_expr_with_etool(
1029+
expression,
1030+
etool_id,
1031+
parent,
1032+
target,
1033+
step,
1034+
replace_etool,
1035+
)
1036+
setattr(
1037+
target_process.requirements[req_index],
1038+
attr,
1039+
f"$(inputs._{attr})",
1040+
)
1041+
generated_res_reqs.append((etool_id, attr))
1042+
1043+
case cwl.InitialWorkDirRequirement() if (
1044+
not skip_command_line2 and req.listing
1045+
):
10451046
if isinstance(req.listing, str):
10461047
expression = get_expression(req.listing, inputs, None)
10471048
if expression:

0 commit comments

Comments
 (0)