Skip to content

Commit

Permalink
Merge pull request #202 from common-workflow-language/command-line-re…
Browse files Browse the repository at this point in the history
…cord-parameters

Command line record parameters
  • Loading branch information
mr-c authored Oct 5, 2016
2 parents c2a84a8 + 8644b63 commit 2b3b842
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 21 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ diff-cover.html: coverage-gcovr.xml coverage.xml

## test : run the ${MODULE} test suite
test: FORCE
python tests/test_examples.py
./setup.py test

sloccount.sc: ${PYSOURCES} Makefile
sloccount --duplicates --wide --details $^ > sloccount.sc
Expand Down
57 changes: 41 additions & 16 deletions cwltool/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,6 @@ def output_callback(out, processStatus):

return final_output[0]


class FSAction(argparse.Action):
objclass = None # type: Text

Expand Down Expand Up @@ -293,22 +292,15 @@ class FileAppendAction(FSAppendAction):
class DirectoryAppendAction(FSAppendAction):
objclass = "Directory"

def generate_parser(toolparser, tool, namemap):
# type: (argparse.ArgumentParser, Process, Dict[Text, Text]) -> argparse.ArgumentParser
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"])
def add_argument(toolparser, name, inptype, records, description="",
default=None):
# type: (argparse.ArgumentParser, Text, Any, List[Text], Text, Any) -> None
if len(name) == 1:
flag = "-"
else:
flag = "--"

namemap[name.replace("-", "_")] = name

inptype = inp["type"]

required = True
if isinstance(inptype, list):
if inptype[0] == "null":
Expand All @@ -319,10 +311,9 @@ def generate_parser(toolparser, tool, namemap):
_logger.debug(u"Can't make command line argument from %s", inptype)
return None

ahelp = inp.get("description", "").replace("%", "%%")
ahelp = description.replace("%", "%%")
action = None # type: Union[argparse.Action, Text]
atype = None # type: Any
default = None # type: Any

if inptype == "File":
action = cast(argparse.Action, FileAction)
Expand All @@ -337,6 +328,16 @@ def generate_parser(toolparser, tool, namemap):
action = "append"
elif isinstance(inptype, dict) and inptype["type"] == "enum":
atype = Text
elif isinstance(inptype, dict) and inptype["type"] == "record":
records.append(name)
for field in inptype['fields']:
fieldname = name+"."+shortname(field['name'])
fieldtype = field['type']
fielddescription = field.get("doc", "")
add_argument(
toolparser, fieldname, fieldtype, records,
fielddescription)
return
if inptype == "string":
atype = Text
elif inptype == "int":
Expand All @@ -348,8 +349,7 @@ def generate_parser(toolparser, tool, namemap):
elif inptype == "boolean":
action = "store_true"

if "default" in inp:
default = inp["default"]
if default:
required = False

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


def generate_parser(toolparser, tool, namemap, records):
# type: (argparse.ArgumentParser, Process, Dict[Text, Text], List[Text]) -> argparse.ArgumentParser
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"])
namemap[name.replace("-", "_")] = name
inptype = inp["type"]
description = inp.get("doc", "")
default = inp.get("default", None)
add_argument(toolparser, name, inptype, records, description, default)

return toolparser


Expand Down Expand Up @@ -406,12 +420,23 @@ def load_job_order(args, t, stdin, print_input_deps=False, relative_deps=False,
else:
input_basedir = args.basedir if args.basedir else os.getcwd()
namemap = {} # type: Dict[Text, Text]
toolparser = generate_parser(argparse.ArgumentParser(prog=args.workflow), t, namemap)
records = [] # type: List[Text]
toolparser = generate_parser(
argparse.ArgumentParser(prog=args.workflow), t, namemap, records)
if toolparser:
if args.tool_help:
toolparser.print_help()
return 0
cmd_line = vars(toolparser.parse_args(args.job_order))
for record_name in records:
record = {}
record_items = {
k:v for k,v in cmd_line.iteritems()
if k.startswith(record_name)}
for key, value in record_items.iteritems():
record[key[len(record_name)+1:]] = value
del cmd_line[key]
cmd_line[str(record_name)] = record

if cmd_line["job_order"]:
try:
Expand Down
43 changes: 43 additions & 0 deletions tests/test_toolargparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,25 @@ class ToolArgparse(unittest.TestCase):
- echo
- "ff"
stdout: foo
'''

script3='''
#!/usr/bin/env cwl-runner
cwlVersion: v1.0
class: ExpressionTool
inputs:
foo:
type:
type: record
fields:
one: File
two: string
expression: $(inputs.foo.two)
outputs: []
'''

def test_help(self):
Expand All @@ -59,3 +78,27 @@ def test_bool(self):
self.assertEquals(main([f.name, '--help']), 0)
except SystemExit as e:
self.assertEquals(e.code, 0)

def test_record_help(self):
with NamedTemporaryFile() as f:
f.write(self.script3)
f.flush()
try:
self.assertEquals(main([f.name, '--help']), 0)
except SystemExit as e:
self.assertEquals(e.code, 0)

def test_record(self):
with NamedTemporaryFile() as f:
f.write(self.script3)
f.flush()
try:
self.assertEquals(main([f.name, '--foo.one', 'README.rst',
'--foo.two', 'test']), 0)
except SystemExit as e:
self.assertEquals(e.code, 0)



if __name__ == '__main__':
unittest.main()
7 changes: 4 additions & 3 deletions typeshed/2.7/argparse.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ class ArgumentParser:
help: str = ...,
metavar: Union[str, Tuple[str, ...]] = ...,
dest: str = ...,
version: str = ...) -> None: ... # weirdly documented
version: str = ...,
**kwargs: Any) -> None: ... # weirdly documented
def parse_args(self, args: Optional[Sequence[str]] = ...,
namespace: Optional[Namespace] = ...) -> Namespace: ...
def add_subparsers(self, title: str = ...,
Expand All @@ -70,8 +71,8 @@ class ArgumentParser:
dest: Optional[str] = ...,
help: Optional[str] = ...,
metavar: Optional[str] = ...) -> _SubParsersAction: ...
def add_argument_group(self, title: Optional[str] = ...,
description: Optional[str] = ...) -> _ArgumentGroup: ...
def add_argument_group(self, title: Optional[Text] = ...,
description: Optional[Text] = ...) -> _ArgumentGroup: ...
def add_mutually_exclusive_group(self, required: bool = ...) -> _MutuallyExclusiveGroup: ...
def set_defaults(self, **kwargs: Any) -> None: ...
def get_default(self, dest: str) -> Any: ...
Expand Down
2 changes: 1 addition & 1 deletion typeshed/2.7/requests/sessions.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class Session(SessionRedirectMixin):
json=...) -> Response: ...
def get(self, url: AnyStr, **kwargs) -> Response: ...
def options(self, url: str, **kwargs) -> Response: ...
def head(self, url: str, **kwargs) -> Response: ...
def head(self, url: AnyStr, **kwargs) -> Response: ...
def post(self, url: str, data=..., json=..., **kwargs) -> Response: ...
def put(self, url: str, data=..., **kwargs) -> Response: ...
def patch(self, url: str, data=..., **kwargs) -> Response: ...
Expand Down

0 comments on commit 2b3b842

Please sign in to comment.