Page Menu
Home
Software Heritage
Search
Configure Global Search
Log In
Files
F8395220
core.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
65 KB
Subscribers
None
core.py
View Options
import
os
import
sys
import
codecs
from
contextlib
import
contextmanager
from
itertools
import
repeat
from
functools
import
update_wrapper
from
.types
import
convert_type
,
IntRange
,
BOOL
from
.utils
import
make_str
,
make_default_short_help
,
echo
from
.exceptions
import
ClickException
,
UsageError
,
BadParameter
,
Abort
,
\
MissingParameter
from
.termui
import
prompt
,
confirm
from
.formatting
import
HelpFormatter
,
join_options
from
.parser
import
OptionParser
,
split_opt
from
._compat
import
PY2
,
isidentifier
,
iteritems
_missing
=
object
()
SUBCOMMAND_METAVAR
=
'COMMAND [ARGS]...'
SUBCOMMANDS_METAVAR
=
'COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]...'
def
_bashcomplete
(
cmd
,
prog_name
,
complete_var
=
None
):
"""Internal handler for the bash completion support."""
if
complete_var
is
None
:
complete_var
=
'_
%s
_COMPLETE'
%
(
prog_name
.
replace
(
'-'
,
'_'
))
.
upper
()
complete_instr
=
os
.
environ
.
get
(
complete_var
)
if
not
complete_instr
:
return
from
._bashcomplete
import
bashcomplete
if
bashcomplete
(
cmd
,
prog_name
,
complete_var
,
complete_instr
):
sys
.
exit
(
1
)
def
batch
(
iterable
,
batch_size
):
return
list
(
zip
(
*
repeat
(
iter
(
iterable
),
batch_size
)))
def
invoke_param_callback
(
callback
,
ctx
,
param
,
value
):
code
=
getattr
(
callback
,
'__code__'
,
None
)
args
=
getattr
(
code
,
'co_argcount'
,
3
)
if
args
<
3
:
# This will become a warning in Click 3.0:
from
warnings
import
warn
warn
(
Warning
(
'Invoked legacy parameter callback "
%s
". The new '
'signature for such callbacks starting with '
'click 2.0 is (ctx, param, value).'
%
callback
),
stacklevel
=
3
)
return
callback
(
ctx
,
value
)
return
callback
(
ctx
,
param
,
value
)
@contextmanager
def
augment_usage_errors
(
ctx
,
param
=
None
):
"""Context manager that attaches extra information to exceptions that
fly.
"""
try
:
yield
except
BadParameter
as
e
:
if
e
.
ctx
is
None
:
e
.
ctx
=
ctx
if
param
is
not
None
and
e
.
param
is
None
:
e
.
param
=
param
raise
except
UsageError
as
e
:
if
e
.
ctx
is
None
:
e
.
ctx
=
ctx
raise
def
iter_params_for_processing
(
invocation_order
,
declaration_order
):
"""Given a sequence of parameters in the order as should be considered
for processing and an iterable of parameters that exist, this returns
a list in the correct order as they should be processed.
"""
def
sort_key
(
item
):
try
:
idx
=
invocation_order
.
index
(
item
)
except
ValueError
:
idx
=
float
(
'inf'
)
return
(
not
item
.
is_eager
,
idx
)
return
sorted
(
declaration_order
,
key
=
sort_key
)
class
Context
(
object
):
"""The context is a special internal object that holds state relevant
for the script execution at every single level. It's normally invisible
to commands unless they opt-in to getting access to it.
The context is useful as it can pass internal objects around and can
control special execution features such as reading data from
environment variables.
A context can be used as context manager in which case it will call
:meth:`close` on teardown.
.. versionadded:: 2.0
Added the `resilient_parsing`, `help_option_names`,
`token_normalize_func` parameters.
.. versionadded:: 3.0
Added the `allow_extra_args` and `allow_interspersed_args`
parameters.
.. versionadded:: 4.0
Added the `color`, `ignore_unknown_options`, and
`max_content_width` parameters.
:param command: the command class for this context.
:param parent: the parent context.
:param info_name: the info name for this invocation. Generally this
is the most descriptive name for the script or
command. For the toplevel script it is usually
the name of the script, for commands below it it's
the name of the script.
:param obj: an arbitrary object of user data.
:param auto_envvar_prefix: the prefix to use for automatic environment
variables. If this is `None` then reading
from environment variables is disabled. This
does not affect manually set environment
variables which are always read.
:param default_map: a dictionary (like object) with default values
for parameters.
:param terminal_width: the width of the terminal. The default is
inherit from parent context. If no context
defines the terminal width then auto
detection will be applied.
:param max_content_width: the maximum width for content rendered by
Click (this currently only affects help
pages). This defaults to 80 characters if
not overridden. In other words: even if the
terminal is larger than that, Click will not
format things wider than 80 characters by
default. In addition to that, formatters might
add some safety mapping on the right.
:param resilient_parsing: if this flag is enabled then Click will
parse without any interactivity or callback
invocation. This is useful for implementing
things such as completion support.
:param allow_extra_args: if this is set to `True` then extra arguments
at the end will not raise an error and will be
kept on the context. The default is to inherit
from the command.
:param allow_interspersed_args: if this is set to `False` then options
and arguments cannot be mixed. The
default is to inherit from the command.
:param ignore_unknown_options: instructs click to ignore options it does
not know and keeps them for later
processing.
:param help_option_names: optionally a list of strings that define how
the default help parameter is named. The
default is ``['--help']``.
:param token_normalize_func: an optional function that is used to
normalize tokens (options, choices,
etc.). This for instance can be used to
implement case insensitive behavior.
:param color: controls if the terminal supports ANSI colors or not. The
default is autodetection. This is only needed if ANSI
codes are used in texts that Click prints which is by
default not the case. This for instance would affect
help output.
"""
def
__init__
(
self
,
command
,
parent
=
None
,
info_name
=
None
,
obj
=
None
,
auto_envvar_prefix
=
None
,
default_map
=
None
,
terminal_width
=
None
,
max_content_width
=
None
,
resilient_parsing
=
False
,
allow_extra_args
=
None
,
allow_interspersed_args
=
None
,
ignore_unknown_options
=
None
,
help_option_names
=
None
,
token_normalize_func
=
None
,
color
=
None
):
#: the parent context or `None` if none exists.
self
.
parent
=
parent
#: the :class:`Command` for this context.
self
.
command
=
command
#: the descriptive information name
self
.
info_name
=
info_name
#: the parsed parameters except if the value is hidden in which
#: case it's not remembered.
self
.
params
=
{}
#: the leftover arguments.
self
.
args
=
[]
if
obj
is
None
and
parent
is
not
None
:
obj
=
parent
.
obj
#: the user object stored.
self
.
obj
=
obj
#: A dictionary (-like object) with defaults for parameters.
if
default_map
is
None
\
and
parent
is
not
None
\
and
parent
.
default_map
is
not
None
:
default_map
=
parent
.
default_map
.
get
(
info_name
)
self
.
default_map
=
default_map
#: This flag indicates if a subcommand is going to be executed. A
#: group callback can use this information to figure out if it's
#: being executed directly or because the execution flow passes
#: onwards to a subcommand. By default it's None, but it can be
#: the name of the subcommand to execute.
#:
#: If chaining is enabled this will be set to ``'*'`` in case
#: any commands are executed. It is however not possible to
#: figure out which ones. If you require this knowledge you
#: should use a :func:`resultcallback`.
self
.
invoked_subcommand
=
None
if
terminal_width
is
None
and
parent
is
not
None
:
terminal_width
=
parent
.
terminal_width
#: The width of the terminal (None is autodetection).
self
.
terminal_width
=
terminal_width
if
max_content_width
is
None
and
parent
is
not
None
:
max_content_width
=
parent
.
max_content_width
#: The maximum width of formatted content (None implies a sensible
#: default which is 80 for most things).
self
.
max_content_width
=
max_content_width
if
allow_extra_args
is
None
:
allow_extra_args
=
command
.
allow_extra_args
#: Indicates if the context allows extra args or if it should
#: fail on parsing.
#:
#: .. versionadded:: 3.0
self
.
allow_extra_args
=
allow_extra_args
if
allow_interspersed_args
is
None
:
allow_interspersed_args
=
command
.
allow_interspersed_args
#: Indicates if the context allows mixing of arguments and
#: options or not.
#:
#: .. versionadded:: 3.0
self
.
allow_interspersed_args
=
allow_interspersed_args
if
ignore_unknown_options
is
None
:
ignore_unknown_options
=
command
.
ignore_unknown_options
#: Instructs click to ignore options that a command does not
#: understand and will store it on the context for later
#: processing. This is primarily useful for situations where you
#: want to call into external programs. Generally this pattern is
#: strongly discouraged because it's not possibly to losslessly
#: forward all arguments.
#:
#: .. versionadded:: 4.0
self
.
ignore_unknown_options
=
ignore_unknown_options
if
help_option_names
is
None
:
if
parent
is
not
None
:
help_option_names
=
parent
.
help_option_names
else
:
help_option_names
=
[
'--help'
]
#: The names for the help options.
self
.
help_option_names
=
help_option_names
if
token_normalize_func
is
None
and
parent
is
not
None
:
token_normalize_func
=
parent
.
token_normalize_func
#: An optional normalization function for tokens. This is
#: options, choices, commands etc.
self
.
token_normalize_func
=
token_normalize_func
#: Indicates if resilient parsing is enabled. In that case Click
#: will do its best to not cause any failures.
self
.
resilient_parsing
=
resilient_parsing
# If there is no envvar prefix yet, but the parent has one and
# the command on this level has a name, we can expand the envvar
# prefix automatically.
if
auto_envvar_prefix
is
None
:
if
parent
is
not
None
\
and
parent
.
auto_envvar_prefix
is
not
None
and
\
self
.
info_name
is
not
None
:
auto_envvar_prefix
=
'
%s
_
%s
'
%
(
parent
.
auto_envvar_prefix
,
self
.
info_name
.
upper
())
else
:
self
.
auto_envvar_prefix
=
auto_envvar_prefix
.
upper
()
self
.
auto_envvar_prefix
=
auto_envvar_prefix
if
color
is
None
and
parent
is
not
None
:
color
=
parent
.
color
#: Controls if styling output is wanted or not.
self
.
color
=
color
self
.
_close_callbacks
=
[]
self
.
_depth
=
0
def
__enter__
(
self
):
self
.
_depth
+=
1
return
self
def
__exit__
(
self
,
exc_type
,
exc_value
,
tb
):
self
.
_depth
-=
1
if
self
.
_depth
==
0
:
self
.
close
()
def
_get_invoked_subcommands
(
self
):
from
warnings
import
warn
warn
(
Warning
(
'This API does not work properly and has been largely '
'removed in Click 3.2 to fix a regression the '
'introduction of this API caused. Consult the '
'upgrade documentation for more information. For '
'more information about this see '
'http://click.pocoo.org/upgrading/#upgrading-to-3.2'
),
stacklevel
=
2
)
if
self
.
invoked_subcommand
is
None
:
return
[]
return
[
self
.
invoked_subcommand
]
def
_set_invoked_subcommands
(
self
,
value
):
self
.
invoked_subcommand
=
\
len
(
value
)
>
1
and
'*'
or
value
and
value
[
0
]
or
None
invoked_subcommands
=
property
(
_get_invoked_subcommands
,
_set_invoked_subcommands
)
del
_get_invoked_subcommands
,
_set_invoked_subcommands
def
make_formatter
(
self
):
"""Creates the formatter for the help and usage output."""
return
HelpFormatter
(
width
=
self
.
terminal_width
,
max_width
=
self
.
max_content_width
)
def
call_on_close
(
self
,
f
):
"""This decorator remembers a function as callback that should be
executed when the context tears down. This is most useful to bind
resource handling to the script execution. For instance, file objects
opened by the :class:`File` type will register their close callbacks
here.
:param f: the function to execute on teardown.
"""
self
.
_close_callbacks
.
append
(
f
)
return
f
def
close
(
self
):
"""Invokes all close callbacks."""
for
cb
in
self
.
_close_callbacks
:
cb
()
self
.
_close_callbacks
=
[]
@property
def
command_path
(
self
):
"""The computed command path. This is used for the ``usage``
information on the help page. It's automatically created by
combining the info names of the chain of contexts to the root.
"""
rv
=
''
if
self
.
info_name
is
not
None
:
rv
=
self
.
info_name
if
self
.
parent
is
not
None
:
rv
=
self
.
parent
.
command_path
+
' '
+
rv
return
rv
.
lstrip
()
def
find_root
(
self
):
"""Finds the outermost context."""
node
=
self
while
node
.
parent
is
not
None
:
node
=
node
.
parent
return
node
def
find_object
(
self
,
object_type
):
"""Finds the closest object of a given type."""
node
=
self
while
node
is
not
None
:
if
isinstance
(
node
.
obj
,
object_type
):
return
node
.
obj
node
=
node
.
parent
def
ensure_object
(
self
,
object_type
):
"""Like :meth:`find_object` but sets the innermost object to a
new instance of `object_type` if it does not exist.
"""
rv
=
self
.
find_object
(
object_type
)
if
rv
is
None
:
self
.
obj
=
rv
=
object_type
()
return
rv
def
lookup_default
(
self
,
name
):
"""Looks up the default for a parameter name. This by default
looks into the :attr:`default_map` if available.
"""
if
self
.
default_map
is
not
None
:
rv
=
self
.
default_map
.
get
(
name
)
if
callable
(
rv
):
rv
=
rv
()
return
rv
def
fail
(
self
,
message
):
"""Aborts the execution of the program with a specific error
message.
:param message: the error message to fail with.
"""
raise
UsageError
(
message
,
self
)
def
abort
(
self
):
"""Aborts the script."""
raise
Abort
()
def
exit
(
self
,
code
=
0
):
"""Exits the application with a given exit code."""
sys
.
exit
(
code
)
def
get_usage
(
self
):
"""Helper method to get formatted usage string for the current
context and command.
"""
return
self
.
command
.
get_usage
(
self
)
def
get_help
(
self
):
"""Helper method to get formatted help page for the current
context and command.
"""
return
self
.
command
.
get_help
(
self
)
def
invoke
(
*
args
,
**
kwargs
):
"""Invokes a command callback in exactly the way it expects. There
are two ways to invoke this method:
1. the first argument can be a callback and all other arguments and
keyword arguments are forwarded directly to the function.
2. the first argument is a click command object. In that case all
arguments are forwarded as well but proper click parameters
(options and click arguments) must be keyword arguments and Click
will fill in defaults.
Note that before Click 3.2 keyword arguments were not properly filled
in against the intention of this code and no context was created. For
more information about this change and why it was done in a bugfix
release see :ref:`upgrade-to-3.2`.
"""
self
,
callback
=
args
[:
2
]
ctx
=
self
# This is just to improve the error message in cases where old
# code incorrectly invoked this method. This will eventually be
# removed.
injected_arguments
=
False
# It's also possible to invoke another command which might or
# might not have a callback. In that case we also fill
# in defaults and make a new context for this command.
if
isinstance
(
callback
,
Command
):
other_cmd
=
callback
callback
=
other_cmd
.
callback
ctx
=
Context
(
other_cmd
,
info_name
=
other_cmd
.
name
,
parent
=
self
)
if
callback
is
None
:
raise
TypeError
(
'The given command does not have a '
'callback that can be invoked.'
)
for
param
in
other_cmd
.
params
:
if
param
.
name
not
in
kwargs
and
param
.
expose_value
:
kwargs
[
param
.
name
]
=
param
.
get_default
(
ctx
)
injected_arguments
=
True
args
=
args
[
2
:]
if
getattr
(
callback
,
'__click_pass_context__'
,
False
):
args
=
(
ctx
,)
+
args
with
augment_usage_errors
(
self
):
try
:
with
ctx
:
return
callback
(
*
args
,
**
kwargs
)
except
TypeError
as
e
:
if
not
injected_arguments
:
raise
if
'got multiple values for'
in
str
(
e
):
raise
RuntimeError
(
'You called .invoke() on the context with a command '
'but provided parameters as positional arguments. '
'This is not supported but sometimes worked by chance '
'in older versions of Click. To fix this see '
'http://click.pocoo.org/upgrading/#upgrading-to-3.2'
)
raise
def
forward
(
*
args
,
**
kwargs
):
"""Similar to :meth:`invoke` but fills in default keyword
arguments from the current context if the other command expects
it. This cannot invoke callbacks directly, only other commands.
"""
self
,
cmd
=
args
[:
2
]
# It's also possible to invoke another command which might or
# might not have a callback.
if
not
isinstance
(
cmd
,
Command
):
raise
TypeError
(
'Callback is not a command.'
)
for
param
in
self
.
params
:
if
param
not
in
kwargs
:
kwargs
[
param
]
=
self
.
params
[
param
]
return
self
.
invoke
(
cmd
,
**
kwargs
)
class
BaseCommand
(
object
):
"""The base command implements the minimal API contract of commands.
Most code will never use this as it does not implement a lot of useful
functionality but it can act as the direct subclass of alternative
parsing methods that do not depend on the Click parser.
For instance, this can be used to bridge Click and other systems like
argparse or docopt.
Because base commands do not implement a lot of the API that other
parts of Click take for granted, they are not supported for all
operations. For instance, they cannot be used with the decorators
usually and they have no built-in callback system.
.. versionchanged:: 2.0
Added the `context_settings` parameter.
:param name: the name of the command to use unless a group overrides it.
:param context_settings: an optional dictionary with defaults that are
passed to the context object.
"""
#: the default for the :attr:`Context.allow_extra_args` flag.
allow_extra_args
=
False
#: the default for the :attr:`Context.allow_interspersed_args` flag.
allow_interspersed_args
=
True
#: the default for the :attr:`Context.ignore_unknown_options` flag.
ignore_unknown_options
=
False
def
__init__
(
self
,
name
,
context_settings
=
None
):
#: the name the command thinks it has. Upon registering a command
#: on a :class:`Group` the group will default the command name
#: with this information. You should instead use the
#: :class:`Context`\'s :attr:`~Context.info_name` attribute.
self
.
name
=
name
if
context_settings
is
None
:
context_settings
=
{}
#: an optional dictionary with defaults passed to the context.
self
.
context_settings
=
context_settings
def
get_usage
(
self
,
ctx
):
raise
NotImplementedError
(
'Base commands cannot get usage'
)
def
get_help
(
self
,
ctx
):
raise
NotImplementedError
(
'Base commands cannot get help'
)
def
make_context
(
self
,
info_name
,
args
,
parent
=
None
,
**
extra
):
"""This function when given an info name and arguments will kick
off the parsing and create a new :class:`Context`. It does not
invoke the actual command callback though.
:param info_name: the info name for this invokation. Generally this
is the most descriptive name for the script or
command. For the toplevel script it's usually
the name of the script, for commands below it it's
the name of the script.
:param args: the arguments to parse as list of strings.
:param parent: the parent context if available.
:param extra: extra keyword arguments forwarded to the context
constructor.
"""
for
key
,
value
in
iteritems
(
self
.
context_settings
):
if
key
not
in
extra
:
extra
[
key
]
=
value
ctx
=
Context
(
self
,
info_name
=
info_name
,
parent
=
parent
,
**
extra
)
self
.
parse_args
(
ctx
,
args
)
return
ctx
def
parse_args
(
self
,
ctx
,
args
):
"""Given a context and a list of arguments this creates the parser
and parses the arguments, then modifies the context as necessary.
This is automatically invoked by :meth:`make_context`.
"""
raise
NotImplementedError
(
'Base commands do not know how to parse '
'arguments.'
)
def
invoke
(
self
,
ctx
):
"""Given a context, this invokes the command. The default
implementation is raising a not implemented error.
"""
raise
NotImplementedError
(
'Base commands are not invokable by default'
)
def
main
(
self
,
args
=
None
,
prog_name
=
None
,
complete_var
=
None
,
standalone_mode
=
True
,
**
extra
):
"""This is the way to invoke a script with all the bells and
whistles as a command line application. This will always terminate
the application after a call. If this is not wanted, ``SystemExit``
needs to be caught.
This method is also available by directly calling the instance of
a :class:`Command`.
.. versionadded:: 3.0
Added the `standalone_mode` flag to control the standalone mode.
:param args: the arguments that should be used for parsing. If not
provided, ``sys.argv[1:]`` is used.
:param prog_name: the program name that should be used. By default
the program name is constructed by taking the file
name from ``sys.argv[0]``.
:param complete_var: the environment variable that controls the
bash completion support. The default is
``"_<prog_name>_COMPLETE"`` with prog name in
uppercase.
:param standalone_mode: the default behavior is to invoke the script
in standalone mode. Click will then
handle exceptions and convert them into
error messages and the function will never
return but shut down the interpreter. If
this is set to `False` they will be
propagated to the caller and the return
value of this function is the return value
of :meth:`invoke`.
:param extra: extra keyword arguments are forwarded to the context
constructor. See :class:`Context` for more information.
"""
# If we are in Python 3, we will verify that the environment is
# sane at this point of reject further execution to avoid a
# broken script.
if
not
PY2
:
try
:
import
locale
fs_enc
=
codecs
.
lookup
(
locale
.
getpreferredencoding
())
.
name
except
Exception
:
fs_enc
=
'ascii'
if
fs_enc
==
'ascii'
:
raise
RuntimeError
(
'Click will abort further execution '
'because Python 3 was configured to use '
'ASCII as encoding for the environment. '
'Either switch to Python 2 or consult '
'http://click.pocoo.org/python3/ '
'for mitigation steps.'
)
if
args
is
None
:
args
=
sys
.
argv
[
1
:]
else
:
args
=
list
(
args
)
if
prog_name
is
None
:
prog_name
=
make_str
(
os
.
path
.
basename
(
sys
.
argv
and
sys
.
argv
[
0
]
or
__file__
))
# Hook for the Bash completion. This only activates if the Bash
# completion is actually enabled, otherwise this is quite a fast
# noop.
_bashcomplete
(
self
,
prog_name
,
complete_var
)
try
:
try
:
with
self
.
make_context
(
prog_name
,
args
,
**
extra
)
as
ctx
:
rv
=
self
.
invoke
(
ctx
)
if
not
standalone_mode
:
return
rv
ctx
.
exit
()
except
(
EOFError
,
KeyboardInterrupt
):
echo
(
file
=
sys
.
stderr
)
raise
Abort
()
except
ClickException
as
e
:
if
not
standalone_mode
:
raise
e
.
show
()
sys
.
exit
(
e
.
exit_code
)
except
Abort
:
if
not
standalone_mode
:
raise
echo
(
'Aborted!'
,
file
=
sys
.
stderr
)
sys
.
exit
(
1
)
def
__call__
(
self
,
*
args
,
**
kwargs
):
"""Alias for :meth:`main`."""
return
self
.
main
(
*
args
,
**
kwargs
)
class
Command
(
BaseCommand
):
"""Commands are the basic building block of command line interfaces in
Click. A basic command handles command line parsing and might dispatch
more parsing to commands nested below it.
.. versionchanged:: 2.0
Added the `context_settings` parameter.
:param name: the name of the command to use unless a group overrides it.
:param context_settings: an optional dictionary with defaults that are
passed to the context object.
:param callback: the callback to invoke. This is optional.
:param params: the parameters to register with this command. This can
be either :class:`Option` or :class:`Argument` objects.
:param help: the help string to use for this command.
:param epilog: like the help string but it's printed at the end of the
help page after everything else.
:param short_help: the short help to use for this command. This is
shown on the command listing of the parent command.
:param add_help_option: by default each command registers a ``--help``
option. This can be disabled by this parameter.
"""
def
__init__
(
self
,
name
,
context_settings
=
None
,
callback
=
None
,
params
=
None
,
help
=
None
,
epilog
=
None
,
short_help
=
None
,
options_metavar
=
'[OPTIONS]'
,
add_help_option
=
True
):
BaseCommand
.
__init__
(
self
,
name
,
context_settings
)
#: the callback to execute when the command fires. This might be
#: `None` in which case nothing happens.
self
.
callback
=
callback
#: the list of parameters for this command in the order they
#: should show up in the help page and execute. Eager parameters
#: will automatically be handled before non eager ones.
self
.
params
=
params
or
[]
self
.
help
=
help
self
.
epilog
=
epilog
self
.
options_metavar
=
options_metavar
if
short_help
is
None
and
help
:
short_help
=
make_default_short_help
(
help
)
self
.
short_help
=
short_help
self
.
add_help_option
=
add_help_option
def
get_usage
(
self
,
ctx
):
formatter
=
ctx
.
make_formatter
()
self
.
format_usage
(
ctx
,
formatter
)
return
formatter
.
getvalue
()
.
rstrip
(
'
\n
'
)
def
get_params
(
self
,
ctx
):
rv
=
self
.
params
help_option
=
self
.
get_help_option
(
ctx
)
if
help_option
is
not
None
:
rv
=
rv
+
[
help_option
]
return
rv
def
format_usage
(
self
,
ctx
,
formatter
):
"""Writes the usage line into the formatter."""
pieces
=
self
.
collect_usage_pieces
(
ctx
)
formatter
.
write_usage
(
ctx
.
command_path
,
' '
.
join
(
pieces
))
def
collect_usage_pieces
(
self
,
ctx
):
"""Returns all the pieces that go into the usage line and returns
it as a list of strings.
"""
rv
=
[
self
.
options_metavar
]
for
param
in
self
.
get_params
(
ctx
):
rv
.
extend
(
param
.
get_usage_pieces
(
ctx
))
return
rv
def
get_help_option_names
(
self
,
ctx
):
"""Returns the names for the help option."""
all_names
=
set
(
ctx
.
help_option_names
)
for
param
in
self
.
params
:
all_names
.
difference_update
(
param
.
opts
)
all_names
.
difference_update
(
param
.
secondary_opts
)
return
all_names
def
get_help_option
(
self
,
ctx
):
"""Returns the help option object."""
help_options
=
self
.
get_help_option_names
(
ctx
)
if
not
help_options
or
not
self
.
add_help_option
:
return
def
show_help
(
ctx
,
param
,
value
):
if
value
and
not
ctx
.
resilient_parsing
:
echo
(
ctx
.
get_help
(),
color
=
ctx
.
color
)
ctx
.
exit
()
return
Option
(
help_options
,
is_flag
=
True
,
is_eager
=
True
,
expose_value
=
False
,
callback
=
show_help
,
help
=
'Show this message and exit.'
)
def
make_parser
(
self
,
ctx
):
"""Creates the underlying option parser for this command."""
parser
=
OptionParser
(
ctx
)
parser
.
allow_interspersed_args
=
ctx
.
allow_interspersed_args
parser
.
ignore_unknown_options
=
ctx
.
ignore_unknown_options
for
param
in
self
.
get_params
(
ctx
):
param
.
add_to_parser
(
parser
,
ctx
)
return
parser
def
get_help
(
self
,
ctx
):
"""Formats the help into a string and returns it. This creates a
formatter and will call into the following formatting methods:
"""
formatter
=
ctx
.
make_formatter
()
self
.
format_help
(
ctx
,
formatter
)
return
formatter
.
getvalue
()
.
rstrip
(
'
\n
'
)
def
format_help
(
self
,
ctx
,
formatter
):
"""Writes the help into the formatter if it exists.
This calls into the following methods:
- :meth:`format_usage`
- :meth:`format_help_text`
- :meth:`format_options`
- :meth:`format_epilog`
"""
self
.
format_usage
(
ctx
,
formatter
)
self
.
format_help_text
(
ctx
,
formatter
)
self
.
format_options
(
ctx
,
formatter
)
self
.
format_epilog
(
ctx
,
formatter
)
def
format_help_text
(
self
,
ctx
,
formatter
):
"""Writes the help text to the formatter if it exists."""
if
self
.
help
:
formatter
.
write_paragraph
()
with
formatter
.
indentation
():
formatter
.
write_text
(
self
.
help
)
def
format_options
(
self
,
ctx
,
formatter
):
"""Writes all the options into the formatter if they exist."""
opts
=
[]
for
param
in
self
.
get_params
(
ctx
):
rv
=
param
.
get_help_record
(
ctx
)
if
rv
is
not
None
:
opts
.
append
(
rv
)
if
opts
:
with
formatter
.
section
(
'Options'
):
formatter
.
write_dl
(
opts
)
def
format_epilog
(
self
,
ctx
,
formatter
):
"""Writes the epilog into the formatter if it exists."""
if
self
.
epilog
:
formatter
.
write_paragraph
()
with
formatter
.
indentation
():
formatter
.
write_text
(
self
.
epilog
)
def
parse_args
(
self
,
ctx
,
args
):
parser
=
self
.
make_parser
(
ctx
)
opts
,
args
,
param_order
=
parser
.
parse_args
(
args
=
args
)
for
param
in
iter_params_for_processing
(
param_order
,
self
.
get_params
(
ctx
)):
value
,
args
=
param
.
handle_parse_result
(
ctx
,
opts
,
args
)
if
args
and
not
ctx
.
allow_extra_args
and
not
ctx
.
resilient_parsing
:
ctx
.
fail
(
'Got unexpected extra argument
%s
(
%s
)'
%
(
len
(
args
)
!=
1
and
's'
or
''
,
' '
.
join
(
map
(
make_str
,
args
))))
ctx
.
args
=
args
return
args
def
invoke
(
self
,
ctx
):
"""Given a context, this invokes the attached callback (if it exists)
in the right way.
"""
if
self
.
callback
is
not
None
:
return
ctx
.
invoke
(
self
.
callback
,
**
ctx
.
params
)
class
MultiCommand
(
Command
):
"""A multi command is the basic implementation of a command that
dispatches to subcommands. The most common version is the
:class:`Group`.
:param invoke_without_command: this controls how the multi command itself
is invoked. By default it's only invoked
if a subcommand is provided.
:param no_args_is_help: this controls what happens if no arguments are
provided. This option is enabled by default if
`invoke_without_command` is disabled or disabled
if it's enabled. If enabled this will add
``--help`` as argument if no arguments are
passed.
:param subcommand_metavar: the string that is used in the documentation
to indicate the subcommand place.
:param chain: if this is set to `True` chaining of multiple subcommands
is enabled. This restricts the form of commands in that
they cannot have optional arguments but it allows
multiple commands to be chained together.
:param result_callback: the result callback to attach to this multi
command.
"""
allow_extra_args
=
True
allow_interspersed_args
=
False
def
__init__
(
self
,
name
=
None
,
invoke_without_command
=
False
,
no_args_is_help
=
None
,
subcommand_metavar
=
None
,
chain
=
False
,
result_callback
=
None
,
**
attrs
):
Command
.
__init__
(
self
,
name
,
**
attrs
)
if
no_args_is_help
is
None
:
no_args_is_help
=
not
invoke_without_command
self
.
no_args_is_help
=
no_args_is_help
self
.
invoke_without_command
=
invoke_without_command
if
subcommand_metavar
is
None
:
if
chain
:
subcommand_metavar
=
SUBCOMMANDS_METAVAR
else
:
subcommand_metavar
=
SUBCOMMAND_METAVAR
self
.
subcommand_metavar
=
subcommand_metavar
self
.
chain
=
chain
#: The result callback that is stored. This can be set or
#: overridden with the :func:`resultcallback` decorator.
self
.
result_callback
=
result_callback
def
collect_usage_pieces
(
self
,
ctx
):
rv
=
Command
.
collect_usage_pieces
(
self
,
ctx
)
rv
.
append
(
self
.
subcommand_metavar
)
return
rv
def
format_options
(
self
,
ctx
,
formatter
):
Command
.
format_options
(
self
,
ctx
,
formatter
)
self
.
format_commands
(
ctx
,
formatter
)
def
resultcallback
(
self
,
replace
=
False
):
"""Adds a result callback to the chain command. By default if a
result callback is already registered this will chain them but
this can be disabled with the `replace` parameter. The result
callback is invoked with the return value of the subcommand
(or the list of return values from all subcommands if chaining
is enabled) as well as the parameters as they would be passed
to the main callback.
Example::
@click.group()
@click.option('-i', '--input', default=23)
def cli(input):
return 42
@cli.resultcallback()
def process_result(result, input):
return result + input
.. versionadded:: 3.0
:param replace: if set to `True` an already existing result
callback will be removed.
"""
def
decorator
(
f
):
old_callback
=
self
.
result_callback
if
old_callback
is
None
or
replace
:
self
.
result_callback
=
f
return
f
def
function
(
__value
,
*
args
,
**
kwargs
):
return
f
(
old_callback
(
__value
,
*
args
,
**
kwargs
),
*
args
,
**
kwargs
)
self
.
result_callback
=
rv
=
update_wrapper
(
function
,
f
)
return
rv
return
decorator
def
format_commands
(
self
,
ctx
,
formatter
):
"""Extra format methods for multi methods that adds all the commands
after the options.
"""
rows
=
[]
for
subcommand
in
self
.
list_commands
(
ctx
):
cmd
=
self
.
get_command
(
ctx
,
subcommand
)
# What is this, the tool lied about a command. Ignore it
if
cmd
is
None
:
continue
help
=
cmd
.
short_help
or
''
rows
.
append
((
subcommand
,
help
))
if
rows
:
with
formatter
.
section
(
'Commands'
):
formatter
.
write_dl
(
rows
)
def
parse_args
(
self
,
ctx
,
args
):
if
not
args
and
self
.
no_args_is_help
and
not
ctx
.
resilient_parsing
:
echo
(
ctx
.
get_help
(),
color
=
ctx
.
color
)
ctx
.
exit
()
return
Command
.
parse_args
(
self
,
ctx
,
args
)
def
invoke
(
self
,
ctx
):
def
_process_result
(
value
):
if
self
.
result_callback
is
not
None
:
value
=
ctx
.
invoke
(
self
.
result_callback
,
value
,
**
ctx
.
params
)
return
value
if
not
ctx
.
args
:
# If we are invoked without command the chain flag controls
# how this happens. If we are not in chain mode, the return
# value here is the return value of the command.
# If however we are in chain mode, the return value is the
# return value of the result processor invoked with an empty
# list (which means that no subcommand actually was executed).
if
self
.
invoke_without_command
:
if
not
self
.
chain
:
return
Command
.
invoke
(
self
,
ctx
)
with
ctx
:
Command
.
invoke
(
self
,
ctx
)
return
_process_result
([])
ctx
.
fail
(
'Missing command.'
)
args
=
ctx
.
args
# If we're not in chain mode, we only allow the invocation of a
# single command but we also inform the current context about the
# name of the command to invoke.
if
not
self
.
chain
:
# Make sure the context is entered so we do not clean up
# resources until the result processor has worked.
with
ctx
:
cmd_name
,
cmd
,
args
=
self
.
resolve_command
(
ctx
,
args
)
ctx
.
invoked_subcommand
=
cmd_name
Command
.
invoke
(
self
,
ctx
)
sub_ctx
=
cmd
.
make_context
(
cmd_name
,
args
,
parent
=
ctx
)
with
sub_ctx
:
return
_process_result
(
sub_ctx
.
command
.
invoke
(
sub_ctx
))
# In chain mode we create the contexts step by step, but after the
# base command has been invoked. Because at that point we do not
# know the subcommands yet, the invoked subcommand attribute is
# set to ``*`` to inform the command that subcommands are executed
# but nothing else.
with
ctx
:
ctx
.
invoked_subcommand
=
args
and
'*'
or
None
Command
.
invoke
(
self
,
ctx
)
# Otherwise we make every single context and invoke them in a
# chain. In that case the return value to the result processor
# is the list of all invoked subcommand's results.
contexts
=
[]
while
args
:
cmd_name
,
cmd
,
args
=
self
.
resolve_command
(
ctx
,
args
)
sub_ctx
=
cmd
.
make_context
(
cmd_name
,
args
,
parent
=
ctx
,
allow_extra_args
=
True
,
allow_interspersed_args
=
False
)
contexts
.
append
(
sub_ctx
)
args
=
sub_ctx
.
args
rv
=
[]
for
sub_ctx
in
contexts
:
with
sub_ctx
:
rv
.
append
(
sub_ctx
.
command
.
invoke
(
sub_ctx
))
return
_process_result
(
rv
)
def
resolve_command
(
self
,
ctx
,
args
):
cmd_name
=
make_str
(
args
[
0
])
original_cmd_name
=
cmd_name
# Get the command
cmd
=
self
.
get_command
(
ctx
,
cmd_name
)
# If we can't find the command but there is a normalization
# function available, we try with that one.
if
cmd
is
None
and
ctx
.
token_normalize_func
is
not
None
:
cmd_name
=
ctx
.
token_normalize_func
(
cmd_name
)
cmd
=
self
.
get_command
(
ctx
,
cmd_name
)
# If we don't find the command we want to show an error message
# to the user that it was not provided. However, there is
# something else we should do: if the first argument looks like
# an option we want to kick off parsing again for arguments to
# resolve things like --help which now should go to the main
# place.
if
cmd
is
None
:
if
split_opt
(
cmd_name
)[
0
]:
self
.
parse_args
(
ctx
,
ctx
.
args
)
ctx
.
fail
(
'No such command "
%s
".'
%
original_cmd_name
)
return
cmd_name
,
cmd
,
args
[
1
:]
def
get_command
(
self
,
ctx
,
cmd_name
):
"""Given a context and a command name, this returns a
:class:`Command` object if it exists or returns `None`.
"""
raise
NotImplementedError
()
def
list_commands
(
self
,
ctx
):
"""Returns a list of subcommand names in the order they should
appear.
"""
return
[]
class
Group
(
MultiCommand
):
"""A group allows a command to have subcommands attached. This is the
most common way to implement nesting in Click.
:param commands: a dictionary of commands.
"""
def
__init__
(
self
,
name
=
None
,
commands
=
None
,
**
attrs
):
MultiCommand
.
__init__
(
self
,
name
,
**
attrs
)
#: the registered subcommands by their exported names.
self
.
commands
=
commands
or
{}
def
add_command
(
self
,
cmd
,
name
=
None
):
"""Registers another :class:`Command` with this group. If the name
is not provided, the name of the command is used.
"""
name
=
name
or
cmd
.
name
if
name
is
None
:
raise
TypeError
(
'Command has no name.'
)
self
.
commands
[
name
]
=
cmd
def
command
(
self
,
*
args
,
**
kwargs
):
"""A shortcut decorator for declaring and attaching a command to
the group. This takes the same arguments as :func:`command` but
immediately registers the created command with this instance by
calling into :meth:`add_command`.
"""
def
decorator
(
f
):
cmd
=
command
(
*
args
,
**
kwargs
)(
f
)
self
.
add_command
(
cmd
)
return
cmd
return
decorator
def
group
(
self
,
*
args
,
**
kwargs
):
"""A shortcut decorator for declaring and attaching a group to
the group. This takes the same arguments as :func:`group` but
immediately registers the created command with this instance by
calling into :meth:`add_command`.
"""
def
decorator
(
f
):
cmd
=
group
(
*
args
,
**
kwargs
)(
f
)
self
.
add_command
(
cmd
)
return
cmd
return
decorator
def
get_command
(
self
,
ctx
,
cmd_name
):
return
self
.
commands
.
get
(
cmd_name
)
def
list_commands
(
self
,
ctx
):
return
sorted
(
self
.
commands
)
class
CommandCollection
(
MultiCommand
):
"""A command collection is a multi command that merges multiple multi
commands together into one. This is a straightforward implementation
that accepts a list of different multi commands as sources and
provides all the commands for each of them.
"""
def
__init__
(
self
,
name
=
None
,
sources
=
None
,
**
attrs
):
MultiCommand
.
__init__
(
self
,
name
,
**
attrs
)
#: The list of registered multi commands.
self
.
sources
=
sources
or
[]
def
add_source
(
self
,
multi_cmd
):
"""Adds a new multi command to the chain dispatcher."""
self
.
sources
.
append
(
multi_cmd
)
def
get_command
(
self
,
ctx
,
cmd_name
):
for
source
in
self
.
sources
:
rv
=
source
.
get_command
(
ctx
,
cmd_name
)
if
rv
is
not
None
:
return
rv
def
list_commands
(
self
,
ctx
):
rv
=
set
()
for
source
in
self
.
sources
:
rv
.
update
(
source
.
list_commands
(
ctx
))
return
sorted
(
rv
)
class
Parameter
(
object
):
"""A parameter to a command comes in two versions: they are either
:class:`Option`\s or :class:`Argument`\s. Other subclasses are currently
not supported by design as some of the internals for parsing are
intentionally not finalized.
Some settings are supported by both options and arguments.
.. versionchanged:: 2.0
Changed signature for parameter callback to also be passed the
parameter. In Click 2.0, the old callback format will still work,
but it will raise a warning to give you change to migrate the
code easier.
:param param_decls: the parameter declarations for this option or
argument. This is a list of flags or argument
names.
:param type: the type that should be used. Either a :class:`ParamType`
or a Python type. The later is converted into the former
automatically if supported.
:param required: controls if this is optional or not.
:param default: the default value if omitted. This can also be a callable,
in which case it's invoked when the default is needed
without any arguments.
:param callback: a callback that should be executed after the parameter
was matched. This is called as ``fn(ctx, param,
value)`` and needs to return the value. Before Click
2.0, the signature was ``(ctx, value)``.
:param nargs: the number of arguments to match. If not ``1`` the return
value is a tuple instead of single value. The default for
nargs is ``1`` (except if the type is a tuple, then it's
the arity of the tuple).
:param metavar: how the value is represented in the help page.
:param expose_value: if this is `True` then the value is passed onwards
to the command callback and stored on the context,
otherwise it's skipped.
:param is_eager: eager values are processed before non eager ones. This
should not be set for arguments or it will inverse the
order of processing.
:param envvar: a string or list of strings that are environment variables
that should be checked.
"""
param_type_name
=
'parameter'
def
__init__
(
self
,
param_decls
=
None
,
type
=
None
,
required
=
False
,
default
=
None
,
callback
=
None
,
nargs
=
None
,
metavar
=
None
,
expose_value
=
True
,
is_eager
=
False
,
envvar
=
None
):
self
.
name
,
self
.
opts
,
self
.
secondary_opts
=
\
self
.
_parse_decls
(
param_decls
or
(),
expose_value
)
self
.
type
=
convert_type
(
type
,
default
)
# Default nargs to what the type tells us if we have that
# information available.
if
nargs
is
None
:
if
self
.
type
.
is_composite
:
nargs
=
self
.
type
.
arity
else
:
nargs
=
1
self
.
required
=
required
self
.
callback
=
callback
self
.
nargs
=
nargs
self
.
multiple
=
False
self
.
expose_value
=
expose_value
self
.
default
=
default
self
.
is_eager
=
is_eager
self
.
metavar
=
metavar
self
.
envvar
=
envvar
@property
def
human_readable_name
(
self
):
"""Returns the human readable name of this parameter. This is the
same as the name for options, but the metavar for arguments.
"""
return
self
.
name
def
make_metavar
(
self
):
if
self
.
metavar
is
not
None
:
return
self
.
metavar
metavar
=
self
.
type
.
get_metavar
(
self
)
if
metavar
is
None
:
metavar
=
self
.
type
.
name
.
upper
()
if
self
.
nargs
!=
1
:
metavar
+=
'...'
return
metavar
def
get_default
(
self
,
ctx
):
"""Given a context variable this calculates the default value."""
# Otherwise go with the regular default.
if
callable
(
self
.
default
):
rv
=
self
.
default
()
else
:
rv
=
self
.
default
return
self
.
type_cast_value
(
ctx
,
rv
)
def
add_to_parser
(
self
,
parser
,
ctx
):
pass
def
consume_value
(
self
,
ctx
,
opts
):
value
=
opts
.
get
(
self
.
name
)
if
value
is
None
:
value
=
ctx
.
lookup_default
(
self
.
name
)
if
value
is
None
:
value
=
self
.
value_from_envvar
(
ctx
)
return
value
def
type_cast_value
(
self
,
ctx
,
value
):
"""Given a value this runs it properly through the type system.
This automatically handles things like `nargs` and `multiple` as
well as composite types.
"""
if
self
.
type
.
is_composite
:
if
self
.
nargs
<=
1
:
raise
TypeError
(
'Attempted to invoke composite type '
'but nargs has been set to
%s
. This is '
'not supported; nargs needs to be set to '
'a fixed value > 1.'
%
self
.
nargs
)
if
self
.
multiple
:
return
tuple
(
self
.
type
(
x
or
(),
self
,
ctx
)
for
x
in
value
or
())
return
self
.
type
(
value
or
(),
self
,
ctx
)
def
_convert
(
value
,
level
):
if
level
==
0
:
return
self
.
type
(
value
,
self
,
ctx
)
return
tuple
(
_convert
(
x
,
level
-
1
)
for
x
in
value
or
())
return
_convert
(
value
,
(
self
.
nargs
!=
1
)
+
bool
(
self
.
multiple
))
def
process_value
(
self
,
ctx
,
value
):
"""Given a value and context this runs the logic to convert the
value as necessary.
"""
# If the value we were given is None we do nothing. This way
# code that calls this can easily figure out if something was
# not provided. Otherwise it would be converted into an empty
# tuple for multiple invocations which is inconvenient.
if
value
is
not
None
:
return
self
.
type_cast_value
(
ctx
,
value
)
def
value_is_missing
(
self
,
value
):
if
value
is
None
:
return
True
if
(
self
.
nargs
!=
1
or
self
.
multiple
)
and
value
==
():
return
True
return
False
def
full_process_value
(
self
,
ctx
,
value
):
value
=
self
.
process_value
(
ctx
,
value
)
if
value
is
None
:
value
=
self
.
get_default
(
ctx
)
if
self
.
required
and
self
.
value_is_missing
(
value
):
raise
MissingParameter
(
ctx
=
ctx
,
param
=
self
)
return
value
def
resolve_envvar_value
(
self
,
ctx
):
if
self
.
envvar
is
None
:
return
if
isinstance
(
self
.
envvar
,
(
tuple
,
list
)):
for
envvar
in
self
.
envvar
:
rv
=
os
.
environ
.
get
(
envvar
)
if
rv
is
not
None
:
return
rv
else
:
return
os
.
environ
.
get
(
self
.
envvar
)
def
value_from_envvar
(
self
,
ctx
):
rv
=
self
.
resolve_envvar_value
(
ctx
)
if
rv
is
not
None
and
self
.
nargs
!=
1
:
rv
=
self
.
type
.
split_envvar_value
(
rv
)
return
rv
def
handle_parse_result
(
self
,
ctx
,
opts
,
args
):
with
augment_usage_errors
(
ctx
,
param
=
self
):
value
=
self
.
consume_value
(
ctx
,
opts
)
try
:
value
=
self
.
full_process_value
(
ctx
,
value
)
except
Exception
:
if
not
ctx
.
resilient_parsing
:
raise
value
=
None
if
self
.
callback
is
not
None
:
try
:
value
=
invoke_param_callback
(
self
.
callback
,
ctx
,
self
,
value
)
except
Exception
:
if
not
ctx
.
resilient_parsing
:
raise
if
self
.
expose_value
:
ctx
.
params
[
self
.
name
]
=
value
return
value
,
args
def
get_help_record
(
self
,
ctx
):
pass
def
get_usage_pieces
(
self
,
ctx
):
return
[]
class
Option
(
Parameter
):
"""Options are usually optional values on the command line and
have some extra features that arguments don't have.
All other parameters are passed onwards to the parameter constructor.
:param show_default: controls if the default value should be shown on the
help page. Normally, defaults are not shown.
:param prompt: if set to `True` or a non empty string then the user will
be prompted for input if not set. If set to `True` the
prompt will be the option name capitalized.
:param confirmation_prompt: if set then the value will need to be confirmed
if it was prompted for.
:param hide_input: if this is `True` then the input on the prompt will be
hidden from the user. This is useful for password
input.
:param is_flag: forces this option to act as a flag. The default is
auto detection.
:param flag_value: which value should be used for this flag if it's
enabled. This is set to a boolean automatically if
the option string contains a slash to mark two options.
:param multiple: if this is set to `True` then the argument is accepted
multiple times and recorded. This is similar to ``nargs``
in how it works but supports arbitrary number of
arguments.
:param count: this flag makes an option increment an integer.
:param allow_from_autoenv: if this is enabled then the value of this
parameter will be pulled from an environment
variable in case a prefix is defined on the
context.
:param help: the help string.
"""
param_type_name
=
'option'
def
__init__
(
self
,
param_decls
=
None
,
show_default
=
False
,
prompt
=
False
,
confirmation_prompt
=
False
,
hide_input
=
False
,
is_flag
=
None
,
flag_value
=
None
,
multiple
=
False
,
count
=
False
,
allow_from_autoenv
=
True
,
type
=
None
,
help
=
None
,
**
attrs
):
default_is_missing
=
attrs
.
get
(
'default'
,
_missing
)
is
_missing
Parameter
.
__init__
(
self
,
param_decls
,
type
=
type
,
**
attrs
)
if
prompt
is
True
:
prompt_text
=
self
.
name
.
replace
(
'_'
,
' '
)
.
capitalize
()
elif
prompt
is
False
:
prompt_text
=
None
else
:
prompt_text
=
prompt
self
.
prompt
=
prompt_text
self
.
confirmation_prompt
=
confirmation_prompt
self
.
hide_input
=
hide_input
# Flags
if
is_flag
is
None
:
if
flag_value
is
not
None
:
is_flag
=
True
else
:
is_flag
=
bool
(
self
.
secondary_opts
)
if
is_flag
and
default_is_missing
:
self
.
default
=
False
if
flag_value
is
None
:
flag_value
=
not
self
.
default
self
.
is_flag
=
is_flag
self
.
flag_value
=
flag_value
if
self
.
is_flag
and
isinstance
(
self
.
flag_value
,
bool
)
\
and
type
is
None
:
self
.
type
=
BOOL
self
.
is_bool_flag
=
True
else
:
self
.
is_bool_flag
=
False
# Counting
self
.
count
=
count
if
count
:
if
type
is
None
:
self
.
type
=
IntRange
(
min
=
0
)
if
default_is_missing
:
self
.
default
=
0
self
.
multiple
=
multiple
self
.
allow_from_autoenv
=
allow_from_autoenv
self
.
help
=
help
self
.
show_default
=
show_default
# Sanity check for stuff we don't support
if
__debug__
:
if
self
.
nargs
<
0
:
raise
TypeError
(
'Options cannot have nargs < 0'
)
if
self
.
prompt
and
self
.
is_flag
and
not
self
.
is_bool_flag
:
raise
TypeError
(
'Cannot prompt for flags that are not bools.'
)
if
not
self
.
is_bool_flag
and
self
.
secondary_opts
:
raise
TypeError
(
'Got secondary option for non boolean flag.'
)
if
self
.
is_bool_flag
and
self
.
hide_input
\
and
self
.
prompt
is
not
None
:
raise
TypeError
(
'Hidden input does not work with boolean '
'flag prompts.'
)
if
self
.
count
:
if
self
.
multiple
:
raise
TypeError
(
'Options cannot be multiple and count '
'at the same time.'
)
elif
self
.
is_flag
:
raise
TypeError
(
'Options cannot be count and flags at '
'the same time.'
)
def
_parse_decls
(
self
,
decls
,
expose_value
):
opts
=
[]
secondary_opts
=
[]
name
=
None
possible_names
=
[]
for
decl
in
decls
:
if
isidentifier
(
decl
):
if
name
is
not
None
:
raise
TypeError
(
'Name defined twice'
)
name
=
decl
else
:
split_char
=
decl
[:
1
]
==
'/'
and
';'
or
'/'
if
split_char
in
decl
:
first
,
second
=
decl
.
split
(
split_char
,
1
)
first
=
first
.
rstrip
()
possible_names
.
append
(
split_opt
(
first
))
opts
.
append
(
first
)
secondary_opts
.
append
(
second
.
lstrip
())
else
:
possible_names
.
append
(
split_opt
(
decl
))
opts
.
append
(
decl
)
if
name
is
None
and
possible_names
:
possible_names
.
sort
(
key
=
lambda
x
:
len
(
x
[
0
]))
name
=
possible_names
[
-
1
][
1
]
.
replace
(
'-'
,
'_'
)
.
lower
()
if
not
isidentifier
(
name
):
name
=
None
if
name
is
None
:
if
not
expose_value
:
return
None
,
opts
,
secondary_opts
raise
TypeError
(
'Could not determine name for option'
)
if
not
opts
and
not
secondary_opts
:
raise
TypeError
(
'No options defined but a name was passed (
%s
). '
'Did you mean to declare an argument instead '
'of an option?'
%
name
)
return
name
,
opts
,
secondary_opts
def
add_to_parser
(
self
,
parser
,
ctx
):
kwargs
=
{
'dest'
:
self
.
name
,
'nargs'
:
self
.
nargs
,
'obj'
:
self
,
}
if
self
.
multiple
:
action
=
'append'
elif
self
.
count
:
action
=
'count'
else
:
action
=
'store'
if
self
.
is_flag
:
kwargs
.
pop
(
'nargs'
,
None
)
if
self
.
is_bool_flag
and
self
.
secondary_opts
:
parser
.
add_option
(
self
.
opts
,
action
=
action
+
'_const'
,
const
=
True
,
**
kwargs
)
parser
.
add_option
(
self
.
secondary_opts
,
action
=
action
+
'_const'
,
const
=
False
,
**
kwargs
)
else
:
parser
.
add_option
(
self
.
opts
,
action
=
action
+
'_const'
,
const
=
self
.
flag_value
,
**
kwargs
)
else
:
kwargs
[
'action'
]
=
action
parser
.
add_option
(
self
.
opts
,
**
kwargs
)
def
get_help_record
(
self
,
ctx
):
any_prefix_is_slash
=
[]
def
_write_opts
(
opts
):
rv
,
any_slashes
=
join_options
(
opts
)
if
any_slashes
:
any_prefix_is_slash
[:]
=
[
True
]
if
not
self
.
is_flag
and
not
self
.
count
:
rv
+=
' '
+
self
.
make_metavar
()
return
rv
rv
=
[
_write_opts
(
self
.
opts
)]
if
self
.
secondary_opts
:
rv
.
append
(
_write_opts
(
self
.
secondary_opts
))
help
=
self
.
help
or
''
extra
=
[]
if
self
.
default
is
not
None
and
self
.
show_default
:
extra
.
append
(
'default:
%s
'
%
(
', '
.
join
(
'
%s
'
%
d
for
d
in
self
.
default
)
if
isinstance
(
self
.
default
,
(
list
,
tuple
))
else
self
.
default
,
))
if
self
.
required
:
extra
.
append
(
'required'
)
if
extra
:
help
=
'
%s
[
%s
]'
%
(
help
and
help
+
' '
or
''
,
'; '
.
join
(
extra
))
return
((
any_prefix_is_slash
and
'; '
or
' / '
)
.
join
(
rv
),
help
)
def
get_default
(
self
,
ctx
):
# If we're a non boolean flag out default is more complex because
# we need to look at all flags in the same group to figure out
# if we're the the default one in which case we return the flag
# value as default.
if
self
.
is_flag
and
not
self
.
is_bool_flag
:
for
param
in
ctx
.
command
.
params
:
if
param
.
name
==
self
.
name
and
param
.
default
:
return
param
.
flag_value
return
None
return
Parameter
.
get_default
(
self
,
ctx
)
def
prompt_for_value
(
self
,
ctx
):
"""This is an alternative flow that can be activated in the full
value processing if a value does not exist. It will prompt the
user until a valid value exists and then returns the processed
value as result.
"""
# Calculate the default before prompting anything to be stable.
default
=
self
.
get_default
(
ctx
)
# If this is a prompt for a flag we need to handle this
# differently.
if
self
.
is_bool_flag
:
return
confirm
(
self
.
prompt
,
default
)
return
prompt
(
self
.
prompt
,
default
=
default
,
hide_input
=
self
.
hide_input
,
confirmation_prompt
=
self
.
confirmation_prompt
,
value_proc
=
lambda
x
:
self
.
process_value
(
ctx
,
x
))
def
resolve_envvar_value
(
self
,
ctx
):
rv
=
Parameter
.
resolve_envvar_value
(
self
,
ctx
)
if
rv
is
not
None
:
return
rv
if
self
.
allow_from_autoenv
and
\
ctx
.
auto_envvar_prefix
is
not
None
:
envvar
=
'
%s
_
%s
'
%
(
ctx
.
auto_envvar_prefix
,
self
.
name
.
upper
())
return
os
.
environ
.
get
(
envvar
)
def
value_from_envvar
(
self
,
ctx
):
rv
=
self
.
resolve_envvar_value
(
ctx
)
if
rv
is
None
:
return
None
value_depth
=
(
self
.
nargs
!=
1
)
+
bool
(
self
.
multiple
)
if
value_depth
>
0
and
rv
is
not
None
:
rv
=
self
.
type
.
split_envvar_value
(
rv
)
if
self
.
multiple
and
self
.
nargs
!=
1
:
rv
=
batch
(
rv
,
self
.
nargs
)
return
rv
def
full_process_value
(
self
,
ctx
,
value
):
if
value
is
None
and
self
.
prompt
is
not
None
\
and
not
ctx
.
resilient_parsing
:
return
self
.
prompt_for_value
(
ctx
)
return
Parameter
.
full_process_value
(
self
,
ctx
,
value
)
class
Argument
(
Parameter
):
"""Arguments are positional parameters to a command. They generally
provide fewer features than options but can have infinite ``nargs``
and are required by default.
All parameters are passed onwards to the parameter constructor.
"""
param_type_name
=
'argument'
def
__init__
(
self
,
param_decls
,
required
=
None
,
**
attrs
):
if
required
is
None
:
if
attrs
.
get
(
'default'
)
is
not
None
:
required
=
False
else
:
required
=
attrs
.
get
(
'nargs'
,
1
)
>
0
Parameter
.
__init__
(
self
,
param_decls
,
required
=
required
,
**
attrs
)
@property
def
human_readable_name
(
self
):
if
self
.
metavar
is
not
None
:
return
self
.
metavar
return
self
.
name
.
upper
()
def
make_metavar
(
self
):
if
self
.
metavar
is
not
None
:
return
self
.
metavar
var
=
self
.
name
.
upper
()
if
not
self
.
required
:
var
=
'[
%s
]'
%
var
if
self
.
nargs
!=
1
:
var
+=
'...'
return
var
def
_parse_decls
(
self
,
decls
,
expose_value
):
if
not
decls
:
if
not
expose_value
:
return
None
,
[],
[]
raise
TypeError
(
'Could not determine name for argument'
)
if
len
(
decls
)
==
1
:
name
=
arg
=
decls
[
0
]
name
=
name
.
replace
(
'-'
,
'_'
)
.
lower
()
elif
len
(
decls
)
==
2
:
name
,
arg
=
decls
else
:
raise
TypeError
(
'Arguments take exactly one or two '
'parameter declarations, got
%d
'
%
len
(
decls
))
return
name
,
[
arg
],
[]
def
get_usage_pieces
(
self
,
ctx
):
return
[
self
.
make_metavar
()]
def
add_to_parser
(
self
,
parser
,
ctx
):
parser
.
add_argument
(
dest
=
self
.
name
,
nargs
=
self
.
nargs
,
obj
=
self
)
# Circular dependency between decorators and core
from
.decorators
import
command
,
group
File Metadata
Details
Attached
Mime Type
text/x-python
Expires
Jun 4 2025, 7:36 PM (9 w, 6 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3399255
Attached To
R193 python3-click
Event Timeline
Log In to Comment