|
3 | 3 | from __future__ import absolute_import
|
4 | 4 |
|
5 | 5 | import argparse
|
| 6 | +import collections |
6 | 7 | import functools
|
7 | 8 | import json
|
8 | 9 | import logging
|
@@ -220,6 +221,9 @@ def arg_parser(): # type: () -> argparse.ArgumentParser
|
220 | 221 | parser.add_argument("--relax-path-checks", action="store_true",
|
221 | 222 | default=False, help="Relax requirements on path names to permit "
|
222 | 223 | "spaces and hash characters.", dest="relax_path_checks")
|
| 224 | + exgroup.add_argument("--make-template", action="store_true", |
| 225 | + help="Generate a template input object") |
| 226 | + |
223 | 227 |
|
224 | 228 | parser.add_argument("workflow", type=Text, nargs="?", default=None)
|
225 | 229 | parser.add_argument("job_order", nargs=argparse.REMAINDER)
|
@@ -439,6 +443,56 @@ def generate_parser(toolparser, tool, namemap, records):
|
439 | 443 |
|
440 | 444 | return toolparser
|
441 | 445 |
|
| 446 | +def generate_example_input(inptype): |
| 447 | + defaults = { 'null': 'null', |
| 448 | + 'Any': 'null', |
| 449 | + 'boolean': False, |
| 450 | + 'int': 0, |
| 451 | + 'long': 0, |
| 452 | + 'float': 0.1, |
| 453 | + 'double': 0.1, |
| 454 | + 'string': 'default_string', |
| 455 | + 'File': { 'class': 'File', |
| 456 | + 'path': 'default/file/path' }, |
| 457 | + 'Directory': { 'class': 'Directory', |
| 458 | + 'path': 'default/directory/path' } } |
| 459 | + if (not isinstance(inptype, str) and |
| 460 | + not isinstance(inptype, collections.Mapping) |
| 461 | + and isinstance(inptype, collections.Iterable)): |
| 462 | + if len(inptype) == 2 and 'null' in inptype: |
| 463 | + inptype.remove('null') |
| 464 | + return generate_example_input(inptype[0]) |
| 465 | + # TODO: indicate that this input is optional |
| 466 | + else: |
| 467 | + raise Exception("multi-types other than optional not yet supported" |
| 468 | + " for generating example input objects: %s" |
| 469 | + % inptype) |
| 470 | + if 'type' in inptype: |
| 471 | + if inptype['type'] == 'array': |
| 472 | + return [ generate_example_input(inptype['items']) ] |
| 473 | + elif inptype['type'] == 'enum': |
| 474 | + return 'valid_enum_value' |
| 475 | + # TODO: list valid values in a comment |
| 476 | + elif inptype['type'] == 'record': |
| 477 | + record = {} |
| 478 | + for field in inptype['fields']: |
| 479 | + record[shortname(field)] = generate_example_input(field) |
| 480 | + return record |
| 481 | + else: |
| 482 | + return defaults.get(inptype, 'custom_type') |
| 483 | + # TODO: support custom types, complex arrays |
| 484 | + |
| 485 | + |
| 486 | +def generate_input_template(tool): |
| 487 | + # type: (Process) -> Dict[Text, Any] |
| 488 | + template = {} |
| 489 | + for inp in tool.tool["inputs"]: |
| 490 | + name = shortname(inp["id"]) |
| 491 | + inptype = inp["type"] |
| 492 | + template[name] = generate_example_input(inptype) |
| 493 | + return template |
| 494 | + |
| 495 | + |
442 | 496 |
|
443 | 497 | def load_job_order(args, t, stdin, print_input_deps=False, relative_deps=False,
|
444 | 498 | stdout=sys.stdout, make_fs_access=None, fetcher_constructor=None):
|
@@ -669,7 +723,8 @@ def main(argsl=None, # type: List[str]
|
669 | 723 | 'validate': False,
|
670 | 724 | 'enable_ga4gh_tool_registry': False,
|
671 | 725 | 'ga4gh_tool_registries': [],
|
672 |
| - 'find_default_container': None |
| 726 | + 'find_default_container': None, |
| 727 | + 'make_template': False |
673 | 728 | }):
|
674 | 729 | if not hasattr(args, k):
|
675 | 730 | setattr(args, k, v)
|
@@ -751,6 +806,11 @@ def main(argsl=None, # type: List[str]
|
751 | 806 |
|
752 | 807 | tool = make_tool(document_loader, avsc_names, metadata, uri,
|
753 | 808 | makeTool, make_tool_kwds)
|
| 809 | + if args.make_template: |
| 810 | + yaml.safe_dump(generate_input_template(tool), sys.stdout, |
| 811 | + default_flow_style=False, indent=4, |
| 812 | + block_seq_indent=2) |
| 813 | + return 0 |
754 | 814 |
|
755 | 815 | if args.validate:
|
756 | 816 | return 0
|
|
0 commit comments