Skip to content

Commit 8e4f944

Browse files
committed
initial implementation of parameter groups
1 parent 6c86caa commit 8e4f944

File tree

4 files changed

+114
-6
lines changed

4 files changed

+114
-6
lines changed

cwltool/argparser.py

+35-6
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from .process import Process, shortname
1111
from .resolver import ga4gh_tool_registries
1212
from .software_requirements import SOFTWARE_REQUIREMENTS_ENABLED
13-
from .utils import DEFAULT_TMP_PREFIX
13+
from .utils import DEFAULT_TMP_PREFIX, CWLObjectType
1414

1515

1616
def arg_parser() -> argparse.ArgumentParser:
@@ -845,7 +845,7 @@ def __call__(
845845

846846

847847
def add_argument(
848-
toolparser: argparse.ArgumentParser,
848+
toolparser: Union[argparse.ArgumentParser, "argparse._ArgumentGroup"],
849849
name: str,
850850
inptype: Any,
851851
records: list[str],
@@ -962,14 +962,18 @@ def generate_parser(
962962
toolparser.add_argument("job_order", nargs="?", help="Job input json file")
963963
namemap["job_order"] = "job_order"
964964

965-
for inp in tool.tool["inputs"]:
966-
name = shortname(inp["id"])
965+
inps = tool.tool["inputs"]
966+
967+
def process_input(
968+
inp: CWLObjectType, parser: Union[argparse.ArgumentParser, "argparse._ArgumentGroup"]
969+
) -> None:
970+
name = shortname(cast(str, inp["id"]))
967971
namemap[name.replace("-", "_")] = name
968972
inptype = inp["type"]
969-
description = inp.get("doc", inp.get("label", ""))
973+
description = cast(str, inp.get("doc", inp.get("label", "")))
970974
default = inp.get("default", None)
971975
add_argument(
972-
toolparser,
976+
parser,
973977
name,
974978
inptype,
975979
records,
@@ -980,4 +984,29 @@ def generate_parser(
980984
base_uri,
981985
)
982986

987+
if (groups_req := tool.get_requirement("http://commonwl.org/cwltool#Groups")[0]) is not None:
988+
groups = cast(CWLObjectType, groups_req["groups"])
989+
for group_name in groups.keys():
990+
group_inputs: list[CWLObjectType] = []
991+
group_definition = cast(CWLObjectType, groups[group_name])
992+
for input_name in cast(list[str], group_definition["groupMembers"]):
993+
new_inps: list[CWLObjectType] = []
994+
for inp in inps:
995+
if shortname(inp["id"]) == input_name:
996+
group_inputs.append(inp)
997+
else:
998+
new_inps.append(inp)
999+
inps = new_inps
1000+
1001+
if len(group_inputs) > 0:
1002+
group = toolparser.add_argument_group(
1003+
title=cast(str, group_definition.get("label", group_name)),
1004+
description=cast(Optional[str], group_definition.get("doc", None)),
1005+
)
1006+
for inp in group_inputs:
1007+
process_input(inp, group)
1008+
1009+
for inp in inps:
1010+
process_input(inp, toolparser)
1011+
9831012
return toolparser

cwltool/extensions-v1.2.yml

+32
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ $graph:
240240
- Specify the desired method of dealing with loop outputs
241241
- Default. Propagates only the last computed element to the subsequent steps when the loop terminates.
242242
- Propagates a single array with all output values to the subsequent steps when the loop terminates.
243+
243244
- name: ShmSize
244245
type: record
245246
extends: cwl:ProcessRequirement
@@ -258,3 +259,34 @@ $graph:
258259
than 0. Unit is optional and can be `b` (bytes), `k` (kilobytes), `m`
259260
(megabytes), or `g` (gigabytes). If you omit the unit, the default is
260261
bytes. If you omit the size entirely, the value is `64m`."
262+
263+
- name: Grouping
264+
type: record
265+
extends: [ sld:Documented ]
266+
fields:
267+
- name: GroupName
268+
type: string
269+
- name: groupMembers
270+
type: string[]
271+
jsonldPredicate:
272+
"_type": "@id"
273+
"_container": "@list"
274+
refScope: 0
275+
276+
- name: Groups
277+
type: record
278+
extends: cwl:ProcessRequirement
279+
inVocab: false
280+
fields:
281+
class:
282+
type: string
283+
doc: 'cwltool:Groups'
284+
jsonldPredicate:
285+
"_id": "@type"
286+
"_type": "@vocab"
287+
group:
288+
type:
289+
- type: array
290+
items: "#Grouping"
291+
jsonldPredicate:
292+
mapSubject: GroupName

tests/echo-groups.cwl

+34
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

+13
Original file line numberDiff line numberDiff line change
@@ -285,3 +285,16 @@ def test_ext_validation_no_namespace_warning() -> None:
285285
"URI prefix 'cwltool' of 'cwltool:loop' not recognized, are you "
286286
"missing a $namespaces section?"
287287
) not in stderr
288+
289+
290+
def test_ext_groups_help(capsys: pytest.CaptureFixture[str]) -> None:
291+
error_code, stdout, stderr = get_main_output([get_data("tests/echo-groups.cwl"), "--help"])
292+
assert error_code == 0
293+
assert (
294+
"""my great inputs:
295+
parameters related to the foobar feature
296+
297+
--first FIRST
298+
--second SECOND"""
299+
in capsys.readouterr().out
300+
)

0 commit comments

Comments
 (0)