Skip to main content

argparse-deco - Syntactic sugar for argparse

Project description

argparse-deco is basically syntatic sugar for argparse using decorators. Although it inherited some ideas and concepts from Kevin L. Mitchell’s cli_tools (https://github.com/klmitch/cli_tools), it does not share its source code.

Its main difference is the possibility to abuse Python’s class syntax to define complex CLI tools with nested subcommands and the use of inspect.signature to autogenerate a command’s arguments from a function’s signature.

Simple CLI

The API suffices to use three imports.

>>> from argparse_deco import CLI, Arg, Flag

An an example for a simple CLI, one may use CLI as decorator for a function in order to transform it:

>>> @CLI(prog="prog")
... def prog(
...         integers: Arg(metavar='N', nargs='+', type=int,
...                       help="an integerfor the accumulator"),
...         accumulate: Arg('--sum', action='store_const', const=sum,
...                         help="sum the integers (default: find the max)"
...                         )=max):
...     """Process some integers."""
...     print(accumulate(integers))

The decorator CLI transforms the function prog into an Command instance. Effectively prog takes some command line argument like [ “1”, “2”, “4”, “–sum” ] as cli_args keyword, which is transformed by the argparse module into arguments integer and accumulate passed down to the original function prog:

>>> prog(["1", "2", "4", "--sum"])
7
>>> prog(["1", "2", "4"])
4

In order to obtain the ArgumentParser instance, prog has the class method setup_parser:

>>> parser = prog.setup_parser()
>>> print(parser)
ArgumentParser(prog='prog', usage=None, description='Process some integers.', formatter_class=<class 'argparse.HelpFormatter'>, conflict_handler='error', add_help=True)
>>> parser.print_usage()
usage: prog [-h] [--sum] N [N ...]
>>> parser.print_help()
usage: prog [-h] [--sum] N [N ...]
<BLANKLINE>
Process some integers.
<BLANKLINE>
positional arguments:
  N           an integerfor the accumulator
<BLANKLINE>
optional arguments:
  -h, --help  show this help message and exit
  --sum       sum the integers (default: find the max)

Arguments

In order for a function’s arguments to be processed as ArgumentParser argument, they have to annotated by Arg. Basically Arg allows a the type as keyword, and arbitrary keyword arguments which are passed almost unchanged to ArgumentParser.add_argument.

Parser

While the ArgumentParser instance’s description is usually the function’s docstring, one may want to further customise it using the CLI.parser decorator which accepts any argument ArgumentParser would.

Groups

Arguments can be groupsed by using the Group instead of Arg in the argument’s annotation, which accepts a group name as first keyword and the type as second one. The group can be customised (title, description) using the CLI.group decorator:

>>> @CLI("prog")
... @CLI.group('foo', title="Foo", description="Foo group")
... def prog(
...         bar: Arg['foo'](help="Bar option"),
...         baz: Arg['foo'](help="Baz option")):
...     pass
>>> prog.setup_parser().print_help()
usage: prog [-h] bar baz
<BLANKLINE>
optional arguments:
  -h, --help  show this help message and exit
<BLANKLINE>
Foo:
  Foo group
<BLANKLINE>
  bar         Bar option
  baz         Baz option

Similarily using the CLI.mutually_exclusive decorator, arguments can be turned into a mutually exclusive group.

Subcommands

>>> @CLI("prog")
... @CLI.subparsers(help="sub-command help")
... class prog:
...     def __call__(foo: Flag('--foo', help="foo help")):
...         pass
...     def a(bar: Arg(type=int, help="bar help")):
...         """a help"""
...     def b(baz: Arg('--baz', choices='XYZ', help="baz help")):
...         """b help"""
>>> prog.parser.print_help()
usage: prog [-h] [--foo] {a,b} ...
<BLANKLINE>
positional arguments:
  {a,b}       sub-command help
    a         a help
    b         b help
<BLANKLINE>
optional arguments:
  -h, --help  show this help message and exit
  --foo       foo help
>>> prog.parser.parse_args(['a', '12'])
Namespace(_func=<function prog.a at 0x...>, _parser=..., bar=12, foo=False)
>>> prog.parser.parse_args(['--foo', 'b', '--baz', 'Z'])
Namespace(_func=<function prog.b at 0x...>, _parser=..., baz='Z', foo=True)

Deeper levels of subcommands can be generated using class definitions within:

>>> @CLI("prog")
... class prog:
...     class foo:
...         """foo subcommand"""
...         def bar():
...             """foo bar subsubcommand"""
...         def baz():
...             """foo baz subsubcommand"""
...     class oof:
...         def rab():
...             """oof rab subsubcommand"""
...         def zab():
...             """oof zab subsubcommand"""
>>> prog.parser.print_help()
usage: prog [-h] {foo,oof} ...
<BLANKLINE>
positional arguments:
  {foo,oof}
    foo       foo subcommand
<BLANKLINE>
optional arguments:
  -h, --help  show this help message and exit

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

argparse-deco-0.5.1.tar.gz (8.4 kB view hashes)

Uploaded Source

Built Distribution

argparse_deco-0.5.1-py2.py3-none-any.whl (10.8 kB view hashes)

Uploaded Python 2 Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page