Skip to content

Instantly share code, notes, and snippets.

@jeffryang24
Forked from mivade/cli.py
Created July 21, 2018 04:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeffryang24/2dd53de153f05835d92278eb1c2e3a10 to your computer and use it in GitHub Desktop.
Save jeffryang24/2dd53de153f05835d92278eb1c2e3a10 to your computer and use it in GitHub Desktop.
Using a decorator to simplify subcommand creation with argparse
from argparse import ArgumentParser
cli = ArgumentParser()
subparsers = cli.add_subparsers(dest="subcommand")
def argument(*name_or_flags, **kwargs):
"""Convenience function to properly format arguments to pass to the
subcommand decorator.
"""
return ([*name_or_flags], kwargs)
def subcommand(args=[], parent=subparsers):
"""Decorator to define a new subcommand in a sanity-preserving way.
The function will be stored in the ``func`` variable when the parser
parses arguments so that it can be called directly like so::
args = cli.parse_args()
args.func(args)
Usage example::
@subcommand([argument("-d", help="Enable debug mode", action="store_true")])
def subcommand(args):
print(args)
Then on the command line::
$ python cli.py subcommand -d
"""
def decorator(func):
parser = parent.add_parser(func.__name__, description=func.__doc__)
for arg in args:
parser.add_argument(*arg[0], **arg[1])
parser.set_defaults(func=func)
return decorator
@subcommand()
def nothing(args):
print("Nothing special!")
@subcommand([argument("-d", help="Debug mode", action="store_true")])
def test(args):
print(args)
@subcommand([argument("-f", "--filename", help="A thing with a filename")])
def filename(args):
print(args.filename)
@subcommand([argument("name", help="Name")])
def name(args):
print(args.name)
if __name__ == "__main__":
args = cli.parse_args()
if args.subcommand is None:
cli.print_help()
else:
args.func(args)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment