Create an argparse.ArgumentParser from function docstrings¶
docs |
|
---|---|
tests |
|
package |
Welcome! Additionally to the default behaviour of the
argparse.ArgumentParser
, the funcargparse.FuncArgParser
allows you to
automatically create a parser entirely from the docstring of a function, including the help, metavar, action, type and other parameters
Let’s you chain subparsers
There are a lot of argparse extensions out there, but through the use of the docrep package, this package can extract much more information to automate the creation of the command line utility.
See Getting started for more information.
Content¶
Getting started¶
Motivation¶
Suppose we want a simple script that adds or multiplies two numbers. This code should then be
callable inside python (i.e. we create a function)
executable from the command line
So let’s setup the function in a file called 'add_or_multiply.py'
like this
In [1]: def do_something(a, b, multiply=False):
...: """
...: Multiply or add one number to the others
...:
...: Parameters
...: ----------
...: a: int
...: Number 1
...: b: list of int
...: A list of numbers to add `a` to
...: multiply: bool
...: If True, the numbers are multiplied, not added
...: """
...: if multiply:
...: result = [n * a for n in b]
...: else:
...: result = [n + a for n in b]
...: print(result)
...:
Now, if you want to make a command line script out of it, the usual methodology
is to create an argparse.ArgumentParser
instance and parse the
arguments like this
In [2]: if __name__ == '__main__':
...: from argparse import ArgumentParser
...: parser = ArgumentParser(
...: description='Multiply or add two numbers')
...: parser.add_argument('a', type=int, help='Number 1')
...: parser.add_argument('b', type=int, nargs='+',
...: help='A list of numbers to add `a` to')
...: parser.add_argument('-m', '--multiply', action='store_true',
...: help='Multiply the numbers instead of adding them')
...: args = parser.parse_args('3 2 -m'.split())
...: do_something(**vars(args))
...:
Now, if you parse the arguments, you get
In [3]: parser.print_help()
usage: sphinx-build [-h] [-m] a b [b ...]
Multiply or add two numbers
positional arguments:
a Number 1
b A list of numbers to add `a` to
optional arguments:
-h, --help show this help message and exit
-m, --multiply Multiply the numbers instead of adding them
However, you could skip the entire lines above, if you just use the
funcargparse.FuncArgParser
In [4]: from funcargparse import FuncArgParser
In [5]: parser = FuncArgParser()
In [6]: parser.setup_args(do_something)
Out[6]: <function __main__.do_something(a, b, multiply=False)>
In [7]: parser.update_short(multiply='m')
In [8]: actions = parser.create_arguments()
In [9]: parser.print_help()
usage: sphinx-build [-h] [-m] int int [int ...]
Multiply or add one number to the others
positional arguments:
int Number 1
int A list of numbers to add `a` to
optional arguments:
-h, --help show this help message and exit
-m, --multiply If True, the numbers are multiplied, not added
or you use the parser right in the beginning as a decorator
In [10]: @parser.update_shortf(multiply='m')
....: @parser.setup_args
....: def do_something(a, b, multiply=False):
....: """
....: Multiply or add one number to the others
....:
....: Parameters
....: ----------
....: a: int
....: Number 1
....: b: list of int
....: A list of numbers to add `a` to
....: multiply: bool
....: If True, the numbers are multiplied, not added
....: """
....: if multiply:
....: result = [n * a for n in b]
....: else:
....: result = [n + a for n in b]
....: print(result)
....:
In [11]: actions = parser.create_arguments()
In [12]: parser.print_help()
usage: sphinx-build [-h] [-m] int int [int ...]
Multiply or add one number to the others
positional arguments:
int Number 1
int A list of numbers to add `a` to
optional arguments:
-h, --help show this help message and exit
-m, --multiply If True, the numbers are multiplied, not added
The FuncArgParser
interpretes the docstring
(see Interpretation guidelines for docstrings) and sets up the arguments.
Your '__main__'
part could then simply look like
In [13]: if __name__ == '__main__':
....: parser.parse_to_func()
....:
Usage¶
Generally the usage is
create an instance of the
FuncArgParser
classsetup the arguments using the
setup_args()
functionmodify the arguments (optional) either
in the
FuncArgParser.unfinished_arguments
dictionaryusing the
update_arg()
,update_short()
,update_long()
orappend2help()
methodsusing the equivalent decorator methods
update_argf()
,update_shortf()
,update_longf()
orappend2helpf()
create the arguments using the
create_arguments()
method
Subparsers¶
You can also use subparsers for controlling you program (see the
argparse.ArgumentParser.add_subparsers()
method). They can either be
implemented the classical way via
In [14]: subparsers = parser.add_subparsers()
In [15]: subparser = subparsers.add_parser('test')
And then as with the parent parser you can use function docstrings.
In [16]: @subparser.setup_args
....: def my_other_func(b=1):
....: """
....: Subparser summary
....:
....: Parameters
....: ----------
....: b: int
....: Anything"""
....: print(b * 500)
....:
In [17]: subparser.create_arguments()
Out[17]: [_StoreAction(option_strings=['-b'], dest='b', nargs=None, const=None, default=1, type=<class 'int'>, choices=None, help='Anything', metavar='int')]
In [18]: parser.print_help()