Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/cwltool/argparser.py @ 2:6af9afd405e9 draft
"planemo upload commit 0a63dd5f4d38a1f6944587f52a8cd79874177fc1"
author | shellac |
---|---|
date | Thu, 14 May 2020 14:56:58 -0400 |
parents | 26e78fe6e8c4 |
children |
comparison
equal
deleted
inserted
replaced
1:75ca89e9b81c | 2:6af9afd405e9 |
---|---|
1 """Command line argument parsing for cwltool.""" | |
2 from __future__ import absolute_import, print_function | |
3 | |
4 import argparse | |
5 import os | |
6 from typing import (Any, AnyStr, Dict, List, MutableMapping, MutableSequence, | |
7 Optional, Sequence, Union, cast) | |
8 | |
9 from schema_salad.ref_resolver import file_uri | |
10 from typing_extensions import Text # pylint: disable=unused-import | |
11 # move to a regular typing import when Python 3.3-3.6 is no longer supported | |
12 | |
13 from .loghandler import _logger | |
14 from .process import Process, shortname # pylint: disable=unused-import | |
15 from .resolver import ga4gh_tool_registries | |
16 from .software_requirements import SOFTWARE_REQUIREMENTS_ENABLED | |
17 from .utils import DEFAULT_TMP_PREFIX | |
18 | |
19 | |
20 def arg_parser(): # type: () -> argparse.ArgumentParser | |
21 parser = argparse.ArgumentParser( | |
22 description='Reference executor for Common Workflow Language standards.') | |
23 parser.add_argument("--basedir", type=Text) | |
24 parser.add_argument("--outdir", type=Text, default=os.path.abspath('.'), | |
25 help="Output directory, default current directory") | |
26 | |
27 parser.add_argument("--parallel", action="store_true", default=False, | |
28 help="[experimental] Run jobs in parallel. ") | |
29 envgroup = parser.add_mutually_exclusive_group() | |
30 envgroup.add_argument("--preserve-environment", type=Text, action="append", | |
31 help="Preserve specific environment variable when " | |
32 "running CommandLineTools. May be provided multiple " | |
33 "times.", metavar="ENVVAR", default=["PATH"], | |
34 dest="preserve_environment") | |
35 envgroup.add_argument("--preserve-entire-environment", action="store_true", | |
36 help="Preserve all environment variable when running " | |
37 "CommandLineTools.", default=False, | |
38 dest="preserve_entire_environment") | |
39 | |
40 exgroup = parser.add_mutually_exclusive_group() | |
41 exgroup.add_argument("--rm-container", action="store_true", default=True, | |
42 help="Delete Docker container used by jobs after they exit (default)", | |
43 dest="rm_container") | |
44 | |
45 exgroup.add_argument( | |
46 "--leave-container", action="store_false", default=True, | |
47 help="Do not delete Docker container used by jobs after they exit", | |
48 dest="rm_container") | |
49 | |
50 cidgroup = parser.add_argument_group( | |
51 "Options for recording the Docker container identifier into a file.") | |
52 # Disabled as containerid is now saved by default | |
53 cidgroup.add_argument("--record-container-id", action="store_true", | |
54 default=False, | |
55 help = argparse.SUPPRESS, | |
56 dest="record_container_id") | |
57 | |
58 cidgroup.add_argument( | |
59 "--cidfile-dir", type=Text, help="Store the Docker " | |
60 "container ID into a file in the specified directory.", | |
61 default=None, dest="cidfile_dir") | |
62 | |
63 cidgroup.add_argument( | |
64 "--cidfile-prefix", type=Text, | |
65 help="Specify a prefix to the container ID filename. " | |
66 "Final file name will be followed by a timestamp. " | |
67 "The default is no prefix.", | |
68 default=None, dest="cidfile_prefix") | |
69 | |
70 parser.add_argument("--tmpdir-prefix", type=Text, | |
71 help="Path prefix for temporary directories", | |
72 default=DEFAULT_TMP_PREFIX) | |
73 | |
74 exgroup = parser.add_mutually_exclusive_group() | |
75 exgroup.add_argument("--tmp-outdir-prefix", type=Text, | |
76 help="Path prefix for intermediate output directories", | |
77 default=DEFAULT_TMP_PREFIX) | |
78 | |
79 exgroup.add_argument( | |
80 "--cachedir", type=Text, default="", | |
81 help="Directory to cache intermediate workflow outputs to avoid recomputing steps.") | |
82 | |
83 exgroup = parser.add_mutually_exclusive_group() | |
84 exgroup.add_argument("--rm-tmpdir", action="store_true", default=True, | |
85 help="Delete intermediate temporary directories (default)", | |
86 dest="rm_tmpdir") | |
87 | |
88 exgroup.add_argument("--leave-tmpdir", action="store_false", | |
89 default=True, help="Do not delete intermediate temporary directories", | |
90 dest="rm_tmpdir") | |
91 | |
92 exgroup = parser.add_mutually_exclusive_group() | |
93 exgroup.add_argument( | |
94 "--move-outputs", action="store_const", const="move", default="move", | |
95 help="Move output files to the workflow output directory and delete " | |
96 "intermediate output directories (default).", dest="move_outputs") | |
97 | |
98 exgroup.add_argument("--leave-outputs", action="store_const", const="leave", default="move", | |
99 help="Leave output files in intermediate output directories.", | |
100 dest="move_outputs") | |
101 | |
102 exgroup.add_argument("--copy-outputs", action="store_const", const="copy", default="move", | |
103 help="Copy output files to the workflow output directory, don't delete intermediate output directories.", | |
104 dest="move_outputs") | |
105 | |
106 exgroup = parser.add_mutually_exclusive_group() | |
107 exgroup.add_argument("--enable-pull", default=True, action="store_true", | |
108 help="Try to pull Docker images", dest="pull_image") | |
109 | |
110 exgroup.add_argument("--disable-pull", default=True, action="store_false", | |
111 help="Do not try to pull Docker images", dest="pull_image") | |
112 | |
113 parser.add_argument("--rdf-serializer", | |
114 help="Output RDF serialization format used by --print-rdf (one of turtle (default), n3, nt, xml)", | |
115 default="turtle") | |
116 | |
117 parser.add_argument("--eval-timeout", | |
118 help="Time to wait for a Javascript expression to evaluate before giving an error, default 20s.", | |
119 type=float, | |
120 default=20) | |
121 | |
122 provgroup = parser.add_argument_group("Options for recording provenance " | |
123 "information of the execution") | |
124 provgroup.add_argument("--provenance", | |
125 help="Save provenance to specified folder as a " | |
126 "Research Object that captures and aggregates " | |
127 "workflow execution and data products.", | |
128 type=Text) | |
129 | |
130 provgroup.add_argument("--enable-user-provenance", default=False, | |
131 action="store_true", | |
132 help="Record user account info as part of provenance.", | |
133 dest="user_provenance") | |
134 provgroup.add_argument("--disable-user-provenance", default=False, | |
135 action="store_false", | |
136 help="Do not record user account info in provenance.", | |
137 dest="user_provenance") | |
138 provgroup.add_argument("--enable-host-provenance", default=False, | |
139 action="store_true", | |
140 help="Record host info as part of provenance.", | |
141 dest="host_provenance") | |
142 provgroup.add_argument("--disable-host-provenance", default=False, | |
143 action="store_false", | |
144 help="Do not record host info in provenance.", | |
145 dest="host_provenance") | |
146 provgroup.add_argument( | |
147 "--orcid", help="Record user ORCID identifier as part of " | |
148 "provenance, e.g. https://orcid.org/0000-0002-1825-0097 " | |
149 "or 0000-0002-1825-0097. Alternatively the environment variable " | |
150 "ORCID may be set.", dest="orcid", default=os.environ.get("ORCID", ''), | |
151 type=Text) | |
152 provgroup.add_argument( | |
153 "--full-name", help="Record full name of user as part of provenance, " | |
154 "e.g. Josiah Carberry. You may need to use shell quotes to preserve " | |
155 "spaces. Alternatively the environment variable CWL_FULL_NAME may " | |
156 "be set.", dest="cwl_full_name", default=os.environ.get("CWL_FULL_NAME", ''), | |
157 type=Text) | |
158 | |
159 exgroup = parser.add_mutually_exclusive_group() | |
160 exgroup.add_argument("--print-rdf", action="store_true", | |
161 help="Print corresponding RDF graph for workflow and exit") | |
162 exgroup.add_argument("--print-dot", action="store_true", | |
163 help="Print workflow visualization in graphviz format and exit") | |
164 exgroup.add_argument("--print-pre", action="store_true", help="Print CWL document after preprocessing.") | |
165 exgroup.add_argument("--print-deps", action="store_true", help="Print CWL document dependencies.") | |
166 exgroup.add_argument("--print-input-deps", action="store_true", help="Print input object document dependencies.") | |
167 exgroup.add_argument("--pack", action="store_true", help="Combine components into single document and print.") | |
168 exgroup.add_argument("--version", action="store_true", help="Print version and exit") | |
169 exgroup.add_argument("--validate", action="store_true", help="Validate CWL document only.") | |
170 exgroup.add_argument("--print-supported-versions", action="store_true", help="Print supported CWL specs.") | |
171 exgroup.add_argument("--print-subgraph", action="store_true", | |
172 help="Print workflow subgraph that will execute " | |
173 "(can combine with --target)") | |
174 exgroup.add_argument("--print-targets", action="store_true", help="Print targets (output parameters)") | |
175 | |
176 exgroup = parser.add_mutually_exclusive_group() | |
177 exgroup.add_argument("--strict", action="store_true", | |
178 help="Strict validation (unrecognized or out of place fields are error)", | |
179 default=True, dest="strict") | |
180 exgroup.add_argument("--non-strict", action="store_false", help="Lenient validation (ignore unrecognized fields)", | |
181 default=True, dest="strict") | |
182 | |
183 parser.add_argument("--skip-schemas", action="store_true", | |
184 help="Skip loading of schemas", default=False, dest="skip_schemas") | |
185 | |
186 exgroup = parser.add_mutually_exclusive_group() | |
187 exgroup.add_argument("--verbose", action="store_true", help="Default logging") | |
188 exgroup.add_argument("--quiet", action="store_true", help="Only print warnings and errors.") | |
189 exgroup.add_argument("--debug", action="store_true", help="Print even more logging") | |
190 | |
191 parser.add_argument( | |
192 "--strict-memory-limit", action="store_true", help="When running with " | |
193 "software containers and the Docker engine, pass either the " | |
194 "calculated memory allocation from ResourceRequirements or the " | |
195 "default of 1 gigabyte to Docker's --memory option.") | |
196 | |
197 parser.add_argument("--timestamps", action="store_true", help="Add " | |
198 "timestamps to the errors, warnings, and " | |
199 "notifications.") | |
200 parser.add_argument("--js-console", action="store_true", help="Enable javascript console output") | |
201 parser.add_argument("--disable-js-validation", action="store_true", help="Disable javascript validation.") | |
202 parser.add_argument("--js-hint-options-file", | |
203 type=Text, | |
204 help="File of options to pass to jshint." | |
205 "This includes the added option \"includewarnings\". ") | |
206 dockergroup = parser.add_mutually_exclusive_group() | |
207 dockergroup.add_argument("--user-space-docker-cmd", metavar="CMD", | |
208 help="(Linux/OS X only) Specify a user space docker " | |
209 "command (like udocker or dx-docker) that will be " | |
210 "used to call 'pull' and 'run'") | |
211 dockergroup.add_argument("--singularity", action="store_true", | |
212 default=False, help="[experimental] Use " | |
213 "Singularity runtime for running containers. " | |
214 "Requires Singularity v2.6.1+ and Linux with kernel " | |
215 "version v3.18+ or with overlayfs support " | |
216 "backported.") | |
217 dockergroup.add_argument("--no-container", action="store_false", | |
218 default=True, help="Do not execute jobs in a " | |
219 "Docker container, even when `DockerRequirement` " | |
220 "is specified under `hints`.", | |
221 dest="use_container") | |
222 | |
223 dependency_resolvers_configuration_help = argparse.SUPPRESS | |
224 dependencies_directory_help = argparse.SUPPRESS | |
225 use_biocontainers_help = argparse.SUPPRESS | |
226 conda_dependencies = argparse.SUPPRESS | |
227 | |
228 if SOFTWARE_REQUIREMENTS_ENABLED: | |
229 dependency_resolvers_configuration_help = "Dependency resolver configuration file describing how to adapt 'SoftwareRequirement' packages to current system." | |
230 dependencies_directory_help = "Defaut root directory used by dependency resolvers configuration." | |
231 use_biocontainers_help = "Use biocontainers for tools without an explicitly annotated Docker container." | |
232 conda_dependencies = "Short cut to use Conda to resolve 'SoftwareRequirement' packages." | |
233 | |
234 parser.add_argument("--beta-dependency-resolvers-configuration", default=None, help=dependency_resolvers_configuration_help) | |
235 parser.add_argument("--beta-dependencies-directory", default=None, help=dependencies_directory_help) | |
236 parser.add_argument("--beta-use-biocontainers", default=None, help=use_biocontainers_help, action="store_true") | |
237 parser.add_argument("--beta-conda-dependencies", default=None, help=conda_dependencies, action="store_true") | |
238 | |
239 parser.add_argument("--tool-help", action="store_true", help="Print command line help for tool") | |
240 | |
241 parser.add_argument("--relative-deps", choices=['primary', 'cwd'], | |
242 default="primary", help="When using --print-deps, print paths " | |
243 "relative to primary file or current working directory.") | |
244 | |
245 parser.add_argument("--enable-dev", action="store_true", | |
246 help="Enable loading and running development versions " | |
247 "of CWL spec.", default=False) | |
248 | |
249 parser.add_argument("--enable-ext", action="store_true", | |
250 help="Enable loading and running cwltool extensions " | |
251 "to CWL spec.", default=False) | |
252 | |
253 exgroup = parser.add_mutually_exclusive_group() | |
254 exgroup.add_argument("--enable-color", action="store_true", | |
255 help="Enable logging color (default enabled)", default=True) | |
256 exgroup.add_argument("--disable-color", action="store_false", dest="enable_color", | |
257 help="Disable colored logging (default false)") | |
258 | |
259 parser.add_argument("--default-container", | |
260 help="Specify a default docker container that will be used if the workflow fails to specify one.") | |
261 parser.add_argument("--no-match-user", action="store_true", | |
262 help="Disable passing the current uid to `docker run --user`") | |
263 parser.add_argument("--custom-net", type=Text, | |
264 help="Passed to `docker run` as the '--net' " | |
265 "parameter when NetworkAccess is true.") | |
266 parser.add_argument("--disable-validate", dest="do_validate", | |
267 action="store_false", default=True, | |
268 help=argparse.SUPPRESS) | |
269 | |
270 exgroup = parser.add_mutually_exclusive_group() | |
271 exgroup.add_argument("--enable-ga4gh-tool-registry", action="store_true", help="Enable resolution using GA4GH tool registry API", | |
272 dest="enable_ga4gh_tool_registry", default=True) | |
273 exgroup.add_argument("--disable-ga4gh-tool-registry", action="store_false", help="Disable resolution using GA4GH tool registry API", | |
274 dest="enable_ga4gh_tool_registry", default=True) | |
275 | |
276 parser.add_argument("--add-ga4gh-tool-registry", action="append", help="Add a GA4GH tool registry endpoint to use for resolution, default %s" % ga4gh_tool_registries, | |
277 dest="ga4gh_tool_registries", default=[]) | |
278 | |
279 parser.add_argument("--on-error", | |
280 help="Desired workflow behavior when a step fails. One of 'stop' (do not submit any more steps) or " | |
281 "'continue' (may submit other steps that are not downstream from the error). Default is 'stop'.", | |
282 default="stop", choices=("stop", "continue")) | |
283 | |
284 exgroup = parser.add_mutually_exclusive_group() | |
285 exgroup.add_argument("--compute-checksum", action="store_true", default=True, | |
286 help="Compute checksum of contents while collecting outputs", | |
287 dest="compute_checksum") | |
288 exgroup.add_argument("--no-compute-checksum", action="store_false", | |
289 help="Do not compute checksum of contents while collecting outputs", | |
290 dest="compute_checksum") | |
291 | |
292 parser.add_argument("--relax-path-checks", action="store_true", | |
293 default=False, help="Relax requirements on path names to permit " | |
294 "spaces and hash characters.", dest="relax_path_checks") | |
295 exgroup.add_argument("--make-template", action="store_true", | |
296 help="Generate a template input object") | |
297 | |
298 parser.add_argument("--force-docker-pull", action="store_true", | |
299 default=False, help="Pull latest docker image even if" | |
300 " it is locally present", dest="force_docker_pull") | |
301 parser.add_argument("--no-read-only", action="store_true", | |
302 default=False, help="Do not set root directory in the" | |
303 " container as read-only", dest="no_read_only") | |
304 | |
305 parser.add_argument("--overrides", type=str, | |
306 default=None, help="Read process requirement overrides from file.") | |
307 | |
308 parser.add_argument("--target", "-t", action="append", | |
309 help="Only execute steps that contribute to " | |
310 "listed targets (can provide more than once).") | |
311 | |
312 parser.add_argument("workflow", type=Text, nargs="?", default=None, | |
313 metavar='cwl_document', help="path or URL to a CWL Workflow, " | |
314 "CommandLineTool, or ExpressionTool. If the `inputs_object` has a " | |
315 "`cwl:tool` field indicating the path or URL to the cwl_document, " | |
316 " then the `workflow` argument is optional.") | |
317 parser.add_argument("job_order", nargs=argparse.REMAINDER, | |
318 metavar='inputs_object', help="path or URL to a YAML or JSON " | |
319 "formatted description of the required input values for the given " | |
320 "`cwl_document`.") | |
321 | |
322 return parser | |
323 | |
324 | |
325 def get_default_args(): | |
326 # type: () -> Dict[str, Any] | |
327 """Get default values of cwltool's command line options.""" | |
328 ap = arg_parser() | |
329 args = ap.parse_args([]) | |
330 return vars(args) | |
331 | |
332 | |
333 class FSAction(argparse.Action): | |
334 objclass = None # type: Text | |
335 | |
336 def __init__(self, option_strings, dest, nargs=None, **kwargs): | |
337 # type: (List[Text], Text, Any, **Any) -> None | |
338 """Fail if nargs is used.""" | |
339 if nargs is not None: | |
340 raise ValueError("nargs not allowed") | |
341 super(FSAction, self).__init__(option_strings, dest, **kwargs) | |
342 | |
343 def __call__(self, | |
344 parser, # type: argparse.ArgumentParser | |
345 namespace, # type: argparse.Namespace | |
346 values, # type: Union[AnyStr, Sequence[Any], None] | |
347 option_string=None # type: Optional[Text] | |
348 ): # type: (...) -> None | |
349 setattr(namespace, | |
350 self.dest, | |
351 {"class": self.objclass, | |
352 "location": file_uri(str(os.path.abspath(cast(AnyStr, values))))}) | |
353 | |
354 | |
355 class FSAppendAction(argparse.Action): | |
356 objclass = None # type: Text | |
357 | |
358 def __init__(self, option_strings, dest, nargs=None, **kwargs): | |
359 # type: (List[Text], Text, Any, **Any) -> None | |
360 """Initialize.""" | |
361 if nargs is not None: | |
362 raise ValueError("nargs not allowed") | |
363 super(FSAppendAction, self).__init__(option_strings, dest, **kwargs) | |
364 | |
365 def __call__(self, | |
366 parser, # type: argparse.ArgumentParser | |
367 namespace, # type: argparse.Namespace | |
368 values, # type: Union[AnyStr, Sequence[Any], None] | |
369 option_string=None # type: Optional[Text] | |
370 ): # type: (...) -> None | |
371 g = getattr(namespace, self.dest) | |
372 if not g: | |
373 g = [] | |
374 setattr(namespace, self.dest, g) | |
375 g.append( | |
376 {"class": self.objclass, | |
377 "location": file_uri(str(os.path.abspath(cast(AnyStr, values))))}) | |
378 | |
379 | |
380 class FileAction(FSAction): | |
381 objclass = "File" | |
382 | |
383 | |
384 class DirectoryAction(FSAction): | |
385 objclass = "Directory" | |
386 | |
387 | |
388 class FileAppendAction(FSAppendAction): | |
389 objclass = "File" | |
390 | |
391 | |
392 class DirectoryAppendAction(FSAppendAction): | |
393 objclass = "Directory" | |
394 | |
395 | |
396 def add_argument(toolparser, name, inptype, records, description="", | |
397 default=None, input_required=True): | |
398 # type: (argparse.ArgumentParser, Text, Any, List[Text], Text, Any, bool) -> None | |
399 if len(name) == 1: | |
400 flag = "-" | |
401 else: | |
402 flag = "--" | |
403 | |
404 # if input_required is false, don't make the command line | |
405 # parameter required. | |
406 required = default is None and input_required | |
407 if isinstance(inptype, MutableSequence): | |
408 if inptype[0] == "null": | |
409 required = False | |
410 if len(inptype) == 2: | |
411 inptype = inptype[1] | |
412 else: | |
413 _logger.debug(u"Can't make command line argument from %s", inptype) | |
414 return None | |
415 | |
416 ahelp = description.replace("%", "%%") | |
417 action = None # type: Optional[Union[argparse.Action, Text]] | |
418 atype = None # type: Any | |
419 | |
420 if inptype == "File": | |
421 action = cast(argparse.Action, FileAction) | |
422 elif inptype == "Directory": | |
423 action = cast(argparse.Action, DirectoryAction) | |
424 elif isinstance(inptype, MutableMapping) and inptype["type"] == "array": | |
425 if inptype["items"] == "File": | |
426 action = cast(argparse.Action, FileAppendAction) | |
427 elif inptype["items"] == "Directory": | |
428 action = cast(argparse.Action, DirectoryAppendAction) | |
429 else: | |
430 action = "append" | |
431 elif isinstance(inptype, MutableMapping) and inptype["type"] == "enum": | |
432 atype = Text | |
433 elif isinstance(inptype, MutableMapping) and inptype["type"] == "record": | |
434 records.append(name) | |
435 for field in inptype['fields']: | |
436 fieldname = name + "." + shortname(field['name']) | |
437 fieldtype = field['type'] | |
438 fielddescription = field.get("doc", "") | |
439 add_argument( | |
440 toolparser, fieldname, fieldtype, records, | |
441 fielddescription) | |
442 return | |
443 elif inptype == "string": | |
444 atype = Text | |
445 elif inptype == "int": | |
446 atype = int | |
447 elif inptype == "double": | |
448 atype = float | |
449 elif inptype == "float": | |
450 atype = float | |
451 elif inptype == "boolean": | |
452 action = "store_true" | |
453 else: | |
454 _logger.debug(u"Can't make command line argument from %s", inptype) | |
455 return None | |
456 | |
457 if inptype != "boolean": | |
458 typekw = {'type': atype} | |
459 else: | |
460 typekw = {} | |
461 | |
462 toolparser.add_argument( # type: ignore | |
463 flag + name, required=required, help=ahelp, action=action, | |
464 default=default, **typekw) | |
465 | |
466 | |
467 def generate_parser(toolparser, tool, namemap, records, input_required=True): | |
468 # type: (argparse.ArgumentParser, Process, Dict[Text, Text], List[Text], bool) -> argparse.ArgumentParser | |
469 toolparser.add_argument("job_order", nargs="?", help="Job input json file") | |
470 namemap["job_order"] = "job_order" | |
471 | |
472 for inp in tool.tool["inputs"]: | |
473 name = shortname(inp["id"]) | |
474 namemap[name.replace("-", "_")] = name | |
475 inptype = inp["type"] | |
476 description = inp.get("doc", "") | |
477 default = inp.get("default", None) | |
478 add_argument(toolparser, name, inptype, records, description, default, input_required) | |
479 | |
480 return toolparser |