-
Notifications
You must be signed in to change notification settings - Fork 1
API reference
A decorator to add command line parsing functionality to the function. The
returned function is the same as the original one, but with the execute
function added to it. Usage example:
@command
def main(arg1, *, flag1=False):
# Do stuff
Arguments are added according to the parameters of the wrapped function:
-
Positional parameters, which are any parameter before
*
or*args
in the argument list, are interpreted as positional arguments in the parser. These arguments can be required if the default values are omitted (def func(arg)
), or optional if a default value is provided (def func(arg=None)
). -
Variadic parameters, which are parameters in the form
*args
, are interpreted as a list argument which will take all the remaining position arguments when parsing from command line. A special case is when the argument is named_REMAINDER_
, or ifArgument(remainder=True)
is specified. In which case, this argument will be a sequence capturing all remaining arguments, including optional ones (e.g.--foo
). -
Keyword parameters, which are any parameter after
*
or*args
in the argument list, are interpreted as optional arguments, or sometimes known as flags. By default the argument name is taken as the flag name, with any trailing underscores (_
) stripped out. For example, if the parameter name isfoo
, the flag name is--foo
.The action of the flag varies by the type of the default value. If the default value is
False
, the action will beargparse
'sstore_true
, which means the parameter's value will beTrue
if--foo
is specified, orFalse
otherwise. Similarly, if the default value isTrue
, the parameter value will beTrue
unless--nofoo
is specified. If the default value is not a bool, optional argument value will be assigned to the parameter. For example,--foo bar
will set the value offoo
tobar
.
@command(*extensions,
prog=None, formatter_class=None, allow_abbrev=True,
return_value_processor=None, exception_handler=None)
-
prog
- The program name as a string. This is used in the usage and help messages. -
formatter_class
- Formatter for the help message, which controls behaviors like dedenting and string wrapping. Seeargparse
for details. -
allow-abbrev
- (Python 3.5 or above only) Allows long options to be abbreviated if the abbreviation is unambiguous. Default isTrue
. When this isTrue
, the parser will perform a prefix match on flags, and if there is only one match it will be treated as the flag. For example, in the functiondef main(*, foo, bar, baz)
,--f
will match--foo
, whereas--ba
will raise an exception.
-
return_value_processor
- A callable that takes the return value of the decorated function and processes it. When this isNone
, the default implementation is used, which is toprint()
the result to stdout.
def _default_return_value_processor(val):
if val is not None:
print(val)
-
exception_handler
- A callable that takes the exception raised by the decorated function and processes it. This method should re-raise any exceptions it does not handle. When this isNone
, the default implementation is used, which is to handlesubprocess.CalledProcessError
,NoMatchingDelegate
, andKeyboardInterrupt
to print the error messages instead of printing the entire stack trace.
def _default_exception_handler(exception):
try:
raise exception
except (subprocess.CalledProcessError, RuntimeError) as e:
print('Error:', str(e), file=sys.stderr)
except NoMatchingDelegate as e:
print(str(e), file=sys.stderr)
except KeyboardInterrupt as e:
print('^C', file=sys.stderr)
@command
can also optionally take extensions as positional arguments, and
keyword arguments to customize the HashbangCommand
or the parser. See
Extensions and
documentation for HashbangCommand
below for more.
@command(
Argument('arg', choices=('one', 'two')),
exception_handler=handle_exception)
def main(arg, *, flag=False):
# Do stuff
The Argument
class allows additional configurations to be added to the
argument. It can be added in one of the following two ways:
- As decorator parameter
@command(
Argument('arg', choices=('one', 'two')),
Argument('flag', aliases=('f', 'F')))
def main(arg, *, flag):
# Do stuff
As many arguments as needed can be added to the @command
decorator, in
any order. Just ensure that the first argument of Argument
matches the
name of the function parameter.
- As argument annotation, as defined in PEP 3107.
def main(
arg: Argument(choices=('one', 'two')),
*,
flag: Argument(aliases=('f', 'F'))):
# Do stuff
There is no behavioral difference between these two ways in hashbang. I
find the second way to be slightly more pleasing to the eye and reduces
repetition, but it may go away in future versions of Python from
PEP 563.
Hence the first way is also provided, and is the encouraged way to specify
Argument
configurations.
Argument(name=None, *, choices=None, completer=None, aliases=(),
append=False, help=None, type=None, required=False,
remainder=False)
-
name
- The name of the argument. This is required when usingArgument
as a parameter to@command
, and it must match the name of a parameter in the decorated function. When usingArgument
as an argument annotation,name
should be omitted, and will be ignored if specified. -
choices
- A sequence of strings that corresponds to the possible values of the argument. This is used in both the help message and in tab completion. -
completer
- A callable with the keyword argumentsprefix
,action
,parser
, andparsed_args
. This callable should return a list of possible completion values. This is only used in tab-completion.-
prefix
: The prefix text of the last word before the cursor on the command line. For dynamic completers, this can be used to reduce the work required to generate possible completions. -
action
: Theargparse.Action
instance that this completer was called for. -
parser
: Theargparse.ArgumentParser
instance that the action was taken by. -
parsed_args
: The result of argument parsing so far (theargparse.Namespace
args object normally returned byArgumentParser.parse_args()
).
-
-
completion_validator
- A callable that takes(current_input, keyword_to_check_against)
and returns a boolean indicating whetherkeyword_to_check_against
should be part of the completion.current_input
is the partial word that the user tabbed on.keyword_to_check_against
is one of the choices or output fromcompleter
. The default validator performs a simple prefix match. -
aliases
- A sequence of strings that are aliases of this argument. This is only applicable to optional arguments. For example, if an argumentfoobar
has aliases('f', 'eggspam')
, then--foobar
,-f
, and--eggspam
will all do the same thing. Notice that if an alias is only one character, only one dash is added before it. -
append
- Whether to append the given arguments to a list instead of overwriting the value. For example,--val foobar --val eggspam
will create the valueval=['foobar', 'eggspam']
. The default value of this argument should be empty tuple()
in most typical cases. Non-empty default values are not allowed to avoid the surprising behavior described in https://bugs.python.org/issue16399. -
help
- The string help message for this argument. -
type
- A callable takes a single string input from command line, and returns the converted value. A common usage is to useint
orfloat
to convert to the desired type.argparse.FileType
can also be used here. This can also be used to validate the input, but raising an exception if the input doesn't match expectations. -
required
- Whether the argument is required. This is applicable only to optional arguments. For boolean flags, you will need to specify either--flag
or--noflag
in the command line. For other flags, you must provide a value like--foo bar
. -
remainder
- Boolean indicating whether this is argument should capture all remainders from command line, including unparsed optional arguments. This is applicable only to the var positional argument*arg
. Default value isFalse
, unless the argument is named_REMAINDER_
, in which case remainder isTrue
. -
py_only
- Boolean indicating whether this argument is for Python use only. If this is true, the argument will not be added to the command line parser.
Argument.add_argument(cmd, arg_container, param)
-
cmd
- TheHashbangCommand
object using this argument. This can be used as a vector for communication across extension instances, or to retrieve values set in the prior call toapply_hashbang_command
. For example, an argument group can be placed in the command object, and multiple arguments can be added to the same argument group. Any fields added by the argument to thisHashbangCommand
should be prefixed with_ClassName__
to avoid namespace collision. -
arg_container
- The argument container, which can be anargparse.ArgumentParser
, or the returned group ofArgumentParser.add_argument_group()
orArgumentParser.add_mutually_exclusive_group()
. The argument implementation should calladd_argument
on this parameter. -
param
- Theinspect.Parameter
object describing the parameter in the Python function. This can beNone
for arguments added by extensions, but is guaranteed to not beNone
for regular arguments.
@command.delegator
works the same way as a @command
, but when --help
or tab-completion is invoked, instead of running its own help or completion
methods immediately, it will first try to delegate to a subcommand, so that
a command like git branch --help
will show the help page of git branch
,
not git
itself.
When implementing a delegator, the implementation must either call .execute() on another command, or raise NoMatchingDelegate exception. Any other side-effects, like printing to the terminal or writing to any files, are undesired.
Also see the subcommands
function which will is a convenience function to
create delegating commands based on key-value pairs.
An exception that should be raised when implementing a @command.delegator
when a matching delegator could not be found.
A convenience method to create a @command.delegator
that delegates using
the given keyword arguments or pairs. For example, using
git = subcommands(commit=commit_func, branch=branch_func)
, a parent
command "git" with "commit" and "branch" subcommands are created. When
git.py commit
is executed, it will call commit_func.execute(...)
with
all the remaining arguments. commit_func
and branch_func
should also be
a @command
.
@command
def branch(newbranch=None):
if newbranch is None:
return '\n'.join(Repository('.').heads.keys())
return Repository('.').create_head(newbranch)
@command
def log(*, max_count=None, graph=False):
logs = Repository('.').log()
if graph:
return format_as_graph(logs)
else:
return '\n'.join(logs)
if __name__ == '__main__':
subcommands(branch=branch, log=log).execute()
When a function is decorated with @command
, a HashbangCommand
is
created to inspect its function signature, generating the parser, and
eventually executing the parsing. Its operations are transparent to the
regular user, but its APIs are useful for developing extensions.
HashbangCommand
has the following attributes which extensions can use
to customize the command's behavior:
-
arguments
- An ordered dictionary of the arguments to add to theargparse
parser. The order of the arguments should match the order in which they are declared in the function. The order is preserved in the help message.The keys of the map are the function names, whereas the values are a pair
(param, argument)
.param
is theinspect.Parameter
object, which can beNone
if the argument doesn't correspond to any parameter (i.e. injected by an extension).argument
is an instance ofArgument
which is responsible for callingadd_argument
to theargparse
parser. -
argparse_kwargs
- a dict of keyword arguments to add to the constructorargparse.ArgumentParser
. -
return_value_processor
- A callable that takes the return value of the decorated function and processes it. When this isNone
, the default implementation is used, which is toprint()
the result to stdout. -
exception_handler
- A callable that takes the exception raised by the decorated function and processes it. This method should re-raise any exceptions it does not handle. When this isNone
, the default implementation is used, which is to handlesubprocess.CalledProcessError
,NoMatchingDelegate
, andKeyboardInterrupt
to print the error messages instead of printing the entire stack trace.
In addition, the following read-only fields are also available to allow extensions to get context on the function this command is running on:
-
func
- The decorated function -
signature
- Theinspect.Signature
object created by inspectingfunc
. -
extensions
- The list of extensions applied to this command.
execute(args=None)
The execute
method is also added to the decorated function, so it can be
run using func.execute()
. This method will execute the decorated function
with the given command line arguments in args
, or in sys.argv
if args
is None
.
Extensions are regular objects implementing the function
apply_hashbang_extension(hashbang_cmd)
. This function is called after
all the information from the decorated function has been gathered,
before creating the argparse.ArgumentParser
. Extensions are expected to
modify one the of attributes described above to modify the behavior of the
command.