Skip to content

Commit a5028f9

Browse files
committed
initial implementation of parameter groups
1 parent 0cbbd92 commit a5028f9

5 files changed

Lines changed: 115 additions & 7 deletions

File tree

cwltool/argparser.py

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from .process import Process, shortname
1818
from .resolver import ga4gh_tool_registries
1919
from .software_requirements import SOFTWARE_REQUIREMENTS_ENABLED
20-
from .utils import DEFAULT_TMP_PREFIX
20+
from .utils import DEFAULT_TMP_PREFIX, CWLObjectType
2121

2222

2323
class _env_var_table(Table):
@@ -933,7 +933,7 @@ def __call__(
933933

934934

935935
def add_argument(
936-
toolparser: argparse.ArgumentParser,
936+
toolparser: argparse.ArgumentParser | "argparse._ArgumentGroup",
937937
name: str,
938938
inptype: Any,
939939
records: list[str],
@@ -1047,14 +1047,18 @@ def generate_parser(
10471047
toolparser.add_argument("job_order", nargs="?", help="Job input json file")
10481048
namemap["job_order"] = "job_order"
10491049

1050-
for inp in tool.tool["inputs"]:
1051-
name = shortname(inp["id"])
1050+
inps = tool.tool["inputs"]
1051+
1052+
def process_input(
1053+
inp: CWLObjectType, parser: argparse.ArgumentParser | "argparse._ArgumentGroup"
1054+
) -> None:
1055+
name = shortname(cast(str, inp["id"]))
10521056
namemap[name.replace("-", "_")] = name
10531057
inptype = inp["type"]
1054-
description = inp.get("doc", inp.get("label", ""))
1058+
description = cast(str, inp.get("doc", inp.get("label", "")))
10551059
default = inp.get("default", None)
10561060
add_argument(
1057-
toolparser,
1061+
parser,
10581062
name,
10591063
inptype,
10601064
records,
@@ -1065,6 +1069,31 @@ def generate_parser(
10651069
base_uri,
10661070
)
10671071

1072+
if (groups_req := tool.get_requirement("http://commonwl.org/cwltool#Groups")[0]) is not None:
1073+
groups = cast(CWLObjectType, groups_req["groups"])
1074+
for group_name in groups.keys():
1075+
group_inputs: list[CWLObjectType] = []
1076+
group_definition = cast(CWLObjectType, groups[group_name])
1077+
for input_name in cast(list[str], group_definition["groupMembers"]):
1078+
new_inps: list[CWLObjectType] = []
1079+
for inp in inps:
1080+
if shortname(inp["id"]) == input_name:
1081+
group_inputs.append(inp)
1082+
else:
1083+
new_inps.append(inp)
1084+
inps = new_inps
1085+
1086+
if len(group_inputs) > 0:
1087+
group = toolparser.add_argument_group(
1088+
title=cast(str, group_definition.get("label", group_name)),
1089+
description=cast(str | None, group_definition.get("doc", None)),
1090+
)
1091+
for inp in group_inputs:
1092+
process_input(inp, group)
1093+
1094+
for inp in inps:
1095+
process_input(inp, toolparser)
1096+
10681097
toolparser.add_argument(
10691098
"--generate-help-preview",
10701099
action=HelpPreviewAction,

cwltool/builder.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,7 @@ def tostr(self, value: MutableMapping[str, str] | Any) -> str:
597597
case {"class": "File" | "Directory" as class_name, **rest}:
598598
if "path" not in rest:
599599
raise WorkflowException(
600-
'{} object missing "path": {}'.format(class_name, value)
600+
f'{class_name} object missing "path": {value}'
601601
)
602602
return str(rest["path"])
603603
case ScalarFloat():

cwltool/extensions-v1.2.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ $graph:
245245
- Specify the desired method of dealing with loop outputs
246246
- Default. Propagates only the last computed element to the subsequent steps when the loop terminates.
247247
- Propagates a single array with all output values to the subsequent steps when the loop terminates.
248+
248249
- name: ShmSize
249250
type: record
250251
extends: cwl:ProcessRequirement
@@ -263,3 +264,34 @@ $graph:
263264
than 0. Unit is optional and can be `b` (bytes), `k` (kilobytes), `m`
264265
(megabytes), or `g` (gigabytes). If you omit the unit, the default is
265266
bytes. If you omit the size entirely, the value is `64m`."
267+
268+
- name: Grouping
269+
type: record
270+
extends: [ sld:Documented ]
271+
fields:
272+
- name: GroupName
273+
type: string
274+
- name: groupMembers
275+
type: string[]
276+
jsonldPredicate:
277+
"_type": "@id"
278+
"_container": "@list"
279+
refScope: 0
280+
281+
- name: Groups
282+
type: record
283+
extends: cwl:ProcessRequirement
284+
inVocab: false
285+
fields:
286+
class:
287+
type: string
288+
doc: 'cwltool:Groups'
289+
jsonldPredicate:
290+
"_id": "@type"
291+
"_type": "@vocab"
292+
group:
293+
type:
294+
- type: array
295+
items: "#Grouping"
296+
jsonldPredicate:
297+
mapSubject: GroupName

tests/echo-groups.cwl

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/usr/bin/env cwl-runner
2+
cwlVersion: v1.0
3+
class: CommandLineTool
4+
inputs:
5+
first:
6+
type: string
7+
inputBinding: {}
8+
second:
9+
type: string
10+
inputBinding: {}
11+
third:
12+
type: string
13+
label: groupless
14+
outputs:
15+
- id: out
16+
type: string
17+
outputBinding:
18+
glob: out.txt
19+
loadContents: true
20+
outputEval: $(self[0].contents)
21+
baseCommand: echo
22+
stdout: out.txt
23+
24+
25+
$namespaces:
26+
cwltool: "http://commonwl.org/cwltool#"
27+
28+
hints:
29+
cwltool:Groups:
30+
groups:
31+
my_groups:
32+
groupMembers: [first, second]
33+
label: my great inputs
34+
doc: "parameters related to the foobar feature"

tests/test_ext.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,3 +293,16 @@ def test_ext_in_dollarsign_graph() -> None:
293293
["--validate", "--enable-ext", get_data("tests/wf/hello_gpu.cwl")]
294294
)
295295
assert error_code == 0
296+
297+
298+
def test_ext_groups_help(capsys: pytest.CaptureFixture[str]) -> None:
299+
error_code, stdout, stderr = get_main_output([get_data("tests/echo-groups.cwl"), "--help"])
300+
assert error_code == 0
301+
assert (
302+
"""my great inputs:
303+
parameters related to the foobar feature
304+
305+
--first FIRST
306+
--second SECOND"""
307+
in capsys.readouterr().out
308+
)

0 commit comments

Comments
 (0)