Skip to content

Commit

Permalink
initial implementation of parameter groups
Browse files Browse the repository at this point in the history
  • Loading branch information
mr-c committed Nov 29, 2024
1 parent 6c86caa commit 8e4f944
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 6 deletions.
41 changes: 35 additions & 6 deletions cwltool/argparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from .process import Process, shortname
from .resolver import ga4gh_tool_registries
from .software_requirements import SOFTWARE_REQUIREMENTS_ENABLED
from .utils import DEFAULT_TMP_PREFIX
from .utils import DEFAULT_TMP_PREFIX, CWLObjectType


def arg_parser() -> argparse.ArgumentParser:
Expand Down Expand Up @@ -845,7 +845,7 @@ def __call__(


def add_argument(
toolparser: argparse.ArgumentParser,
toolparser: Union[argparse.ArgumentParser, "argparse._ArgumentGroup"],
name: str,
inptype: Any,
records: list[str],
Expand Down Expand Up @@ -962,14 +962,18 @@ def generate_parser(
toolparser.add_argument("job_order", nargs="?", help="Job input json file")
namemap["job_order"] = "job_order"

for inp in tool.tool["inputs"]:
name = shortname(inp["id"])
inps = tool.tool["inputs"]

def process_input(
inp: CWLObjectType, parser: Union[argparse.ArgumentParser, "argparse._ArgumentGroup"]
) -> None:
name = shortname(cast(str, inp["id"]))
namemap[name.replace("-", "_")] = name
inptype = inp["type"]
description = inp.get("doc", inp.get("label", ""))
description = cast(str, inp.get("doc", inp.get("label", "")))
default = inp.get("default", None)
add_argument(
toolparser,
parser,
name,
inptype,
records,
Expand All @@ -980,4 +984,29 @@ def generate_parser(
base_uri,
)

if (groups_req := tool.get_requirement("http://commonwl.org/cwltool#Groups")[0]) is not None:
groups = cast(CWLObjectType, groups_req["groups"])
for group_name in groups.keys():
group_inputs: list[CWLObjectType] = []
group_definition = cast(CWLObjectType, groups[group_name])
for input_name in cast(list[str], group_definition["groupMembers"]):
new_inps: list[CWLObjectType] = []
for inp in inps:
if shortname(inp["id"]) == input_name:
group_inputs.append(inp)
else:
new_inps.append(inp)
inps = new_inps

if len(group_inputs) > 0:
group = toolparser.add_argument_group(
title=cast(str, group_definition.get("label", group_name)),
description=cast(Optional[str], group_definition.get("doc", None)),
)
for inp in group_inputs:
process_input(inp, group)

for inp in inps:
process_input(inp, toolparser)

return toolparser
32 changes: 32 additions & 0 deletions cwltool/extensions-v1.2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ $graph:
- Specify the desired method of dealing with loop outputs
- Default. Propagates only the last computed element to the subsequent steps when the loop terminates.
- Propagates a single array with all output values to the subsequent steps when the loop terminates.

- name: ShmSize
type: record
extends: cwl:ProcessRequirement
Expand All @@ -258,3 +259,34 @@ $graph:
than 0. Unit is optional and can be `b` (bytes), `k` (kilobytes), `m`
(megabytes), or `g` (gigabytes). If you omit the unit, the default is
bytes. If you omit the size entirely, the value is `64m`."
- name: Grouping
type: record
extends: [ sld:Documented ]
fields:
- name: GroupName
type: string
- name: groupMembers
type: string[]
jsonldPredicate:
"_type": "@id"
"_container": "@list"
refScope: 0

- name: Groups
type: record
extends: cwl:ProcessRequirement
inVocab: false
fields:
class:
type: string
doc: 'cwltool:Groups'
jsonldPredicate:
"_id": "@type"
"_type": "@vocab"
group:
type:
- type: array
items: "#Grouping"
jsonldPredicate:
mapSubject: GroupName
34 changes: 34 additions & 0 deletions tests/echo-groups.cwl
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env cwl-runner
cwlVersion: v1.0
class: CommandLineTool
inputs:
first:
type: string
inputBinding: {}
second:
type: string
inputBinding: {}
third:
type: string
label: groupless
outputs:
- id: out
type: string
outputBinding:
glob: out.txt
loadContents: true
outputEval: $(self[0].contents)
baseCommand: echo
stdout: out.txt


$namespaces:
cwltool: "http://commonwl.org/cwltool#"

hints:
cwltool:Groups:
groups:
my_groups:
groupMembers: [first, second]
label: my great inputs
doc: "parameters related to the foobar feature"
13 changes: 13 additions & 0 deletions tests/test_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,3 +285,16 @@ def test_ext_validation_no_namespace_warning() -> None:
"URI prefix 'cwltool' of 'cwltool:loop' not recognized, are you "
"missing a $namespaces section?"
) not in stderr


def test_ext_groups_help(capsys: pytest.CaptureFixture[str]) -> None:
error_code, stdout, stderr = get_main_output([get_data("tests/echo-groups.cwl"), "--help"])
assert error_code == 0
assert (
"""my great inputs:
parameters related to the foobar feature
--first FIRST
--second SECOND"""
in capsys.readouterr().out
)

0 comments on commit 8e4f944

Please sign in to comment.