Skip to content

Commit 2b3b842

Browse files
authored
Merge pull request #202 from common-workflow-language/command-line-record-parameters
Command line record parameters
2 parents c2a84a8 + 8644b63 commit 2b3b842

File tree

5 files changed

+90
-21
lines changed

5 files changed

+90
-21
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ diff-cover.html: coverage-gcovr.xml coverage.xml
133133

134134
## test : run the ${MODULE} test suite
135135
test: FORCE
136-
python tests/test_examples.py
136+
./setup.py test
137137

138138
sloccount.sc: ${PYSOURCES} Makefile
139139
sloccount --duplicates --wide --details $^ > sloccount.sc

cwltool/main.py

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,6 @@ def output_callback(out, processStatus):
241241

242242
return final_output[0]
243243

244-
245244
class FSAction(argparse.Action):
246245
objclass = None # type: Text
247246

@@ -293,22 +292,15 @@ class FileAppendAction(FSAppendAction):
293292
class DirectoryAppendAction(FSAppendAction):
294293
objclass = "Directory"
295294

296-
def generate_parser(toolparser, tool, namemap):
297-
# type: (argparse.ArgumentParser, Process, Dict[Text, Text]) -> argparse.ArgumentParser
298-
toolparser.add_argument("job_order", nargs="?", help="Job input json file")
299-
namemap["job_order"] = "job_order"
300295

301-
for inp in tool.tool["inputs"]:
302-
name = shortname(inp["id"])
296+
def add_argument(toolparser, name, inptype, records, description="",
297+
default=None):
298+
# type: (argparse.ArgumentParser, Text, Any, List[Text], Text, Any) -> None
303299
if len(name) == 1:
304300
flag = "-"
305301
else:
306302
flag = "--"
307303

308-
namemap[name.replace("-", "_")] = name
309-
310-
inptype = inp["type"]
311-
312304
required = True
313305
if isinstance(inptype, list):
314306
if inptype[0] == "null":
@@ -319,10 +311,9 @@ def generate_parser(toolparser, tool, namemap):
319311
_logger.debug(u"Can't make command line argument from %s", inptype)
320312
return None
321313

322-
ahelp = inp.get("description", "").replace("%", "%%")
314+
ahelp = description.replace("%", "%%")
323315
action = None # type: Union[argparse.Action, Text]
324316
atype = None # type: Any
325-
default = None # type: Any
326317

327318
if inptype == "File":
328319
action = cast(argparse.Action, FileAction)
@@ -337,6 +328,16 @@ def generate_parser(toolparser, tool, namemap):
337328
action = "append"
338329
elif isinstance(inptype, dict) and inptype["type"] == "enum":
339330
atype = Text
331+
elif isinstance(inptype, dict) and inptype["type"] == "record":
332+
records.append(name)
333+
for field in inptype['fields']:
334+
fieldname = name+"."+shortname(field['name'])
335+
fieldtype = field['type']
336+
fielddescription = field.get("doc", "")
337+
add_argument(
338+
toolparser, fieldname, fieldtype, records,
339+
fielddescription)
340+
return
340341
if inptype == "string":
341342
atype = Text
342343
elif inptype == "int":
@@ -348,8 +349,7 @@ def generate_parser(toolparser, tool, namemap):
348349
elif inptype == "boolean":
349350
action = "store_true"
350351

351-
if "default" in inp:
352-
default = inp["default"]
352+
if default:
353353
required = False
354354

355355
if not atype and not action:
@@ -365,6 +365,20 @@ def generate_parser(toolparser, tool, namemap):
365365
flag + name, required=required, help=ahelp, action=action,
366366
default=default, **typekw)
367367

368+
369+
def generate_parser(toolparser, tool, namemap, records):
370+
# type: (argparse.ArgumentParser, Process, Dict[Text, Text], List[Text]) -> argparse.ArgumentParser
371+
toolparser.add_argument("job_order", nargs="?", help="Job input json file")
372+
namemap["job_order"] = "job_order"
373+
374+
for inp in tool.tool["inputs"]:
375+
name = shortname(inp["id"])
376+
namemap[name.replace("-", "_")] = name
377+
inptype = inp["type"]
378+
description = inp.get("doc", "")
379+
default = inp.get("default", None)
380+
add_argument(toolparser, name, inptype, records, description, default)
381+
368382
return toolparser
369383

370384

@@ -406,12 +420,23 @@ def load_job_order(args, t, stdin, print_input_deps=False, relative_deps=False,
406420
else:
407421
input_basedir = args.basedir if args.basedir else os.getcwd()
408422
namemap = {} # type: Dict[Text, Text]
409-
toolparser = generate_parser(argparse.ArgumentParser(prog=args.workflow), t, namemap)
423+
records = [] # type: List[Text]
424+
toolparser = generate_parser(
425+
argparse.ArgumentParser(prog=args.workflow), t, namemap, records)
410426
if toolparser:
411427
if args.tool_help:
412428
toolparser.print_help()
413429
return 0
414430
cmd_line = vars(toolparser.parse_args(args.job_order))
431+
for record_name in records:
432+
record = {}
433+
record_items = {
434+
k:v for k,v in cmd_line.iteritems()
435+
if k.startswith(record_name)}
436+
for key, value in record_items.iteritems():
437+
record[key[len(record_name)+1:]] = value
438+
del cmd_line[key]
439+
cmd_line[str(record_name)] = record
415440

416441
if cmd_line["job_order"]:
417442
try:

tests/test_toolargparse.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,25 @@ class ToolArgparse(unittest.TestCase):
4242
- echo
4343
- "ff"
4444
stdout: foo
45+
'''
46+
47+
script3='''
48+
#!/usr/bin/env cwl-runner
49+
50+
cwlVersion: v1.0
51+
class: ExpressionTool
52+
53+
inputs:
54+
foo:
55+
type:
56+
type: record
57+
fields:
58+
one: File
59+
two: string
60+
61+
expression: $(inputs.foo.two)
62+
63+
outputs: []
4564
'''
4665

4766
def test_help(self):
@@ -59,3 +78,27 @@ def test_bool(self):
5978
self.assertEquals(main([f.name, '--help']), 0)
6079
except SystemExit as e:
6180
self.assertEquals(e.code, 0)
81+
82+
def test_record_help(self):
83+
with NamedTemporaryFile() as f:
84+
f.write(self.script3)
85+
f.flush()
86+
try:
87+
self.assertEquals(main([f.name, '--help']), 0)
88+
except SystemExit as e:
89+
self.assertEquals(e.code, 0)
90+
91+
def test_record(self):
92+
with NamedTemporaryFile() as f:
93+
f.write(self.script3)
94+
f.flush()
95+
try:
96+
self.assertEquals(main([f.name, '--foo.one', 'README.rst',
97+
'--foo.two', 'test']), 0)
98+
except SystemExit as e:
99+
self.assertEquals(e.code, 0)
100+
101+
102+
103+
if __name__ == '__main__':
104+
unittest.main()

typeshed/2.7/argparse.pyi

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ class ArgumentParser:
5858
help: str = ...,
5959
metavar: Union[str, Tuple[str, ...]] = ...,
6060
dest: str = ...,
61-
version: str = ...) -> None: ... # weirdly documented
61+
version: str = ...,
62+
**kwargs: Any) -> None: ... # weirdly documented
6263
def parse_args(self, args: Optional[Sequence[str]] = ...,
6364
namespace: Optional[Namespace] = ...) -> Namespace: ...
6465
def add_subparsers(self, title: str = ...,
@@ -70,8 +71,8 @@ class ArgumentParser:
7071
dest: Optional[str] = ...,
7172
help: Optional[str] = ...,
7273
metavar: Optional[str] = ...) -> _SubParsersAction: ...
73-
def add_argument_group(self, title: Optional[str] = ...,
74-
description: Optional[str] = ...) -> _ArgumentGroup: ...
74+
def add_argument_group(self, title: Optional[Text] = ...,
75+
description: Optional[Text] = ...) -> _ArgumentGroup: ...
7576
def add_mutually_exclusive_group(self, required: bool = ...) -> _MutuallyExclusiveGroup: ...
7677
def set_defaults(self, **kwargs: Any) -> None: ...
7778
def get_default(self, dest: str) -> Any: ...

typeshed/2.7/requests/sessions.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class Session(SessionRedirectMixin):
7878
json=...) -> Response: ...
7979
def get(self, url: AnyStr, **kwargs) -> Response: ...
8080
def options(self, url: str, **kwargs) -> Response: ...
81-
def head(self, url: str, **kwargs) -> Response: ...
81+
def head(self, url: AnyStr, **kwargs) -> Response: ...
8282
def post(self, url: str, data=..., json=..., **kwargs) -> Response: ...
8383
def put(self, url: str, data=..., **kwargs) -> Response: ...
8484
def patch(self, url: str, data=..., **kwargs) -> Response: ...

0 commit comments

Comments
 (0)