├── .gitignore ├── LICENSE.TXT ├── MANIFEST.in ├── README.md ├── argparse ├── __init__.py ├── argparse_cwl_translation.py └── argparse_galaxy_translation.py ├── click ├── __init__.py └── click_cwl_translation.py ├── cmdline2cwl ├── __init__.py ├── cwl_tool.py └── templates │ ├── cwltool.j2 │ ├── cwltool_inputs.j2 │ └── cwltool_outputs.j2 ├── example.py ├── example.xml ├── examples ├── argparse │ └── cnvkit-tools │ │ ├── check_wrappers_in_dir.sh │ │ ├── cnvkit-access.cwl │ │ ├── cnvkit-antitarget.cwl │ │ ├── cnvkit-batch.cwl │ │ ├── cnvkit-breaks.cwl │ │ ├── cnvkit-call.cwl │ │ ├── cnvkit-coverage.cwl │ │ ├── cnvkit-diagram.cwl │ │ ├── cnvkit-export-bed.cwl │ │ ├── cnvkit-export-cdt.cwl │ │ ├── cnvkit-export-jtv.cwl │ │ ├── cnvkit-export-nexus-basic.cwl │ │ ├── cnvkit-export-nexus-ogt.cwl │ │ ├── cnvkit-export-seg.cwl │ │ ├── cnvkit-export-theta.cwl │ │ ├── cnvkit-export-vcf.cwl │ │ ├── cnvkit-fix.cwl │ │ ├── cnvkit-gainloss.cwl │ │ ├── cnvkit-gender.cwl │ │ ├── cnvkit-heatmap.cwl │ │ ├── cnvkit-import-picard.cwl │ │ ├── cnvkit-import-seg.cwl │ │ ├── cnvkit-import-theta.cwl │ │ ├── cnvkit-loh.cwl │ │ ├── cnvkit-metrics.cwl │ │ ├── cnvkit-reference.cwl │ │ ├── cnvkit-rescale.cwl │ │ ├── cnvkit-scatter.cwl │ │ ├── cnvkit-segment.cwl │ │ ├── cnvkit-segmetrics.cwl │ │ ├── cnvkit-target.cwl │ │ ├── cnvkit-version.cwl │ │ ├── data.json │ │ ├── genome2access.cwl │ │ ├── genome2access.py │ │ └── output.txt └── click │ └── genmod-tools │ ├── genmod-annotate.cwl │ ├── genmod-build.cwl │ ├── genmod-compound.cwl │ ├── genmod-filter.cwl │ ├── genmod-models.cwl │ ├── genmod-score.cwl │ └── genmod-sort.cwl ├── gxargparse ├── __init__.py └── check_path.py ├── requirements.txt ├── setup.cfg ├── setup.py └── test ├── __init__.py ├── cwl_classes.py ├── test-data ├── index.cwl ├── index.py ├── index_new.cwl ├── inp.txt ├── inp.txt.idx1 ├── job.json ├── main.cwl ├── search.cwl ├── search.py └── search_new.cwl ├── test_arg2cwl.py ├── test_click2cwl.py └── test_utils.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io 2 | 3 | ### vim ### 4 | [._]*.s[a-w][a-z] 5 | [._]s[a-w][a-z] 6 | *.un~ 7 | Session.vim 8 | .netrwhist 9 | *~ 10 | 11 | 12 | ### Python ### 13 | # Byte-compiled / optimized / DLL files 14 | __pycache__/ 15 | *.py[cod] 16 | 17 | # C extensions 18 | *.so 19 | 20 | # Distribution / packaging 21 | .Python 22 | env/ 23 | build/ 24 | develop-eggs/ 25 | dist/ 26 | downloads/ 27 | eggs/ 28 | lib/ 29 | lib64/ 30 | parts/ 31 | sdist/ 32 | var/ 33 | *.egg-info/ 34 | .installed.cfg 35 | *.egg 36 | 37 | # PyInstaller 38 | # Usually these files are written by a python script from a template 39 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 40 | *.manifest 41 | *.spec 42 | 43 | # Installer logs 44 | pip-log.txt 45 | pip-delete-this-directory.txt 46 | 47 | # Unit test / coverage reports 48 | htmlcov/ 49 | .tox/ 50 | .coverage 51 | .cache 52 | nosetests.xml 53 | coverage.xml 54 | 55 | # Translations 56 | *.mo 57 | *.pot 58 | 59 | # Django stuff: 60 | *.log 61 | 62 | # Sphinx documentation 63 | docs/_build/ 64 | 65 | # PyBuilder 66 | target/ 67 | 68 | -------------------------------------------------------------------------------- /LICENSE.TXT: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md 2 | include cmdline2cwl/templates/*.j2 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | `gxargparse` was originally designed to generate Galaxy XML from Python tools which use argparse, but then it was extended to support [Common Workflow Language] (http://www.commonwl.org/v1.0/CommandLineTool.html) command-line tools generation, and not only for argparse, but also for [click](click.pocoo.org/6/) argument parser. For more info about CWL generation jump straight to [argparse2cwl](#argparse2cwl). 2 | 3 | 4 | # `gxargparse` 5 | 6 | Galaxy argparse aims to be a drop-in replacement for argparse, quite literally. 7 | You can write use your normal import 8 | 9 | ```python 10 | import argparse 11 | ``` 12 | 13 | and continue writing code. All functions are passed straight through to 14 | argparse, but `gxargparse` captures them and copies some information along the 15 | way. This information captured is used to produce [Galaxy Tool XML](https://github.com/erasche/galaxyxml) when it's 16 | requested with the `--generate_galaxy_xml` flag. 17 | 18 | ## How it works 19 | 20 | Internally, `gxargparse`, masquerading as `argparse` attempts to find and 21 | import the **real** argparse. It then stores a reference to the code module for 22 | the system argparse, and presents the user with all of the functions that 23 | stdlib's argparse provides. Every function call is passed through the system 24 | argparse. However, gxargparse captures the details of those calls and when Tool 25 | XML is requested, it builds up the tool definition according to IUC tool 26 | standards. 27 | 28 | ## Examples 29 | 30 | You can see the `example.py` file for an example with numerous types of 31 | arguments and options that you might see in real tools. Accordingly there is an `example.xml` file with the output. 32 | 33 | ## It doesn't work!! 34 | 35 | If you are not able to use the `--generate_galaxy_xml` flag after 36 | installing, it is probably because of module load order. gxargparse must 37 | precede argparse in the path. Certain cases seem to work correctly (`python 38 | setup.py install` in a virtualenv) while other cases do not (`pip install 39 | gxargparse`). 40 | 41 | To easily correct this, run the tool `gxargparse_check_path` which is installed 42 | as part of this package. Correctly functioning paths will produce the 43 | following: 44 | 45 | ```console 46 | $ gxargparse_check_path 47 | Ready to go! 48 | ``` 49 | 50 | while incorrectly ordered paths will produce a helpful error message: 51 | 52 | ```console 53 | $ gxargparse_check_path 54 | Incorrect ordering, please set 55 | 56 | PYTHONPATH=/home/users/esr/Projects/test/.venv/local/lib/python2.7/site-packages 57 | 58 | ``` 59 | 60 | This can even be used inline: 61 | 62 | ```console 63 | user@host:$ PYTHONPATH=$(gxargparse_check_path -q) python my_script.py --generate_galaxy_xml 64 | ``` 65 | 66 | ## TODO 67 | 68 | This code doesn't cover the entirety of the `argparse` API yet, and there are some bugs to work out on the XML generation side: 69 | 70 | - argparse 71 | - groups not supported (in galaxy, everything should still work in argparse) 72 | - some features like templating of the version string (please submit bugs) 73 | - galaxyxml 74 | - bugs in conditionals/whens (probably) 75 | - bugs, bugs, bugs! 76 | - gxargparse 77 | - support help text 78 | - support declaring output files in an `argparse`-esque manner 79 | 80 | 81 | # argparse2cwl 82 | 83 | `argparse2cwl` forms CWL tool descriptions from programs which use `argparse` as their argument parser. 84 | No code changes are required, just use the normal import: 85 | 86 | import argparse 87 | 88 | and continue writing code. All functions are passed straight through to `argparse`, but `argparse2cwl` captures them and copies some information along the way. This information captured is used to produce CWL tool definition when it's requested with the `--generate_cwl_tool` flag. 89 | 90 | 91 | ## Installing ## 92 | 93 | Installation process: 94 | 95 | 1. Clone the source repository: 96 | 97 | $ git clone https://github.com/common-workflow-language/gxargparse.git 98 | 99 | 2. Run 100 | 101 | $ cd gxargparse 102 | $ python setup.py install 103 | 104 | You can ensure it's working when you pass `--help_arg2cwl` flag to any command-line program inside your environment. If the option is not recognized, try 105 | 106 | $ gxargparse_check_path 107 | 108 | which is installed as part of this package. It will produce a helpful error message if the paths are incorrectly ordered. Also make sure you have installed it under proper Python version. 109 | 110 | 111 | ## Running ## 112 | 113 | To run `argparse2cwl`, call your tool as usually without actual arguments with `--generate_cwl_tool` option: 114 | 115 | $ --generate_cwl_tool 116 | 117 | Simple example 118 | 119 | $ python example.py --generate_cwl_tool 120 | 121 | Example for [CNVkit](https://github.com/etal/cnvkit) toolkit: 122 | 123 | $ cnvkit.py batch --generate_cwl_tool -d ~/cnvkit-tools/ --generate_outputs 124 | 125 | 126 | If there are subcommands in the provided command, all possible tools will be generated, for instance, for CNVkit 127 | 128 | $ cnvkit.py --generate_cwl_tool 129 | 130 | will produce CWL tool descriptions for `cnvkit.py batch`, `cnvkit.py access`, `cnvkit.py export bed`, `cnvkit.py export cdt` and all other subcommands. 131 | 132 | 133 | Other options (which work only with `--generate_cwl_tool` provided, except for help message) are: 134 | 135 | * `-o FILENAME`, `--output_section FILENAME`: File with manually filled output section which is put to a formed CWL tool. Argparse2cwl is not very good at generating outputs, it recognizes output files only if they have type `argparse.FileType('w')`, so output section is often blank and should be filled manually. 136 | 137 | * `-go`, `--generate_outputs`: flag for generating outputs not only from arguments that are instances of `argparse.FileType('w')`, but also from every argument which contains `output` keyword in its name. For instance, argument `--output-file` with no type will also be placed to output section. However, '--output-directory' argument will also be treated like File, so generated tools must be checked carefully if when this option is selected. 138 | 139 | * `-b`, `basecommand`: command which appears in `basecommand` field in a resulting tool. It is handy to use this option when you run tool with shebang, but want `python` to be in `basecommand` field and the file amidst arguments. 140 | Example: 141 | 142 | ```$ .search.py --generate_cwl_tool -b python```. 143 | 144 | Basecommand of the formed tool will be `['python']`, and `search` will be a positional argument on position 0. 145 | 146 | * `-d`, `--directory`: directory for storing tool descriptions. 147 | 148 | * `--help_arg2cwl`: prints this help message. 149 | 150 | 151 | 152 | ## Argparse notes ## 153 | 154 | Some of argparse features can not be ported to CWL. 155 | 156 | 1. `nargs=N`. Number of arguments can not be specified in CWL (yet). 157 | 2. `const` argument of `add_argument()`. All constants must be specified in job files. 158 | 3. Custom types and custom actions are not supported. 159 | 4. Argument groups don't work in CWL as arguments are sorted with a [special algorithm](http://www.commonwl.org/draft-3/CommandLineTool.html#Input_binding) 160 | 5. Mutual exclusion is not supported. 161 | 162 | # click2cwl 163 | 164 | *click2cwl* shares absolutely the same logic as argparse2cwl, the only difference is it is adjusted to work with [click](http://click.pocoo.org/) argument parser. Whenever click is imported, gxargparse grabs its commands, arguments, options and forms CWL parameters out of them. 165 | 166 | # License 167 | 168 | - Apache License, v2 169 | -------------------------------------------------------------------------------- /argparse/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import print_function 3 | 4 | import re 5 | import sys 6 | from cmdline2cwl import Arg2CWLParser, load_argparse 7 | 8 | ap = load_argparse() 9 | import galaxyxml.tool as gxt 10 | import galaxyxml.tool.parameters as gxtp 11 | from . import argparse_galaxy_translation as agt 12 | from . import argparse_cwl_translation as act 13 | from cmdline2cwl import cwl_tool as cwlt 14 | 15 | # This fetches a reference to ourselves 16 | __selfmodule__ = sys.modules[__name__] 17 | # Static list of imports 18 | __argparse_exports__ = list(filter(lambda x: not x.startswith('__'), dir(ap))) 19 | # Set the attribute on ourselves. 20 | for x in __argparse_exports__: 21 | setattr(__selfmodule__, x, getattr(ap, x)) 22 | 23 | tools = [] 24 | 25 | 26 | 27 | 28 | class ArgumentParser(ap.ArgumentParser): 29 | 30 | 31 | def __init__(self, 32 | prog=None, 33 | usage=None, 34 | description=None, 35 | epilog=None, 36 | parents=[], 37 | formatter_class=HelpFormatter, 38 | prefix_chars='-', 39 | fromfile_prefix_chars=None, 40 | argument_default=None, 41 | conflict_handler='error', 42 | add_help=True): 43 | 44 | self.argument_list = [] 45 | self.argument_names = [] 46 | tools.append(self) 47 | super(ArgumentParser, self).__init__(prog=prog, 48 | usage=usage, 49 | description=description, 50 | epilog=epilog, 51 | parents=parents, 52 | formatter_class=formatter_class, 53 | prefix_chars=prefix_chars, 54 | fromfile_prefix_chars=fromfile_prefix_chars, 55 | argument_default=argument_default, 56 | conflict_handler=conflict_handler, 57 | add_help=add_help) 58 | 59 | def add_argument(self, *args, **kwargs): 60 | result = ap.ArgumentParser.add_argument(self, *args, **kwargs) 61 | # to avoid duplicate ids when there's a positional and an optional param with the same dest 62 | if result.dest in self.argument_names: 63 | if result.__class__.__name__ == '_AppendConstAction': 64 | # append_const params with the same dest are populated in job.json 65 | return 66 | else: 67 | result.dest = '_' + result.dest 68 | self.argument_list.append(result) 69 | self.argument_names.append(result.dest) 70 | 71 | def parse_args(self, *args, **kwargs): 72 | 73 | arg2cwl_parser = Arg2CWLParser() 74 | if '--generate_cwl_tool' in sys.argv: 75 | kwargs = arg2cwl_parser.process_arguments() 76 | self.parse_args_cwl(*args, **kwargs) 77 | 78 | elif '--generate_galaxy_xml' in sys.argv: 79 | self.parse_args_galaxy_nouse(*args, **kwargs) 80 | 81 | elif '--help_arg2cwl' in sys.argv: 82 | arg2cwl_parser.parser.print_help() 83 | sys.exit() 84 | else: 85 | return ap.ArgumentParser.parse_args(self, *args, **kwargs) 86 | 87 | def parse_args_cwl(self, *args, **kwargs): 88 | for argp in tools: 89 | # make subparser description out of its help message 90 | if argp._subparsers: 91 | # there were cases during testing, when instances other than _SubParsesAction type 92 | # got into ._subparsers._group_actions 93 | for subparser in filter(lambda action: isinstance(action, _SubParsersAction), 94 | argp._subparsers._group_actions): 95 | for choice_action in subparser._choices_actions: 96 | subparser.choices[choice_action.dest].description = choice_action.help 97 | # if the command is subparser itself, we don't need its CWL wrapper 98 | else: 99 | # if user provides a generic command like `cnvkit.py` - all possible descriptions are generated 100 | # if a specific command like `cnvkit.py batch` is given and 101 | # there are no subparsers - only this description is built 102 | if kwargs.get('command', argp.prog) in argp.prog: 103 | tool = cwlt.CWLTool(argp.prog, 104 | argp.description, 105 | kwargs['formcommand'], 106 | kwargs.get('basecommand', ''), 107 | kwargs.get('output_section', '')) 108 | at = act.ArgparseCWLTranslation(kwargs.get('generate_outputs', False)) 109 | for result in argp._actions: 110 | argument_type = result.__class__.__name__ 111 | if hasattr(at, argument_type): 112 | methodToCall = getattr(at, argument_type) 113 | cwlt_parameter = methodToCall(result) 114 | if cwlt_parameter is not None: 115 | tool.inputs.append(cwlt_parameter) 116 | if isinstance(cwlt_parameter, cwlt.OutputParam): 117 | tool.outputs.append(cwlt_parameter) 118 | 119 | if argp.epilog is not None: 120 | tool.description += argp.epilog 121 | 122 | data = tool.export() 123 | # if there is more than one file, ignore specified filename 124 | if 'filename' in kwargs and len(tools)==1: 125 | filename = kwargs['filename'] 126 | else: 127 | filename = '{0}.cwl'.format(tool.name.replace('.py','')) 128 | filename = re.sub('\s+', '-', filename) 129 | directory = kwargs.get('directory', '') 130 | if directory and directory[-1] != '/': 131 | directory += '/' 132 | filename = directory + filename 133 | with open(filename, 'w') as f: 134 | f.write(data) 135 | if 'verbose' in kwargs: 136 | print(data) 137 | else: 138 | continue 139 | sys.exit(0) 140 | 141 | def parse_args_galaxy_nouse(self, *args, **kwargs): 142 | self.tool = gxt.Tool( 143 | self.prog, 144 | self.prog, 145 | self.print_version() or '1.0', 146 | self.description, 147 | self.prog, 148 | interpreter='python', 149 | version_command='python %s --version' % sys.argv[0]) 150 | 151 | self.inputs = gxtp.Inputs() 152 | self.outputs = gxtp.Outputs() 153 | 154 | self.at = agt.ArgparseGalaxyTranslation() 155 | # Only build up arguments if the user actually requests it 156 | for result in self.argument_list: 157 | # I am SO thankful they return the argument here. SO useful. 158 | argument_type = result.__class__.__name__ 159 | # http://stackoverflow.com/a/3071 160 | if hasattr(self.at, argument_type): 161 | methodToCall = getattr(self.at, argument_type) 162 | gxt_parameter = methodToCall(result, tool=self.tool) 163 | if gxt_parameter is not None: 164 | if isinstance(gxt_parameter, gxtp.InputParameter): 165 | self.inputs.append(gxt_parameter) 166 | else: 167 | self.outputs.append(gxt_parameter) 168 | 169 | # TODO: replace with argparse-esque library to do this. 170 | stdout = gxtp.OutputParameter('default', 'txt') 171 | stdout.command_line_override = '> $default' 172 | self.outputs.append(stdout) 173 | 174 | self.tool.inputs = self.inputs 175 | self.tool.outputs = self.outputs 176 | if self.epilog is not None: 177 | self.tool.help = self.epilog 178 | else: 179 | self.tool.help = "TODO: Write help" 180 | 181 | data = self.tool.export() 182 | print(data) 183 | sys.exit() 184 | -------------------------------------------------------------------------------- /argparse/argparse_cwl_translation.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | import sys 4 | 5 | from cmdline2cwl import cwl_tool as cwlt 6 | 7 | PY_TO_CWL_TYPES = { 8 | 'str': 'string', 9 | 'bool': 'boolean', 10 | 'int': 'int', 11 | 'float': 'float', 12 | 'list': 'array', 13 | 'TextIOWrapper': 'File', 14 | 'open': 'File' 15 | } 16 | 17 | class ArgparseCWLTranslation: 18 | 19 | def __init__(self, generate_outputs=False): 20 | self.positional_count = 0 21 | # generate_outputs option allows to form output arguments in CWL tool description from arguments 22 | # which merely contain keyword `output` in their name 23 | # Example: parser.add_argument('--output-file', help='some file for output') will be placed into 24 | # output section (normally only files with FileType('w') are placed into output section 25 | # However, such behaviour is tricky as '--output-directory' argument will also be treated like File 26 | # so check generated tools carefully if you choose this option 27 | self.generate_outputs = generate_outputs 28 | 29 | def __cwl_param_from_type(self, param): 30 | """Based on a type, convert to appropriate cwlt class 31 | """ 32 | from argparse import FileType 33 | if param.default == sys.stdout: 34 | param.default = None 35 | if hasattr(param, 'optional'): 36 | optional = param.optional 37 | else: 38 | optional = False 39 | if not hasattr(param, 'items_type'): 40 | param.items_type = None 41 | prefix = None 42 | if param.option_strings: 43 | prefix = param.option_strings[-1] 44 | if not param.required: 45 | optional = True 46 | if param.option_strings: 47 | position = None 48 | else: 49 | self.positional_count += 1 50 | position = self.positional_count 51 | kwargs_positional = {'id': param.dest, 52 | 'position': position, 53 | 'description': param.help, 54 | 'default': param.default, 55 | 'prefix': prefix, 56 | 'optional': optional, 57 | 'items_type': param.items_type, 58 | 'type': self.get_cwl_type(param.type) or 'str'} 59 | 60 | if param.choices is not None: 61 | kwargs_positional['choices'] = param.choices 62 | kwargs_positional['type'] = 'enum' 63 | if (isinstance(param.type, FileType) and 'w' in param.type._mode)\ 64 | or (self.generate_outputs and 'output' in param.dest): 65 | cwlparam = cwlt.OutputParam(**kwargs_positional) 66 | else: 67 | cwlparam = cwlt.Param(**kwargs_positional) 68 | return cwlparam 69 | 70 | 71 | def __args_from_nargs(self, param): 72 | if param.nargs: 73 | if not param.nargs == '?': 74 | param.items_type = self.get_cwl_type(param.type) 75 | param.type = list 76 | 77 | if param.nargs == '?' or param.nargs == '*': 78 | param.optional = True 79 | param.required = False 80 | 81 | return param 82 | 83 | def _StoreAction(self, param): 84 | param = self.__args_from_nargs(param) 85 | cwlparam = self.__cwl_param_from_type(param) 86 | return cwlparam 87 | 88 | 89 | def _StoreTrueAction(self, param): 90 | return self.__StoreBoolAction(param) 91 | 92 | def _StoreFalseAction(self, param): 93 | return self.__StoreBoolAction(param) 94 | 95 | def _AppendAction(self, param, **kwargs): 96 | param.items_type = self.get_cwl_type(param.type) 97 | param.type = list 98 | cwlparam = self.__cwl_param_from_type(param) 99 | cwlparam.items_type = param.items_type 100 | return cwlparam 101 | 102 | def _AppendConstAction(self, param): 103 | """ 104 | AppendConst argument is formed once from `dest` field. `Const` option is ignored 105 | and must be provided again in job.json 106 | """ 107 | param.type = list 108 | param.optional = True 109 | cwlparam = self.__cwl_param_from_type(param) 110 | return cwlparam 111 | 112 | def __StoreBoolAction(self, param): 113 | param.type = bool 114 | cwlparam = self.__cwl_param_from_type(param) 115 | return cwlparam 116 | 117 | @staticmethod 118 | def get_cwl_type(py_type): 119 | """ 120 | converts given Python type to a CWL type 121 | >>> ArgparseCWLTranslation.get_cwl_type(list) 122 | 'array' 123 | """ 124 | if py_type is None: 125 | return None 126 | if type(py_type) is type: 127 | return PY_TO_CWL_TYPES[py_type.__name__] 128 | elif type(py_type).__name__ == 'builtin_function_or_method' or type(py_type).__name__ == 'FileType': 129 | return 'File' 130 | else: # type given as a string: 'str', 'int' etc. 131 | return PY_TO_CWL_TYPES[py_type] 132 | -------------------------------------------------------------------------------- /argparse/argparse_galaxy_translation.py: -------------------------------------------------------------------------------- 1 | import galaxyxml.tool.parameters as gxtp 2 | 3 | class ArgparseGalaxyTranslation(object): 4 | 5 | def __gxtp_param_from_type(self, param, flag, label, num_dashes, gxparam_extra_kwargs, default=None): 6 | from argparse import FileType 7 | """Based on a type, convert to appropriate gxtp class 8 | """ 9 | if default is None and (param.type in (int, float)): 10 | default = 0 11 | 12 | if param.choices is not None: 13 | choices = {k: k for k in param.choices} 14 | gxparam = gxtp.SelectParam(flag, default=default, label=label, 15 | num_dashes=num_dashes, options=choices, **gxparam_extra_kwargs) 16 | elif param.type == int: 17 | gxparam = gxtp.IntegerParam(flag, default, label=label, 18 | num_dashes=num_dashes, **gxparam_extra_kwargs) 19 | elif param.type == float: 20 | gxparam = gxtp.FloatParam(flag, default, label=label, 21 | num_dashes=num_dashes, **gxparam_extra_kwargs) 22 | elif param.type == None or param.type == str: 23 | gxparam = gxtp.TextParam(flag, default=default, label=label, 24 | num_dashes=num_dashes, **gxparam_extra_kwargs) 25 | elif param.type == file: 26 | gxparam = gxtp.DataParam(flag, label=label, 27 | num_dashes=num_dashes, **gxparam_extra_kwargs) 28 | elif isinstance(param.type, FileType): 29 | if 'w' in param.type._mode: 30 | gxparam = gxtp.OutputParameter( 31 | flag, format='data', default=default, label=label, 32 | num_dashes=num_dashes, **gxparam_extra_kwargs) 33 | else: 34 | gxparam = gxtp.DataParam( 35 | flag, default=default, label=label, num_dashes=num_dashes, 36 | **gxparam_extra_kwargs) 37 | else: 38 | gxparam = None 39 | 40 | return gxparam 41 | 42 | def __args_from_nargs(self, param, repeat_name, repeat_var_name, positional, flag): 43 | """Based on param.nargs, return the appropriate overrides 44 | """ 45 | gxrepeat_args = [] 46 | gxrepeat_kwargs = {} 47 | gxrepeat_cli_after = None 48 | gxrepeat_cli_before = None 49 | gxrepeat_cli_actual = None 50 | 51 | gxparam_cli_before = None 52 | gxparam_cli_after = None 53 | 54 | if positional: 55 | gxrepeat_cli_actual = '"$%s"' % (repeat_var_name) 56 | else: 57 | gxrepeat_cli_actual = '%s "$%s"' % (param.option_strings[0], repeat_var_name) 58 | 59 | if isinstance(param.nargs, int): 60 | # N (an integer). N arguments from the command line will be 61 | # gathered together into a list. For example: 62 | if param.nargs > 1: 63 | gxrepeat_args = [repeat_name, 'repeat_title'] 64 | gxrepeat_kwargs = { 65 | 'min': param.nargs, 66 | 'max': param.nargs, 67 | } 68 | else: 69 | # If we have only one, we don't want a gxrepeat, so we leave well 70 | # enough alone 71 | gxrepeat_args = None 72 | elif param.nargs == '?': 73 | # '?'. One argument will be consumed from the command line if 74 | # possible, and produced as a single item. If no command-line 75 | # argument is present, the value from default will be produced. 76 | # Note that for optional arguments, there is an additional case - 77 | # the option string is present but not followed by a command-line 78 | # argument. In this case the value from const will be produced 79 | 80 | # This does NOT provide a way to access the value in const, but 81 | # that seems like a HORRIBLE idea anyway. Seriously, who does that. 82 | gxparam_cli_before = """\n#if $%s and $%s is not None:""" % (flag, flag) 83 | gxparam_cli_after = '#end if' 84 | 85 | gxrepeat_args = None 86 | elif param.nargs is None: 87 | # Very similar to '?' but without the case of "optional + specified 88 | # withouth an argument" being OK 89 | # 90 | # This has changed over time, we're (probably) going overboard here. 91 | gxparam_cli_before = """\n#if $%s and $%s is not None:""" % (flag, flag) 92 | gxparam_cli_after = '#end if' 93 | gxrepeat_args = None 94 | elif param.nargs == '*': 95 | # '*'. All command-line arguments present are gathered into a list. 96 | # Note that it generally doesn't make much sense to have more than 97 | # one positional argument with nargs='*', but multiple optional 98 | # arguments with nargs='*' is possible. For example: 99 | 100 | # This needs to be handled with a 101 | #set files = '" "'.join( [ str( $file ) for $file in $inputB ] ) 102 | 103 | gxrepeat_args = [repeat_name, 'repeat_title'] 104 | #gxrepeat_cli_after = '#end if\n' 105 | gxrepeat_cli_after = '' 106 | gxrepeat_cli_before = """\n#set %s = '" "'.join([ str($var.%s) for $var in $%s ])""" % (repeat_var_name, flag, repeat_name) 107 | elif param.nargs == '+': 108 | # '+'. Just like '*', all command-line args present are gathered 109 | # into a list. Additionally, an error message will be generated if 110 | # there wasn't at least one command-line argument present. For 111 | # example: 112 | gxrepeat_args = [repeat_name, 'repeat_title'] 113 | gxrepeat_kwargs = {'min': 1} 114 | gxrepeat_cli_after = '' 115 | gxrepeat_cli_before = """\n#set %s = '" "'.join([ str($var.%s) for $var in $%s ])""" % (repeat_var_name, flag, repeat_name) 116 | else: 117 | raise Exception("TODO: Handle argparse.REMAINDER") 118 | 119 | return (gxrepeat_args, gxrepeat_kwargs, gxrepeat_cli_after, 120 | gxrepeat_cli_before, gxrepeat_cli_actual, gxparam_cli_before, gxparam_cli_after) 121 | 122 | 123 | def __init__(self): 124 | self.repeat_count = 0 125 | self.positional_count = 0 126 | 127 | def _VersionAction(self, param, tool=None): 128 | # passing tool is TERRIBLE, I know. 129 | # TODO handle their templating of version 130 | 131 | # This is kinda ugly but meh. 132 | tool.root.attrib['version'] = param.version 133 | 134 | # Count the repeats for unique names 135 | # TODO improve 136 | 137 | 138 | def _StoreAction(self, param, tool=None): 139 | """ 140 | Parse argparse arguments action type of "store", the default. 141 | 142 | param: argparse.Action 143 | """ 144 | gxparam = None 145 | gxrepeat = None 146 | self.repeat_count += 1 147 | gxparam_extra_kwargs = {} 148 | 149 | if not param.required: 150 | gxparam_extra_kwargs['optional'] = True 151 | 152 | # Positional arguments don't have an option strings 153 | positional = len(param.option_strings) == 0 154 | 155 | if not positional: 156 | flag = max(param.option_strings, key=len) # Pick the longest of 157 | # the options strings 158 | else: 159 | flag = '' 160 | self.positional_count += 1 161 | 162 | repeat_name = 'repeat_%s' % self.repeat_count 163 | repeat_var_name = 'repeat_var_%s' % self.repeat_count 164 | 165 | # TODO: Replace with logic supporting characters other than - 166 | flag_wo_dashes = flag.lstrip('-') 167 | num_dashes = len(flag) - len(flag_wo_dashes) 168 | 169 | # Moved because needed in developing repeat CLI 170 | if positional: 171 | flag_wo_dashes = 'positional_%s' % self.positional_count 172 | # SO unclean 173 | gxparam_extra_kwargs['positional'] = True 174 | 175 | 176 | # Figure out parameters and overrides from param.nargs, mainly. 177 | # This is really unpleasant. 178 | (gxrepeat_args, gxrepeat_kwargs, gxrepeat_cli_after, 179 | gxrepeat_cli_before, gxrepeat_cli_actual, gxparam_cli_before, 180 | gxparam_cli_after) = \ 181 | self.__args_from_nargs(param, repeat_name, repeat_var_name, positional, flag_wo_dashes) 182 | 183 | 184 | 185 | # Build the gxrepeat if it's needed 186 | if gxrepeat_args is not None: 187 | gxrepeat = gxtp.Repeat(*gxrepeat_args, **gxrepeat_kwargs) 188 | if gxrepeat_cli_before is not None: 189 | gxrepeat.command_line_before_override = gxrepeat_cli_before 190 | if gxrepeat_cli_after is not None: 191 | gxrepeat.command_line_after_override = gxrepeat_cli_after 192 | if gxrepeat_cli_actual is not None: 193 | gxrepeat.command_line_override = gxrepeat_cli_actual 194 | else: 195 | gxrepeat = None 196 | 197 | 198 | gxparam = self.__gxtp_param_from_type(param, flag_wo_dashes, 199 | param.help, num_dashes, gxparam_extra_kwargs, default=param.default) 200 | 201 | # Not really happy with this way of doing this 202 | if gxparam_cli_before is not None: 203 | gxparam.command_line_before_override = gxparam_cli_before 204 | 205 | if gxparam_cli_after is not None: 206 | gxparam.command_line_after_override = gxparam_cli_after 207 | 208 | # if positional argument, wipe out the CLI flag that's usually present 209 | if positional: 210 | gxparam.command_line_override = '$%s' % flag_wo_dashes 211 | 212 | if gxrepeat is not None and gxparam is not None: 213 | gxrepeat.append(gxparam) 214 | return gxrepeat 215 | elif gxrepeat is None and gxparam is not None: 216 | return gxparam 217 | else: 218 | raise Exception("huh") 219 | return None 220 | 221 | def _StoreTrueAction(self, param, **kwargs): 222 | return self._StoreConstAction(param, **kwargs) 223 | 224 | def _StoreFalseAction(self, param, **kwargs): 225 | return self._StoreConstAction(param, **kwargs) 226 | 227 | def _AppendAction(self, param, **kwargs): 228 | self.repeat_count += 1 229 | repeat_name = 'repeat_%s' % self.repeat_count 230 | # TODO: Replace with logic supporting characters other than - 231 | flag = max(param.option_strings, key=len) # Pick one of the options 232 | # strings 233 | flag_wo_dashes = flag.lstrip('-') 234 | num_dashes = len(flag) - len(flag_wo_dashes) 235 | 236 | gxparam = self.__gxtp_param_from_type(param, flag_wo_dashes, param.help, num_dashes, {}) 237 | gxrepeat = gxtp.Repeat(repeat_name, 'Repeated Variable') 238 | gxrepeat.command_line_override = '%s $%s.%s' % (param.option_strings[0], 'i', flag_wo_dashes) 239 | gxrepeat.append(gxparam) 240 | return gxrepeat 241 | 242 | 243 | def _StoreConstAction(self, param, **kwargs): 244 | flag = max(param.option_strings, key=len) # Pick one of the options 245 | # strings 246 | flag_wo_dashes = flag.lstrip('-') 247 | num_dashes = len(flag) - len(flag_wo_dashes) 248 | 249 | gxparam = gxtp.BooleanParam(flag_wo_dashes, label=param.help, 250 | num_dashes=num_dashes) 251 | 252 | return gxparam 253 | -------------------------------------------------------------------------------- /click/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import print_function 3 | 4 | import os 5 | import re 6 | import sys 7 | 8 | from click import click_cwl_translation as cct 9 | from cmdline2cwl import cwl_tool as cwlt 10 | from cmdline2cwl import load_conflicting_package, Arg2CWLParser 11 | 12 | CLICK_NUMBER = 5 13 | click = load_conflicting_package('click', 'gxargparse', CLICK_NUMBER) 14 | __selfmodule__ = sys.modules[__name__] 15 | # This fetches a reference to ourselves 16 | 17 | __click_exports__ = list(filter(lambda x: not x.startswith('__'), dir(click))) 18 | # Set the attribute on ourselves. 19 | for x in __click_exports__: 20 | setattr(__selfmodule__, x, getattr(click, x)) 21 | 22 | 23 | class Arg2CWLMixin: 24 | def __call__(self, *args, **kwargs): 25 | arg2cwl_parser = Arg2CWLParser() 26 | if '--generate_cwl_tool' in sys.argv: 27 | 28 | arg2cwl_options = arg2cwl_parser.process_arguments() 29 | if hasattr(self, 'commands'): 30 | for command in self.commands.values(): 31 | self.form_tool(arg2cwl_options, command) 32 | else: 33 | self.form_tool(arg2cwl_options) 34 | 35 | elif '--help_arg2cwl' in sys.argv: 36 | arg2cwl_parser.parser.print_help() 37 | sys.exit() 38 | else: 39 | click.BaseCommand.__call__(self, *args, **kwargs) 40 | 41 | def form_tool(self, arg2cwl_options, command=None): 42 | name = os.path.basename(sys.argv[0]) 43 | if command is None: 44 | command = self 45 | else: 46 | name += ' %s' % command.name 47 | 48 | tool = cwlt.CWLTool(name, 49 | command.help, 50 | arg2cwl_options['formcommand'], 51 | arg2cwl_options.get('basecommand', ''), 52 | arg2cwl_options.get('output_section', '')) 53 | 54 | ct = cct.ClickCWLTranslation() 55 | for option in command.params: 56 | cwl_param = ct.get_cwl_param(option) 57 | if cwl_param is not None: 58 | tool.inputs.append(cwl_param) 59 | if isinstance(cwl_param, cwlt.OutputParam): 60 | tool.outputs.append(cwl_param) 61 | data = tool.export() 62 | self._write_tool(tool, data, arg2cwl_options.get('directory', '')) 63 | 64 | def _write_tool(self, tool, data, directory): 65 | filename = '{0}.cwl'.format(tool.name.replace('.py', '')) 66 | filename = re.sub('\s+', '-', filename) 67 | if directory and directory[-1] != '/': 68 | directory += '/' 69 | filename = directory + filename 70 | with open(filename, 'w') as f: 71 | f.write(data) 72 | print(data) 73 | 74 | 75 | class Arg2CWLCommand(Arg2CWLMixin, click.Command): 76 | pass 77 | 78 | 79 | class Arg2CWLGroup(Arg2CWLMixin, click.Group): 80 | pass 81 | 82 | 83 | def command(name=None, cls=Arg2CWLCommand, **attrs): 84 | """override click function 'command' """ 85 | 86 | return click.command(name, cls, **attrs) 87 | 88 | 89 | def group(name=None, **attrs): 90 | """override click function 'group' """ 91 | 92 | attrs.setdefault('cls', Arg2CWLGroup) 93 | return command(name, **attrs) 94 | -------------------------------------------------------------------------------- /click/click_cwl_translation.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | import sys 4 | 5 | import click 6 | from cmdline2cwl import cwl_tool as cwlt 7 | 8 | PY_TO_CWL_TYPES = { 9 | 'str': 'string', 10 | 'bool': 'boolean', 11 | 'int': 'int', 12 | 'float': 'float', 13 | 'list': 'array', 14 | 'TextIOWrapper': 'File', 15 | 'open': 'File' 16 | } 17 | 18 | CLICK_TO_CWL_TYPES = { 19 | 'integer': 'int', 20 | 'text': 'string', 21 | 'choice': 'enum', 22 | 'integer range': 'array', 23 | 'float range': 'array', 24 | 'float': 'float', 25 | 'boolean': 'boolean', 26 | 'uuid': 'string', 27 | 'filename': 'File', 28 | 'file': 'File', 29 | 'directory': 'Directory', 30 | 'path': 'string' 31 | } 32 | 33 | 34 | class ClickCWLTranslation: 35 | def __init__(self, generate_outputs=False): 36 | self.positional_count = 0 37 | # generate_outputs option allows to form output arguments in CWL tool description from arguments 38 | # which merely contain keyword `output` in their name 39 | # Example: parser.add_argument('--output-file', help='some file for output') will be placed into 40 | # output section (normally only files with FileType('w') are placed into output section 41 | # However, such behaviour is tricky as '--output-directory' argument will also be treated like File 42 | # so check generated tools carefully if you choose this option 43 | self.generate_outputs = generate_outputs 44 | 45 | def __cwl_param_from_type(self, param): 46 | """Based on a type, convert to appropriate cwlt class 47 | """ 48 | if param.default == sys.stdout: 49 | param.default = None 50 | if hasattr(param, 'optional'): 51 | optional = param.optional 52 | else: 53 | optional = False 54 | if not hasattr(param, 'items_type'): 55 | param.items_type = None 56 | prefix = None 57 | position = None 58 | if param.param_type_name == 'option': 59 | prefix = param.opts[-1] 60 | if not param.required: 61 | optional = True 62 | else: 63 | self.positional_count += 1 64 | position = self.positional_count 65 | param_type = self.get_cwl_type(param.type) or 'str' 66 | kwargs_positional = {'id': param.name, 67 | 'position': position, 68 | 'description': getattr(param, 'help', param.human_readable_name), 69 | 'default': param.default, 70 | 'prefix': prefix, 71 | 'optional': optional, 72 | 'items_type': param.items_type, 73 | 'type': param_type} 74 | 75 | if type(param.type) is click.Choice: 76 | kwargs_positional['choices'] = param.type.choices 77 | if (isinstance(param.type, click.types.File) and 'w' in param.type.mode) \ 78 | or (self.generate_outputs and 'output' in param.dest): 79 | cwlparam = cwlt.OutputParam(**kwargs_positional) 80 | else: 81 | cwlparam = cwlt.Param(**kwargs_positional) 82 | return cwlparam 83 | 84 | def __args_from_nargs(self, param): 85 | if param.nargs == '-1': 86 | param.items_type = self.get_cwl_type(param.type) 87 | param.type = list 88 | return param 89 | 90 | def get_cwl_param(self, param): 91 | param = self.__args_from_nargs(param) 92 | cwlparam = self.__cwl_param_from_type(param) 93 | return cwlparam 94 | 95 | @staticmethod 96 | def get_cwl_type(py_type): 97 | if py_type is None: 98 | return None 99 | elif isinstance(py_type, click.types.ParamType): 100 | if isinstance(py_type, click.types.Tuple): 101 | return str(list(map(lambda click_type: CLICK_TO_CWL_TYPES[click_type.name], py_type.types))).strip('[]') 102 | cwl_type = CLICK_TO_CWL_TYPES[py_type.name] 103 | return cwl_type 104 | else: 105 | return PY_TO_CWL_TYPES[py_type.__name__] 106 | -------------------------------------------------------------------------------- /cmdline2cwl/__init__.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import re 3 | import sys 4 | from builtins import range 5 | 6 | logging.basicConfig(level=logging.INFO) 7 | logger = logging.getLogger(__name__) 8 | 9 | __version__ = '0.3.1' 10 | 11 | 12 | def load_argparse(): 13 | ARGPARSE_NUMBER = 1 14 | return load_conflicting_package('argparse', 'gxargparse', ARGPARSE_NUMBER) 15 | 16 | 17 | def load_conflicting_package(name, not_name, module_number): 18 | """Load a conflicting package 19 | Some assumptions are made, namely that your package includes the "official" 20 | one as part of the name. E.g. gxargparse/argparse, you would call this with: 21 | 22 | >>> real_argparse = load_conflicting_package('argparse', 'gxargparse', 1) 23 | 24 | http://stackoverflow.com/a/6032023 25 | """ 26 | import imp 27 | for i in range(0, 100): 28 | random_name = 'random_name_%d' % (i,) 29 | if random_name not in sys.modules: 30 | break 31 | else: 32 | random_name = None 33 | if random_name is None: 34 | raise RuntimeError("Couldn't manufacture an unused module name.") 35 | # NB: This code is unlikely to work for nonstdlib overrides. 36 | # This will hold the correct sys.path for the REAL argparse 37 | for path in sys.path: 38 | try: 39 | (f, pathname, desc) = imp.find_module(name, [path]) 40 | if not_name not in pathname and desc[2] == module_number: 41 | module = imp.load_module(random_name, f, pathname, desc) 42 | # f.close() 43 | return sys.modules[random_name] 44 | except: 45 | # Many sys.paths won't contain the module of interest 46 | pass 47 | return None 48 | 49 | 50 | class Arg2CWLParser: 51 | def __init__(self): 52 | ap = load_argparse() # avoid circular imports 53 | help_text = """ 54 | argparse2cwl forms CWL command line tool from Python tool 55 | Example: $ python program.py --generate_cwl_tool -b python 56 | """ 57 | arg2cwl_parser = ap.ArgumentParser(prog=sys.argv[0], description=help_text, 58 | formatter_class=ap.RawDescriptionHelpFormatter, add_help=False) 59 | arg2cwl_parser.add_argument('tools', nargs='*', 60 | help='Command for running your tool(s), without arguments') 61 | arg2cwl_parser.add_argument('-d', '--directory', 62 | help='Directory to store CWL tool descriptions') 63 | arg2cwl_parser.add_argument('-f', '--filename', 64 | help='Name of the generated file (if single). Default - the name of the running command') 65 | arg2cwl_parser.add_argument('-v', '--verbose', action='store_true', 66 | help='Print generated file(s) to stdout') 67 | arg2cwl_parser.add_argument('-b', '--basecommand', 68 | help='Command that appears in `basecommand` field in CWL tool ' 69 | 'instead of the default one') 70 | arg2cwl_parser.add_argument('-o', '--output_section', metavar='FILENAME', 71 | help='File with output section which will be put to a formed CWL tool') 72 | arg2cwl_parser.add_argument('-go', '--generate_outputs', action='store_true', 73 | help='Form output section from args than contain `output` keyword in their names') 74 | arg2cwl_parser.add_argument('--help_arg2cwl', 75 | help='Show this help message and exit', action='help') 76 | self.parser = arg2cwl_parser 77 | 78 | def process_arguments(self): 79 | self.parser.add_argument('--generate_cwl_tool', action='store_true') 80 | self.args = self.parser.parse_args() 81 | logger.debug('sys argv: ', sys.argv) 82 | commands = [self.parser.prog.split('/')[-1]] 83 | if self.args.tools: 84 | commands.extend(self.args.tools) 85 | command = ' '.join(commands) 86 | kwargs = dict() 87 | kwargs['command'] = command.strip() 88 | 89 | shebang = re.search(r'\./[\w-]*?.py$', self.parser.prog) 90 | if shebang: 91 | kwargs['basecommand'] = shebang.group(0) 92 | 93 | formcommand = '' 94 | if kwargs.get('basecommand', ''): 95 | formcommand += kwargs['basecommand'] 96 | else: 97 | formcommand += kwargs['command'] 98 | 99 | attrs = ['directory', 'filename', 'output_section', 'basecommand', 'generate_outputs', 'verbose'] 100 | for arg in attrs: 101 | if getattr(self.args, arg): 102 | kwargs[arg] = getattr(self.args, arg) 103 | 104 | if kwargs.get('output_section', ''): 105 | formcommand += ' -o FILENAME' 106 | if kwargs.get('filename', ''): 107 | formcommand += ' -f FILENAME' 108 | if kwargs.get('basecommand', ''): 109 | formcommand += ' -b {0}'.format(kwargs['basecommand']) 110 | if kwargs.get('generate_outputs', ''): 111 | formcommand += ' -go' 112 | kwargs['formcommand'] = formcommand 113 | return kwargs 114 | -------------------------------------------------------------------------------- /cmdline2cwl/cwl_tool.py: -------------------------------------------------------------------------------- 1 | import re 2 | import os 3 | 4 | from jinja2 import Environment, FileSystemLoader 5 | 6 | from cmdline2cwl import __version__ 7 | 8 | class Param: 9 | def __init__(self, id, type, position=None, description=None, default=None, prefix=None, optional=False, items_type=None, **kwargs): 10 | self.id = id 11 | self.position = position 12 | self.type = type 13 | self.default = default 14 | self.prefix = prefix 15 | self.optional = optional 16 | self.items_type = items_type 17 | if description: 18 | self.description = description.replace(':', ' -') \ 19 | .replace('\n', ' ') # `:` is a special character and must be replaced with smth 20 | self.description = re.sub('\s{2,}', ' ', self.description) 21 | else: 22 | self.description = None 23 | if self.type == 'enum': 24 | self.choices = list(kwargs.pop('choices', [])) 25 | 26 | 27 | class OutputParam(Param): 28 | pass 29 | 30 | class CWLTool(object): 31 | 32 | def __init__(self, name, description, formcommand, basecommand=None, output_file=None): 33 | self.name = name 34 | self.output_file = output_file # file with manually filled output section 35 | if description: 36 | self.description = description.replace('\n', '\n ') 37 | else: 38 | self.description = None 39 | self.env = Environment( 40 | loader=FileSystemLoader(os.path.abspath(os.path.join(os.path.dirname(__file__), 'templates'))), 41 | trim_blocks=True, 42 | lstrip_blocks=True) 43 | if basecommand: 44 | self.basecommands = [basecommand] 45 | else: 46 | self.basecommands = self.name.split() 47 | self.formcommand = formcommand 48 | self.inputs = [] 49 | self.outputs = [] 50 | 51 | def export(self): 52 | inputs_template = self.env.get_template('cwltool_inputs.j2') 53 | outputs_template = self.env.get_template('cwltool_outputs.j2') 54 | main_template = self.env.get_template('cwltool.j2') 55 | inputs = inputs_template.render(tool=self, basecommand=self.basecommands) 56 | if self.output_file: 57 | with open(self.output_file) as f: 58 | outputs = f.read() 59 | else: 60 | outputs = outputs_template.render(tool=self) 61 | import argparse 62 | return main_template.render(tool=self, 63 | version=__version__, 64 | formcommand=self.formcommand, 65 | stripped_options_command=re.sub('-.*', '', self.formcommand), 66 | basecommand=self.basecommands, 67 | inputs=inputs, 68 | outputs=outputs) 69 | -------------------------------------------------------------------------------- /cmdline2cwl/templates/cwltool.j2: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. {{ version }} 3 | # To generate again: $ {{ formcommand }} --generate_cwl_tool 4 | # Help: $ {{ stripped_options_command }} --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: {{ basecommand }} 10 | 11 | doc: | 12 | {{ tool.description }} 13 | 14 | inputs: 15 | {{ inputs }} 16 | 17 | {{ outputs }} -------------------------------------------------------------------------------- /cmdline2cwl/templates/cwltool_inputs.j2: -------------------------------------------------------------------------------- 1 | {% if 'python' in basecommand[0] %} 2 | {{ tool.name }}: 3 | type: File 4 | default: 5 | class: File 6 | path: {{ tool.name }} 7 | inputBinding: 8 | position: 0 9 | {% endif %} 10 | {% for param in tool.inputs %} 11 | {% set param_attrs %} 12 | {% if param.type == "enum" or param.type == "array"%} 13 | type: 14 | {% if param.optional %} - "null" 15 | - type: {{ param.type }}{% else %} 16 | type: {{ param.type }}{% endif %} 17 | {% if param.type == "array" %} 18 | 19 | items: {{ param.items_type or "string" }} 20 | {% elif param.type == "enum" %} 21 | 22 | symbols: {{ param.choices }}{% endif %}{% else %} 23 | type: {% if param.optional %}["null", {{ param.type }}]{% else %}{{ param.type }} 24 | {% endif %} 25 | {% endif %} 26 | 27 | {% if param.default != None %} 28 | default: {{ param.default }} 29 | {% endif %} 30 | {% if param.description %} doc: {{ param.description }}{% endif %} 31 | {% if param.position or param.prefix %} 32 | 33 | inputBinding: 34 | {% if param.position %} position: {{ param.position }}{% endif %} 35 | {% if param.prefix %} prefix: {{ param.prefix }} {% endif %} 36 | {% endif %} 37 | {% endset %} 38 | 39 | {{ param.id }}: 40 | {{ param_attrs|indent(2) }} 41 | {% endfor %} 42 | 43 | -------------------------------------------------------------------------------- /cmdline2cwl/templates/cwltool_outputs.j2: -------------------------------------------------------------------------------- 1 | outputs: 2 | {% for param in tool.outputs %} 3 | 4 | {% set param_attrs %} 5 | type: File 6 | {% if param.default %} default: {{ param.default }} {% endif %} 7 | 8 | {% if param.description %} doc: {{ param.description }}{% endif %} 9 | 10 | outputBinding: 11 | glob: $(inputs.{{ param.id }}.path) 12 | {% endset %} 13 | {{ param.id + '_out'}}: 14 | {{ param_attrs|indent(2) }} 15 | {% else %} 16 | [] 17 | {% endfor %} -------------------------------------------------------------------------------- /example.py: -------------------------------------------------------------------------------- 1 | # /usr/bin/python3 2 | import argparse 3 | 4 | parser = argparse.ArgumentParser(description='Process some integers.', prefix_chars='-+', epilog="here's some epilog text", formatter_class=argparse.ArgumentDefaultsHelpFormatter) 5 | parser.add_argument('keyword', metavar='Q', type=str, nargs=1, 6 | help='action keyword') 7 | 8 | parser.add_argument('integers', metavar='N', type=int, nargs='+', 9 | help='an integer for the accumulator') 10 | 11 | parser.add_argument('--sum', '-s', dest='accumulate', action='store_const', 12 | const=sum, default=max, help='sum the integers (default: find the max)') 13 | 14 | parser.add_argument('--foo', nargs='?', help='foo help') 15 | parser.add_argument('--bar', nargs='*', default=[1, 2, 3], help='BAR!') 16 | parser.add_argument('--true', action='store_true', help='Store a true') 17 | parser.add_argument('--false', action='store_false', help='Store a false') 18 | parser.add_argument('--append', action='append', help='Append a value') 19 | 20 | parser.add_argument('--nargs2', nargs=2, help='nargs2') 21 | 22 | parser.add_argument('--mode', choices=['rock', 'paper', 'scissors'], default='scissors') 23 | 24 | 25 | parser.add_argument('--version', action='version', version='2.0') 26 | args = parser.parse_args() 27 | -------------------------------------------------------------------------------- /example.xml: -------------------------------------------------------------------------------- 1 | 2 | Process some integers. 3 | 4 | 5 | 6 | python example.py --version 7 | $default]]> 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/check_wrappers_in_dir.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for file in {.,}*; 4 | do 5 | echo "$file"; 6 | cwl-runner "$file" data.json; 7 | done -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-access.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'access'] 10 | 11 | description: | 12 | List the locations of accessible sequence regions in a FASTA file. 13 | 14 | inputs: 15 | 16 | fa_fname: 17 | type: string 18 | 19 | description: Genome FASTA file name 20 | inputBinding: 21 | position: 1 22 | 23 | min_gap_size: 24 | type: ["null", int] 25 | default: 5000 26 | description: Minimum gap size between accessible sequence regions. Regions separated by less than this distance will be joined together. [Default - %(default)s] 27 | inputBinding: 28 | prefix: --min-gap-size 29 | 30 | exclude: 31 | type: 32 | - "null" 33 | - type: array 34 | items: string 35 | 36 | default: [] 37 | description: Additional regions to exclude, in BED format. Can be used multiple times. 38 | inputBinding: 39 | prefix: --exclude 40 | 41 | output: 42 | type: ["null", File] 43 | description: Output file name 44 | inputBinding: 45 | prefix: --output 46 | 47 | 48 | outputs: 49 | 50 | output_out: 51 | type: File 52 | 53 | description: Output file name 54 | outputBinding: 55 | glob: $(inputs.output.path) 56 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-antitarget.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'antitarget'] 10 | 11 | description: | 12 | Derive a background/antitarget BED file from a target BED file. 13 | 14 | inputs: 15 | 16 | interval: 17 | type: string 18 | 19 | description: BED or interval file listing the targeted regions. 20 | inputBinding: 21 | position: 1 22 | 23 | access: 24 | type: ["null", string] 25 | description: Regions of accessible sequence on chromosomes (.bed), as output by genome2access.py. 26 | inputBinding: 27 | prefix: --access 28 | 29 | avg_size: 30 | type: ["null", int] 31 | default: 100000 32 | description: Average size of antitarget bins (results are approximate). [Default - %(default)s] 33 | inputBinding: 34 | prefix: --avg-size 35 | 36 | min_size: 37 | type: ["null", int] 38 | description: Minimum size of antitarget bins (smaller regions are dropped). [Default - 1/16 avg size, calculated] 39 | inputBinding: 40 | prefix: --min-size 41 | 42 | output: 43 | type: ["null", string] 44 | description: Output file name. 45 | inputBinding: 46 | prefix: --output 47 | 48 | 49 | outputs: 50 | [] 51 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-batch.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.3.0 3 | # To generate again: $ cnvkit.py batch -go --generate_cwl_tool 4 | # Help: $ cnvkit.py batch --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'batch'] 10 | 11 | description: | 12 | Run the complete CNVkit pipeline on one or more BAM files. 13 | 14 | inputs: 15 | 16 | bam_files: 17 | type: 18 | - "null" 19 | - type: array 20 | items: string 21 | 22 | description: Mapped sequence reads (.bam) 23 | inputBinding: 24 | position: 1 25 | 26 | male_reference: 27 | type: ["null", boolean] 28 | default: False 29 | description: Use or assume a male reference (i.e. female samples will have +1 log-CNR of chrX; otherwise male samples would have -1 chrX). 30 | inputBinding: 31 | prefix: --male-reference 32 | 33 | count_reads: 34 | type: ["null", boolean] 35 | default: False 36 | description: Get read depths by counting read midpoints within each bin. (An alternative algorithm). 37 | inputBinding: 38 | prefix: --count-reads 39 | 40 | processes: 41 | type: ["null", int] 42 | default: 1 43 | description: Number of subprocesses used to running each of the BAM files in parallel. Give 0 or a negative value to use the maximum number of available CPUs. [Default - process each BAM in serial] 44 | inputBinding: 45 | prefix: --processes 46 | 47 | rlibpath: 48 | type: ["null", str] 49 | description: Path to an alternative site-library to use for R packages. 50 | inputBinding: 51 | prefix: --rlibpath 52 | 53 | normal: 54 | type: 55 | - "null" 56 | - type: array 57 | items: string 58 | 59 | description: Normal samples (.bam) to construct the pooled reference. If this option is used but no files are given, a "flat" reference will be built. 60 | inputBinding: 61 | prefix: --normal 62 | 63 | fasta: 64 | type: ["null", str] 65 | description: Reference genome, FASTA format (e.g. UCSC hg19.fa) 66 | inputBinding: 67 | prefix: --fasta 68 | 69 | targets: 70 | type: ["null", str] 71 | description: Target intervals (.bed or .list) 72 | inputBinding: 73 | prefix: --targets 74 | 75 | antitargets: 76 | type: ["null", str] 77 | description: Antitarget intervals (.bed or .list) 78 | inputBinding: 79 | prefix: --antitargets 80 | 81 | annotate: 82 | type: ["null", str] 83 | description: UCSC refFlat.txt or ensFlat.txt file for the reference genome. Pull gene names from this file and assign them to the target regions. 84 | inputBinding: 85 | prefix: --annotate 86 | 87 | short_names: 88 | type: ["null", boolean] 89 | default: False 90 | description: Reduce multi-accession bait labels to be short and consistent. 91 | inputBinding: 92 | prefix: --short-names 93 | 94 | split: 95 | type: ["null", boolean] 96 | default: False 97 | description: Split large tiled intervals into smaller, consecutive targets. 98 | inputBinding: 99 | prefix: --split 100 | 101 | target_avg_size: 102 | type: ["null", int] 103 | description: Average size of split target bins (results are approximate). 104 | inputBinding: 105 | prefix: --target-avg-size 106 | 107 | access: 108 | type: ["null", str] 109 | description: Regions of accessible sequence on chromosomes (.bed), as output by the 'access' command. 110 | inputBinding: 111 | prefix: --access 112 | 113 | antitarget_avg_size: 114 | type: ["null", int] 115 | description: Average size of antitarget bins (results are approximate). 116 | inputBinding: 117 | prefix: --antitarget-avg-size 118 | 119 | antitarget_min_size: 120 | type: ["null", int] 121 | description: Minimum size of antitarget bins (smaller regions are dropped). 122 | inputBinding: 123 | prefix: --antitarget-min-size 124 | 125 | output_reference: 126 | type: ["null", str] 127 | description: Output filename/path for the new reference file being created. (If given, ignores the -o/--output-dir option and will write the file to the given path. Otherwise, "reference.cnn" will be created in the current directory or specified output directory.) 128 | inputBinding: 129 | prefix: --output-reference 130 | 131 | reference: 132 | type: ["null", str] 133 | description: Copy number reference file (.cnn). 134 | inputBinding: 135 | prefix: --reference 136 | 137 | output_dir: 138 | type: ["null", str] 139 | default: . 140 | description: Output directory. 141 | inputBinding: 142 | prefix: --output-dir 143 | 144 | scatter: 145 | type: ["null", boolean] 146 | default: False 147 | description: Create a whole-genome copy ratio profile as a PDF scatter plot. 148 | inputBinding: 149 | prefix: --scatter 150 | 151 | diagram: 152 | type: ["null", boolean] 153 | default: False 154 | description: Create a diagram of copy ratios on chromosomes as a PDF. 155 | inputBinding: 156 | prefix: --diagram 157 | 158 | 159 | outputs: 160 | 161 | output_reference_out: 162 | type: File 163 | 164 | description: Output filename/path for the new reference file being created. (If given, ignores the -o/--output-dir option and will write the file to the given path. Otherwise, "reference.cnn" will be created in the current directory or specified output directory.) 165 | outputBinding: 166 | glob: $(inputs.output_reference.path) 167 | 168 | output_dir_out: 169 | type: File 170 | default: . 171 | description: Output directory. 172 | outputBinding: 173 | glob: $(inputs.output_dir.path) 174 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-breaks.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'breaks'] 10 | 11 | description: | 12 | List the targeted genes in which a copy number breakpoint occurs. 13 | 14 | inputs: 15 | 16 | filename: 17 | type: string 18 | 19 | description: Processed sample coverage data file (*.cnr), the output of the 'fix' sub-command. 20 | inputBinding: 21 | position: 1 22 | 23 | segment: 24 | type: string 25 | 26 | description: Segmentation calls (.cns), the output of the 'segment' command). 27 | inputBinding: 28 | position: 2 29 | 30 | min_probes: 31 | type: ["null", int] 32 | default: 1 33 | description: Minimum number of within-gene probes on both sides of a breakpoint to report it. [Default - %(default)d] 34 | inputBinding: 35 | prefix: --min-probes 36 | 37 | output: 38 | type: ["null", string] 39 | description: Output table file name. 40 | inputBinding: 41 | prefix: --output 42 | 43 | 44 | outputs: 45 | [] 46 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-call.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'call'] 10 | 11 | description: | 12 | Call copy number variants from segmented log2 ratios. 13 | 14 | inputs: 15 | 16 | filename: 17 | type: string 18 | 19 | description: Copy ratios (.cnr or .cns). 20 | inputBinding: 21 | position: 1 22 | 23 | center: 24 | type: 25 | - "null" 26 | - type: enum 27 | symbols: ['mean', 'median', 'mode', 'biweight'] 28 | description: Re-center the log2 ratio values using this estimate of the center or average value. 29 | inputBinding: 30 | prefix: --center 31 | 32 | method: 33 | type: 34 | - "null" 35 | - type: enum 36 | symbols: ['threshold', 'clonal', 'none'] 37 | default: threshold 38 | description: Calling method. [Default - %(default)s] 39 | inputBinding: 40 | prefix: --method 41 | 42 | ploidy: 43 | type: ["null", int] 44 | default: 2 45 | description: Ploidy of the sample cells. [Default - %(default)d] 46 | inputBinding: 47 | prefix: --ploidy 48 | 49 | purity: 50 | type: ["null", float] 51 | description: Estimated tumor cell fraction, a.k.a. purity or cellularity. 52 | inputBinding: 53 | prefix: --purity 54 | 55 | vcf: 56 | type: ["null", string] 57 | description: VCF file name containing variants for assigning allele frequencies and copy number. 58 | inputBinding: 59 | prefix: --vcf 60 | 61 | gender: 62 | type: 63 | - "null" 64 | - type: enum 65 | symbols: ['m', 'male', 'Male', 'f', 'female', 'Female'] 66 | description: Specify the sample's gender as male or female. (Otherwise guessed from chrX copy number). 67 | inputBinding: 68 | prefix: --gender 69 | 70 | male_reference: 71 | type: ["null", boolean] 72 | default: False 73 | description: Was a male reference used? If so, expect half ploidy on chrX and chrY; otherwise, only chrY has half ploidy. In CNVkit, if a male reference was used, the "neutral" copy number (ploidy) of chrX is 1; chrY is haploid for either gender reference. 74 | inputBinding: 75 | prefix: --male-reference 76 | 77 | output: 78 | type: ["null", string] 79 | description: Output table file name (CNR-like table of segments, .cns). 80 | inputBinding: 81 | prefix: --output 82 | 83 | 84 | outputs: 85 | [] 86 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-coverage.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'coverage'] 10 | 11 | description: | 12 | Calculate coverage in the given regions from BAM read depths. 13 | 14 | inputs: 15 | 16 | bam_file: 17 | type: string 18 | 19 | description: Mapped sequence reads (.bam) 20 | inputBinding: 21 | position: 1 22 | 23 | interval: 24 | type: string 25 | 26 | description: Intervals (.bed or .list) 27 | inputBinding: 28 | position: 2 29 | 30 | count: 31 | type: ["null", boolean] 32 | default: False 33 | description: Get read depths by counting read midpoints within each bin. (An alternative algorithm). 34 | inputBinding: 35 | prefix: --count 36 | 37 | min_mapq: 38 | type: ["null", int] 39 | default: 0 40 | description: Minimum mapping quality score (phred scale 0-60) to count a read for coverage depth. [Default - %(default)s] 41 | inputBinding: 42 | prefix: --min-mapq 43 | 44 | output: 45 | type: ["null", string] 46 | description: Output file name. 47 | inputBinding: 48 | prefix: --output 49 | 50 | 51 | outputs: 52 | [] 53 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-diagram.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'diagram'] 10 | 11 | description: | 12 | Draw copy number (log2 coverages, CBS calls) on chromosomes as a diagram. 13 | 14 | If both the raw probes and segments are given, show them side-by-side on 15 | each chromosome (segments on the left side, probes on the right side). 16 | 17 | 18 | inputs: 19 | 20 | filename: 21 | type: ["null", string] 22 | description: Processed coverage data file (*.cnr), the output of the 'fix' sub-command. 23 | inputBinding: 24 | position: 1 25 | 26 | segment: 27 | type: ["null", string] 28 | description: Segmentation calls (.cns), the output of the 'segment' command. 29 | inputBinding: 30 | prefix: --segment 31 | 32 | threshold: 33 | type: ["null", float] 34 | default: 0.5 35 | description: Copy number change threshold to label genes. [Default - %(default)s] 36 | inputBinding: 37 | prefix: --threshold 38 | 39 | min_probes: 40 | type: ["null", int] 41 | default: 3 42 | description: Minimum number of covered probes to label a gene. [Default - %(default)d] 43 | inputBinding: 44 | prefix: --min-probes 45 | 46 | male_reference: 47 | type: ["null", boolean] 48 | default: False 49 | description: Assume inputs are already corrected against a male reference (i.e. female samples will have +1 log-CNR of chrX; otherwise male samples would have -1 chrX). 50 | inputBinding: 51 | prefix: --male-reference 52 | 53 | output: 54 | type: ["null", string] 55 | description: Output PDF file name. 56 | inputBinding: 57 | prefix: --output 58 | 59 | 60 | outputs: 61 | [] 62 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-export-bed.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'export', 'bed'] 10 | 11 | description: | 12 | Convert segments to BED format. 13 | 14 | Input is a segmentation file (.cns) where, preferably, log2 ratios have 15 | already been adjusted to integer absolute values using the 'call' command. 16 | 17 | 18 | inputs: 19 | 20 | segments: 21 | type: 22 | type: array 23 | items: string 24 | 25 | description: Segmented copy ratio data files (*.cns), the output of the 'segment' or 'call' sub-commands. 26 | inputBinding: 27 | position: 1 28 | 29 | sample_id: 30 | type: ["null", string] 31 | description: Identifier to write in the 4th column of the BED file. [Default - use the sample ID, taken from the file name] 32 | inputBinding: 33 | prefix: --sample-id 34 | 35 | ploidy: 36 | type: ["null", int] 37 | default: 2 38 | description: Ploidy of the sample cells. [Default - %(default)d] 39 | inputBinding: 40 | prefix: --ploidy 41 | 42 | gender: 43 | type: 44 | - "null" 45 | - type: enum 46 | symbols: ['m', 'male', 'Male', 'f', 'female', 'Female'] 47 | description: Specify the sample's gender as male or female. (Otherwise guessed from chrX copy number). 48 | inputBinding: 49 | prefix: --gender 50 | 51 | show: 52 | type: 53 | - "null" 54 | - type: enum 55 | symbols: ['ploidy', 'variant', 'all'] 56 | default: ploidy 57 | description: Which segmented regions to show - 'all' = all segment regions; 'variant' = CNA regions with non-neutral copy number; 'ploidy' = CNA regions with non-default ploidy. [Default - %(default)s] 58 | inputBinding: 59 | prefix: --show 60 | 61 | show_all: 62 | type: ["null", boolean] 63 | default: False 64 | description: Write all segmented regions. [DEPRECATED; use "--show all" instead] 65 | inputBinding: 66 | prefix: --show-all 67 | 68 | male_reference: 69 | type: ["null", boolean] 70 | default: False 71 | description: Was a male reference used? If so, expect half ploidy on chrX and chrY; otherwise, only chrY has half ploidy. In CNVkit, if a male reference was used, the "neutral" copy number (ploidy) of chrX is 1; chrY is haploid for either gender reference. 72 | inputBinding: 73 | prefix: --male-reference 74 | 75 | output: 76 | type: ["null", string] 77 | description: Output file name. 78 | inputBinding: 79 | prefix: --output 80 | 81 | 82 | outputs: 83 | [] 84 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-export-cdt.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'export', 'cdt'] 10 | 11 | description: | 12 | Convert log2 ratios to CDT format. Compatible with Java TreeView. 13 | 14 | inputs: 15 | 16 | filenames: 17 | type: 18 | type: array 19 | items: string 20 | 21 | description: Log2 copy ratio data file(s) (*.cnr), the output of the 'fix' sub-command. 22 | inputBinding: 23 | position: 1 24 | 25 | output: 26 | type: ["null", string] 27 | description: Output file name. 28 | inputBinding: 29 | prefix: --output 30 | 31 | 32 | outputs: 33 | [] 34 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-export-jtv.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'export', 'jtv'] 10 | 11 | description: | 12 | Convert log2 ratios to Java TreeView's native format. 13 | 14 | inputs: 15 | 16 | filenames: 17 | type: 18 | type: array 19 | items: string 20 | 21 | description: Log2 copy ratio data file(s) (*.cnr), the output of the 'fix' sub-command. 22 | inputBinding: 23 | position: 1 24 | 25 | output: 26 | type: ["null", string] 27 | description: Output file name. 28 | inputBinding: 29 | prefix: --output 30 | 31 | 32 | outputs: 33 | [] 34 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-export-nexus-basic.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'export', 'nexus-basic'] 10 | 11 | description: | 12 | Convert bin-level log2 ratios to Nexus Copy Number "basic" format. 13 | 14 | inputs: 15 | 16 | filename: 17 | type: string 18 | 19 | description: Log2 copy ratio data file (*.cnr), the output of the 'fix' sub-command. 20 | inputBinding: 21 | position: 1 22 | 23 | output: 24 | type: ["null", string] 25 | description: Output file name. 26 | inputBinding: 27 | prefix: --output 28 | 29 | 30 | outputs: 31 | [] 32 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-export-nexus-ogt.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'export', 'nexus-ogt'] 10 | 11 | description: | 12 | Convert log2 ratios and b-allele freqs to Nexus "Custom-OGT" format. 13 | 14 | inputs: 15 | 16 | filename: 17 | type: string 18 | 19 | description: Log2 copy ratio data file (*.cnr), the output of the 'fix' sub-command. 20 | inputBinding: 21 | position: 1 22 | 23 | vcf: 24 | type: string 25 | 26 | description: VCF of SNVs for the same sample, to calculate b-allele frequencies. 27 | inputBinding: 28 | position: 2 29 | 30 | sample_id: 31 | type: ["null", string] 32 | description: Specify the name of the sample in the VCF to use to extract b-allele frequencies. 33 | inputBinding: 34 | prefix: --sample-id 35 | 36 | min_variant_depth: 37 | type: ["null", int] 38 | default: 20 39 | description: Minimum read depth for a SNV to be included in the b-allele frequency calculation. [Default - %(default)s] 40 | inputBinding: 41 | prefix: --min-variant-depth 42 | 43 | min_weight: 44 | type: ["null", float] 45 | default: 0.0 46 | description: Minimum weight (between 0 and 1) for a bin to be included in the output. [Default - %(default)s] 47 | inputBinding: 48 | prefix: --min-weight 49 | 50 | output: 51 | type: ["null", string] 52 | description: Output file name. 53 | inputBinding: 54 | prefix: --output 55 | 56 | 57 | outputs: 58 | [] 59 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-export-seg.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'export', 'seg'] 10 | 11 | description: | 12 | Convert segments to SEG format. 13 | 14 | Compatible with IGV and GenePattern. 15 | 16 | 17 | inputs: 18 | 19 | filenames: 20 | type: 21 | type: array 22 | items: string 23 | 24 | description: Segmented copy ratio data file(s) (*.cns), the output of the 'segment' sub-command. 25 | inputBinding: 26 | position: 1 27 | 28 | output: 29 | type: ["null", string] 30 | description: Output file name. 31 | inputBinding: 32 | prefix: --output 33 | 34 | 35 | outputs: 36 | [] 37 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-export-theta.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'export', 'theta'] 10 | 11 | description: | 12 | Convert segments to THetA2 input file format (*.input). 13 | 14 | inputs: 15 | 16 | tumor_segment: 17 | type: string 18 | 19 | description: Tumor-sample segmentation file from CNVkit (.cns). 20 | inputBinding: 21 | position: 1 22 | 23 | normal_reference: 24 | type: ["null", string] 25 | description: Reference copy number profile (.cnn), or normal-sample bin-level log2 copy ratios (.cnr). [DEPRECATED] 26 | inputBinding: 27 | position: 2 28 | 29 | reference: 30 | type: ["null", string] 31 | description: Reference copy number profile (.cnn), or normal-sample bin-level log2 copy ratios (.cnr). Use if the tumor_segment input file does not contain a "weight" column. 32 | inputBinding: 33 | prefix: --reference 34 | 35 | vcf: 36 | type: ["null", string] 37 | description: VCF file containing SNVs observed in both the tumor and normal samples. Tumor sample ID should match the `tumor_segment` filename or be specified with -i/--sample-id. 38 | inputBinding: 39 | prefix: --vcf 40 | 41 | sample_id: 42 | type: ["null", string] 43 | description: Specify the name of the tumor sample in the VCF (given with -v/--vcf). [Default - taken the tumor_segment file name] 44 | inputBinding: 45 | prefix: --sample-id 46 | 47 | normal_id: 48 | type: ["null", string] 49 | description: Corresponding normal sample ID in the input VCF. 50 | inputBinding: 51 | prefix: --normal-id 52 | 53 | min_depth: 54 | type: ["null", int] 55 | default: 20 56 | description: Minimum read depth for a SNP in the VCF to be counted. [Default - %(default)s] 57 | inputBinding: 58 | prefix: --min-depth 59 | 60 | output: 61 | type: ["null", string] 62 | description: Output file name. 63 | inputBinding: 64 | prefix: --output 65 | 66 | 67 | outputs: 68 | [] 69 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-export-vcf.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'export', 'vcf'] 10 | 11 | description: | 12 | Convert segments to VCF format. 13 | 14 | Input is a segmentation file (.cns) where, preferably, log2 ratios have 15 | already been adjusted to integer absolute values using the 'call' command. 16 | 17 | 18 | inputs: 19 | 20 | segments: 21 | type: string 22 | 23 | description: Segmented copy ratio data file (*.cns), the output of the 'segment' or 'call' sub-commands. 24 | inputBinding: 25 | position: 1 26 | 27 | sample_id: 28 | type: ["null", string] 29 | description: Sample name to write in the genotype field of the output VCF file. [Default - use the sample ID, taken from the file name] 30 | inputBinding: 31 | prefix: --sample-id 32 | 33 | ploidy: 34 | type: ["null", int] 35 | default: 2 36 | description: Ploidy of the sample cells. [Default - %(default)d] 37 | inputBinding: 38 | prefix: --ploidy 39 | 40 | gender: 41 | type: 42 | - "null" 43 | - type: enum 44 | symbols: ['m', 'male', 'Male', 'f', 'female', 'Female'] 45 | description: Specify the sample's gender as male or female. (Otherwise guessed from chrX copy number). 46 | inputBinding: 47 | prefix: --gender 48 | 49 | male_reference: 50 | type: ["null", boolean] 51 | default: False 52 | description: Was a male reference used? If so, expect half ploidy on chrX and chrY; otherwise, only chrY has half ploidy. In CNVkit, if a male reference was used, the "neutral" copy number (ploidy) of chrX is 1; chrY is haploid for either gender reference. 53 | inputBinding: 54 | prefix: --male-reference 55 | 56 | output: 57 | type: ["null", string] 58 | description: Output file name. 59 | inputBinding: 60 | prefix: --output 61 | 62 | 63 | outputs: 64 | [] 65 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-fix.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'fix'] 10 | 11 | description: | 12 | Combine target and antitarget coverages and correct for biases. 13 | 14 | Adjust raw coverage data according to the given reference, correct potential 15 | biases and re-center. 16 | 17 | 18 | inputs: 19 | 20 | target: 21 | type: string 22 | 23 | description: Target coverage file (.targetcoverage.cnn). 24 | inputBinding: 25 | position: 1 26 | 27 | antitarget: 28 | type: string 29 | 30 | description: Antitarget coverage file (.antitargetcoverage.cnn). 31 | inputBinding: 32 | position: 2 33 | 34 | reference: 35 | type: string 36 | 37 | description: Reference coverage (.cnn). 38 | inputBinding: 39 | position: 3 40 | 41 | do_gc: 42 | type: ["null", boolean] 43 | default: True 44 | description: Skip GC correction. 45 | inputBinding: 46 | prefix: --no-gc 47 | 48 | do_edge: 49 | type: ["null", boolean] 50 | default: True 51 | description: Skip edge-effect correction. 52 | inputBinding: 53 | prefix: --no-edge 54 | 55 | do_rmask: 56 | type: ["null", boolean] 57 | default: True 58 | description: Skip RepeatMasker correction. 59 | inputBinding: 60 | prefix: --no-rmask 61 | 62 | output: 63 | type: ["null", string] 64 | description: Output file name. 65 | inputBinding: 66 | prefix: --output 67 | 68 | 69 | outputs: 70 | [] 71 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-gainloss.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'gainloss'] 10 | 11 | description: | 12 | Identify targeted genes with copy number gain or loss. 13 | 14 | inputs: 15 | 16 | filename: 17 | type: string 18 | 19 | description: Processed sample coverage data file (*.cnr), the output of the 'fix' sub-command. 20 | inputBinding: 21 | position: 1 22 | 23 | segment: 24 | type: ["null", string] 25 | description: Segmentation calls (.cns), the output of the 'segment' command). 26 | inputBinding: 27 | prefix: --segment 28 | 29 | threshold: 30 | type: ["null", float] 31 | default: 0.2 32 | description: Copy number change threshold to report a gene gain/loss. [Default - %(default)s] 33 | inputBinding: 34 | prefix: --threshold 35 | 36 | min_probes: 37 | type: ["null", int] 38 | default: 3 39 | description: Minimum number of covered probes to report a gain/loss. [Default - %(default)d] 40 | inputBinding: 41 | prefix: --min-probes 42 | 43 | drop_low_coverage: 44 | type: ["null", boolean] 45 | default: False 46 | description: Drop very-low-coverage bins before segmentation to avoid false-positive deletions in poor-quality tumor samples. 47 | inputBinding: 48 | prefix: --drop-low-coverage 49 | 50 | male_reference: 51 | type: ["null", boolean] 52 | default: False 53 | description: Assume inputs are already corrected against a male reference (i.e. female samples will have +1 log-coverage of chrX; otherwise male samples would have -1 chrX). 54 | inputBinding: 55 | prefix: --male-reference 56 | 57 | output: 58 | type: ["null", string] 59 | description: Output table file name. 60 | inputBinding: 61 | prefix: --output 62 | 63 | 64 | outputs: 65 | [] 66 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-gender.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'gender'] 10 | 11 | description: | 12 | Guess samples' gender from the relative coverage of chromosome X. 13 | 14 | inputs: 15 | 16 | targets: 17 | type: 18 | type: array 19 | items: string 20 | 21 | description: Copy number or copy ratio files (*.cnn, *.cnr). 22 | inputBinding: 23 | position: 1 24 | 25 | male_reference: 26 | type: ["null", boolean] 27 | default: False 28 | description: Assume inputs are already normalized to a male reference (i.e. female samples will have +1 log-coverage of chrX; otherwise male samples would have -1 chrX). 29 | inputBinding: 30 | prefix: --male-reference 31 | 32 | output: 33 | type: ["null", string] 34 | description: Output table file name. 35 | inputBinding: 36 | prefix: --output 37 | 38 | 39 | outputs: 40 | [] 41 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-heatmap.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'heatmap'] 10 | 11 | description: | 12 | Plot copy number for multiple samples as a heatmap. 13 | 14 | inputs: 15 | 16 | filenames: 17 | type: 18 | type: array 19 | items: string 20 | 21 | description: Sample coverages as raw probes (.cnr) or segments (.cns). 22 | inputBinding: 23 | position: 1 24 | 25 | chromosome: 26 | type: ["null", string] 27 | description: Chromosome (e.g. 'chr1') or chromosomal range (e.g. 'chr1 -2333000-2444000') to display. If a range is given, all targeted genes in this range will be shown, unless '--gene'/'-g' is already given. 28 | inputBinding: 29 | prefix: --chromosome 30 | 31 | desaturate: 32 | type: ["null", boolean] 33 | default: False 34 | description: Tweak color saturation to focus on significant changes. 35 | inputBinding: 36 | prefix: --desaturate 37 | 38 | output: 39 | type: ["null", string] 40 | description: Output PDF file name. 41 | inputBinding: 42 | prefix: --output 43 | 44 | 45 | outputs: 46 | [] 47 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-import-picard.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'import-picard'] 10 | 11 | description: | 12 | Convert Picard CalculateHsMetrics tabular output to CNVkit .cnn files. 13 | 14 | The input file is generated by the PER_TARGET_COVERAGE option in the 15 | CalculateHsMetrics script in Picard tools. 16 | 17 | 18 | inputs: 19 | 20 | targets: 21 | type: 22 | - "null" 23 | - type: array 24 | items: string 25 | 26 | default: ['.'] 27 | description: Sample coverage .csv files (target and antitarget), or the directory that contains them. 28 | inputBinding: 29 | position: 1 30 | 31 | output_dir: 32 | type: ["null", string] 33 | default: . 34 | description: Output directory name. 35 | inputBinding: 36 | prefix: --output-dir 37 | 38 | 39 | outputs: 40 | [] 41 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-import-seg.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'import-seg'] 10 | 11 | description: | 12 | Convert a SEG file to CNVkit .cns files. 13 | 14 | inputs: 15 | 16 | segfile: 17 | type: string 18 | 19 | description: Input file in SEG format. May contain multiple samples. 20 | inputBinding: 21 | position: 1 22 | 23 | chromosomes: 24 | type: ["null", string] 25 | description: Mapping of chromosome indexes to names. Syntax - "from1 -to1,from2 -to2". Or use "human" for the preset - "23 -X,24 -Y,25 -M". 26 | inputBinding: 27 | prefix: --chromosomes 28 | 29 | prefix: 30 | type: ["null", string] 31 | description: Prefix to add to chromosome names (e.g 'chr' to rename '8' in the SEG file to 'chr8' in the output). 32 | inputBinding: 33 | prefix: --prefix 34 | 35 | from_log10: 36 | type: ["null", boolean] 37 | default: False 38 | description: Convert base-10 logarithm values in the input to base-2 logs. 39 | inputBinding: 40 | prefix: --from-log10 41 | 42 | output_dir: 43 | type: ["null", string] 44 | default: . 45 | description: Output directory name. 46 | inputBinding: 47 | prefix: --output-dir 48 | 49 | 50 | outputs: 51 | [] 52 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-import-theta.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'import-theta'] 10 | 11 | description: | 12 | Convert THetA output to a BED-like, CNVkit-like tabular format. 13 | 14 | Equivalently, use the THetA results file to convert CNVkit .cns segments to 15 | integer copy number calls. 16 | 17 | 18 | inputs: 19 | 20 | tumor_cns: 21 | type: string 22 | 23 | 24 | inputBinding: 25 | position: 1 26 | 27 | theta_results: 28 | type: string 29 | 30 | 31 | inputBinding: 32 | position: 2 33 | 34 | ploidy: 35 | type: ["null", int] 36 | default: 2 37 | description: Ploidy of normal cells. [Default - %(default)d] 38 | inputBinding: 39 | prefix: --ploidy 40 | 41 | output_dir: 42 | type: ["null", string] 43 | default: . 44 | description: Output directory name. 45 | inputBinding: 46 | prefix: --output-dir 47 | 48 | 49 | outputs: 50 | [] 51 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-loh.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'loh'] 10 | 11 | description: | 12 | [DEPRECATED] Plot allelic frequencies at each variant position in a VCF file. 13 | 14 | Divergence from 0.5 indicates loss of heterozygosity in a tumor sample. 15 | 16 | Instead, use the command "scatter -v". 17 | 18 | 19 | inputs: 20 | 21 | variants: 22 | type: string 23 | 24 | description: Sample variants in VCF format. 25 | inputBinding: 26 | position: 1 27 | 28 | segment: 29 | type: ["null", string] 30 | description: Segmentation calls (.cns), the output of the 'segment' command. 31 | inputBinding: 32 | prefix: --segment 33 | 34 | min_depth: 35 | type: ["null", int] 36 | default: 20 37 | description: Minimum read depth for a variant to be displayed. [Default - %(default)s] 38 | inputBinding: 39 | prefix: --min-depth 40 | 41 | sample_id: 42 | type: ["null", string] 43 | description: Sample name to use for LOH calculations from the input VCF. 44 | inputBinding: 45 | prefix: --sample-id 46 | 47 | normal_id: 48 | type: ["null", string] 49 | description: Corresponding normal sample ID in the input VCF. 50 | inputBinding: 51 | prefix: --normal-id 52 | 53 | trend: 54 | type: ["null", boolean] 55 | default: False 56 | description: Draw a smoothed local trendline on the scatter plot. 57 | inputBinding: 58 | prefix: --trend 59 | 60 | output: 61 | type: ["null", string] 62 | description: Output PDF file name. 63 | inputBinding: 64 | prefix: --output 65 | 66 | 67 | outputs: 68 | [] 69 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-metrics.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'metrics'] 10 | 11 | description: | 12 | Compute coverage deviations and other metrics for self-evaluation. 13 | 14 | 15 | inputs: 16 | 17 | cnarrays: 18 | type: 19 | type: array 20 | items: string 21 | 22 | description: One or more bin-level coverage data files (*.cnn, *.cnr). 23 | inputBinding: 24 | position: 1 25 | 26 | segments: 27 | type: 28 | type: array 29 | items: string 30 | 31 | description: One or more segmentation data files (*.cns, output of the 'segment' command). If more than one file is given, the number must match the coverage data files, in which case the input files will be paired together in the given order. Otherwise, the same segments will be used for all coverage files. 32 | inputBinding: 33 | prefix: --segments 34 | 35 | output: 36 | type: ["null", string] 37 | description: Output table file name. 38 | inputBinding: 39 | prefix: --output 40 | 41 | 42 | outputs: 43 | [] 44 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-reference.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'reference'] 10 | 11 | description: | 12 | Compile a coverage reference from the given files (normal samples). 13 | 14 | inputs: 15 | 16 | references: 17 | type: 18 | - "null" 19 | - type: array 20 | items: string 21 | 22 | description: Normal-sample target or antitarget .cnn files, or the directory that contains them. 23 | inputBinding: 24 | position: 1 25 | 26 | fasta: 27 | type: ["null", string] 28 | description: Reference genome, FASTA format (e.g. UCSC hg19.fa) 29 | inputBinding: 30 | prefix: --fasta 31 | 32 | targets: 33 | type: ["null", string] 34 | description: Target intervals (.bed or .list) 35 | inputBinding: 36 | prefix: --targets 37 | 38 | antitargets: 39 | type: ["null", string] 40 | description: Antitarget intervals (.bed or .list) 41 | inputBinding: 42 | prefix: --antitargets 43 | 44 | male_reference: 45 | type: ["null", boolean] 46 | default: False 47 | description: Create a male reference - shift female samples' chrX log-coverage by -1, so the reference chrX average is -1. Otherwise, shift male samples' chrX by +1, so the reference chrX average is 0. 48 | inputBinding: 49 | prefix: --male-reference 50 | 51 | do_gc: 52 | type: ["null", boolean] 53 | default: True 54 | description: Skip GC correction. 55 | inputBinding: 56 | prefix: --no-gc 57 | 58 | do_edge: 59 | type: ["null", boolean] 60 | default: True 61 | description: Skip edge-effect correction. 62 | inputBinding: 63 | prefix: --no-edge 64 | 65 | do_rmask: 66 | type: ["null", boolean] 67 | default: True 68 | description: Skip RepeatMasker correction. 69 | inputBinding: 70 | prefix: --no-rmask 71 | 72 | output: 73 | type: ["null", string] 74 | description: Output file name. 75 | inputBinding: 76 | prefix: --output 77 | 78 | 79 | outputs: 80 | [] 81 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-rescale.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'rescale'] 10 | 11 | description: | 12 | [DEPRECATED] Rescale segment copy ratios given known purity and ploidy. 13 | 14 | Instead, use the command "call -m none". 15 | 16 | 17 | inputs: 18 | 19 | filename: 20 | type: string 21 | 22 | description: Copy ratios (.cnr or .cns). 23 | inputBinding: 24 | position: 1 25 | 26 | center: 27 | type: 28 | - "null" 29 | - type: enum 30 | symbols: ['mean', 'median', 'mode', 'biweight'] 31 | description: Re-center the log2 ratio values using this estimate of the center or average value. 32 | inputBinding: 33 | prefix: --center 34 | 35 | ploidy: 36 | type: ["null", int] 37 | default: 2 38 | description: Ploidy of the sample cells. [Default - %(default)d] 39 | inputBinding: 40 | prefix: --ploidy 41 | 42 | purity: 43 | type: ["null", float] 44 | description: Estimated tumor cell fraction, a.k.a. purity or cellularity. 45 | inputBinding: 46 | prefix: --purity 47 | 48 | gender: 49 | type: 50 | - "null" 51 | - type: enum 52 | symbols: ['m', 'male', 'Male', 'f', 'female', 'Female'] 53 | description: Specify the sample's gender as male or female. (Otherwise guessed from chrX copy number). 54 | inputBinding: 55 | prefix: --gender 56 | 57 | male_reference: 58 | type: ["null", boolean] 59 | default: False 60 | description: Was a male reference used? If so, expect half ploidy on chrX and chrY; otherwise, only chrY has half ploidy. In CNVkit, if a male reference was used, the "neutral" copy number (ploidy) of chrX is 1; chrY is haploid for either gender reference. 61 | inputBinding: 62 | prefix: --male-reference 63 | 64 | output: 65 | type: ["null", string] 66 | description: Output table file name (CNR-like table of segments, .cns). 67 | inputBinding: 68 | prefix: --output 69 | 70 | 71 | outputs: 72 | [] 73 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-scatter.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'scatter'] 10 | 11 | description: | 12 | Plot probe log2 coverages and segmentation calls together. 13 | 14 | inputs: 15 | 16 | filename: 17 | type: ["null", string] 18 | description: Processed bin-level copy ratios (*.cnr), the output of the 'fix' sub-command. 19 | inputBinding: 20 | position: 1 21 | 22 | segment: 23 | type: ["null", string] 24 | description: Segmentation calls (.cns), the output of the 'segment' command. 25 | inputBinding: 26 | prefix: --segment 27 | 28 | chromosome: 29 | type: ["null", string] 30 | description: Chromosome (e.g. 'chr1') or chromosomal range (e.g. 'chr1 -2333000-2444000') to display. If a range is given, all targeted genes in this range will be shown, unless '--gene'/'-g' is already given. 31 | inputBinding: 32 | prefix: --chromosome 33 | 34 | gene: 35 | type: ["null", string] 36 | description: Name of gene or genes (comma-separated) to display. 37 | inputBinding: 38 | prefix: --gene 39 | 40 | range_list: 41 | type: ["null", string] 42 | description: File listing the chromosomal ranges to display, as BED, interval list or "chr -start-end" text. Creates focal plots similar to -c/--chromosome for each listed region, combined into a multi-page PDF. The output filename must also be specified (-o/--output). 43 | inputBinding: 44 | prefix: --range-list 45 | 46 | sample_id: 47 | type: ["null", string] 48 | description: Specify the name of the sample in the VCF to use for b-allele frequency extraction and to show in plot title. 49 | inputBinding: 50 | prefix: --sample-id 51 | 52 | normal_id: 53 | type: ["null", string] 54 | description: Corresponding normal sample ID in the input VCF. 55 | inputBinding: 56 | prefix: --normal-id 57 | 58 | background_marker: 59 | type: ["null", string] 60 | description: Plot antitargets with this symbol, in zoomed/selected regions. [Default - same as targets] 61 | inputBinding: 62 | prefix: --background-marker 63 | 64 | trend: 65 | type: ["null", boolean] 66 | default: False 67 | description: Draw a smoothed local trendline on the scatter plot. 68 | inputBinding: 69 | prefix: --trend 70 | 71 | vcf: 72 | type: ["null", string] 73 | description: VCF file name containing variants to plot for SNV allele frequencies. 74 | inputBinding: 75 | prefix: --vcf 76 | 77 | min_variant_depth: 78 | type: ["null", int] 79 | default: 20 80 | description: Minimum read depth for a SNV to be displayed in the b-allele frequency plot. [Default - %(default)s] 81 | inputBinding: 82 | prefix: --min-variant-depth 83 | 84 | width: 85 | type: ["null", float] 86 | default: 1000000.0 87 | description: Width of margin to show around the selected gene or region on the chromosome (use with --gene or --region). [Default - %(default)d] 88 | inputBinding: 89 | prefix: --width 90 | 91 | y_min: 92 | type: ["null", float] 93 | description: y-axis lower limit. 94 | inputBinding: 95 | prefix: --y-min 96 | 97 | y_max: 98 | type: ["null", float] 99 | description: y-axis upper limit. 100 | inputBinding: 101 | prefix: --y-max 102 | 103 | output: 104 | type: ["null", string] 105 | description: Output table file name. 106 | inputBinding: 107 | prefix: --output 108 | 109 | 110 | outputs: 111 | [] 112 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-segment.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'segment'] 10 | 11 | description: | 12 | Infer copy number segments from the given coverage table. 13 | 14 | inputs: 15 | 16 | filename: 17 | type: string 18 | 19 | description: Bin-level log2 ratios (.cnr file), as produced by 'fix'. 20 | inputBinding: 21 | position: 1 22 | 23 | output: 24 | type: ["null", string] 25 | description: Output table file name (CNR-like table of segments, .cns). 26 | inputBinding: 27 | prefix: --output 28 | 29 | dataframe: 30 | type: ["null", string] 31 | description: File name to save the raw R dataframe emitted by CBS or Fused Lasso. (Useful for debugging.) 32 | inputBinding: 33 | prefix: --dataframe 34 | 35 | method: 36 | type: 37 | - "null" 38 | - type: enum 39 | symbols: ['cbs', 'haar', 'flasso'] 40 | default: cbs 41 | description: Segmentation method (CBS, HaarSeg, or Fused Lasso). [Default - %(default)s] 42 | inputBinding: 43 | prefix: --method 44 | 45 | threshold: 46 | type: ["null", float] 47 | description: Significance threshold (p-value or FDR, depending on method) to accept breakpoints during segmentation. 48 | inputBinding: 49 | prefix: --threshold 50 | 51 | vcf: 52 | type: ["null", string] 53 | description: VCF file name containing variants for segmentation by allele frequencies. 54 | inputBinding: 55 | prefix: --vcf 56 | 57 | drop_low_coverage: 58 | type: ["null", boolean] 59 | default: False 60 | description: Drop very-low-coverage bins before segmentation to avoid false-positive deletions in poor-quality tumor samples. 61 | inputBinding: 62 | prefix: --drop-low-coverage 63 | 64 | drop_outliers: 65 | type: ["null", float] 66 | default: 10 67 | description: Drop outlier bins more than this many multiples of the 95th quantile away from the average within a rolling window. Set to 0 for no outlier filtering. [Default - %(default)g] 68 | inputBinding: 69 | prefix: --drop-outliers 70 | 71 | rlibpath: 72 | type: ["null", string] 73 | description: Path to an alternative site-library to use for R packages. 74 | inputBinding: 75 | prefix: --rlibpath 76 | 77 | 78 | outputs: 79 | [] 80 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-segmetrics.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'segmetrics'] 10 | 11 | description: | 12 | Compute segment-level metrics from bin-level log2 ratios. 13 | 14 | inputs: 15 | 16 | cnarray: 17 | type: string 18 | 19 | description: Bin-level copy ratio data file (*.cnn, *.cnr). 20 | inputBinding: 21 | position: 1 22 | 23 | segments: 24 | type: string 25 | 26 | description: Segmentation data file (*.cns, output of the 'segment' command). 27 | inputBinding: 28 | prefix: --segments 29 | 30 | drop_low_coverage: 31 | type: ["null", boolean] 32 | default: False 33 | description: Drop very-low-coverage bins before segmentation to avoid false-positive deletions in poor-quality tumor samples. 34 | inputBinding: 35 | prefix: --drop-low-coverage 36 | 37 | output: 38 | type: ["null", string] 39 | description: Output table file name. 40 | inputBinding: 41 | prefix: --output 42 | 43 | stdev: 44 | type: ["null", boolean] 45 | default: False 46 | description: Standard deviation. 47 | inputBinding: 48 | prefix: --stdev 49 | 50 | mad: 51 | type: ["null", boolean] 52 | default: False 53 | description: Median absolute deviation (standardized). 54 | inputBinding: 55 | prefix: --mad 56 | 57 | iqr: 58 | type: ["null", boolean] 59 | default: False 60 | description: Inter-quartile range. 61 | inputBinding: 62 | prefix: --iqr 63 | 64 | bivar: 65 | type: ["null", boolean] 66 | default: False 67 | description: Tukey's biweight midvariance. 68 | inputBinding: 69 | prefix: --bivar 70 | 71 | ci: 72 | type: ["null", boolean] 73 | default: False 74 | description: Confidence interval (by bootstrap). 75 | inputBinding: 76 | prefix: --ci 77 | 78 | pi: 79 | type: ["null", boolean] 80 | default: False 81 | description: Prediction interval. 82 | inputBinding: 83 | prefix: --pi 84 | 85 | alpha: 86 | type: ["null", float] 87 | default: 0.05 88 | description: Level to estimate confidence and prediction intervals; use with --ci and --pi. [Default - %(default)s] 89 | inputBinding: 90 | prefix: --alpha 91 | 92 | bootstrap: 93 | type: ["null", int] 94 | default: 100 95 | description: Number of bootstrap iterations to estimate confidence interval; use with --ci. [Default - %(default)d] 96 | inputBinding: 97 | prefix: --bootstrap 98 | 99 | 100 | outputs: 101 | [] 102 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-target.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'target'] 10 | 11 | description: | 12 | Transform bait intervals into targets more suitable for CNVkit. 13 | 14 | inputs: 15 | 16 | interval: 17 | type: string 18 | 19 | description: BED or interval file listing the targeted regions. 20 | inputBinding: 21 | position: 1 22 | 23 | annotate: 24 | type: ["null", string] 25 | description: UCSC refFlat.txt or ensFlat.txt file for the reference genome. Pull gene names from this file and assign them to the target regions. 26 | inputBinding: 27 | prefix: --annotate 28 | 29 | short_names: 30 | type: ["null", boolean] 31 | default: False 32 | description: Reduce multi-accession bait labels to be short and consistent. 33 | inputBinding: 34 | prefix: --short-names 35 | 36 | split: 37 | type: ["null", boolean] 38 | default: False 39 | description: Split large tiled intervals into smaller, consecutive targets. 40 | inputBinding: 41 | prefix: --split 42 | 43 | avg_size: 44 | type: ["null", int] 45 | default: 266.6666666666667 46 | description: Average size of split target bins (results are approximate). [Default - %(default)s] 47 | inputBinding: 48 | prefix: --avg-size 49 | 50 | output: 51 | type: ["null", string] 52 | description: Output file name. 53 | inputBinding: 54 | prefix: --output 55 | 56 | 57 | outputs: 58 | [] 59 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/cnvkit-version.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.2.8 3 | # To generate again: $ cnvkit.py --generate_cwl_tool 4 | # Help: $ cnvkit.py --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['cnvkit.py', 'version'] 10 | 11 | description: | 12 | Display this program's version. 13 | 14 | inputs: 15 | 16 | 17 | outputs: 18 | [] 19 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "file": { 3 | "class": "File", 4 | "path": "inp.txt" 5 | }, 6 | "term":"here" 7 | } -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/genome2access.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | 3 | cwlVersion: "cwl:draft-3.dev2" 4 | 5 | class: CommandLineTool 6 | baseCommand: ["python"] 7 | 8 | requirements: 9 | - class: InlineJavascriptRequirement 10 | 11 | description: | 12 | List the locations of accessible sequence regions in a FASTA file. 13 | 14 | Inaccessible regions, e.g. telomeres and centromeres, are masked out with N in 15 | the reference genome sequence; this script scans those to identify the 16 | coordinates of the accessible regions (those between the long spans of N's). 17 | 18 | DEPRECATED -- use "cnvkit.py access" instead. 19 | 20 | 21 | inputs: 22 | 23 | - id: fa_fname 24 | type: string 25 | description: Genome FASTA file name 26 | inputBinding: 27 | position: 1 28 | 29 | - id: min_gap_size 30 | type: int 31 | default: 5000 32 | description: Minimum gap size between accessible sequence 33 | regions. Regions separated by less than this distance will 34 | be joined together. [Default- %(default)s] 35 | inputBinding: 36 | position: 2 37 | 38 | - id: exclude 39 | type: 40 | type: array 41 | items: string 42 | description: Additional regions to exclude, in BED format. Can be 43 | used multiple times. 44 | inputBinding: 45 | position: 3 46 | 47 | - id: output 48 | type: File 49 | description: Output file name 50 | inputBinding: 51 | position: 4 52 | - id: genome2access.py 53 | type: File 54 | default: 55 | class: File 56 | path: genome2access.py 57 | inputBinding: 58 | position: 0 59 | 60 | outputs: 61 | - id: output_out 62 | type: File 63 | description: Output file name 64 | outputBinding: 65 | glob: $(inputs.output.path) 66 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/genome2access.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """List the locations of accessible sequence regions in a FASTA file. 4 | 5 | Inaccessible regions, e.g. telomeres and centromeres, are masked out with N in 6 | the reference genome sequence; this script scans those to identify the 7 | coordinates of the accessible regions (those between the long spans of N's). 8 | 9 | DEPRECATED -- use "cnvkit.py access" instead. 10 | """ 11 | 12 | import argparse 13 | import sys 14 | 15 | import logging 16 | logging.basicConfig(level=logging.INFO, format="%(message)s") 17 | 18 | 19 | 20 | AP = argparse.ArgumentParser(description=__doc__) 21 | AP.add_argument("fa_fname", 22 | help="Genome FASTA file name") 23 | AP.add_argument("-s", "--min-gap-size", type=int, default=5000, 24 | help="""Minimum gap size between accessible sequence 25 | regions. Regions separated by less than this distance will 26 | be joined together. [Default: %(default)s]""") 27 | AP.add_argument("-x", "--exclude", action="append", default=[], 28 | help="""Additional regions to exclude, in BED format. Can be 29 | used multiple times.""") 30 | AP.add_argument("-o", "--output", 31 | type=argparse.FileType('w'), default=sys.stdout, 32 | help="Output file name") 33 | args = AP.parse_args() 34 | 35 | # Closes over args.output 36 | def write_row(chrom, run_start, run_end): 37 | args.output.write("%s\t%s\t%s\n" % (chrom, run_start, run_end)) 38 | args.output.flush() 39 | 40 | 41 | -------------------------------------------------------------------------------- /examples/argparse/cnvkit-tools/output.txt: -------------------------------------------------------------------------------- 1 | outputs: 2 | - id: outfile 3 | type: File 4 | source: "#main/search/result" 5 | - id: indexedfile 6 | type: File 7 | source: "#main/index/result" -------------------------------------------------------------------------------- /examples/click/genmod-tools/genmod-annotate.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.3.0 3 | # To generate again: $ genmod --generate_cwl_tool 4 | # Help: $ genmod --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['genmod', 'annotate'] 10 | 11 | description: | 12 | Annotate vcf variants. 13 | 14 | Annotate variants with a number of different sources. 15 | Please use --help for more info. 16 | 17 | inputs: 18 | 19 | variant_file: 20 | type: File 21 | 22 | description: or - 23 | inputBinding: 24 | position: 1 25 | 26 | annotate_regions: 27 | type: ["null", boolean] 28 | default: False 29 | description: Increase output verbosity. 30 | inputBinding: 31 | prefix: --annotate_regions 32 | 33 | cadd_file: 34 | type: ["null", string] 35 | description: Specify the path to a bgzipped cadd file (with index) with variant scores. This command can be used multiple times if multiple cadd files. 36 | inputBinding: 37 | prefix: --cadd_file 38 | 39 | thousand_g: 40 | type: ["null", string] 41 | description: Specify the path to a bgzipped vcf file (with index) with 1000g variants 42 | inputBinding: 43 | prefix: --thousand_g 44 | 45 | exac: 46 | type: ["null", string] 47 | description: Specify the path to a bgzipped vcf file (with index) with exac variants. 48 | inputBinding: 49 | prefix: --exac 50 | 51 | cosmic: 52 | type: ["null", string] 53 | description: Specify the path to a bgzipped vcf file (with index) with COSMIC variants. 54 | inputBinding: 55 | prefix: --cosmic 56 | 57 | max_af: 58 | type: ["null", boolean] 59 | default: False 60 | description: If the MAX AF should be annotated 61 | inputBinding: 62 | prefix: --max_af 63 | 64 | spidex: 65 | type: ["null", string] 66 | description: Specify the path to a bgzipped tsv file (with index) with spidex information. 67 | inputBinding: 68 | prefix: --spidex 69 | 70 | annotation_dir: 71 | type: ["null", string] 72 | default: /usr/local/lib/python2.7/dist-packages/genmod/annotations 73 | description: Specify the path to the directory where the annotation databases are. Default is the gene pred files that comes with the distribution. 74 | inputBinding: 75 | prefix: --annotation_dir 76 | 77 | cadd_raw: 78 | type: ["null", boolean] 79 | default: False 80 | description: If the raw cadd scores should be annotated. 81 | inputBinding: 82 | prefix: --cadd_raw 83 | 84 | processes: 85 | type: ["null", int] 86 | default: 4 87 | description: Define how many processes that should be use for annotation. 88 | inputBinding: 89 | prefix: --processes 90 | 91 | outfile: 92 | type: ["null", File] 93 | description: Specify the path to a file where results should be stored. 94 | inputBinding: 95 | prefix: --outfile 96 | 97 | silent: 98 | type: ["null", boolean] 99 | default: False 100 | description: Do not print the variants. 101 | inputBinding: 102 | prefix: --silent 103 | 104 | temp_dir: 105 | type: ["null", string] 106 | description: Path to tempdir 107 | inputBinding: 108 | prefix: --temp_dir 109 | 110 | 111 | outputs: 112 | 113 | outfile_out: 114 | type: File 115 | 116 | description: Specify the path to a file where results should be stored. 117 | outputBinding: 118 | glob: $(inputs.outfile.path) 119 | -------------------------------------------------------------------------------- /examples/click/genmod-tools/genmod-build.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.3.0 3 | # To generate again: $ genmod --generate_cwl_tool 4 | # Help: $ genmod --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['genmod', 'build'] 10 | 11 | description: | 12 | Build a new annotation database 13 | 14 | Build an annotation database from an annotation file. 15 | 16 | inputs: 17 | 18 | annotation_file: 19 | type: string 20 | 21 | description: ANNOTATION_FILE 22 | inputBinding: 23 | position: 1 24 | 25 | outdir: 26 | type: ["null", string] 27 | description: Specify the path to a folder where the annotation files should be stored. 28 | inputBinding: 29 | prefix: --outdir 30 | 31 | annotation_type: 32 | type: 33 | - "null" 34 | - type: enum 35 | symbols: [] 36 | default: gene_pred 37 | description: Specify the format of the annotation file. 38 | inputBinding: 39 | prefix: --annotation_type 40 | 41 | splice_padding: 42 | type: ["null", int] 43 | default: 2 44 | description: Specify the the number of bases that the exons should be padded with. Default is 2 bases. 45 | inputBinding: 46 | prefix: --splice_padding 47 | 48 | verbose: 49 | type: 50 | - "null" 51 | - type: array 52 | items: string 53 | 54 | default: 0 55 | description: Increase output verbosity. 56 | inputBinding: 57 | prefix: --verbose 58 | 59 | 60 | outputs: 61 | [] 62 | -------------------------------------------------------------------------------- /examples/click/genmod-tools/genmod-compound.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.3.0 3 | # To generate again: $ genmod --generate_cwl_tool 4 | # Help: $ genmod --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['genmod', 'compound'] 10 | 11 | description: | 12 | Score compound variants in a vcf file based on their rank score. 13 | 14 | inputs: 15 | 16 | variant_file: 17 | type: File 18 | 19 | description: or - 20 | inputBinding: 21 | position: 1 22 | 23 | silent: 24 | type: ["null", boolean] 25 | default: False 26 | description: Do not print the variants. 27 | inputBinding: 28 | prefix: --silent 29 | 30 | outfile: 31 | type: ["null", File] 32 | description: Specify the path to a file where results should be stored. 33 | inputBinding: 34 | prefix: --outfile 35 | 36 | processes: 37 | type: ["null", int] 38 | default: 4 39 | description: Define how many processes that should be use for annotation. 40 | inputBinding: 41 | prefix: --processes 42 | 43 | temp_dir: 44 | type: ["null", string] 45 | description: Path to tempdir 46 | inputBinding: 47 | prefix: --temp_dir 48 | 49 | vep: 50 | type: ["null", boolean] 51 | default: False 52 | description: If variants are annotated with the Variant Effect Predictor. 53 | inputBinding: 54 | prefix: --vep 55 | 56 | 57 | outputs: 58 | 59 | outfile_out: 60 | type: File 61 | 62 | description: Specify the path to a file where results should be stored. 63 | outputBinding: 64 | glob: $(inputs.outfile.path) 65 | -------------------------------------------------------------------------------- /examples/click/genmod-tools/genmod-filter.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.3.0 3 | # To generate again: $ genmod --generate_cwl_tool 4 | # Help: $ genmod --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['genmod', 'filter'] 10 | 11 | description: | 12 | Filter vcf variants. 13 | 14 | Filter variants based on their annotation 15 | 16 | inputs: 17 | 18 | variant_file: 19 | type: File 20 | 21 | description: or - 22 | inputBinding: 23 | position: 1 24 | 25 | annotation: 26 | type: ["null", string] 27 | default: 1000GAF 28 | description: Specify the info annotation to search for. Default 1000GAF 29 | inputBinding: 30 | prefix: --annotation 31 | 32 | threshold: 33 | type: ["null", float] 34 | default: 0.05 35 | description: Threshold for filter variants. Default 0.05 36 | inputBinding: 37 | prefix: --threshold 38 | 39 | discard: 40 | type: ["null", boolean] 41 | default: False 42 | description: If variants without the annotation should be discarded 43 | inputBinding: 44 | prefix: --discard 45 | 46 | greater: 47 | type: ["null", boolean] 48 | default: False 49 | description: If greater than threshold should be used instead of less thatn threshold. 50 | inputBinding: 51 | prefix: --greater 52 | 53 | silent: 54 | type: ["null", boolean] 55 | default: False 56 | description: Do not print the variants. 57 | inputBinding: 58 | prefix: --silent 59 | 60 | outfile: 61 | type: ["null", File] 62 | description: Specify the path to a file where results should be stored. 63 | inputBinding: 64 | prefix: --outfile 65 | 66 | 67 | outputs: 68 | 69 | outfile_out: 70 | type: File 71 | 72 | description: Specify the path to a file where results should be stored. 73 | outputBinding: 74 | glob: $(inputs.outfile.path) 75 | -------------------------------------------------------------------------------- /examples/click/genmod-tools/genmod-models.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.3.0 3 | # To generate again: $ genmod --generate_cwl_tool 4 | # Help: $ genmod --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['genmod', 'models'] 10 | 11 | description: | 12 | Annotate genetic models for vcf variants. 13 | 14 | Checks what patterns of inheritance that are followed in a VCF file. 15 | The analysis is family based so each family that are specified in the family 16 | file and exists in the variant file will get it's own annotation. 17 | 18 | inputs: 19 | 20 | variant_file: 21 | type: File 22 | 23 | description: or - 24 | inputBinding: 25 | position: 1 26 | 27 | family_file: 28 | type: ["null", File] 29 | 30 | inputBinding: 31 | prefix: --family_file 32 | 33 | family_type: 34 | type: 35 | - "null" 36 | - type: enum 37 | symbols: [] 38 | default: ped 39 | description: If the analysis use one of the known setups, please specify which one. 40 | inputBinding: 41 | prefix: --family_type 42 | 43 | reduced_penetrance: 44 | type: ["null", File] 45 | description: File with gene ids that have reduced penetrance. 46 | inputBinding: 47 | prefix: --reduced_penetrance 48 | 49 | vep: 50 | type: ["null", boolean] 51 | default: False 52 | description: If variants are annotated with the Variant Effect Predictor. 53 | inputBinding: 54 | prefix: --vep 55 | 56 | phased: 57 | type: ["null", boolean] 58 | default: False 59 | description: If data is phased use this flag. 60 | inputBinding: 61 | prefix: --phased 62 | 63 | strict: 64 | type: ["null", boolean] 65 | default: False 66 | description: If strict model annotations should be used(see documentation). 67 | inputBinding: 68 | prefix: --strict 69 | 70 | processes: 71 | type: ["null", int] 72 | default: 4 73 | description: Define how many processes that should be use for annotation. 74 | inputBinding: 75 | prefix: --processes 76 | 77 | silent: 78 | type: ["null", boolean] 79 | default: False 80 | description: Do not print the variants. 81 | inputBinding: 82 | prefix: --silent 83 | 84 | whole_gene: 85 | type: ["null", boolean] 86 | default: False 87 | description: If compounds should be checked over the whole gene. 88 | inputBinding: 89 | prefix: --whole_gene 90 | 91 | keyword: 92 | type: ["null", string] 93 | default: Annotation 94 | description: What annotation keyword that should be used when searching for features. 95 | inputBinding: 96 | prefix: --keyword 97 | 98 | outfile: 99 | type: ["null", File] 100 | description: Specify the path to a file where results should be stored. 101 | inputBinding: 102 | prefix: --outfile 103 | 104 | temp_dir: 105 | type: ["null", string] 106 | description: Path to tempdir 107 | inputBinding: 108 | prefix: --temp_dir 109 | 110 | 111 | outputs: 112 | 113 | outfile_out: 114 | type: File 115 | 116 | description: Specify the path to a file where results should be stored. 117 | outputBinding: 118 | glob: $(inputs.outfile.path) 119 | -------------------------------------------------------------------------------- /examples/click/genmod-tools/genmod-score.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.3.0 3 | # To generate again: $ genmod --generate_cwl_tool 4 | # Help: $ genmod --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['genmod', 'score'] 10 | 11 | description: | 12 | Score variants in a vcf file using a Weighted Sum Model. 13 | 14 | The specific scores should be defined in a config file, see examples on 15 | github. 16 | 17 | inputs: 18 | 19 | variant_file: 20 | type: File 21 | 22 | description: or - 23 | inputBinding: 24 | position: 1 25 | 26 | family_id: 27 | type: ["null", string] 28 | default: 1 29 | 30 | inputBinding: 31 | prefix: --family_id 32 | 33 | family_file: 34 | type: ["null", File] 35 | 36 | inputBinding: 37 | prefix: --family_file 38 | 39 | family_type: 40 | type: 41 | - "null" 42 | - type: enum 43 | symbols: [] 44 | default: ped 45 | description: If the analysis use one of the known setups, please specify which one. 46 | inputBinding: 47 | prefix: --family_type 48 | 49 | silent: 50 | type: ["null", boolean] 51 | default: False 52 | description: Do not print the variants. 53 | inputBinding: 54 | prefix: --silent 55 | 56 | skip_plugin_check: 57 | type: ["null", boolean] 58 | default: False 59 | description: If continue even if plugins does not exist in vcf. 60 | inputBinding: 61 | prefix: --skip_plugin_check 62 | 63 | rank_results: 64 | type: ["null", boolean] 65 | default: False 66 | description: Add a info field that shows how the different categories contribute to the rank score. 67 | inputBinding: 68 | prefix: --rank_results 69 | 70 | outfile: 71 | type: ["null", File] 72 | description: Specify the path to a file where results should be stored. 73 | inputBinding: 74 | prefix: --outfile 75 | 76 | score_config: 77 | type: ["null", string] 78 | description: The plug-in config file(.ini) 79 | inputBinding: 80 | prefix: --score_config 81 | 82 | 83 | outputs: 84 | 85 | outfile_out: 86 | type: File 87 | 88 | description: Specify the path to a file where results should be stored. 89 | outputBinding: 90 | glob: $(inputs.outfile.path) 91 | -------------------------------------------------------------------------------- /examples/click/genmod-tools/genmod-sort.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was generated automatically by argparse2cwl ver. 0.3.0 3 | # To generate again: $ genmod --generate_cwl_tool 4 | # Help: $ genmod --help_arg2cwl 5 | 6 | cwlVersion: "cwl:v1.0" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['genmod', 'sort'] 10 | 11 | description: | 12 | Sort a VCF file based on rank score. 13 | 14 | inputs: 15 | 16 | variant_file: 17 | type: File 18 | 19 | description: or - 20 | inputBinding: 21 | position: 1 22 | 23 | outfile: 24 | type: ["null", File] 25 | description: Specify the path to a file where results should be stored. 26 | inputBinding: 27 | prefix: --outfile 28 | 29 | family_id: 30 | type: ["null", string] 31 | description: Specify the family id for sorting. 32 | inputBinding: 33 | prefix: --family_id 34 | 35 | silent: 36 | type: ["null", boolean] 37 | default: False 38 | description: Do not print the variants. 39 | inputBinding: 40 | prefix: --silent 41 | 42 | temp_dir: 43 | type: ["null", string] 44 | description: Path to tempdir 45 | inputBinding: 46 | prefix: --temp_dir 47 | 48 | position: 49 | type: ["null", boolean] 50 | default: False 51 | description: If variants should be sorted by position. 52 | inputBinding: 53 | prefix: --position 54 | 55 | 56 | outputs: 57 | 58 | outfile_out: 59 | type: File 60 | 61 | description: Specify the path to a file where results should be stored. 62 | outputBinding: 63 | glob: $(inputs.outfile.path) 64 | -------------------------------------------------------------------------------- /gxargparse/__init__.py: -------------------------------------------------------------------------------- 1 | """Stub for gxargparse""" 2 | -------------------------------------------------------------------------------- /gxargparse/check_path.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """gxargparse_check_path checks for proper ordering of the system path 3 | 4 | If gxargparse appears after python stdlib's argparse, it won't behave properly, 5 | thus we provide a small check utility to ensure proper ordering and provide 6 | suggestions if not functional. 7 | """ 8 | from __future__ import print_function 9 | import sys, imp, os 10 | import argparse 11 | 12 | def get_args(): 13 | help_text = """Check the path for the correct setting to be able to take advantage 14 | of gxargparse. 15 | """ 16 | parser = argparse.ArgumentParser(prog='gxargparse_check_path', description=help_text) 17 | parser.add_argument('-q', dest='quiet', action='store_true', help='run quietly') 18 | return parser.parse_args() 19 | 20 | def main(): 21 | args = get_args() 22 | 23 | good_paths = [] 24 | incorrect_ordering = False 25 | for path in sys.path: 26 | try: 27 | (handle, pathname, desc) = imp.find_module('argparse', [path]) 28 | if desc[2] == 5: 29 | good_paths.append(pathname) 30 | elif len(good_paths) == 0: 31 | incorrect_ordering = True 32 | except: 33 | pass 34 | 35 | if incorrect_ordering: 36 | if len(good_paths) == 0: 37 | if not args.quiet: 38 | print("gxargparse not installed") 39 | else: 40 | if args.quiet: 41 | print(os.path.dirname(good_paths[0])) 42 | else: 43 | print("Incorrect ordering, please set\n\n\tPYTHONPATH=%s\n" % (os.path.dirname(good_paths[0]))) 44 | else: 45 | if not args.quiet: 46 | print("Ready to go!") 47 | 48 | if __name__ == '__main__': 49 | main() 50 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | galaxyxml 2 | jinja2>=2.8 3 | future -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [wheel] 2 | universal = 1 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | from setuptools import setup 5 | 6 | from cmdline2cwl import __version__ 7 | 8 | if sys.argv[-1] == 'publish': 9 | os.system("python setup.py sdist bdist_wheel upload; git push") 10 | sys.exit() 11 | 12 | setup(name="gxargparse", 13 | version=__version__, 14 | description='Instrument for forming Galaxy XML and CWL tool descriptions from argparse arguments', 15 | author='Eric Rasche, Anton Khodak', 16 | author_email='rasche.eric@yandex.ru, anton.khodak@ukr.net', 17 | install_requires=['galaxyxml', 'jinja2', 'future'], 18 | url='https://github.com/common-workflow-language/gxargparse', 19 | packages=["argparse", "gxargparse", "click", "cmdline2cwl"], 20 | entry_points={ 21 | 'console_scripts': [ 22 | 'gxargparse_check_path = gxargparse.check_path:main', 23 | ] 24 | }, 25 | classifiers=[ 26 | 'Development Status :: 3 - Alpha', 27 | 'Operating System :: OS Independent', 28 | 'Intended Audience :: Developers', 29 | 'Environment :: Console', 30 | 'License :: OSI Approved :: Apache Software License', 31 | ], 32 | include_package_data=True, 33 | ) 34 | -------------------------------------------------------------------------------- /test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/common-workflow-lab/gxargparse/d81713e94fd0d78edf0b469ef5afafa89daa64e9/test/__init__.py -------------------------------------------------------------------------------- /test/cwl_classes.py: -------------------------------------------------------------------------------- 1 | from yaml import load 2 | from collections import OrderedDict 3 | 4 | 5 | class InputBinding: 6 | def __init__(self, ib): 7 | self.position = ib.get('position', None) 8 | self.prefix = ib.get('prefix', None) 9 | 10 | 11 | class OutputBinding: 12 | def __init__(self, ob): 13 | self.glob = ob.get('glob', None) 14 | 15 | 16 | class Param: 17 | 18 | def __init__(self, param): 19 | self.id = param['id'] 20 | self.type = param.get('type', None) 21 | self.description = param.get('doc', param.get('description', None)) 22 | 23 | 24 | class InputParam(Param): 25 | 26 | def __init__(self, param): 27 | super(InputParam, self).__init__(param) 28 | if type(self.type) is list and self.type[0] == 'null': 29 | self.optional = True 30 | else: 31 | self.optional = False 32 | self.default = param.get('default', None) 33 | input_binding = param.get('inputBinding', None) 34 | if input_binding: 35 | self.input_binding = InputBinding(input_binding) 36 | 37 | 38 | class OutputParam(Param): 39 | 40 | def __init__(self, param): 41 | super(OutputParam, self).__init__(param) 42 | output_binding = param.get('outputBinding', None) 43 | if output_binding: 44 | self.output_binding = OutputBinding(output_binding) 45 | 46 | 47 | class Tool: 48 | 49 | def __init__(self, filename): 50 | 51 | with open(filename) as f: 52 | tool = load(f) 53 | self.tool_class = tool['class'] 54 | if self.tool_class != 'CommandLineTool': 55 | raise ValueError('Wrong tool class') 56 | self.basecommand = tool['baseCommand'] 57 | self.inputs = OrderedDict() 58 | if type(tool['inputs']) is list: # ids not mapped 59 | for param_dict in tool['inputs']: 60 | param = InputParam(param_dict) 61 | self.inputs[param.id] = param 62 | elif type(tool['inputs']) is dict: # ids mapped 63 | for id, param_dict in tool['inputs'].items(): 64 | param_dict['id'] = id 65 | param = InputParam(param_dict) 66 | self.inputs[id] = param 67 | self.outputs = OrderedDict() 68 | if tool['outputs']: 69 | if type(tool['outputs']) is list: # ids not mapped 70 | for param_dict in tool['outputs']: 71 | param = OutputParam(param_dict) 72 | self.outputs[param.id] = param 73 | elif type(tool['outputs']) is dict: # ids mapped 74 | for id, param_dict in tool['outputs'].items(): 75 | param_dict['id'] = id 76 | param = OutputParam(param_dict) 77 | self.outputs[id] = param 78 | self.description = tool.get('doc', tool.get('description', '')) 79 | self.cwl_version = tool.get('cwlVersion', '') 80 | 81 | -------------------------------------------------------------------------------- /test/test-data/index.cwl: -------------------------------------------------------------------------------- 1 | cwlVersion: cwl:draft-3 2 | class: CommandLineTool 3 | baseCommand: python 4 | requirements: 5 | - class: CreateFileRequirement 6 | fileDef: 7 | - filename: input.txt 8 | fileContent: $(inputs.file) 9 | 10 | inputs: 11 | - id: file 12 | type: File 13 | inputBinding: 14 | position: 1 15 | - id: index.py 16 | type: File 17 | default: 18 | class: File 19 | path: index.py 20 | inputBinding: 21 | position: 0 22 | outputs: 23 | - id: result 24 | type: File 25 | outputBinding: 26 | glob: input.txt 27 | secondaryFiles: 28 | - ".idx1" 29 | - "^.idx2" -------------------------------------------------------------------------------- /test/test-data/index.py: -------------------------------------------------------------------------------- 1 | from builtins import str 2 | #!/usr/bin/env python 3 | 4 | # Toy program to generate inverted index of word to line. 5 | # Takes input text file on stdin and prints output index on stdout. 6 | 7 | import sys 8 | import os 9 | 10 | # to invoke own argparse from this directory (test-data) we must put it on the first place in sys.path 11 | argparse_dir = os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', '..')) 12 | sys.path.insert(0, argparse_dir) 13 | 14 | import argparse 15 | 16 | 17 | words = {} 18 | 19 | parser = argparse.ArgumentParser(description='Generate inverted index of word to line') 20 | parser.add_argument('mainfile', type=argparse.FileType('r'), help='Text file to be indexed') 21 | 22 | args = parser.parse_args() 23 | 24 | mainfile = args.mainfile 25 | indexfile = mainfile.name + ".idx1" 26 | 27 | main = mainfile 28 | index = open(indexfile, "w") 29 | 30 | linenum = 0 31 | for l in main: 32 | linenum += 1 33 | l = l.rstrip().lower().replace(".", "").replace(",", "").replace(";", "").replace("-", " ") 34 | for w in l.split(" "): 35 | if w: 36 | if w not in words: 37 | words[w] = set() 38 | words[w].add(linenum) 39 | 40 | for w in sorted(words.keys()): 41 | index.write("%s: %s" % (w, ", ".join((str(i) for i in words[w]))) + "\n") 42 | -------------------------------------------------------------------------------- /test/test-data/index_new.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | 3 | cwlVersion: "cwl:draft-3.dev2" 4 | 5 | class: CommandLineTool 6 | baseCommand: ["python"] 7 | 8 | requirements: 9 | - $import: envvar-global.cwl 10 | - $import: linux-sort-docker.cwl 11 | - class: InlineJavascriptRequirement 12 | 13 | description: | 14 | Generate inverted index of word to line 15 | 16 | inputs: 17 | 18 | 19 | - id: mainfile 20 | type: File 21 | inputBinding: 22 | position: 1 23 | 24 | - id: index.py 25 | type: File 26 | default: 27 | class: File 28 | path: index.py 29 | inputBinding: 30 | position: 0 31 | 32 | 33 | outputs: 34 | [] -------------------------------------------------------------------------------- /test/test-data/inp.txt: -------------------------------------------------------------------------------- 1 | Some text here 2 | and here 3 | and again some here 4 | asdfasdf 99992 2 3 kj -------------------------------------------------------------------------------- /test/test-data/inp.txt.idx1: -------------------------------------------------------------------------------- 1 | 2: 4 2 | 3: 4 3 | 99992: 4 4 | again: 3 5 | and: 2, 3 6 | asdfasdf: 4 7 | here: 1, 2, 3 8 | kj: 4 9 | some: 1, 3 10 | text: 1 11 | -------------------------------------------------------------------------------- /test/test-data/job.json: -------------------------------------------------------------------------------- 1 | { 2 | "file": { 3 | "class": "File", 4 | "path": "inp.txt" 5 | }, 6 | "term":"here" 7 | } 8 | -------------------------------------------------------------------------------- /test/test-data/main.cwl: -------------------------------------------------------------------------------- 1 | cwlVersion: cwl:draft-3 2 | $graph: 3 | - id: index 4 | class: CommandLineTool 5 | baseCommand: python 6 | requirements: 7 | - class: CreateFileRequirement 8 | fileDef: 9 | - filename: input.txt 10 | fileContent: $(inputs.file) 11 | - class: InlineJavascriptRequirement 12 | 13 | inputs: 14 | - id: file 15 | type: File 16 | inputBinding: 17 | position: 1 18 | - id: index.py 19 | type: File 20 | default: 21 | class: File 22 | path: index.py 23 | inputBinding: 24 | position: 0 25 | outputs: 26 | [] 27 | 28 | - id: search 29 | class: CommandLineTool 30 | baseCommand: python 31 | requirements: 32 | - class: InlineJavascriptRequirement 33 | inputs: 34 | - id: file 35 | type: File 36 | inputBinding: 37 | position: 1 38 | secondaryFiles: 39 | - ".idx1" 40 | - id: search.py 41 | type: File 42 | default: 43 | class: File 44 | path: search.py 45 | inputBinding: 46 | position: 0 47 | - id: term 48 | type: string 49 | inputBinding: 50 | position: 2 51 | outputs: 52 | - id: result 53 | type: File 54 | outputBinding: 55 | glob: result.txt 56 | stdout: result.txt 57 | 58 | - id: main 59 | class: Workflow 60 | inputs: 61 | - id: infile 62 | type: File 63 | - id: term 64 | type: string 65 | outputs: 66 | - id: outfile 67 | type: File 68 | source: "#main/search/result" 69 | - id: indexedfile 70 | type: File 71 | source: "#main/index/result" 72 | 73 | steps: 74 | - id: index 75 | run: "#index" 76 | inputs: 77 | - { id: file, source: "#main/infile" } 78 | outputs: 79 | - id: result 80 | 81 | - id: search 82 | run: "#search" 83 | inputs: 84 | - { id: file, source: "#main/index/result" } 85 | - { id: term, source: "#main/term" } 86 | outputs: 87 | - id: result -------------------------------------------------------------------------------- /test/test-data/search.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | # This tool description was formed automatically by argparse2cwl ver. 0.2.5 3 | # To form again: $ python --generate_cwl_tool 4 | # Help: $ python --help_arg2cwl 5 | 6 | cwlVersion: "cwl:draft-3" 7 | 8 | class: CommandLineTool 9 | baseCommand: ['python'] 10 | 11 | requirements: 12 | - class: InlineJavascriptRequirement 13 | 14 | description: | 15 | Toy program to search inverted index and print out each line the term appears 16 | 17 | inputs: 18 | 19 | - id: search.py 20 | type: File 21 | default: 22 | class: File 23 | path: search.py 24 | inputBinding: 25 | position: 0 26 | 27 | 28 | - id: mainfile 29 | type: File 30 | 31 | description: Text file to be indexed 32 | inputBinding: 33 | position: 1 34 | 35 | - id: term 36 | type: string 37 | 38 | description: Term for search 39 | inputBinding: 40 | position: 2 41 | 42 | outputs: 43 | [] 44 | -------------------------------------------------------------------------------- /test/test-data/search.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from __future__ import print_function 4 | import os 5 | import sys 6 | 7 | # to invoke own argparse from this directory (test-data) we must put it on the first place in sys.path 8 | argparse_dir = os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', '..')) 9 | sys.path.insert(0, argparse_dir) 10 | 11 | import argparse 12 | 13 | 14 | parser = argparse.ArgumentParser(description="Toy program to search inverted index and " 15 | "print out each line the term appears") 16 | 17 | parser.add_argument('mainfile', type=argparse.FileType('r'), help='Text file to be indexed') 18 | parser.add_argument('term', type=str, help='Term for search') 19 | 20 | args = parser.parse_args() 21 | 22 | mainfile = args.mainfile 23 | indexfile = mainfile.name + ".idx1" 24 | term = args.term 25 | 26 | main = mainfile 27 | index = open(indexfile) 28 | 29 | st = term + ": " 30 | 31 | for a in index: 32 | if a.startswith(st): 33 | n = [int(i) for i in a[len(st):].split(", ") if i] 34 | linenum = 0 35 | for l in main: 36 | linenum += 1 37 | if linenum in n: 38 | print(linenum, l.rstrip()) 39 | break 40 | 41 | -------------------------------------------------------------------------------- /test/test-data/search_new.cwl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env cwl-runner 2 | 3 | cwlVersion: "cwl:draft-3.dev2" 4 | 5 | class: CommandLineTool 6 | baseCommand: ["python"] 7 | 8 | requirements: 9 | - $import: envvar-global.cwl 10 | - $import: linux-sort-docker.cwl 11 | - class: InlineJavascriptRequirement 12 | 13 | description: | 14 | Toy program to search inverted index and print out each line the term appears 15 | 16 | inputs: 17 | 18 | 19 | - id: mainfile 20 | type: File 21 | inputBinding: 22 | position: 1 23 | 24 | - id: term 25 | type: string 26 | inputBinding: 27 | position: 2 28 | 29 | - id: search.py 30 | type: File 31 | default: 32 | class: File 33 | path: search.py 34 | inputBinding: 35 | position: 0 36 | 37 | 38 | outputs: 39 | [] -------------------------------------------------------------------------------- /test/test_arg2cwl.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | import shutil 4 | import unittest 5 | from itertools import chain 6 | from unittest import mock 7 | from io import StringIO 8 | 9 | import yaml 10 | 11 | import argparse 12 | from cmdline2cwl import Arg2CWLParser 13 | from argparse.argparse_cwl_translation import ArgparseCWLTranslation as ac 14 | from test.cwl_classes import Tool 15 | 16 | 17 | class GeneralTestCase(unittest.TestCase): 18 | maxDiff = None 19 | 20 | @staticmethod 21 | def prepare_argument_parser(name=None, add_help=True): 22 | parser = argparse.ArgumentParser(prog=name, description='test program', add_help=add_help) 23 | parser.add_argument('keyword', metavar='Q', type=str, nargs=1, 24 | help='action keyword') 25 | parser.add_argument('integers', metavar='N', type=int, nargs='+', 26 | help='an integer for \n' 27 | 'the accumulator') 28 | parser.add_argument('choices', type=int, choices=range(5, 10)) 29 | parser.add_argument('foo', type=str, 30 | help='positional argument with the same dest as optional argument') 31 | parser.add_argument('positional_nargs_asteriks', nargs='*', 32 | help='positional argument with nargs = *') 33 | parser.add_argument('positional_nargs_question_mark', nargs='?', 34 | help='positional argument with nargs = ?') 35 | parser.add_argument('positional_with_choices', choices=['rock', 'paper', 'scissors']) 36 | parser.add_argument('--req', required=True, help='required optional') 37 | parser.add_argument('--foo', nargs='?', help='foo help') 38 | parser.add_argument('--open', type=open, help='argument with type `open`') 39 | parser.add_argument('--file', nargs='?', help='foo help', type=argparse.FileType('w')) 40 | parser.add_argument('--bar', nargs='*', default=[1, 2, 3], help='BAR!') 41 | parser.add_argument('--true_p', action='store_true', help='Store a true') 42 | parser.add_argument('--false_p', action='store_false', help='Store a false') 43 | parser.add_argument('--append', action='append', help='Append a value') 44 | parser.add_argument('--str', dest='types', action='append_const', const=str, help='Append a value') 45 | parser.add_argument('--int', dest='types', action='append_const', const=int, help='Append a value') 46 | parser.add_argument('--output-file', help='Output file') 47 | 48 | parser.add_argument('--nargs2', nargs=2, help='nargs2') 49 | 50 | parser.add_argument('--mode', choices=['rock', 'paper', 'scissors'], default='scissors') 51 | 52 | parser.add_argument('--version', action='version', version='2.0') 53 | parser.set_defaults(foo='Lorem Ipsum') 54 | return parser 55 | 56 | 57 | def test_help_message(self): 58 | tool_parser = self.prepare_argument_parser(name='test_help_message') 59 | testargs = ["test.py", "--help_arg2cwl"] 60 | with mock.patch('sys.stdout', new=StringIO()) as fakeOutput, mock.patch.object(sys, 'argv', testargs): 61 | arg2cwl_parser = Arg2CWLParser().parser 62 | with self.assertRaises(SystemExit) as result: 63 | tool_parser.parse_args() 64 | self.assertEqual(result.exception.code, 0) 65 | help_message_actual = fakeOutput.getvalue().strip() 66 | # flushing stdout 67 | fakeOutput.truncate(0) 68 | fakeOutput.seek(0) 69 | arg2cwl_parser.print_help() 70 | help_message_desired = fakeOutput.getvalue().strip() 71 | self.assertEqual(help_message_actual, help_message_desired) 72 | 73 | def test_subparser(self): 74 | """ 75 | Tests if tools with subparsers run without errors 76 | """ 77 | parser = self.prepare_argument_parser(name="test_subparser") 78 | subparsers = parser.add_subparsers() 79 | subparser = subparsers.add_parser('sub', help='test subparser') 80 | subparser.add_argument('keyword', type=str) 81 | testargs = ["test.py", "sub", "--generate_cwl_tool"] 82 | with self.assertRaises(SystemExit) as result: 83 | with unittest.mock.patch.object(sys, 'argv', testargs): 84 | parser.parse_args() 85 | self.assertEqual(result.exception.code, 0) 86 | 87 | def test_output_directory_storage_for_CWL_tool(self): 88 | parser = self.prepare_argument_parser(name="test-directory.py") 89 | directory = os.path.dirname(__file__) 90 | new_dir = 'test/' 91 | os.mkdir(new_dir) 92 | testargs = ["test-directory.py", "--generate_cwl_tool", "-d", new_dir] 93 | with mock.patch.object(sys, 'argv', testargs): 94 | with self.assertRaises(SystemExit) as result: 95 | parser.parse_args() 96 | self.assertEqual(result.exception.code, 0) 97 | filepath = os.path.join(directory, new_dir, 'test-directory.cwl') 98 | self.assertTrue(os.path.isfile(filepath)) 99 | shutil.rmtree(new_dir) 100 | 101 | 102 | class CWLTestCase(unittest.TestCase): 103 | test_dir = "test_dir/" 104 | 105 | def setUp(self): 106 | if os.path.exists(self.test_dir): 107 | shutil.rmtree(self.test_dir) 108 | os.mkdir(self.test_dir) 109 | 110 | def tearDown(self): 111 | shutil.rmtree(self.test_dir) 112 | 113 | def get_simple_tool(self, parser_name, testargs=None, add_help=True): 114 | parser = GeneralTestCase.prepare_argument_parser(parser_name, add_help) 115 | if not testargs: 116 | testargs = [parser_name, "--generate_cwl_tool", "-d", self.test_dir] 117 | with mock.patch.object(sys, 'argv', testargs): 118 | with self.assertRaises(SystemExit) as result: 119 | parser.parse_args() 120 | self.assertEqual(result.exception.code, 0) 121 | return parser, Tool(self.test_dir + parser_name.replace('.py', '.cwl').strip('./')) 122 | 123 | @staticmethod 124 | def _strip_help_version_actions(actions): 125 | return filter(lambda action: type(action).__name__ not in ('_HelpAction', '_VersionAction'), actions) 126 | 127 | def test_position(self): 128 | parser_name = "test-position.py" 129 | parser, tool = self.get_simple_tool(parser_name) 130 | positional_count = 1 131 | for positional in parser._positionals._group_actions: 132 | self.assertEqual(positional_count, tool.inputs[positional.dest].input_binding.position) 133 | positional_count += 1 134 | for optional in self._strip_help_version_actions(parser._optionals._group_actions): 135 | self.assertRaises(AttributeError, tool.inputs[optional.dest].input_binding.position) 136 | self.assertIs(tool.inputs[optional.dest].input_binding.position, None) 137 | 138 | def test_shebang(self): 139 | parser_name = './test-shebang.py' 140 | parser, tool = self.get_simple_tool(parser_name) 141 | self.assertEqual([parser_name], tool.basecommand) 142 | 143 | def test_basecommand(self): 144 | """ 145 | if `basecommand` is provided in a program which is run with shebang, 146 | it replaces autogenerated shebang basecommand 147 | """ 148 | parser_name = './test-shebang.py' 149 | file_name = parser_name.strip('./') 150 | testargs = [parser_name, "--generate_cwl_tool", "-d", self.test_dir, "-b", "python3"] 151 | parser, tool = self.get_simple_tool(file_name, testargs) 152 | self.assertEqual(['python3'], tool.basecommand) 153 | self.assertEqual(file_name, tool.inputs[file_name].id) 154 | 155 | def test_default(self): 156 | parser, tool = self.get_simple_tool('test-default.py') 157 | for action in self._strip_help_version_actions(parser._actions): 158 | tool_default = tool.inputs[action.dest].default 159 | if action.default == 'null': 160 | action.default = None 161 | self.assertEqual(action.default, tool_default) 162 | 163 | def test_optional(self): 164 | parser, tool = self.get_simple_tool('test-optional.py') 165 | for action in self._strip_help_version_actions(parser._actions): 166 | if (action.option_strings and not action.required) or action.nargs in ('*', '?'): 167 | self.assertEqual('null', tool.inputs[action.dest].type[0]) 168 | else: 169 | self.assertNotIsInstance(tool.inputs[action.dest].type, list) 170 | 171 | def test_type(self): 172 | parser, tool = self.get_simple_tool('test-optional.py') 173 | for action in self._strip_help_version_actions(parser._actions): 174 | arg_type = tool.inputs[action.dest].type 175 | if type(arg_type) is list: # if argument is optional, the first type in list is `null` 176 | arg_type = arg_type[1] # the second is the actual type 177 | if action.choices: 178 | if type(action.choices) is range: 179 | self.assertEqual(list(action.choices), arg_type['symbols']) 180 | else: 181 | self.assertEqual(action.choices, arg_type['symbols']) 182 | self.assertEqual('enum', arg_type['type']) 183 | if action.type: 184 | if isinstance(action.type, argparse.FileType): 185 | action_type = 'File' 186 | else: 187 | action_type = ac.get_cwl_type(action.type) 188 | if (action.nargs and action.nargs != '?') \ 189 | or type(action).__name__.startswith("_Append"): 190 | self.assertEqual('array', arg_type['type']) 191 | self.assertEqual(action.items_type or 'string', arg_type['items']) 192 | elif action.choices: 193 | self.assertTrue(all(isinstance(x, action.type) for x in arg_type['symbols'])) 194 | else: 195 | self.assertEqual(action_type, arg_type) 196 | 197 | def test_output_replacement(self): 198 | """ 199 | `--output_section FILENAME` option 200 | """ 201 | output_section = \ 202 | {'outputs':[ 203 | {'id': 'outfile1', 204 | 'type': 'File', 205 | 'description': 'output file', 206 | 'outputBinding':{ 207 | 'glob': '$(inputs.outputPrefix+".vcf.gz")', 208 | } 209 | } 210 | ] 211 | } 212 | output_file = self.test_dir + 'example_output.cwl' 213 | with open(output_file, 'w') as f: 214 | yaml.dump(output_section, f) 215 | filename = 'test_output.py' 216 | testargs = [filename, "--generate_cwl_tool", "-d", self.test_dir, "-o", output_file] 217 | parser, tool = self.get_simple_tool(filename, testargs) 218 | output_0_name = output_section['outputs'][0]['id'] 219 | self.assertEqual(output_section['outputs'][0]['id'], tool.outputs[output_0_name].id) 220 | self.assertEqual(output_section['outputs'][0]['outputBinding']['glob'], 221 | tool.outputs[output_0_name].output_binding.glob) 222 | 223 | def test_outputs(self): 224 | parser_name = 'test-outputs.py' 225 | testargs = [parser_name, "--generate_cwl_tool", "-d", self.test_dir, "-go"] 226 | parser, tool = self.get_simple_tool(parser_name, testargs) 227 | for action in self._strip_help_version_actions(parser._actions): 228 | if 'output' in action.dest: 229 | self.assertTrue(tool.outputs[action.dest+'_out'].id) 230 | 231 | def test_parents(self): 232 | mum, mum_tool = self.get_simple_tool('mum.py', add_help=False) 233 | dad = argparse.ArgumentParser(prog='daddy.py', description='test program', add_help=False) 234 | dad.add_argument('pos_arg', type=int) 235 | dad.add_argument('--opt_arg', action='store_true') 236 | kid_name = 'kid.py' 237 | kid = argparse.ArgumentParser(prog=kid_name, parents=[mum, dad]) 238 | kid.add_argument('--kids_argument', nargs='*') 239 | testargs = [kid_name, "--generate_cwl_tool", "-d", self.test_dir] 240 | with mock.patch.object(sys, 'argv', testargs): 241 | with self.assertRaises(SystemExit) as result: 242 | kid.parse_args() 243 | self.assertEqual(result.exception.code, 0) 244 | tool = Tool(self.test_dir + kid_name.replace('.py', '.cwl').strip('./')) 245 | actions = list(chain(self._strip_help_version_actions(mum._actions), 246 | self._strip_help_version_actions(dad._actions))) 247 | arguments = [arg.dest for arg in actions] 248 | arguments.append('kids_argument') 249 | for arg in arguments: 250 | self.assertIn(arg, tool.inputs.keys()) 251 | 252 | def test_prefixes(self): 253 | parser_name = 'test-prefix-chars.py' 254 | parser = argparse.ArgumentParser(prog=parser_name, 255 | prefix_chars='-+', 256 | description='test prefix chars program') 257 | parser.add_argument('keyword', type=str, nargs=1, 258 | help='action keyword') 259 | parser.add_argument('integers', metavar='N', type=int, nargs='+', 260 | help='an integer for \n' 261 | 'the accumulator') 262 | parser.add_argument('choices', type=int, choices=range(5, 10)) 263 | parser.add_argument('foo', type=str, 264 | help='positional argument with the same dest as optional argument') 265 | parser.add_argument('--req', required=True, help='required optional') 266 | parser.add_argument('++foo', nargs='?', help='foo help') 267 | parser.add_argument('+open', type=open, help='argument with type `open`') 268 | parser.add_argument('-file', nargs='?', help='foo help', type=argparse.FileType('w')) 269 | parser.add_argument('--bar', nargs='*', default=[1, 2, 3], help='BAR!') 270 | testargs = [parser_name, "--generate_cwl_tool", "-d", self.test_dir] 271 | with mock.patch.object(sys, 'argv', testargs): 272 | with self.assertRaises(SystemExit) as result: 273 | parser.parse_args() 274 | self.assertEqual(result.exception.code, 0) 275 | tool = Tool(self.test_dir + parser_name.replace('.py', '.cwl').strip('./')) 276 | for optional in self._strip_help_version_actions(parser._optionals._group_actions): 277 | self.assertEqual(tool.inputs[optional.dest].input_binding.prefix, optional.option_strings[0]) 278 | 279 | def test_type_conversions(self): 280 | self.assertEqual(ac.get_cwl_type(open), 'File') 281 | self.assertEqual(ac.get_cwl_type(argparse.FileType('r')), 'File') 282 | self.assertEqual(ac.get_cwl_type(str), 'string') 283 | self.assertEqual(ac.get_cwl_type('str'), 'string') 284 | 285 | 286 | if __name__ == '__main__': 287 | unittest.main() -------------------------------------------------------------------------------- /test/test_click2cwl.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import sys 4 | import unittest 5 | from unittest import mock 6 | 7 | import click 8 | from test.cwl_classes import Tool 9 | 10 | 11 | class CWLTestCase(unittest.TestCase): 12 | maxDiff = None 13 | test_dir = "test_dir/" 14 | 15 | 16 | def setUp(self): 17 | if os.path.exists(self.test_dir): 18 | shutil.rmtree(self.test_dir) 19 | os.mkdir(self.test_dir) 20 | 21 | def tearDown(self): 22 | shutil.rmtree(self.test_dir) 23 | 24 | def standard_testargs(self, parser_name): 25 | return [parser_name, "--generate_cwl_tool", "-d", self.test_dir] 26 | 27 | def open_tool(self, parser_name): 28 | return Tool(self.test_dir + parser_name.replace('.py', '.cwl').strip('./')) 29 | 30 | def generate_and_open_test_tool(self, testargs, function, parser_name): 31 | with mock.patch.object(sys, 'argv', testargs): 32 | function() 33 | return self.open_tool(parser_name) 34 | 35 | @staticmethod 36 | def prepare_argument_parser(): 37 | @click.command() 38 | @click.argument('keyword', type=click.STRING) 39 | @click.option('--choices', type=click.Choice(['md5', 'sha1'])) 40 | @click.option('--double-type', type=(str, int), default=(None, None)) 41 | def function(): 42 | pass 43 | 44 | return function 45 | 46 | def get_simple_tool(self, parser_name, testargs=None, add_help=True): 47 | parser = self.prepare_argument_parser() 48 | if not testargs: 49 | testargs = self.standard_testargs(parser_name) 50 | return parser, self.generate_and_open_test_tool(testargs, parser, parser_name) 51 | 52 | def test_subparser(self): 53 | """ 54 | Tests if tools with subparsers run without errors 55 | """ 56 | @click.group() 57 | @click.pass_context 58 | @click.option('--debug', default=False) 59 | def cli(debug): 60 | pass 61 | 62 | @cli.command() 63 | @click.option('-s', '--some-option') 64 | def sync(some_option): 65 | pass 66 | 67 | @cli.command() 68 | @click.option('-o', '--some-other-option') 69 | def async(some_option): 70 | pass 71 | 72 | parser_name = 'test-group.py' 73 | with mock.patch.object(sys, 'argv', self.standard_testargs(parser_name)): 74 | cli() 75 | sync_tool = self.open_tool('test-group-sync.cwl') 76 | async_tool = self.open_tool('test-group-async.cwl') 77 | self.assertEqual(sync_tool.inputs['some_option'].input_binding.prefix, '--some-option') 78 | self.assertEqual(async_tool.inputs['some_other_option'].input_binding.prefix, '--some-other-option') 79 | 80 | def test_basecommand(self): 81 | """ 82 | if `basecommand` is provided in a program which is run with shebang, 83 | it replaces autogenerated shebang basecommand 84 | """ 85 | parser_name = './test-shebang.py' 86 | file_name = parser_name.strip('./') 87 | testargs = [parser_name, "--generate_cwl_tool", "-d", self.test_dir, "-b", "python3"] 88 | parser, tool = self.get_simple_tool(file_name, testargs) 89 | self.assertEqual(['python3'], tool.basecommand) 90 | self.assertEqual(file_name, tool.inputs[file_name].id) 91 | 92 | def test_choices(self): 93 | choices = ['rock', 'scissors', 'paper'] 94 | 95 | @click.command() 96 | @click.option('--item', type=click.Choice(choices)) 97 | def function(item): 98 | pass 99 | 100 | parser_name = 'test-choices.py' 101 | tool = self.generate_and_open_test_tool(self.standard_testargs(parser_name), function, parser_name) 102 | self.assertEqual(tool.inputs['item'].type[1]['symbols'], choices) 103 | 104 | def test_tuples(self): 105 | @click.command() 106 | @click.option('--item', type=(str, int), default=(None, None)) 107 | def function(item): 108 | pass 109 | 110 | parser_name = 'test-type.py' 111 | tool = self.generate_and_open_test_tool(self.standard_testargs(parser_name), function, parser_name) 112 | self.assertEqual(tool.inputs['item'].type, ['null', 'string', 'int']) 113 | 114 | def test_flags(self): 115 | @click.command() 116 | @click.option('--shout/--no-shout', default=False) 117 | @click.option('--simple-shout', is_flag=True) 118 | def function(shout): 119 | pass 120 | 121 | parser_name = 'test-flags.py' 122 | tool = self.generate_and_open_test_tool(self.standard_testargs(parser_name), function, parser_name) 123 | self.assertEqual(tool.inputs['shout'].type, ['null', 'boolean']) 124 | self.assertEqual(tool.inputs['simple_shout'].type, ['null', 'boolean']) 125 | self.assertEqual(tool.inputs['shout'].default, False) 126 | self.assertEqual(tool.inputs['simple_shout'].default, False) 127 | 128 | def test_prefix_chars(self): 129 | @click.command() 130 | @click.option('+w/-w') 131 | def function(w): 132 | pass 133 | 134 | parser_name = 'test-prefix-chars.py' 135 | tool = self.generate_and_open_test_tool(self.standard_testargs(parser_name), function, parser_name) 136 | self.assertEqual(tool.inputs['w'].type, ['null', 'boolean']) 137 | 138 | def test_docstring(self): 139 | @click.command() 140 | @click.argument('argument') 141 | def function(w): 142 | """This script prints hello NAME COUNT times.""" 143 | pass 144 | 145 | parser_name = 'test-docstring.py' 146 | tool = self.generate_and_open_test_tool(self.standard_testargs(parser_name), function, parser_name) 147 | self.assertEqual(tool.description.strip('\n'), function.__doc__) 148 | 149 | if __name__ == '__main__': 150 | unittest.main() -------------------------------------------------------------------------------- /test/test_utils.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from builtins import str 3 | from builtins import range 4 | import sys 5 | import itertools 6 | import hashlib 7 | import copy 8 | 9 | if sys.version_info < (2, 7): 10 | from unittest2 import TestCase 11 | else: 12 | from unittest import TestCase 13 | 14 | 15 | class GeneralTests(TestCase): 16 | 17 | def test_load(self): 18 | gxap = sys.modules['gxargparse'] 19 | ap = sys.modules['argparse'] 20 | # Ensure we've loaded the correct argparse ;) 21 | self.assertTrue('gxargparse/argparse' in str(ap)) 22 | self.assertTrue('gxargparse/gxargparse' in str(gxap)) 23 | 24 | import argparse as fake_ap 25 | # Do we have a ref to the real ap 26 | self.assertTrue('ap' in dir(fake_ap)) 27 | # Is it the real argparse? 28 | self.assertTrue('_os' in dir(fake_ap.ap)) 29 | 30 | def __gen_id(self, kwargs): 31 | key = "" 32 | for x in sorted(kwargs.keys()): 33 | key += str(kwargs[x]) 34 | digest = hashlib.sha1(key).hexdigest() 35 | repl = 'qrstuvwxyz' 36 | for c in range(10): 37 | digest = digest.replace(str(c), repl[c]) 38 | return digest 39 | 40 | def dict_product(self, odl, key_name, new_key_list): 41 | for x in new_key_list: 42 | if x is None: 43 | for od in odl: 44 | yield od 45 | else: 46 | for od in odl: 47 | od2 = copy.deepcopy(od) 48 | od2[key_name] = x 49 | yield od2 50 | 51 | def test_dict_product(self): 52 | a = [{'a': 0}, {'a': 1}] 53 | correct = [ 54 | {'a': 0}, 55 | {'a': 1}, 56 | {'a': 0, 'b': 1}, 57 | {'a': 1, 'b': 1}, 58 | ] 59 | 60 | results = list(self.dict_product(a, 'b', [None, 1])) 61 | self.assertCountEqual(correct, results) 62 | 63 | def __blacklist(self, item_list): 64 | for i in item_list: 65 | try: 66 | if i['action'] in ('store_true', 'store_false', 'count', 'version', 'help'): 67 | if 'type' not in i and 'nargs' not in i: 68 | yield i 69 | else: 70 | yield i 71 | except Exception: 72 | yield i 73 | 74 | def arg_gen(self): 75 | import argparse 76 | prefixes = ['--'] 77 | types = [None, str, int, float, argparse.FileType('w'), argparse.FileType('r')] 78 | nargs = [None, 1, 2, '+', '*', '?'] 79 | actions = [None, 'store', 'store_true', 'store_false', 80 | 'append', 'count', 'version', 'help'] 81 | 82 | a0 = list(self.dict_product([{}], 'type', types)) 83 | a1 = list(self.dict_product(a0, 'nargs', nargs)) 84 | a2 = list(self.dict_product(a1, 'action', actions)) 85 | a3 = list(self.dict_product(a2, 'prefix', prefixes)) 86 | 87 | for x in self.__blacklist(a3): 88 | prefix = x['prefix'] 89 | id = self.__gen_id(x) 90 | del x['prefix'] 91 | yield {'args': prefix + id, 92 | 'kwargs': x} 93 | 94 | 95 | def parse_args(self, args, **setup): 96 | import argparse 97 | parser = argparse.ArgumentParser(**setup) 98 | 99 | for arg in self.arg_gen(): 100 | print(arg) 101 | parser.add_argument(arg['args'], **arg['kwargs']) 102 | return parser.parse_args(args) 103 | 104 | 105 | class SimpleTests(TestCase): 106 | pass 107 | --------------------------------------------------------------------------------