import enum
import errno
import os
import sys
import typing
import typing as t
from collections import abc
from contextlib import contextmanager
from contextlib import ExitStack
from functools import partial
from functools import update_wrapper
from gettext import gettext as _
from gettext import ngettext
from itertools import repeat
from . import types
from . _unicodefun import _verify_python_env
from . exceptions import Abort
from . exceptions import BadParameter
from . exceptions import ClickException
from . exceptions import Exit
from . exceptions import MissingParameter
from . exceptions import UsageError
from . formatting import HelpFormatter
from . formatting import join_options
from . globals import pop_context
from . globals import push_context
from . parser import _flag_needs_value
from . parser import OptionParser
from . parser import split_opt
from . termui import confirm
from . termui import prompt
from . termui import style
from . utils import _detect_program_name
from . utils import _expand_args
from . utils import echo
from . utils import make_default_short_help
from . utils import make_str
from . utils import PacifyFlushWrapper
if t . TYPE_CHECKING :
import typing_extensions as te
from . shell_completion import CompletionItem
F = t . TypeVar ( " F " , bound = t . Callable [ . . . , t . Any ] )
V = t . TypeVar ( " V " )
def _complete_visible_commands (
ctx : " Context " , incomplete : str
) - > t . Iterator [ t . Tuple [ str , " Command " ] ] :
""" List all the subcommands of a group that start with the
incomplete value and aren ' t hidden.
: param ctx : Invocation context for the group .
: param incomplete : Value being completed . May be empty .
"""
multi = t . cast ( MultiCommand , ctx . command )
for name in multi . list_commands ( ctx ) :
if name . startswith ( incomplete ) :
command = multi . get_command ( ctx , name )
if command is not None and not command . hidden :
yield name , command
def _check_multicommand (
base_command : " MultiCommand " , cmd_name : str , cmd : " Command " , register : bool = False
) - > None :
if not base_command . chain or not isinstance ( cmd , MultiCommand ) :
return
if register :
hint = (
" It is not possible to add multi commands as children to "
" another multi command that is in chain mode. "
)
else :
hint = (
" Found a multi command as subcommand to a multi command "
" that is in chain mode. This is not supported. "
)
raise RuntimeError (
f " { hint } . Command { base_command . name !r} is set to chain and "
f " { cmd_name !r} was added as a subcommand but it in itself is a "
f " multi command. ( { cmd_name !r} is a { type ( cmd ) . __name__ } "
f " within a chained { type ( base_command ) . __name__ } named "
f " { base_command . name !r} ). "
)
def batch ( iterable : t . Iterable [ V ] , batch_size : int ) - > t . List [ t . Tuple [ V , . . . ] ] :
return list ( zip ( * repeat ( iter ( iterable ) , batch_size ) ) )
@contextmanager
def augment_usage_errors (
ctx : " Context " , param : t . Optional [ " Parameter " ] = None
) - > t . Iterator [ None ] :
""" Context manager that attaches extra information to exceptions. """
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 : t . Sequence [ " Parameter " ] ,
declaration_order : t . Sequence [ " Parameter " ] ,
) - > t . List [ " Parameter " ] :
""" 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 : " Parameter " ) - > t . Tuple [ bool , float ] :
try :
idx : float = invocation_order . index ( item )
except ValueError :
idx = float ( " inf " )
return not item . is_eager , idx
return sorted ( declaration_order , key = sort_key )
class ParameterSource ( enum . Enum ) :
""" This is an :class:`~enum.Enum` that indicates the source of a
parameter ' s value.
Use : meth : ` click . Context . get_parameter_source ` to get the
source for a parameter by name .
. . versionchanged : : 8.0
Use : class : ` ~ enum . Enum ` and drop the ` ` validate ` ` method .
. . versionchanged : : 8.0
Added the ` ` PROMPT ` ` value .
"""
COMMANDLINE = enum . auto ( )
""" The value was provided by the command line args. """
ENVIRONMENT = enum . auto ( )
""" The value was provided with an environment variable. """
DEFAULT = enum . auto ( )
""" Used the default specified by the parameter. """
DEFAULT_MAP = enum . auto ( )
""" Used a default provided by :attr:`Context.default_map`. """
PROMPT = enum . auto ( )
""" Used a prompt to confirm a default or provide a value. """
class Context :
""" 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 .
: 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 . Default values will also be
ignored . 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 .
: param show_default : Show defaults for all options . If not set ,
defaults to the value from a parent context . Overrides an
option ' s ``show_default`` argument.
. . versionchanged : : 8.0
The ` ` show_default ` ` parameter defaults to the value from the
parent context .
. . versionchanged : : 7.1
Added the ` ` show_default ` ` parameter .
. . versionchanged : : 4.0
Added the ` ` color ` ` , ` ` ignore_unknown_options ` ` , and
` ` max_content_width ` ` parameters .
. . versionchanged : : 3.0
Added the ` ` allow_extra_args ` ` and ` ` allow_interspersed_args ` `
parameters .
. . versionchanged : : 2.0
Added the ` ` resilient_parsing ` ` , ` ` help_option_names ` ` , and
` ` token_normalize_func ` ` parameters .
"""
#: The formatter class to create with :meth:`make_formatter`.
#:
#: .. versionadded:: 8.0
formatter_class : t . Type [ " HelpFormatter " ] = HelpFormatter
def __init__ (
self ,
command : " Command " ,
parent : t . Optional [ " Context " ] = None ,
info_name : t . Optional [ str ] = None ,
obj : t . Optional [ t . Any ] = None ,
auto_envvar_prefix : t . Optional [ str ] = None ,
default_map : t . Optional [ t . Dict [ str , t . Any ] ] = None ,
terminal_width : t . Optional [ int ] = None ,
max_content_width : t . Optional [ int ] = None ,
resilient_parsing : bool = False ,
allow_extra_args : t . Optional [ bool ] = None ,
allow_interspersed_args : t . Optional [ bool ] = None ,
ignore_unknown_options : t . Optional [ bool ] = None ,
help_option_names : t . Optional [ t . List [ str ] ] = None ,
token_normalize_func : t . Optional [ t . Callable [ [ str ] , str ] ] = None ,
color : t . Optional [ bool ] = None ,
show_default : t . Optional [ bool ] = None ,
) - > 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
#: Map of parameter names to their parsed values. Parameters
#: with ``expose_value=False`` are not stored.
self . params : t . Dict [ str , t . Any ] = { }
#: the leftover arguments.
self . args : t . List [ str ] = [ ]
#: protected arguments. These are arguments that are prepended
#: to `args` when certain parsing scenarios are encountered but
#: must be never propagated to another arguments. This is used
#: to implement nested parsing.
self . protected_args : t . List [ str ] = [ ]
if obj is None and parent is not None :
obj = parent . obj
#: the user object stored.
self . obj : t . Any = obj
self . _meta : t . Dict [ str , t . Any ] = getattr ( parent , " meta " , { } )
#: A dictionary (-like object) with defaults for parameters.
if (
default_map is None
and info_name is not None
and parent is not None
and parent . default_map is not None
) :
default_map = parent . default_map . get ( info_name )
self . default_map : t . Optional [ t . Dict [ str , t . Any ] ] = 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:`result_callback`.
self . invoked_subcommand : t . Optional [ str ] = 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 : t . Optional [ int ] = 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 : t . Optional [ int ] = 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 : bool = 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 : bool = 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 : t . List [ str ] = 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 : t . Optional [
t . Callable [ [ str ] , str ]
] = token_normalize_func
#: Indicates if resilient parsing is enabled. In that case Click
#: will do its best to not cause any failures and default values
#: will be ignored. Useful for completion.
self . resilient_parsing : bool = 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 = (
f " { parent . auto_envvar_prefix } _ { self . info_name . upper ( ) } "
)
else :
auto_envvar_prefix = auto_envvar_prefix . upper ( )
if auto_envvar_prefix is not None :
auto_envvar_prefix = auto_envvar_prefix . replace ( " - " , " _ " )
self . auto_envvar_prefix : t . Optional [ str ] = 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 : t . Optional [ bool ] = color
if show_default is None and parent is not None :
show_default = parent . show_default
#: Show option default values when formatting help text.
self . show_default : t . Optional [ bool ] = show_default
self . _close_callbacks : t . List [ t . Callable [ [ ] , t . Any ] ] = [ ]
self . _depth = 0
self . _parameter_source : t . Dict [ str , ParameterSource ] = { }
self . _exit_stack = ExitStack ( )
def to_info_dict ( self ) - > t . Dict [ str , t . Any ] :
""" Gather information that could be useful for a tool generating
user - facing documentation . This traverses the entire CLI
structure .
. . code - block : : python
with Context ( cli ) as ctx :
info = ctx . to_info_dict ( )
. . versionadded : : 8.0
"""
return {
" command " : self . command . to_info_dict ( self ) ,
" info_name " : self . info_name ,
" allow_extra_args " : self . allow_extra_args ,
" allow_interspersed_args " : self . allow_interspersed_args ,
" ignore_unknown_options " : self . ignore_unknown_options ,
" auto_envvar_prefix " : self . auto_envvar_prefix ,
}
def __enter__ ( self ) - > " Context " :
self . _depth + = 1
push_context ( self )
return self
def __exit__ ( self , exc_type , exc_value , tb ) : # type: ignore
self . _depth - = 1
if self . _depth == 0 :
self . close ( )
pop_context ( )
@contextmanager
def scope ( self , cleanup : bool = True ) - > t . Iterator [ " Context " ] :
""" This helper method can be used with the context object to promote
it to the current thread local ( see : func : ` get_current_context ` ) .
The default behavior of this is to invoke the cleanup functions which
can be disabled by setting ` cleanup ` to ` False ` . The cleanup
functions are typically used for things such as closing file handles .
If the cleanup is intended the context object can also be directly
used as a context manager .
Example usage : :
with ctx . scope ( ) :
assert get_current_context ( ) is ctx
This is equivalent : :
with ctx :
assert get_current_context ( ) is ctx
. . versionadded : : 5.0
: param cleanup : controls if the cleanup functions should be run or
not . The default is to run these functions . In
some situations the context only wants to be
temporarily pushed in which case this can be disabled .
Nested pushes automatically defer the cleanup .
"""
if not cleanup :
self . _depth + = 1
try :
with self as rv :
yield rv
finally :
if not cleanup :
self . _depth - = 1
@property
def meta ( self ) - > t . Dict [ str , t . Any ] :
""" This is a dictionary which is shared with all the contexts
that are nested . It exists so that click utilities can store some
state here if they need to . It is however the responsibility of
that code to manage this dictionary well .
The keys are supposed to be unique dotted strings . For instance
module paths are a good choice for it . What is stored in there is
irrelevant for the operation of click . However what is important is
that code that places data here adheres to the general semantics of
the system .
Example usage : :
LANG_KEY = f ' { __name__ } .lang '
def set_language ( value ) :
ctx = get_current_context ( )
ctx . meta [ LANG_KEY ] = value
def get_language ( ) :
return get_current_context ( ) . meta . get ( LANG_KEY , ' en_US ' )
. . versionadded : : 5.0
"""
return self . _meta
def make_formatter ( self ) - > HelpFormatter :
""" Creates the :class:`~click.HelpFormatter` for the help and
usage output .
To quickly customize the formatter class used without overriding
this method , set the : attr : ` formatter_class ` attribute .
. . versionchanged : : 8.0
Added the : attr : ` formatter_class ` attribute .
"""
return self . formatter_class (
width = self . terminal_width , max_width = self . max_content_width
)
def with_resource ( self , context_manager : t . ContextManager [ V ] ) - > V :
""" Register a resource as if it were used in a ``with``
statement . The resource will be cleaned up when the context is
popped .
Uses : meth : ` contextlib . ExitStack . enter_context ` . It calls the
resource ' s ``__enter__()`` method and returns the result. When
the context is popped , it closes the stack , which calls the
resource ' s ``__exit__()`` method.
To register a cleanup function for something that isn ' t a
context manager , use : meth : ` call_on_close ` . Or use something
from : mod : ` contextlib ` to turn it into a context manager first .
. . code - block : : python
@click.group ( )
@click.option ( " --name " )
@click.pass_context
def cli ( ctx ) :
ctx . obj = ctx . with_resource ( connect_db ( name ) )
: param context_manager : The context manager to enter .
: return : Whatever ` ` context_manager . __enter__ ( ) ` ` returns .
. . versionadded : : 8.0
"""
return self . _exit_stack . enter_context ( context_manager )
def call_on_close ( self , f : t . Callable [ . . . , t . Any ] ) - > t . Callable [ . . . , t . Any ] :
""" Register a function to be called when the context tears down.
This can be used to close resources opened during the script
execution . Resources that support Python ' s context manager
protocol which would be used in a ` ` with ` ` statement should be
registered with : meth : ` with_resource ` instead .
: param f : The function to execute on teardown .
"""
return self . _exit_stack . callback ( f )
def close ( self ) - > None :
""" Invoke all close callbacks registered with
: meth : ` call_on_close ` , and exit all context managers entered
with : meth : ` with_resource ` .
"""
self . _exit_stack . close ( )
# In case the context is reused, create a new exit stack.
self . _exit_stack = ExitStack ( )
@property
def command_path ( self ) - > str :
""" 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 :
parent_command_path = [ self . parent . command_path ]
if isinstance ( self . parent . command , Command ) :
for param in self . parent . command . get_params ( self ) :
parent_command_path . extend ( param . get_usage_pieces ( self ) )
rv = f " { ' ' . join ( parent_command_path ) } { rv } "
return rv . lstrip ( )
def find_root ( self ) - > " Context " :
""" Finds the outermost context. """
node = self
while node . parent is not None :
node = node . parent
return node
def find_object ( self , object_type : t . Type [ V ] ) - > t . Optional [ V ] :
""" Finds the closest object of a given type. """
node : t . Optional [ " Context " ] = self
while node is not None :
if isinstance ( node . obj , object_type ) :
return node . obj
node = node . parent
return None
def ensure_object ( self , object_type : t . Type [ V ] ) - > V :
""" 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
@typing.overload
def lookup_default (
self , name : str , call : " te.Literal[True] " = True
) - > t . Optional [ t . Any ] :
. . .
@typing.overload
def lookup_default (
self , name : str , call : " te.Literal[False] " = . . .
) - > t . Optional [ t . Union [ t . Any , t . Callable [ [ ] , t . Any ] ] ] :
. . .
def lookup_default ( self , name : str , call : bool = True ) - > t . Optional [ t . Any ] :
""" Get the default for a parameter from :attr:`default_map`.
: param name : Name of the parameter .
: param call : If the default is a callable , call it . Disable to
return the callable instead .
. . versionchanged : : 8.0
Added the ` ` call ` ` parameter .
"""
if self . default_map is not None :
value = self . default_map . get ( name )
if call and callable ( value ) :
return value ( )
return value
return None
def fail ( self , message : str ) - > " te.NoReturn " :
""" 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 ) - > " te.NoReturn " :
""" Aborts the script. """
raise Abort ( )
def exit ( self , code : int = 0 ) - > " te.NoReturn " :
""" Exits the application with a given exit code. """
raise Exit ( code )
def get_usage ( self ) - > str :
""" Helper method to get formatted usage string for the current
context and command .
"""
return self . command . get_usage ( self )
def get_help ( self ) - > str :
""" Helper method to get formatted help page for the current
context and command .
"""
return self . command . get_help ( self )
def _make_sub_context ( self , command : " Command " ) - > " Context " :
""" Create a new context of the same type as this context, but
for a new command .
: meta private :
"""
return type ( self ) ( command , info_name = command . name , parent = self )
def invoke (
__self , # noqa: B902
__callback : t . Union [ " Command " , t . Callable [ . . . , t . Any ] ] ,
* args : t . Any ,
* * kwargs : t . Any ,
) - > t . Any :
""" 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 ` .
. . versionchanged : : 8.0
All ` ` kwargs ` ` are tracked in : attr : ` params ` so they will be
passed if : meth : ` forward ` is called at multiple levels .
"""
if isinstance ( __callback , Command ) :
other_cmd = __callback
if other_cmd . callback is None :
raise TypeError (
" The given command does not have a callback that can be invoked. "
)
else :
__callback = other_cmd . callback
ctx = __self . _make_sub_context ( other_cmd )
for param in other_cmd . params :
if param . name not in kwargs and param . expose_value :
kwargs [ param . name ] = param . type_cast_value ( # type: ignore
ctx , param . get_default ( ctx )
)
# Track all kwargs as params, so that forward() will pass
# them on in subsequent calls.
ctx . params . update ( kwargs )
else :
ctx = __self
with augment_usage_errors ( __self ) :
with ctx :
return __callback ( * args , * * kwargs )
def forward (
__self , __cmd : " Command " , * args : t . Any , * * kwargs : t . Any # noqa: B902
) - > t . Any :
""" 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 .
. . versionchanged : : 8.0
All ` ` kwargs ` ` are tracked in : attr : ` params ` so they will be
passed if ` ` forward ` ` is called at multiple levels .
"""
# Can only forward to other commands, not direct callbacks.
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 , * args , * * kwargs )
def set_parameter_source ( self , name : str , source : ParameterSource ) - > None :
""" Set the source of a parameter. This indicates the location
from which the value of the parameter was obtained .
: param name : The name of the parameter .
: param source : A member of : class : ` ~ click . core . ParameterSource ` .
"""
self . _parameter_source [ name ] = source
def get_parameter_source ( self , name : str ) - > t . Optional [ ParameterSource ] :
""" Get the source of a parameter. This indicates the location
from which the value of the parameter was obtained .
This can be useful for determining when a user specified a value
on the command line that is the same as the default value . It
will be : attr : ` ~ click . core . ParameterSource . DEFAULT ` only if the
value was actually taken from the default .
: param name : The name of the parameter .
: rtype : ParameterSource
. . versionchanged : : 8.0
Returns ` ` None ` ` if the parameter was not provided from any
source .
"""
return self . _parameter_source . get ( name )
class BaseCommand :
""" 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 context class to create with :meth:`make_context`.
#:
#: .. versionadded:: 8.0
context_class : t . Type [ Context ] = Context
#: 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 : t . Optional [ str ] ,
context_settings : t . Optional [ t . Dict [ str , t . Any ] ] = None ,
) - > 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 : t . Dict [ str , t . Any ] = context_settings
def to_info_dict ( self , ctx : Context ) - > t . Dict [ str , t . Any ] :
""" Gather information that could be useful for a tool generating
user - facing documentation . This traverses the entire structure
below this command .
Use : meth : ` click . Context . to_info_dict ` to traverse the entire
CLI structure .
: param ctx : A : class : ` Context ` representing this command .
. . versionadded : : 8.0
"""
return { " name " : self . name }
def __repr__ ( self ) - > str :
return f " < { self . __class__ . __name__ } { self . name } > "
def get_usage ( self , ctx : Context ) - > str :
raise NotImplementedError ( " Base commands cannot get usage " )
def get_help ( self , ctx : Context ) - > str :
raise NotImplementedError ( " Base commands cannot get help " )
def make_context (
self ,
info_name : t . Optional [ str ] ,
args : t . List [ str ] ,
parent : t . Optional [ Context ] = None ,
* * extra : t . Any ,
) - > Context :
""" 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 .
To quickly customize the context class used without overriding
this method , set the : attr : ` context_class ` attribute .
: 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 ' s usually
the name of the script , for commands below it it ' s
the name of the command .
: 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 .
. . versionchanged : : 8.0
Added the : attr : ` context_class ` attribute .
"""
for key , value in self . context_settings . items ( ) :
if key not in extra :
extra [ key ] = value
ctx = self . context_class (
self , info_name = info_name , parent = parent , * * extra # type: ignore
)
with ctx . scope ( cleanup = False ) :
self . parse_args ( ctx , args )
return ctx
def parse_args ( self , ctx : Context , args : t . List [ str ] ) - > t . List [ str ] :
""" 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 : Context ) - > t . Any :
""" 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 shell_complete ( self , ctx : Context , incomplete : str ) - > t . List [ " CompletionItem " ] :
""" Return a list of completions for the incomplete value. Looks
at the names of chained multi - commands .
Any command could be part of a chained multi - command , so sibling
commands are valid at any point during command completion . Other
command classes will return more completions .
: param ctx : Invocation context for this command .
: param incomplete : Value being completed . May be empty .
. . versionadded : : 8.0
"""
from click . shell_completion import CompletionItem
results : t . List [ " CompletionItem " ] = [ ]
while ctx . parent is not None :
ctx = ctx . parent
if isinstance ( ctx . command , MultiCommand ) and ctx . command . chain :
results . extend (
CompletionItem ( name , help = command . get_short_help_str ( ) )
for name , command in _complete_visible_commands ( ctx , incomplete )
if name not in ctx . protected_args
)
return results
@typing.overload
def main (
self ,
args : t . Optional [ t . Sequence [ str ] ] = None ,
prog_name : t . Optional [ str ] = None ,
complete_var : t . Optional [ str ] = None ,
standalone_mode : " te.Literal[True] " = True ,
* * extra : t . Any ,
) - > " te.NoReturn " :
. . .
@typing.overload
def main (
self ,
args : t . Optional [ t . Sequence [ str ] ] = None ,
prog_name : t . Optional [ str ] = None ,
complete_var : t . Optional [ str ] = None ,
standalone_mode : bool = . . . ,
* * extra : t . Any ,
) - > t . Any :
. . .
def main (
self ,
args : t . Optional [ t . Sequence [ str ] ] = None ,
prog_name : t . Optional [ str ] = None ,
complete_var : t . Optional [ str ] = None ,
standalone_mode : bool = True ,
windows_expand_args : bool = True ,
* * extra : t . Any ,
) - > t . Any :
""" 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 ` .
: 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 windows_expand_args : Expand glob patterns , user dir , and
env vars in command line args on Windows .
: param extra : extra keyword arguments are forwarded to the context
constructor . See : class : ` Context ` for more information .
. . versionchanged : : 8.0 .1
Added the ` ` windows_expand_args ` ` parameter to allow
disabling command line arg expansion on Windows .
. . versionchanged : : 8.0
When taking arguments from ` ` sys . argv ` ` on Windows , glob
patterns , user dir , and env vars are expanded .
. . versionchanged : : 3.0
Added the ` ` standalone_mode ` ` parameter .
"""
# Verify that the environment is configured correctly, or reject
# further execution to avoid a broken script.
_verify_python_env ( )
if args is None :
args = sys . argv [ 1 : ]
if os . name == " nt " and windows_expand_args :
args = _expand_args ( args )
else :
args = list ( args )
if prog_name is None :
prog_name = _detect_program_name ( )
# Process shell completion requests and exit early.
self . _main_shell_completion ( extra , 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
# it's not safe to `ctx.exit(rv)` here!
# note that `rv` may actually contain data like "1" which
# has obvious effects
# more subtle case: `rv=[None, None]` can come out of
# chained commands which all returned `None` -- so it's not
# even always obvious that `rv` indicates success/failure
# by its truthiness/falsiness
ctx . exit ( )
except ( EOFError , KeyboardInterrupt ) :
echo ( file = sys . stderr )
raise Abort ( ) from None
except ClickException as e :
if not standalone_mode :
raise
e . show ( )
sys . exit ( e . exit_code )
except OSError as e :
if e . errno == errno . EPIPE :
sys . stdout = t . cast ( t . TextIO , PacifyFlushWrapper ( sys . stdout ) )
sys . stderr = t . cast ( t . TextIO , PacifyFlushWrapper ( sys . stderr ) )
sys . exit ( 1 )
else :
raise
except Exit as e :
if standalone_mode :
sys . exit ( e . exit_code )
else :
# in non-standalone mode, return the exit code
# note that this is only reached if `self.invoke` above raises
# an Exit explicitly -- thus bypassing the check there which
# would return its result
# the results of non-standalone execution may therefore be
# somewhat ambiguous: if there are codepaths which lead to
# `ctx.exit(1)` and to `return 1`, the caller won't be able to
# tell the difference between the two
return e . exit_code
except Abort :
if not standalone_mode :
raise
echo ( _ ( " Aborted! " ) , file = sys . stderr )
sys . exit ( 1 )
def _main_shell_completion (
self ,
ctx_args : t . Dict [ str , t . Any ] ,
prog_name : str ,
complete_var : t . Optional [ str ] = None ,
) - > None :
""" Check if the shell is asking for tab completion, process
that , then exit early . Called from : meth : ` main ` before the
program is invoked .
: param prog_name : Name of the executable in the shell .
: param complete_var : Name of the environment variable that holds
the completion instruction . Defaults to
` ` _ { PROG_NAME } _COMPLETE ` ` .
"""
if complete_var is None :
complete_var = f " _ { prog_name } _COMPLETE " . replace ( " - " , " _ " ) . upper ( )
instruction = os . environ . get ( complete_var )
if not instruction :
return
from . shell_completion import shell_complete
rv = shell_complete ( self , ctx_args , prog_name , complete_var , instruction )
sys . exit ( rv )
def __call__ ( self , * args : t . Any , * * kwargs : t . Any ) - > t . Any :
""" 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 .
. . versionchanged : : 8.0
Added repr showing the command name
. . versionchanged : : 7.1
Added the ` no_args_is_help ` 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 .
: param no_args_is_help : this controls what happens if no arguments are
provided . This option is disabled by default .
If enabled this will add ` ` - - help ` ` as argument
if no arguments are passed
: param hidden : hide this command from help outputs .
: param deprecated : issues a message indicating that
the command is deprecated .
"""
def __init__ (
self ,
name : t . Optional [ str ] ,
context_settings : t . Optional [ t . Dict [ str , t . Any ] ] = None ,
callback : t . Optional [ t . Callable [ . . . , t . Any ] ] = None ,
params : t . Optional [ t . List [ " Parameter " ] ] = None ,
help : t . Optional [ str ] = None ,
epilog : t . Optional [ str ] = None ,
short_help : t . Optional [ str ] = None ,
options_metavar : t . Optional [ str ] = " [OPTIONS] " ,
add_help_option : bool = True ,
no_args_is_help : bool = False ,
hidden : bool = False ,
deprecated : bool = False ,
) - > None :
super ( ) . __init__ ( 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 : t . List [ " Parameter " ] = params or [ ]
# if a form feed (page break) is found in the help text, truncate help
# text to the content preceding the first form feed
if help and " \f " in help :
help = help . split ( " \f " , 1 ) [ 0 ]
self . help = help
self . epilog = epilog
self . options_metavar = options_metavar
self . short_help = short_help
self . add_help_option = add_help_option
self . no_args_is_help = no_args_is_help
self . hidden = hidden
self . deprecated = deprecated
def to_info_dict ( self , ctx : Context ) - > t . Dict [ str , t . Any ] :
info_dict = super ( ) . to_info_dict ( ctx )
info_dict . update (
params = [ param . to_info_dict ( ) for param in self . get_params ( ctx ) ] ,
help = self . help ,
epilog = self . epilog ,
short_help = self . short_help ,
hidden = self . hidden ,
deprecated = self . deprecated ,
)
return info_dict
def get_usage ( self , ctx : Context ) - > str :
""" Formats the usage line into a string and returns it.
Calls : meth : ` format_usage ` internally .
"""
formatter = ctx . make_formatter ( )
self . format_usage ( ctx , formatter )
return formatter . getvalue ( ) . rstrip ( " \n " )
def get_params ( self , ctx : Context ) - > t . List [ " Parameter " ] :
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 : Context , formatter : HelpFormatter ) - > None :
""" Writes the usage line into the formatter.
This is a low - level method called by : meth : ` get_usage ` .
"""
pieces = self . collect_usage_pieces ( ctx )
formatter . write_usage ( ctx . command_path , " " . join ( pieces ) )
def collect_usage_pieces ( self , ctx : Context ) - > t . List [ str ] :
""" Returns all the pieces that go into the usage line and returns
it as a list of strings .
"""
rv = [ self . options_metavar ] if self . options_metavar else [ ]
for param in self . get_params ( ctx ) :
rv . extend ( param . get_usage_pieces ( ctx ) )
return rv
def get_help_option_names ( self , ctx : Context ) - > t . List [ str ] :
""" 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 list ( all_names )
def get_help_option ( self , ctx : Context ) - > t . Optional [ " Option " ] :
""" Returns the help option object. """
help_options = self . get_help_option_names ( ctx )
if not help_options or not self . add_help_option :
return None
def show_help ( ctx : Context , param : " Parameter " , value : str ) - > None :
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 : Context ) - > OptionParser :
""" Creates the underlying option parser for this command. """
parser = OptionParser ( ctx )
for param in self . get_params ( ctx ) :
param . add_to_parser ( parser , ctx )
return parser
def get_help ( self , ctx : Context ) - > str :
""" Formats the help into a string and returns it.
Calls : meth : ` format_help ` internally .
"""
formatter = ctx . make_formatter ( )
self . format_help ( ctx , formatter )
return formatter . getvalue ( ) . rstrip ( " \n " )
def get_short_help_str ( self , limit : int = 45 ) - > str :
""" Gets short help for the command or makes it by shortening the
long help string .
"""
text = self . short_help or " "
if not text and self . help :
text = make_default_short_help ( self . help , limit )
if self . deprecated :
text = _ ( " (Deprecated) {text} " ) . format ( text = text )
return text . strip ( )
def format_help ( self , ctx : Context , formatter : HelpFormatter ) - > None :
""" Writes the help into the formatter if it exists.
This is a low - level method called by : meth : ` get_help ` .
This calls 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 : Context , formatter : HelpFormatter ) - > None :
""" Writes the help text to the formatter if it exists. """
text = self . help or " "
if self . deprecated :
text = _ ( " (Deprecated) {text} " ) . format ( text = text )
if text :
formatter . write_paragraph ( )
with formatter . indentation ( ) :
formatter . write_text ( text )
def format_options ( self , ctx : Context , formatter : HelpFormatter ) - > None :
""" 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 : Context , formatter : HelpFormatter ) - > None :
""" 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 : Context , args : t . List [ str ] ) - > t . List [ str ] :
if not args and self . no_args_is_help and not ctx . resilient_parsing :
echo ( ctx . get_help ( ) , color = ctx . color )
ctx . exit ( )
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 (
ngettext (
" Got unexpected extra argument ( {args} ) " ,
" Got unexpected extra arguments ( {args} ) " ,
len ( args ) ,
) . format ( args = " " . join ( map ( str , args ) ) )
)
ctx . args = args
return args
def invoke ( self , ctx : Context ) - > t . Any :
""" Given a context, this invokes the attached callback (if it exists)
in the right way .
"""
if self . deprecated :
message = _ (
" DeprecationWarning: The command {name!r} is deprecated. "
) . format ( name = self . name )
echo ( style ( message , fg = " red " ) , err = True )
if self . callback is not None :
return ctx . invoke ( self . callback , * * ctx . params )
def shell_complete ( self , ctx : Context , incomplete : str ) - > t . List [ " CompletionItem " ] :
""" Return a list of completions for the incomplete value. Looks
at the names of options and chained multi - commands .
: param ctx : Invocation context for this command .
: param incomplete : Value being completed . May be empty .
. . versionadded : : 8.0
"""
from click . shell_completion import CompletionItem
results : t . List [ " CompletionItem " ] = [ ]
if incomplete and not incomplete [ 0 ] . isalnum ( ) :
for param in self . get_params ( ctx ) :
if (
not isinstance ( param , Option )
or param . hidden
or (
not param . multiple
and ctx . get_parameter_source ( param . name ) # type: ignore
is ParameterSource . COMMANDLINE
)
) :
continue
results . extend (
CompletionItem ( name , help = param . help )
for name in [ * param . opts , * param . secondary_opts ]
if name . startswith ( incomplete )
)
results . extend ( super ( ) . shell_complete ( ctx , incomplete ) )
return results
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 . This can be set or changed later with the
: meth : ` result_callback ` decorator .
"""
allow_extra_args = True
allow_interspersed_args = False
def __init__ (
self ,
name : t . Optional [ str ] = None ,
invoke_without_command : bool = False ,
no_args_is_help : t . Optional [ bool ] = None ,
subcommand_metavar : t . Optional [ str ] = None ,
chain : bool = False ,
result_callback : t . Optional [ t . Callable [ . . . , t . Any ] ] = None ,
* * attrs : t . Any ,
) - > None :
super ( ) . __init__ ( 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 = " COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]... "
else :
subcommand_metavar = " COMMAND [ARGS]... "
self . subcommand_metavar = subcommand_metavar
self . chain = chain
# The result callback that is stored. This can be set or
# overridden with the :func:`result_callback` decorator.
self . _result_callback = result_callback
if self . chain :
for param in self . params :
if isinstance ( param , Argument ) and not param . required :
raise RuntimeError (
" Multi commands in chain mode cannot have "
" optional arguments. "
)
def to_info_dict ( self , ctx : Context ) - > t . Dict [ str , t . Any ] :
info_dict = super ( ) . to_info_dict ( ctx )
commands = { }
for name in self . list_commands ( ctx ) :
command = self . get_command ( ctx , name )
if command is None :
continue
sub_ctx = ctx . _make_sub_context ( command )
with sub_ctx . scope ( cleanup = False ) :
commands [ name ] = command . to_info_dict ( sub_ctx )
info_dict . update ( commands = commands , chain = self . chain )
return info_dict
def collect_usage_pieces ( self , ctx : Context ) - > t . List [ str ] :
rv = super ( ) . collect_usage_pieces ( ctx )
rv . append ( self . subcommand_metavar )
return rv
def format_options ( self , ctx : Context , formatter : HelpFormatter ) - > None :
super ( ) . format_options ( ctx , formatter )
self . format_commands ( ctx , formatter )
def result_callback ( self , replace : bool = False ) - > t . Callable [ [ F ] , F ] :
""" Adds a result callback to the 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.result_callback ( )
def process_result ( result , input ) :
return result + input
: param replace : if set to ` True ` an already existing result
callback will be removed .
. . versionchanged : : 8.0
Renamed from ` ` resultcallback ` ` .
. . versionadded : : 3.0
"""
def decorator ( f : F ) - > F :
old_callback = self . _result_callback
if old_callback is None or replace :
self . _result_callback = f
return f
def function ( __value , * args , * * kwargs ) : # type: ignore
inner = old_callback ( __value , * args , * * kwargs ) # type: ignore
return f ( inner , * args , * * kwargs )
self . _result_callback = rv = update_wrapper ( t . cast ( F , function ) , f )
return rv
return decorator
def resultcallback ( self , replace : bool = False ) - > t . Callable [ [ F ] , F ] :
import warnings
warnings . warn (
" ' resultcallback ' has been renamed to ' result_callback ' . "
" The old name will be removed in Click 8.1. " ,
DeprecationWarning ,
stacklevel = 2 ,
)
return self . result_callback ( replace = replace )
def format_commands ( self , ctx : Context , formatter : HelpFormatter ) - > None :
""" Extra format methods for multi methods that adds all the commands
after the options .
"""
commands = [ ]
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
if cmd . hidden :
continue
commands . append ( ( subcommand , cmd ) )
# allow for 3 times the default spacing
if len ( commands ) :
limit = formatter . width - 6 - max ( len ( cmd [ 0 ] ) for cmd in commands )
rows = [ ]
for subcommand , cmd in commands :
help = cmd . get_short_help_str ( limit )
rows . append ( ( subcommand , help ) )
if rows :
with formatter . section ( _ ( " Commands " ) ) :
formatter . write_dl ( rows )
def parse_args ( self , ctx : Context , args : t . List [ str ] ) - > t . List [ str ] :
if not args and self . no_args_is_help and not ctx . resilient_parsing :
echo ( ctx . get_help ( ) , color = ctx . color )
ctx . exit ( )
rest = super ( ) . parse_args ( ctx , args )
if self . chain :
ctx . protected_args = rest
ctx . args = [ ]
elif rest :
ctx . protected_args , ctx . args = rest [ : 1 ] , rest [ 1 : ]
return ctx . args
def invoke ( self , ctx : Context ) - > t . Any :
def _process_result ( value : t . Any ) - > t . Any :
if self . _result_callback is not None :
value = ctx . invoke ( self . _result_callback , value , * * ctx . params )
return value
if not ctx . protected_args :
if self . invoke_without_command :
# No subcommand was invoked, so the result callback is
# invoked with None for regular groups, or an empty list
# for chained groups.
with ctx :
super ( ) . invoke ( ctx )
return _process_result ( [ ] if self . chain else None )
ctx . fail ( _ ( " Missing command. " ) )
# Fetch args back out
args = [ * ctx . protected_args , * ctx . args ]
ctx . args = [ ]
ctx . protected_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 )
assert cmd is not None
ctx . invoked_subcommand = cmd_name
super ( ) . invoke ( 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 = " * " if args else None
super ( ) . invoke ( 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 )
assert cmd is not None
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 = 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 : Context , args : t . List [ str ]
) - > t . Tuple [ t . Optional [ str ] , t . Optional [ Command ] , t . List [ str ] ] :
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 and not ctx . resilient_parsing :
if split_opt ( cmd_name ) [ 0 ] :
self . parse_args ( ctx , ctx . args )
ctx . fail ( _ ( " No such command {name!r} . " ) . format ( name = original_cmd_name ) )
return cmd_name if cmd else None , cmd , args [ 1 : ]
def get_command ( self , ctx : Context , cmd_name : str ) - > t . Optional [ Command ] :
""" 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 : Context ) - > t . List [ str ] :
""" Returns a list of subcommand names in the order they should
appear .
"""
return [ ]
def shell_complete ( self , ctx : Context , incomplete : str ) - > t . List [ " CompletionItem " ] :
""" Return a list of completions for the incomplete value. Looks
at the names of options , subcommands , and chained
multi - commands .
: param ctx : Invocation context for this command .
: param incomplete : Value being completed . May be empty .
. . versionadded : : 8.0
"""
from click . shell_completion import CompletionItem
results = [
CompletionItem ( name , help = command . get_short_help_str ( ) )
for name , command in _complete_visible_commands ( ctx , incomplete )
]
results . extend ( super ( ) . shell_complete ( ctx , incomplete ) )
return results
class Group ( MultiCommand ) :
""" A group allows a command to have subcommands attached. This is
the most common way to implement nesting in Click .
: param name : The name of the group command .
: param commands : A dict mapping names to : class : ` Command ` objects .
Can also be a list of : class : ` Command ` , which will use
: attr : ` Command . name ` to create the dict .
: param attrs : Other command arguments described in
: class : ` MultiCommand ` , : class : ` Command ` , and
: class : ` BaseCommand ` .
. . versionchanged : : 8.0
The ` ` commmands ` ` argument can be a list of command objects .
"""
#: If set, this is used by the group's :meth:`command` decorator
#: as the default :class:`Command` class. This is useful to make all
#: subcommands use a custom command class.
#:
#: .. versionadded:: 8.0
command_class : t . Optional [ t . Type [ Command ] ] = None
#: If set, this is used by the group's :meth:`group` decorator
#: as the default :class:`Group` class. This is useful to make all
#: subgroups use a custom group class.
#:
#: If set to the special value :class:`type` (literally
#: ``group_class = type``), this group's class will be used as the
#: default class. This makes a custom group class continue to make
#: custom groups.
#:
#: .. versionadded:: 8.0
group_class : t . Optional [ t . Union [ t . Type [ " Group " ] , t . Type [ type ] ] ] = None
# Literal[type] isn't valid, so use Type[type]
def __init__ (
self ,
name : t . Optional [ str ] = None ,
commands : t . Optional [ t . Union [ t . Dict [ str , Command ] , t . Sequence [ Command ] ] ] = None ,
* * attrs : t . Any ,
) - > None :
super ( ) . __init__ ( name , * * attrs )
if commands is None :
commands = { }
elif isinstance ( commands , abc . Sequence ) :
commands = { c . name : c for c in commands if c . name is not None }
#: The registered subcommands by their exported names.
self . commands : t . Dict [ str , Command ] = commands
def add_command ( self , cmd : Command , name : t . Optional [ str ] = None ) - > 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. " )
_check_multicommand ( self , name , cmd , register = True )
self . commands [ name ] = cmd
def command (
self , * args : t . Any , * * kwargs : t . Any
) - > t . Callable [ [ t . Callable [ . . . , t . Any ] ] , Command ] :
""" A shortcut decorator for declaring and attaching a command to
the group . This takes the same arguments as : func : ` command ` and
immediately registers the created command with this group by
calling : meth : ` add_command ` .
To customize the command class used , set the
: attr : ` command_class ` attribute .
. . versionchanged : : 8.0
Added the : attr : ` command_class ` attribute .
"""
from . decorators import command
if self . command_class is not None and " cls " not in kwargs :
kwargs [ " cls " ] = self . command_class
def decorator ( f : t . Callable [ . . . , t . Any ] ) - > Command :
cmd = command ( * args , * * kwargs ) ( f )
self . add_command ( cmd )
return cmd
return decorator
def group (
self , * args : t . Any , * * kwargs : t . Any
) - > t . Callable [ [ t . Callable [ . . . , t . Any ] ] , " Group " ] :
""" A shortcut decorator for declaring and attaching a group to
the group . This takes the same arguments as : func : ` group ` and
immediately registers the created group with this group by
calling : meth : ` add_command ` .
To customize the group class used , set the : attr : ` group_class `
attribute .
. . versionchanged : : 8.0
Added the : attr : ` group_class ` attribute .
"""
from . decorators import group
if self . group_class is not None and " cls " not in kwargs :
if self . group_class is type :
kwargs [ " cls " ] = type ( self )
else :
kwargs [ " cls " ] = self . group_class
def decorator ( f : t . Callable [ . . . , t . Any ] ) - > " Group " :
cmd = group ( * args , * * kwargs ) ( f )
self . add_command ( cmd )
return cmd
return decorator
def get_command ( self , ctx : Context , cmd_name : str ) - > t . Optional [ Command ] :
return self . commands . get ( cmd_name )
def list_commands ( self , ctx : Context ) - > t . List [ str ] :
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 : t . Optional [ str ] = None ,
sources : t . Optional [ t . List [ MultiCommand ] ] = None ,
* * attrs : t . Any ,
) - > None :
super ( ) . __init__ ( name , * * attrs )
#: The list of registered multi commands.
self . sources : t . List [ MultiCommand ] = sources or [ ]
def add_source ( self , multi_cmd : MultiCommand ) - > None :
""" Adds a new multi command to the chain dispatcher. """
self . sources . append ( multi_cmd )
def get_command ( self , ctx : Context , cmd_name : str ) - > t . Optional [ Command ] :
for source in self . sources :
rv = source . get_command ( ctx , cmd_name )
if rv is not None :
if self . chain :
_check_multicommand ( self , cmd_name , rv )
return rv
return None
def list_commands ( self , ctx : Context ) - > t . List [ str ] :
rv : t . Set [ str ] = set ( )
for source in self . sources :
rv . update ( source . list_commands ( ctx ) )
return sorted ( rv )
def _check_iter ( value : t . Any ) - > t . Iterator [ t . Any ] :
""" Check if the value is iterable but not a string. Raises a type
error , or return an iterator over the value .
"""
if isinstance ( value , str ) :
raise TypeError
return iter ( value )
class Parameter :
r """ 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 .
: 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 function to further process or validate the value
after type conversion . It is called as ` ` f ( ctx , param , value ) ` `
and must return the value . It is called for all sources ,
including prompts .
: 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 ) . If ` ` nargs = - 1 ` ` , all remaining
parameters are collected .
: 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 shell_complete : A function that returns custom shell
completions . Used instead of the param ' s type completion if
given . Takes ` ` ctx , param , incomplete ` ` and must return a list
of : class : ` ~ click . shell_completion . CompletionItem ` or a list of
strings .
. . versionchanged : : 8.0
` ` process_value ` ` validates required parameters and bounded
` ` nargs ` ` , and invokes the parameter callback before returning
the value . This allows the callback to validate prompts .
` ` full_process_value ` ` is removed .
. . versionchanged : : 8.0
` ` autocompletion ` ` is renamed to ` ` shell_complete ` ` and has new
semantics described above . The old name is deprecated and will
be removed in 8.1 , until then it will be wrapped to match the
new requirements .
. . versionchanged : : 8.0
For ` ` multiple = True , nargs > 1 ` ` , the default must be a list of
tuples .
. . versionchanged : : 8.0
Setting a default is no longer required for ` ` nargs > 1 ` ` , it will
default to ` ` None ` ` . ` ` multiple = True ` ` or ` ` nargs = - 1 ` ` will
default to ` ` ( ) ` ` .
. . versionchanged : : 7.1
Empty environment variables are ignored rather than taking the
empty string value . This makes it possible for scripts to clear
variables if they can ' t unset them.
. . versionchanged : : 2.0
Changed signature for parameter callback to also be passed the
parameter . The old callback format will still work , but it will
raise a warning to give you a chance to migrate the code easier .
"""
param_type_name = " parameter "
def __init__ (
self ,
param_decls : t . Optional [ t . Sequence [ str ] ] = None ,
type : t . Optional [ t . Union [ types . ParamType , t . Any ] ] = None ,
required : bool = False ,
default : t . Optional [ t . Union [ t . Any , t . Callable [ [ ] , t . Any ] ] ] = None ,
callback : t . Optional [ t . Callable [ [ Context , " Parameter " , t . Any ] , t . Any ] ] = None ,
nargs : t . Optional [ int ] = None ,
multiple : bool = False ,
metavar : t . Optional [ str ] = None ,
expose_value : bool = True ,
is_eager : bool = False ,
envvar : t . Optional [ t . Union [ str , t . Sequence [ str ] ] ] = None ,
shell_complete : t . Optional [
t . Callable [
[ Context , " Parameter " , str ] ,
t . Union [ t . List [ " CompletionItem " ] , t . List [ str ] ] ,
]
] = None ,
autocompletion : t . Optional [
t . Callable [
[ Context , t . List [ str ] , str ] , t . List [ t . Union [ t . Tuple [ str , str ] , str ] ]
]
] = None ,
) - > None :
self . name , self . opts , self . secondary_opts = self . _parse_decls (
param_decls or ( ) , expose_value
)
self . type = types . 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 = multiple
self . expose_value = expose_value
self . default = default
self . is_eager = is_eager
self . metavar = metavar
self . envvar = envvar
if autocompletion is not None :
import warnings
warnings . warn (
" ' autocompletion ' is renamed to ' shell_complete ' . The old name is "
" deprecated and will be removed in Click 8.1. See the docs about "
" ' Parameter ' for information about new behavior. " ,
DeprecationWarning ,
stacklevel = 2 ,
)
def shell_complete (
ctx : Context , param : " Parameter " , incomplete : str
) - > t . List [ " CompletionItem " ] :
from click . shell_completion import CompletionItem
out = [ ]
for c in autocompletion ( ctx , [ ] , incomplete ) : # type: ignore
if isinstance ( c , tuple ) :
c = CompletionItem ( c [ 0 ] , help = c [ 1 ] )
elif isinstance ( c , str ) :
c = CompletionItem ( c )
if c . value . startswith ( incomplete ) :
out . append ( c )
return out
self . _custom_shell_complete = shell_complete
if __debug__ :
if self . type . is_composite and nargs != self . type . arity :
raise ValueError (
f " ' nargs ' must be { self . type . arity } (or None) for "
f " type { self . type !r} , but it was { nargs } . "
)
# Skip no default or callable default.
check_default = default if not callable ( default ) else None
if check_default is not None :
if multiple :
try :
# Only check the first value against nargs.
check_default = next ( _check_iter ( check_default ) , None )
except TypeError :
raise ValueError (
" ' default ' must be a list when ' multiple ' is true. "
) from None
# Can be None for multiple with empty default.
if nargs != 1 and check_default is not None :
try :
_check_iter ( check_default )
except TypeError :
if multiple :
message = (
" ' default ' must be a list of lists when ' multiple ' is "
" true and ' nargs ' != 1. "
)
else :
message = " ' default ' must be a list when ' nargs ' != 1. "
raise ValueError ( message ) from None
if nargs > 1 and len ( check_default ) != nargs :
subject = " item length " if multiple else " length "
raise ValueError (
f " ' default ' { subject } must match nargs= { nargs } . "
)
def to_info_dict ( self ) - > t . Dict [ str , t . Any ] :
""" Gather information that could be useful for a tool generating
user - facing documentation .
Use : meth : ` click . Context . to_info_dict ` to traverse the entire
CLI structure .
. . versionadded : : 8.0
"""
return {
" name " : self . name ,
" param_type_name " : self . param_type_name ,
" opts " : self . opts ,
" secondary_opts " : self . secondary_opts ,
" type " : self . type . to_info_dict ( ) ,
" required " : self . required ,
" nargs " : self . nargs ,
" multiple " : self . multiple ,
" default " : self . default ,
" envvar " : self . envvar ,
}
def __repr__ ( self ) - > str :
return f " < { self . __class__ . __name__ } { self . name } > "
def _parse_decls (
self , decls : t . Sequence [ str ] , expose_value : bool
) - > t . Tuple [ t . Optional [ str ] , t . List [ str ] , t . List [ str ] ] :
raise NotImplementedError ( )
@property
def human_readable_name ( self ) - > str :
""" 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 # type: ignore
def make_metavar ( self ) - > str :
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
@typing.overload
def get_default (
self , ctx : Context , call : " te.Literal[True] " = True
) - > t . Optional [ t . Any ] :
. . .
@typing.overload
def get_default (
self , ctx : Context , call : bool = . . .
) - > t . Optional [ t . Union [ t . Any , t . Callable [ [ ] , t . Any ] ] ] :
. . .
def get_default (
self , ctx : Context , call : bool = True
) - > t . Optional [ t . Union [ t . Any , t . Callable [ [ ] , t . Any ] ] ] :
""" Get the default for the parameter. Tries
: meth : ` Context . lookup_default ` first , then the local default .
: param ctx : Current context .
: param call : If the default is a callable , call it . Disable to
return the callable instead .
. . versionchanged : : 8.0 .2
Type casting is no longer performed when getting a default .
. . versionchanged : : 8.0 .1
Type casting can fail in resilient parsing mode . Invalid
defaults will not prevent showing help text .
. . versionchanged : : 8.0
Looks at ` ` ctx . default_map ` ` first .
. . versionchanged : : 8.0
Added the ` ` call ` ` parameter .
"""
value = ctx . lookup_default ( self . name , call = False ) # type: ignore
if value is None :
value = self . default
if call and callable ( value ) :
value = value ( )
return value
def add_to_parser ( self , parser : OptionParser , ctx : Context ) - > None :
raise NotImplementedError ( )
def consume_value (
self , ctx : Context , opts : t . Mapping [ str , t . Any ]
) - > t . Tuple [ t . Any , ParameterSource ] :
value = opts . get ( self . name ) # type: ignore
source = ParameterSource . COMMANDLINE
if value is None :
value = self . value_from_envvar ( ctx )
source = ParameterSource . ENVIRONMENT
if value is None :
value = ctx . lookup_default ( self . name ) # type: ignore
source = ParameterSource . DEFAULT_MAP
if value is None :
value = self . get_default ( ctx )
source = ParameterSource . DEFAULT
return value , source
def type_cast_value ( self , ctx : Context , value : t . Any ) - > t . Any :
""" Convert and validate a value against the option ' s
: attr : ` type ` , : attr : ` multiple ` , and : attr : ` nargs ` .
"""
if value is None :
return ( ) if self . multiple or self . nargs == - 1 else None
def check_iter ( value : t . Any ) - > t . Iterator :
try :
return _check_iter ( value )
except TypeError :
# This should only happen when passing in args manually,
# the parser should construct an iterable when parsing
# the command line.
raise BadParameter (
_ ( " Value must be an iterable. " ) , ctx = ctx , param = self
) from None
if self . nargs == 1 or self . type . is_composite :
convert : t . Callable [ [ t . Any ] , t . Any ] = partial (
self . type , param = self , ctx = ctx
)
elif self . nargs == - 1 :
def convert ( value : t . Any ) - > t . Tuple :
return tuple ( self . type ( x , self , ctx ) for x in check_iter ( value ) )
else : # nargs > 1
def convert ( value : t . Any ) - > t . Tuple :
value = tuple ( check_iter ( value ) )
if len ( value ) != self . nargs :
raise BadParameter (
ngettext (
" Takes {nargs} values but 1 was given. " ,
" Takes {nargs} values but {len} were given. " ,
len ( value ) ,
) . format ( nargs = self . nargs , len = len ( value ) ) ,
ctx = ctx ,
param = self ,
)
return tuple ( self . type ( x , self , ctx ) for x in value )
if self . multiple :
return tuple ( convert ( x ) for x in check_iter ( value ) )
return convert ( value )
def value_is_missing ( self , value : t . Any ) - > bool :
if value is None :
return True
if ( self . nargs != 1 or self . multiple ) and value == ( ) :
return True
return False
def process_value ( self , ctx : Context , value : t . Any ) - > t . Any :
value = self . type_cast_value ( ctx , value )
if self . required and self . value_is_missing ( value ) :
raise MissingParameter ( ctx = ctx , param = self )
if self . callback is not None :
value = self . callback ( ctx , self , value )
return value
def resolve_envvar_value ( self , ctx : Context ) - > t . Optional [ str ] :
if self . envvar is None :
return None
if isinstance ( self . envvar , str ) :
rv = os . environ . get ( self . envvar )
if rv :
return rv
else :
for envvar in self . envvar :
rv = os . environ . get ( envvar )
if rv :
return rv
return None
def value_from_envvar ( self , ctx : Context ) - > t . Optional [ t . Any ] :
rv : t . Optional [ t . Any ] = 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 : Context , opts : t . Mapping [ str , t . Any ] , args : t . List [ str ]
) - > t . Tuple [ t . Any , t . List [ str ] ] :
with augment_usage_errors ( ctx , param = self ) :
value , source = self . consume_value ( ctx , opts )
ctx . set_parameter_source ( self . name , source ) # type: ignore
try :
value = self . process_value ( ctx , value )
except Exception :
if not ctx . resilient_parsing :
raise
value = None
if self . expose_value :
ctx . params [ self . name ] = value # type: ignore
return value , args
def get_help_record ( self , ctx : Context ) - > t . Optional [ t . Tuple [ str , str ] ] :
pass
def get_usage_pieces ( self , ctx : Context ) - > t . List [ str ] :
return [ ]
def get_error_hint ( self , ctx : Context ) - > str :
""" Get a stringified version of the param for use in error messages to
indicate which param caused the error .
"""
hint_list = self . opts or [ self . human_readable_name ]
return " / " . join ( f " ' { x } ' " for x in hint_list )
def shell_complete ( self , ctx : Context , incomplete : str ) - > t . List [ " CompletionItem " ] :
""" Return a list of completions for the incomplete value. If a
` ` shell_complete ` ` function was given during init , it is used .
Otherwise , the : attr : ` type `
: meth : ` ~ click . types . ParamType . shell_complete ` function is used .
: param ctx : Invocation context for this command .
: param incomplete : Value being completed . May be empty .
. . versionadded : : 8.0
"""
if self . _custom_shell_complete is not None :
results = self . _custom_shell_complete ( ctx , self , incomplete )
if results and isinstance ( results [ 0 ] , str ) :
from click . shell_completion import CompletionItem
results = [ CompletionItem ( c ) for c in results ]
return t . cast ( t . List [ " CompletionItem " ] , results )
return self . type . shell_complete ( ctx , self , incomplete )
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 . If this
value is a string , it shows the string instead of the
value . This is particularly useful for dynamic options .
: param show_envvar : controls if an environment variable should be shown on
the help page . Normally , environment variables
are not shown .
: param prompt : if set to ` True ` or a non empty string then the user will be
prompted for input . If set to ` True ` the prompt will be the
option name capitalized .
: param confirmation_prompt : Prompt a second time to confirm the
value if it was prompted for . Can be set to a string instead of
` ` True ` ` to customize the message .
: param prompt_required : If set to ` ` False ` ` , the user will be
prompted for input only when the option was specified as a flag
without a value .
: 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 hidden : hide this option from help outputs .
. . versionchanged : : 8.0 .1
` ` type ` ` is detected from ` ` flag_value ` ` if given .
"""
param_type_name = " option "
def __init__ (
self ,
param_decls : t . Optional [ t . Sequence [ str ] ] = None ,
show_default : t . Union [ bool , str ] = False ,
prompt : t . Union [ bool , str ] = False ,
confirmation_prompt : t . Union [ bool , str ] = False ,
prompt_required : bool = True ,
hide_input : bool = False ,
is_flag : t . Optional [ bool ] = None ,
flag_value : t . Optional [ t . Any ] = None ,
multiple : bool = False ,
count : bool = False ,
allow_from_autoenv : bool = True ,
type : t . Optional [ t . Union [ types . ParamType , t . Any ] ] = None ,
help : t . Optional [ str ] = None ,
hidden : bool = False ,
show_choices : bool = True ,
show_envvar : bool = False ,
* * attrs : t . Any ,
) - > None :
default_is_missing = " default " not in attrs
super ( ) . __init__ ( param_decls , type = type , multiple = multiple , * * attrs )
if prompt is True :
if self . name is None :
raise TypeError ( " ' name ' is required with ' prompt=True ' . " )
prompt_text : t . Optional [ str ] = self . name . replace ( " _ " , " " ) . capitalize ( )
elif prompt is False :
prompt_text = None
else :
prompt_text = t . cast ( str , prompt )
self . prompt = prompt_text
self . confirmation_prompt = confirmation_prompt
self . prompt_required = prompt_required
self . hide_input = hide_input
self . hidden = hidden
# If prompt is enabled but not required, then the option can be
# used as a flag to indicate using prompt or flag_value.
self . _flag_needs_value = self . prompt is not None and not self . prompt_required
if is_flag is None :
if flag_value is not None :
# Implicitly a flag because flag_value was set.
is_flag = True
elif self . _flag_needs_value :
# Not a flag, but when used as a flag it shows a prompt.
is_flag = False
else :
# Implicitly a flag because flag options were given.
is_flag = bool ( self . secondary_opts )
elif is_flag is False and not self . _flag_needs_value :
# Not a flag, and prompt is not enabled, can be used as a
# flag if flag_value is set.
self . _flag_needs_value = flag_value is not None
if is_flag and default_is_missing :
self . default : t . Union [ t . Any , t . Callable [ [ ] , t . Any ] ] = False
if flag_value is None :
flag_value = not self . default
if is_flag and type is None :
# Re-guess the type from the flag value instead of the
# default.
self . type = types . convert_type ( None , flag_value )
self . is_flag : bool = is_flag
self . is_bool_flag = is_flag and isinstance ( self . type , types . BoolParamType )
self . flag_value : t . Any = flag_value
# Counting
self . count = count
if count :
if type is None :
self . type = types . IntRange ( min = 0 )
if default_is_missing :
self . default = 0
self . allow_from_autoenv = allow_from_autoenv
self . help = help
self . show_default = show_default
self . show_choices = show_choices
self . show_envvar = show_envvar
if __debug__ :
if self . nargs == - 1 :
raise TypeError ( " nargs=-1 is not supported for options. " )
if self . prompt and self . is_flag and not self . is_bool_flag :
raise TypeError ( " ' prompt ' is not valid for non-boolean flag. " )
if not self . is_bool_flag and self . secondary_opts :
raise TypeError ( " Secondary flag is not valid for non-boolean flag. " )
if self . is_bool_flag and self . hide_input and self . prompt is not None :
raise TypeError (
" ' prompt ' with ' hide_input ' is not valid for boolean flag. "
)
if self . count :
if self . multiple :
raise TypeError ( " ' count ' is not valid with ' multiple ' . " )
if self . is_flag :
raise TypeError ( " ' count ' is not valid with ' is_flag ' . " )
def to_info_dict ( self ) - > t . Dict [ str , t . Any ] :
info_dict = super ( ) . to_info_dict ( )
info_dict . update (
help = self . help ,
prompt = self . prompt ,
is_flag = self . is_flag ,
flag_value = self . flag_value ,
count = self . count ,
hidden = self . hidden ,
)
return info_dict
def _parse_decls (
self , decls : t . Sequence [ str ] , expose_value : bool
) - > t . Tuple [ t . Optional [ str ] , t . List [ str ] , t . List [ str ] ] :
opts = [ ]
secondary_opts = [ ]
name = None
possible_names = [ ]
for decl in decls :
if decl . isidentifier ( ) :
if name is not None :
raise TypeError ( f " Name ' { name } ' defined twice " )
name = decl
else :
split_char = " ; " if decl [ : 1 ] == " / " else " / "
if split_char in decl :
first , second = decl . split ( split_char , 1 )
first = first . rstrip ( )
if first :
possible_names . append ( split_opt ( first ) )
opts . append ( first )
second = second . lstrip ( )
if second :
secondary_opts . append ( second . lstrip ( ) )
if first == second :
raise ValueError (
f " Boolean option { decl !r} cannot use the "
" same flag for true/false. "
)
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 ] ) ) # group long options first
name = possible_names [ 0 ] [ 1 ] . replace ( " - " , " _ " ) . lower ( )
if not name . isidentifier ( ) :
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 (
f " No options defined but a name was passed ( { name } ). "
" Did you mean to declare an argument instead? Did "
f " you mean to pass ' -- { name } ' ? "
)
return name , opts , secondary_opts
def add_to_parser ( self , parser : OptionParser , ctx : Context ) - > None :
if self . multiple :
action = " append "
elif self . count :
action = " count "
else :
action = " store "
if self . is_flag :
action = f " { action } _const "
if self . is_bool_flag and self . secondary_opts :
parser . add_option (
obj = self , opts = self . opts , dest = self . name , action = action , const = True
)
parser . add_option (
obj = self ,
opts = self . secondary_opts ,
dest = self . name ,
action = action ,
const = False ,
)
else :
parser . add_option (
obj = self ,
opts = self . opts ,
dest = self . name ,
action = action ,
const = self . flag_value ,
)
else :
parser . add_option (
obj = self ,
opts = self . opts ,
dest = self . name ,
action = action ,
nargs = self . nargs ,
)
def get_help_record ( self , ctx : Context ) - > t . Optional [ t . Tuple [ str , str ] ] :
if self . hidden :
return None
any_prefix_is_slash = False
def _write_opts ( opts : t . Sequence [ str ] ) - > str :
nonlocal any_prefix_is_slash
rv , any_slashes = join_options ( opts )
if any_slashes :
any_prefix_is_slash = True
if not self . is_flag and not self . count :
rv + = f " { 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 . show_envvar :
envvar = self . envvar
if envvar is None :
if (
self . allow_from_autoenv
and ctx . auto_envvar_prefix is not None
and self . name is not None
) :
envvar = f " { ctx . auto_envvar_prefix } _ { self . name . upper ( ) } "
if envvar is not None :
var_str = (
envvar
if isinstance ( envvar , str )
else " , " . join ( str ( d ) for d in envvar )
)
extra . append ( _ ( " env var: {var} " ) . format ( var = var_str ) )
# Temporarily enable resilient parsing to avoid type casting
# failing for the default. Might be possible to extend this to
# help formatting in general.
resilient = ctx . resilient_parsing
ctx . resilient_parsing = True
try :
default_value = self . get_default ( ctx , call = False )
finally :
ctx . resilient_parsing = resilient
show_default_is_str = isinstance ( self . show_default , str )
if show_default_is_str or (
default_value is not None and ( self . show_default or ctx . show_default )
) :
if show_default_is_str :
default_string = f " ( { self . show_default } ) "
elif isinstance ( default_value , ( list , tuple ) ) :
default_string = " , " . join ( str ( d ) for d in default_value )
elif callable ( default_value ) :
default_string = _ ( " (dynamic) " )
elif self . is_bool_flag and self . secondary_opts :
# For boolean flags that have distinct True/False opts,
# use the opt without prefix instead of the value.
default_string = split_opt (
( self . opts if self . default else self . secondary_opts ) [ 0 ]
) [ 1 ]
else :
default_string = str ( default_value )
if default_string :
extra . append ( _ ( " default: {default} " ) . format ( default = default_string ) )
if (
isinstance ( self . type , types . _NumberRangeBase )
# skip count with default range type
and not ( self . count and self . type . min == 0 and self . type . max is None )
) :
range_str = self . type . _describe_range ( )
if range_str :
extra . append ( range_str )
if self . required :
extra . append ( _ ( " required " ) )
if extra :
extra_str = " ; " . join ( extra )
help = f " { help } [ { extra_str } ] " if help else f " [ { extra_str } ] "
return ( " ; " if any_prefix_is_slash else " / " ) . join ( rv ) , help
@typing.overload
def get_default (
self , ctx : Context , call : " te.Literal[True] " = True
) - > t . Optional [ t . Any ] :
. . .
@typing.overload
def get_default (
self , ctx : Context , call : bool = . . .
) - > t . Optional [ t . Union [ t . Any , t . Callable [ [ ] , t . Any ] ] ] :
. . .
def get_default (
self , ctx : Context , call : bool = True
) - > t . Optional [ t . Union [ t . Any , t . Callable [ [ ] , t . Any ] ] ] :
# If we're a non boolean flag our 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 # type: ignore
return None
return super ( ) . get_default ( ctx , call = call )
def prompt_for_value ( self , ctx : Context ) - > t . Any :
""" 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 .
"""
assert self . prompt is not None
# 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 ,
type = self . type ,
hide_input = self . hide_input ,
show_choices = self . show_choices ,
confirmation_prompt = self . confirmation_prompt ,
value_proc = lambda x : self . process_value ( ctx , x ) ,
)
def resolve_envvar_value ( self , ctx : Context ) - > t . Optional [ str ] :
rv = super ( ) . resolve_envvar_value ( ctx )
if rv is not None :
return rv
if (
self . allow_from_autoenv
and ctx . auto_envvar_prefix is not None
and self . name is not None
) :
envvar = f " { ctx . auto_envvar_prefix } _ { self . name . upper ( ) } "
rv = os . environ . get ( envvar )
return rv
def value_from_envvar ( self , ctx : Context ) - > t . Optional [ t . Any ] :
rv : t . Optional [ t . Any ] = self . resolve_envvar_value ( ctx )
if rv is None :
return None
value_depth = ( self . nargs != 1 ) + bool ( self . multiple )
if value_depth > 0 :
rv = self . type . split_envvar_value ( rv )
if self . multiple and self . nargs != 1 :
rv = batch ( rv , self . nargs )
return rv
def consume_value (
self , ctx : Context , opts : t . Mapping [ str , " Parameter " ]
) - > t . Tuple [ t . Any , ParameterSource ] :
value , source = super ( ) . consume_value ( ctx , opts )
# The parser will emit a sentinel value if the option can be
# given as a flag without a value. This is different from None
# to distinguish from the flag not being given at all.
if value is _flag_needs_value :
if self . prompt is not None and not ctx . resilient_parsing :
value = self . prompt_for_value ( ctx )
source = ParameterSource . PROMPT
else :
value = self . flag_value
source = ParameterSource . COMMANDLINE
elif (
self . multiple
and value is not None
and any ( v is _flag_needs_value for v in value )
) :
value = [ self . flag_value if v is _flag_needs_value else v for v in value ]
source = ParameterSource . COMMANDLINE
# The value wasn't set, or used the param's default, prompt if
# prompting is enabled.
elif (
source in { None , ParameterSource . DEFAULT }
and self . prompt is not None
and ( self . required or self . prompt_required )
and not ctx . resilient_parsing
) :
value = self . prompt_for_value ( ctx )
source = ParameterSource . PROMPT
return value , source
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 : t . Sequence [ str ] ,
required : t . Optional [ bool ] = None ,
* * attrs : t . Any ,
) - > None :
if required is None :
if attrs . get ( " default " ) is not None :
required = False
else :
required = attrs . get ( " nargs " , 1 ) > 0
if " multiple " in attrs :
raise TypeError ( " __init__() got an unexpected keyword argument ' multiple ' . " )
super ( ) . __init__ ( param_decls , required = required , * * attrs )
if __debug__ :
if self . default is not None and self . nargs == - 1 :
raise TypeError ( " ' default ' is not supported for nargs=-1. " )
@property
def human_readable_name ( self ) - > str :
if self . metavar is not None :
return self . metavar
return self . name . upper ( ) # type: ignore
def make_metavar ( self ) - > str :
if self . metavar is not None :
return self . metavar
var = self . type . get_metavar ( self )
if not var :
var = self . name . upper ( ) # type: ignore
if not self . required :
var = f " [ { var } ] "
if self . nargs != 1 :
var + = " ... "
return var
def _parse_decls (
self , decls : t . Sequence [ str ] , expose_value : bool
) - > t . Tuple [ t . Optional [ str ] , t . List [ str ] , t . List [ str ] ] :
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 ( )
else :
raise TypeError (
" Arguments take exactly one parameter declaration, got "
f " { len ( decls ) } . "
)
return name , [ arg ] , [ ]
def get_usage_pieces ( self , ctx : Context ) - > t . List [ str ] :
return [ self . make_metavar ( ) ]
def get_error_hint ( self , ctx : Context ) - > str :
return f " ' { self . make_metavar ( ) } ' "
def add_to_parser ( self , parser : OptionParser , ctx : Context ) - > None :
parser . add_argument ( dest = self . name , nargs = self . nargs , obj = self )