Hello Ted,
> Can I just convert func(args) to func(*args) and be done with it?
I'm afraid, no. Below I'll try to explain what *args is and what to do.
The "natural" notation:
def func(*xs):
pass
The decorator-based notation:
@arg('xs', nargs='*')
def func(xs):
pass
The CLI signature:
func [xs [xs ...]]
As you see, the `args` in `func(*args)` is a single argument that
accepts 0..n values (aka nargs='*').
Using a "catch-all" object (like an argparse.Namespace instance named
"args" or anything of the sort) is not pythonic in any way.
Still, there are valid cases when such objects are preferable and even
more DRY (e.g. when the whole function signature is duplicated with
@arg decorators). Here are two valid options:
@arg('foo')
@expects_obj
def func(ns): # "ns", "args" or whatever
print ns.foo
@arg('foo')
def func(**kwargs):
print kwargs['foo']
Adding the `@expects_obj` decorator is enough for the old-style
function to survive the update. If you have a set of old-style
commands, it may be a good idea to wrap them before assembling instead
of decorating:
old_commands = [foo, bar, baz, quux]
parser.add_commands([expects_obj(c) for c in old_commands])
This way the declarations can be left completely intact.
However, I would really consider switching to the more pythonic
syntax. Most @arg decorators only add help messages (because other
stuff is usually correctly inferred by Argh from the function
signature). If the argument names are well-thought and the whole CLI
is well-structured, there's little need it additional help.
Cheers,
Andy