|
import inspect
|
|
from argparse import ArgumentParser
|
|
|
|
|
|
def get_main(function):
|
|
"""Create a main function for a command.
|
|
|
|
The main function will be callable using the command-line arguments:
|
|
`main('--flag', '--option=option')`
|
|
|
|
The command will be called according to its argspec using available args.
|
|
"""
|
|
parser = get_parser(function)
|
|
|
|
def main(*args: str):
|
|
namespace = parser.parse_args(args if args else None)
|
|
return call(function, namespace)
|
|
|
|
return main
|
|
|
|
|
|
def get_parser(function):
|
|
"""Create a parser for a function.
|
|
|
|
The parser description will use the function docstring.
|
|
|
|
Example:
|
|
|
|
.. code: python
|
|
|
|
from argparse_decorators import add_argument, get_parser
|
|
|
|
@add_argument("argument")
|
|
def command(argument)
|
|
...
|
|
|
|
parser = get_parser(command)
|
|
|
|
It's same as:
|
|
|
|
.. code: python
|
|
|
|
import argparse
|
|
|
|
from argparse_decorators import add_argument, get_parser
|
|
|
|
def command(argument)
|
|
...
|
|
|
|
parser = argparse.ArgumentParser(description=command.__doc__)
|
|
parser.add_argument("argument")
|
|
|
|
|
|
The parser will be configured according to __argparse_annotations__.
|
|
"""
|
|
parser = ArgumentParser(description=function.__doc__)
|
|
configure_parser(parser, function)
|
|
return parser
|
|
|
|
|
|
def configure_parser(parser, command):
|
|
"""Configure a parser from a decorated function."""
|
|
annotations = getattr(command, "__argparse_annotations__", [])
|
|
for args, kwargs in annotations:
|
|
parser.add_argument(*args, **kwargs)
|
|
|
|
|
|
def call(function, args):
|
|
"""Call a function according to its argspec using available cli args.
|
|
|
|
Example:
|
|
|
|
.. code: python
|
|
|
|
import argparse
|
|
|
|
from argparse_decorators import add_argument, call
|
|
|
|
|
|
@add_argument("argument")
|
|
def command(argument)
|
|
assert argument == "value"
|
|
|
|
|
|
call(command, argparse.Namespace(argument="value"))
|
|
|
|
The parser will be configured according to __argparse_annotations__.
|
|
"""
|
|
argspec = inspect.getargspec(function)
|
|
call_args = {arg: getattr(args, arg) for arg in argspec.args}
|
|
return function(**call_args)
|
|
|
|
|
|
def add_argument(*args, **kwargs):
|
|
"""Build a decorator that will add argparse annotations to a function."""
|
|
return lambda decorated: _add_annotation(decorated, (args, kwargs))
|
|
|
|
|
|
def _add_annotation(function, argument):
|
|
"""Add argparse annotations to a function."""
|
|
annotations = getattr(function, "__argparse_annotations__", [])
|
|
annotations.append(argument)
|
|
setattr(function, "__argparse_annotations__", annotations)
|
|
return function
|