Skip to content

Commit 3439627

Browse files
committed
use structural pattern matching
1 parent 422a998 commit 3439627

File tree

1 file changed

+146
-159
lines changed

1 file changed

+146
-159
lines changed

cwlupgrader/main.py

Lines changed: 146 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -120,51 +120,47 @@ def upgrade_document(
120120
main_updater = None
121121
inner_updater = None
122122

123-
if version == "cwl:draft-3" or version == "draft-3":
124-
if target_version == "v1.0":
125-
main_updater = draft3_to_v1_0
126-
inner_updater = _draft3_to_v1_0
127-
elif target_version == "v1.1":
128-
main_updater = draft3_to_v1_1
129-
inner_updater = _draft3_to_v1_1
130-
elif target_version == "v1.2":
131-
main_updater = draft3_to_v1_2
132-
inner_updater = _draft3_to_v1_2
133-
elif target_version == "latest":
134-
main_updater = draft3_to_v1_2
135-
inner_updater = _draft3_to_v1_2
136-
elif version == "v1.0":
137-
if target_version == "v1.0":
138-
_logger.info("Not upgrading v1.0 document as requested.")
123+
match version:
124+
case "cwl:draft-3" | "draft-3":
125+
match target_version:
126+
case "v1.0":
127+
main_updater = draft3_to_v1_0
128+
inner_updater = _draft3_to_v1_0
129+
case "v1.1":
130+
main_updater = draft3_to_v1_1
131+
inner_updater = _draft3_to_v1_1
132+
case "v1.2" | "latest":
133+
main_updater = draft3_to_v1_2
134+
inner_updater = _draft3_to_v1_2
135+
case "v1.0":
136+
match target_version:
137+
case "v1.0":
138+
_logger.info("Not upgrading v1.0 document as requested.")
139+
return
140+
case "v1.1":
141+
main_updater = v1_0_to_v1_1
142+
inner_updater = _v1_0_to_v1_1
143+
case "v1.2" | "latest":
144+
main_updater = v1_0_to_v1_2
145+
inner_updater = _v1_0_to_v1_2
146+
case "v1.1":
147+
match target_version:
148+
case "v1.1":
149+
_logger.info("Not upgrading v1.1 document as requested.")
150+
return
151+
case "v1.2" | "latest":
152+
main_updater = v1_1_to_v1_2
153+
inner_updater = _v1_1_to_v1_2
154+
case "v1.2":
155+
match target_version:
156+
case "v1.2":
157+
_logger.info("Not upgrading v1.2 document as requested.")
158+
return document
159+
case "latest":
160+
return document
161+
case _:
162+
_logger.error(f"Unknown cwlVersion in source document: {version}")
139163
return
140-
elif target_version == "v1.1":
141-
main_updater = v1_0_to_v1_1
142-
inner_updater = _v1_0_to_v1_1
143-
elif target_version == "v1.2":
144-
main_updater = v1_0_to_v1_2
145-
inner_updater = _v1_0_to_v1_2
146-
elif target_version == "latest":
147-
main_updater = v1_0_to_v1_2
148-
inner_updater = _v1_0_to_v1_2
149-
elif version == "v1.1":
150-
if target_version == "v1.1":
151-
_logger.info("Not upgrading v1.1 document as requested.")
152-
return
153-
elif target_version == "v1.2":
154-
main_updater = v1_1_to_v1_2
155-
inner_updater = _v1_1_to_v1_2
156-
elif target_version == "latest":
157-
main_updater = v1_1_to_v1_2
158-
inner_updater = _v1_1_to_v1_2
159-
elif version == "v1.2":
160-
if target_version == "v1.2":
161-
_logger.info("Not upgrading v1.2 document as requested.")
162-
return document
163-
elif target_version == "latest":
164-
return document
165-
else:
166-
_logger.error(f"Unknown cwlVersion in source document: {version}")
167-
return
168164

169165
if main_updater is None or inner_updater is None:
170166
_logger.error(f"Cannot downgrade from cwlVersion {version} to {target_version}")
@@ -292,12 +288,12 @@ def draft3_to_v1_2(document: CommentedMap, outdir: str) -> CommentedMap:
292288

293289
def _draft3_to_v1_0(document: CommentedMap, outdir: str) -> CommentedMap:
294290
"""Inner loop for transforming draft-3 to v1.0."""
295-
if "class" in document:
296-
if document["class"] == "Workflow":
291+
match document:
292+
case {"class": "Workflow"}:
297293
workflow_clean(document)
298-
elif document["class"] == "File":
294+
case {"class": "File"}:
299295
document["location"] = document.pop("path")
300-
elif document["class"] == "CommandLineTool":
296+
case {"class": "CommandLineTool"}:
301297
input_output_clean(document)
302298
hints_and_requirements_clean(document)
303299
if (
@@ -340,32 +336,19 @@ def _draft3_to_v1_2(document: CommentedMap, outdir: str) -> CommentedMap:
340336

341337
def _v1_0_to_v1_1(document: CommentedMap, outdir: str) -> CommentedMap:
342338
"""Inner loop for transforming draft-3 to v1.0."""
343-
if "class" in document:
344-
if document["class"] == "Workflow":
339+
match document:
340+
case {"class": "Workflow"}:
345341
upgrade_v1_0_hints_and_reqs(document)
346342
move_up_loadcontents(document)
347343
cleanup_v1_0_input_bindings(document)
348-
steps = document["steps"]
349-
if isinstance(steps, MutableSequence):
350-
for index, entry in enumerate(steps):
351-
with SourceLine(steps, index, Exception):
352-
upgrade_v1_0_hints_and_reqs(entry)
353-
if "run" in entry and isinstance(entry["run"], CommentedMap):
354-
process = entry["run"]
355-
_v1_0_to_v1_1(process, outdir)
356-
if "cwlVersion" in process:
357-
del process["cwlVersion"]
358-
elif isinstance(entry["run"], str) and "#" not in entry["run"]:
359-
path = Path(document.lc.filename).parent / entry["run"]
360-
process = v1_0_to_v1_1(load_cwl_document(str(path)), outdir)
361-
write_cwl_document(process, path.name, outdir)
362-
elif isinstance(steps, MutableMapping):
363-
for step_name in steps:
364-
with SourceLine(steps, step_name, Exception):
365-
entry = steps[step_name]
366-
upgrade_v1_0_hints_and_reqs(entry)
367-
if "run" in entry:
368-
if isinstance(entry["run"], CommentedMap):
344+
match document["steps"]:
345+
case MutableSequence() as steps:
346+
for index, entry in enumerate(steps):
347+
with SourceLine(steps, index, Exception):
348+
upgrade_v1_0_hints_and_reqs(entry)
349+
if "run" in entry and isinstance(
350+
entry["run"], CommentedMap
351+
):
369352
process = entry["run"]
370353
_v1_0_to_v1_1(process, outdir)
371354
if "cwlVersion" in process:
@@ -379,43 +362,59 @@ def _v1_0_to_v1_1(document: CommentedMap, outdir: str) -> CommentedMap:
379362
load_cwl_document(str(path)), outdir
380363
)
381364
write_cwl_document(process, path.name, outdir)
382-
elif isinstance(entry["run"], str) and "#" in entry["run"]:
383-
pass # reference to $graph entry
384-
else:
385-
raise Exception(
386-
"'run' entry was neither a CWL Process nor "
387-
"a path to one: %s.",
388-
entry["run"],
389-
)
390-
elif document["class"] == "CommandLineTool":
365+
case MutableMapping() as steps:
366+
for step_name in steps:
367+
with SourceLine(steps, step_name, Exception):
368+
entry = steps[step_name]
369+
upgrade_v1_0_hints_and_reqs(entry)
370+
match entry:
371+
case {"run": CommentedMap() as process}:
372+
_v1_0_to_v1_1(process, outdir)
373+
if "cwlVersion" in process:
374+
del process["cwlVersion"]
375+
case {"run": str(run)} if "#" not in run:
376+
path = Path(document.lc.filename).parent / run
377+
process = v1_0_to_v1_1(
378+
load_cwl_document(str(path)), outdir
379+
)
380+
write_cwl_document(process, path.name, outdir)
381+
case {"run": str(run)} if "#" in run:
382+
pass # reference to $graph entry
383+
case _:
384+
raise Exception(
385+
"'run' entry was neither a CWL Process nor "
386+
"a path to one: %s.",
387+
entry["run"],
388+
)
389+
case {"class": "CommandLineTool"}:
391390
upgrade_v1_0_hints_and_reqs(document)
392391
move_up_loadcontents(document)
393392
network_access = has_hint_or_req(document, "NetworkAccess")
394393
listing = has_hint_or_req(document, "LoadListingRequirement")
395-
reqs = document.get("requirements", {})
396394
# TODO: add comments to explain the extra hints
397-
if isinstance(reqs, MutableSequence):
398-
if not network_access:
399-
reqs.append({"class": "NetworkAccess", "networkAccess": True})
400-
if not listing:
401-
reqs.append(
402-
cmap(
403-
{
404-
"class": "LoadListingRequirement",
405-
"loadListing": "deep_listing",
406-
}
407-
)
408-
)
409-
elif isinstance(reqs, MutableMapping):
410-
if not network_access:
411-
reqs["NetworkAccess"] = {"networkAccess": True}
412-
if not listing:
413-
reqs["LoadListingRequirement"] = cmap(
414-
{"loadListing": "deep_listing"}
415-
)
416395
if "requirements" not in document:
417-
document["requirements"] = reqs
418-
elif document["class"] == "ExpressionTool":
396+
document["requirements"] = {}
397+
match document:
398+
case {"requirements": MutableSequence() as reqs}:
399+
if not network_access:
400+
reqs.append({"class": "NetworkAccess", "networkAccess": True})
401+
if not listing:
402+
reqs.append(
403+
cmap(
404+
{
405+
"class": "LoadListingRequirement",
406+
"loadListing": "deep_listing",
407+
}
408+
)
409+
)
410+
case {"requirements": MutableMapping() as reqs}:
411+
if not network_access:
412+
reqs["NetworkAccess"] = {"networkAccess": True}
413+
if not listing:
414+
reqs["LoadListingRequirement"] = cmap(
415+
{"loadListing": "deep_listing"}
416+
)
417+
case {"class": "ExpressionTool"}:
419418
move_up_loadcontents(document)
420419
cleanup_v1_0_input_bindings(document)
421420
return document
@@ -427,57 +426,46 @@ def _v1_0_to_v1_2(document: CommentedMap, outdir: str) -> CommentedMap:
427426

428427

429428
def _v1_1_to_v1_2(document: CommentedMap, outdir: str) -> CommentedMap:
430-
if "class" in document:
431-
if document["class"] == "Workflow":
432-
steps = document["steps"]
433-
if isinstance(steps, MutableSequence):
434-
for index, entry in enumerate(steps):
435-
with SourceLine(steps, index, Exception):
436-
if "run" in entry and isinstance(entry["run"], CommentedMap):
437-
process = entry["run"]
429+
match document:
430+
case {"class": "Workflow", "steps": MutableSequence() as steps}:
431+
for index, entry in enumerate(steps):
432+
with SourceLine(steps, index, Exception):
433+
match entry:
434+
case {"run": CommentedMap() as process}:
438435
_v1_1_to_v1_2(process, outdir)
439436
if "cwlVersion" in process:
440437
del process["cwlVersion"]
441-
442-
elif isinstance(entry["run"], str) and "#" not in entry["run"]:
438+
case {"run": str(run)} if "#" not in run:
443439
if hasattr(document.lc, "filename"):
444440
dirname = Path(document.lc.filename).parent
445441
else:
446442
dirname = Path(outdir)
447-
path = dirname / entry["run"]
443+
path = dirname / run
448444
process = v1_1_to_v1_2(load_cwl_document(str(path)), outdir)
449445
write_cwl_document(process, path.name, outdir)
450-
elif isinstance(steps, MutableMapping):
451-
for step_name in steps:
452-
with SourceLine(steps, step_name, Exception):
453-
entry = steps[step_name]
454-
if "run" in entry:
455-
if isinstance(entry["run"], CommentedMap):
456-
process = entry["run"]
457-
_v1_1_to_v1_2(process, outdir)
458-
if "cwlVersion" in process:
459-
del process["cwlVersion"]
460-
elif (
461-
isinstance(entry["run"], str)
462-
and "#" not in entry["run"]
463-
):
464-
if hasattr(document.lc, "filename"):
465-
dirname = Path(document.lc.filename).parent
466-
else:
467-
dirname = Path(outdir)
468-
path = dirname / entry["run"]
469-
process = v1_1_to_v1_2(
470-
load_cwl_document(str(path)), outdir
471-
)
472-
write_cwl_document(process, path.name, outdir)
473-
elif isinstance(entry["run"], str) and "#" in entry["run"]:
474-
pass # reference to $graph entry
446+
case {"class": "Workflow", "steps": MutableMapping() as steps}:
447+
for step_name in steps:
448+
with SourceLine(steps, step_name, Exception):
449+
match steps[step_name]:
450+
case {"run": CommentedMap() as process}:
451+
_v1_1_to_v1_2(process, outdir)
452+
if "cwlVersion" in process:
453+
del process["cwlVersion"]
454+
case {"run": str(run)} if "#" not in run:
455+
if hasattr(document.lc, "filename"):
456+
dirname = Path(document.lc.filename).parent
475457
else:
476-
raise Exception(
477-
"'run' entry was neither a CWL Process nor "
478-
"a path to one: %s.",
479-
entry["run"],
480-
)
458+
dirname = Path(outdir)
459+
path = dirname / run
460+
process = v1_1_to_v1_2(load_cwl_document(str(path)), outdir)
461+
write_cwl_document(process, path.name, outdir)
462+
case {"run": str(run)} if "#" in run:
463+
pass # reference to $graph entry
464+
case {"run": run}:
465+
raise Exception(
466+
"'run' entry was neither a CWL Process nor "
467+
"a path to one: {run}."
468+
)
481469
return document
482470

483471

@@ -683,22 +671,21 @@ def input_output_clean(document: dict[str, Any]) -> None:
683671

684672
def array_type_raise_sf(param: MutableMapping[str, Any]) -> None:
685673
"""Move up draft-3 secondaryFile specs on File members in Arrays."""
686-
typ = param["type"]
687-
if isinstance(typ, MutableSequence):
688-
for index, param2 in enumerate(typ):
689-
with SourceLine(typ, index, Exception):
690-
if isinstance(param2, MutableMapping) and "type" in param2:
691-
array_type_raise_sf(param2)
692-
elif (
693-
isinstance(typ, MutableMapping)
694-
and "type" in typ
695-
and typ["type"] == "array"
696-
and "items" in typ
697-
and "File" in typ["items"]
698-
and "secondaryFiles" in typ
699-
):
700-
param["secondaryFiles"] = typ["secondaryFiles"]
701-
del typ["secondaryFiles"]
674+
match param["type"]:
675+
case MutableSequence() as typ:
676+
for index, param2 in enumerate(typ):
677+
with SourceLine(typ, index, Exception):
678+
if isinstance(param2, MutableMapping) and "type" in param2:
679+
array_type_raise_sf(param2)
680+
case {
681+
"type": "array",
682+
"items": items,
683+
"secondaryFiles": sec_files,
684+
} as typ if (
685+
"File" in items
686+
):
687+
param["secondaryFiles"] = sec_files
688+
del typ["secondaryFiles"]
702689

703690

704691
def hints_and_requirements_clean(document: dict[str, Any]) -> None:

0 commit comments

Comments
 (0)