In [1]:
from imp import reload
import autoargs; reload(autoargs);

argparse made easy!


In [2]:
# pass your function and args from your sys.argv, and you're off to the races!
def myprint(arg1, arg2):
    print("arg1:", arg1)
    print("arg2:", arg2)
autoargs.autocall(myprint, ["first", "second"])


arg1: first
arg2: second

In [3]:
# if you want your arguments to be types, use any function that expects a string
#  and returns the type you want in your arg annotation
def str_repeat(s: str, n: int):
    print((s * n).strip())
autoargs.autocall(str_repeat, ["args are easy!\n", "3"])
# if your args value is a string, it gets split using shlex
autoargs.autocall(str_repeat, "'still easy!\n' 3")


args are easy!
args are easy!
args are easy!
still easy!
still easy!
still easy!

In [4]:
import functools
import operator
# varargs are supported too!
def product(*args: float):
    return functools.reduce(operator.mul, args, 1.0)
print(autoargs.autocall(product, ["5", "10", "0.5"]))

def join(delimiter, *args):
    return delimiter.join(args)
print(autoargs.autocall(join, [", ", "pretty easy", "right?"]))


25.0
pretty easy, right?

In [5]:
def aggregate(*args: float, op: {'sum', 'mul'}):
    if op == "sum":
        return sum(args)
    elif op == "mul":
        return product(*args)
autoargs.autocall(aggregate, ["--help"])


usage: aggregate [-h] --op {sum,mul} [args [args ...]]

positional arguments:
  args            float

optional arguments:
  -h, --help      show this help message and exit
  --op {sum,mul}
An exception has occurred, use %tb to see the full traceback.

SystemExit: 0
To exit: use 'exit', 'quit', or Ctrl-D.

In [6]:
# kwargs are supported using command-line syntax
def land_of_defaults(a="default-a", argb="b default"):
    print(a, argb)
autoargs.autocall(land_of_defaults, []) # => "" (no args in call)
autoargs.autocall(land_of_defaults, ['-aOverride!']) # => "-aOverride!"
autoargs.autocall(land_of_defaults, ['-a', 'Override!']) # => "-a Override!"
autoargs.autocall(land_of_defaults, ['--argb', 'Override!']) # => "--argb Override!"
# warning! if an argument has a default, it can only be given via this kwarg syntax


default-a b default
Override! b default
Override! b default
default-a Override!

In [7]:
# if you want to require a kwarg, use a kwonly-arg
def required_arg(normal, default="boring", *, required):
    print(normal, default, required)
autoargs.autocall(required_arg, ["normal", "--required", "val"])
autoargs.autocall(required_arg, ["normal"])


normal boring val
usage: required_arg [-h] [--default DEFAULT] --required REQUIRED normal
required_arg: error: the following arguments are required: --required
An exception has occurred, use %tb to see the full traceback.

SystemExit: 2
To exit: use 'exit', 'quit', or Ctrl-D.

Invalid Arg Handling

Speaking of errors, invalid arguments are caught by the parser. This means that you get CLI-like error messages, like the user would be expecting if this were a CLI interface.


In [7]:
def oops(arg: int):
    return "%s is an integer!" % arg
autoargs.autocall(oops, [])


usage: oops [-h] arg
oops: error: the following arguments are required: arg
An exception has occurred, use %tb to see the full traceback.

SystemExit: 2
To exit: use 'exit', 'quit', or Ctrl-D.

In [8]:
autoargs.autocall(oops, ["spam"])


usage: oops [-h] arg
oops: error: argument arg: invalid int value: 'spam'
An exception has occurred, use %tb to see the full traceback.

SystemExit: 2
To exit: use 'exit', 'quit', or Ctrl-D.

In [9]:
autoargs.autocall(oops, ["20", "spam"])


usage: oops [-h] arg
oops: error: unrecognized arguments: spam
An exception has occurred, use %tb to see the full traceback.

SystemExit: 2
To exit: use 'exit', 'quit', or Ctrl-D.

parser


In [10]:
# if you want access to the parser, go right ahead!
parser = autoargs.autoparser(myprint)
parser


Out[10]:
ArgumentParser(prog='myprint', usage=None, description=None, formatter_class=<class 'argparse.HelpFormatter'>, conflict_handler='error', add_help=True)

In [11]:
parsed = parser.parse_args(["first", "second"])
parsed


Out[11]:
Namespace(arg1='first', arg2='second')

In [12]:
vars(parsed)


Out[12]:
{'arg1': 'first', 'arg2': 'second'}

todo:

  • parsing a whole module/object (fns become subparsers)
  • using autoargs to call other module's fns from command line
  • setup.py
  • add to pypi
  • proper docs
  • all of the above with appropriate testing

stay tuned for these and (potentially) other ideas! feel free to add issues