Context¶
Every app has a special internal object that keeps track of state relevant to the script's execution.
For some advanced use-cases, you may want to access it directly.
This can be done by declaring a function parameter of type typer.Context.
Similarly, you can also declare a function parameter with type typer.CallbackParam in case a callback could be used
by several CLI parameters, and you need to figure out which one it was.
from typing import Annotated
import typer
app = typer.Typer()
def name_callback(ctx: typer.Context, param: typer.CallbackParam, value: str):
if ctx.resilient_parsing:
return
print(f"Validating param: {param.name}")
if value != "Rick":
raise typer.BadParameter("Only Rick is allowed")
return value
@app.command()
def main(name: Annotated[str | None, typer.Option(callback=name_callback)] = None):
print(f"Hello {name}")
if __name__ == "__main__":
app()
typer.Context
¶
Context(
command,
parent=None,
info_name=None,
obj=None,
auto_envvar_prefix=None,
default_map=None,
terminal_width=None,
max_content_width=None,
resilient_parsing=False,
allow_extra_args=None,
allow_interspersed_args=None,
ignore_unknown_options=None,
help_option_names=None,
token_normalize_func=None,
color=None,
show_default=None,
)
Bases: Context
The Context has some additional data about the current execution of your program.
When declaring it in a callback function,
you can access this additional information.
Source code in typer/_click/core.py
def __init__(
self,
command: "Command",
parent: Union["Context", None] = None,
info_name: str | None = None,
obj: Any | None = None,
auto_envvar_prefix: str | None = None,
default_map: MutableMapping[str, Any] | None = None,
terminal_width: int | None = None,
max_content_width: int | None = None,
resilient_parsing: bool = False,
allow_extra_args: bool | None = None,
allow_interspersed_args: bool | None = None,
ignore_unknown_options: bool | None = None,
help_option_names: list[str] | None = None,
token_normalize_func: Callable[[str], str] | None = None,
color: bool | None = None,
show_default: bool | None = None,
) -> None:
self.parent = parent
self.command = command
self.info_name = info_name
# Map of parameter names to their parsed values.
self.params: dict[str, Any] = {}
# the leftover arguments.
self.args: list[str] = []
# protected arguments. used to implement nested parsing.
self._protected_args: list[str] = []
# the collected prefixes of the command's options.
self._opt_prefixes: set[str] = set(parent._opt_prefixes) if parent else set()
if obj is None and parent is not None:
obj = parent.obj
self.obj: Any = obj
self._meta: dict[str, 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: MutableMapping[str, Any] | None = default_map
# This flag indicates if a subcommand is going to be executed.
self.invoked_subcommand: str | None = 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: int | None = terminal_width
if max_content_width is None and parent is not None:
max_content_width = parent.max_content_width
self.max_content_width: int | None = max_content_width
if allow_extra_args is None:
allow_extra_args = command.allow_extra_args
self.allow_extra_args = allow_extra_args
if allow_interspersed_args is None:
allow_interspersed_args = command.allow_interspersed_args
self.allow_interspersed_args: bool = allow_interspersed_args
if ignore_unknown_options is None:
ignore_unknown_options = command.ignore_unknown_options
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"]
self.help_option_names: 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. (options, choices, commands etc.)
self.token_normalize_func: Callable[[str], str] | None = token_normalize_func
# Indicates if resilient parsing is enabled.
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: str | None = 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: bool | None = 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: bool | None = show_default
self._close_callbacks: list[Callable[[], Any]] = []
self._depth = 0
self._parameter_source: dict[str, ParameterSource] = {}
self._exit_stack = ExitStack()
meta
property
¶
meta
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.
command_path
property
¶
command_path
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.
scope
¶
scope(cleanup=True)
This helper method can be used with the context object to promote
it to the current thread local (see 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.
Source code in typer/_click/core.py
@contextmanager
def scope(self, cleanup: bool = True) -> Iterator["Context"]:
"""This helper method can be used with the context object to promote
it to the current thread local (see `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.
"""
if not cleanup:
self._depth += 1
try:
with self as rv:
yield rv
finally:
if not cleanup:
self._depth -= 1
make_formatter
¶
make_formatter()
Creates the HelpFormatter for the help and usage output.
Source code in typer/_click/core.py
def make_formatter(self) -> HelpFormatter:
"""Creates the HelpFormatter for the help and
usage output.
"""
return self.formatter_class(
width=self.terminal_width, max_width=self.max_content_width
)
with_resource
¶
with_resource(context_manager)
Register a resource as if it were used in a with
statement. The resource will be cleaned up when the context is
popped.
Uses 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 call_on_close. Or use something
from contextlib to turn it into a context manager first.
Source code in typer/_click/core.py
def with_resource(self, context_manager: AbstractContextManager[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 `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 `call_on_close`. Or use something
from `contextlib` to turn it into a context manager first.
"""
return self._exit_stack.enter_context(context_manager)
call_on_close
¶
call_on_close(f)
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 with_resource instead.
Source code in typer/_click/core.py
def call_on_close(self, f: Callable[..., Any]) -> Callable[..., 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 `with_resource` instead.
"""
return self._exit_stack.callback(f)
close
¶
close()
Invoke all close callbacks registered with call_on_close,
and exit all context managers entered with with_resource.
Source code in typer/_click/core.py
def close(self) -> None:
"""Invoke all close callbacks registered with `call_on_close`,
and exit all context managers entered with `with_resource`.
"""
self._close_with_exception_info(None, None, None)
find_root
¶
find_root()
Finds the outermost context.
Source code in typer/_click/core.py
def find_root(self) -> "Context":
"""Finds the outermost context."""
node = self
while node.parent is not None:
node = node.parent
return node
find_object
¶
find_object(object_type)
Finds the closest object of a given type.
Source code in typer/_click/core.py
def find_object(self, object_type: type[V]) -> V | None:
"""Finds the closest object of a given type."""
node: Context | None = self
while node is not None:
if isinstance(node.obj, object_type):
return node.obj
node = node.parent
return None
ensure_object
¶
ensure_object(object_type)
Like find_object but sets the innermost object to a
new instance of object_type if it does not exist.
Source code in typer/_click/core.py
def ensure_object(self, object_type: type[V]) -> V:
"""Like `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
lookup_default
¶
lookup_default(
name: str, call: Literal[True] = True
) -> Any | None
lookup_default(
name: str, call: Literal[False] = ...
) -> Any | Callable[[], Any] | None
lookup_default(name, call=True)
Get the default for a parameter from default_map.
Source code in typer/_click/core.py
def lookup_default(self, name: str, call: bool = True) -> Any | None:
"""Get the default for a parameter from `default_map`."""
if self.default_map is not None:
value = self.default_map.get(name)
if call and callable(value):
return value()
return value
return None
fail
¶
fail(message)
Aborts the execution of the program with a specific error message.
Source code in typer/_click/core.py
def fail(self, message: str) -> NoReturn:
"""Aborts the execution of the program with a specific error
message.
"""
raise UsageError(message, self)
abort
¶
abort()
Aborts the script.
Source code in typer/_click/core.py
def abort(self) -> NoReturn:
"""Aborts the script."""
raise Abort()
exit
¶
exit(code=0)
Exits the application with a given exit code.
Source code in typer/_click/core.py
def exit(self, code: int = 0) -> NoReturn:
"""Exits the application with a given exit code."""
self.close()
raise Exit(code)
get_usage
¶
get_usage()
Helper method to get formatted usage string for the current context and command.
Source code in typer/_click/core.py
def get_usage(self) -> str:
"""Helper method to get formatted usage string for the current
context and command.
"""
return self.command.get_usage(self)
get_help
¶
get_help()
Helper method to get formatted help page for the current context and command.
Source code in typer/_click/core.py
def get_help(self) -> str:
"""Helper method to get formatted help page for the current
context and command.
"""
return self.command.get_help(self)
invoke
¶
invoke(callback, /, *args, **kwargs)
Invokes a command callback in exactly the way it expects. There are two ways to invoke this method:
- the first argument can be a callback and all other arguments and keyword arguments are forwarded directly to the function.
- 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.
Source code in typer/_click/core.py
def invoke(self, callback: Callable[..., V], /, *args: Any, **kwargs: Any) -> V:
"""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.
"""
ctx = self
with augment_usage_errors(self):
with ctx:
return callback(*args, **kwargs)
set_parameter_source
¶
set_parameter_source(name, source)
Set the source of a parameter. This indicates the location from which the value of the parameter was obtained.
Source code in typer/_click/core.py
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.
"""
self._parameter_source[name] = source
get_parameter_source
¶
get_parameter_source(name)
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 ParameterSource.DEFAULT only if the
value was actually taken from the default.
Source code in typer/_click/core.py
def get_parameter_source(self, name: str) -> ParameterSource | None:
"""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 `ParameterSource.DEFAULT` only if the
value was actually taken from the default.
"""
return self._parameter_source.get(name)
typer.CallbackParam
¶
CallbackParam(
param_decls=None,
type=None,
required=False,
default=None,
callback=None,
nargs=None,
multiple=False,
metavar=None,
expose_value=True,
is_eager=False,
envvar=None,
shell_complete=None,
)
Bases: Parameter
In a callback function, you can declare a function parameter with type CallbackParam
to access the specific Click Parameter object.
Source code in typer/_click/core.py
def __init__(
self,
param_decls: Sequence[str] | None = None,
type: types.ParamType | Any | None = None,
required: bool = False,
default: Any | Callable[[], Any] | None = None,
callback: Callable[[Context, "Parameter", Any], Any] | None = None,
nargs: int | None = None,
multiple: bool = False,
metavar: str | None = None,
expose_value: bool = True,
is_eager: bool = False,
envvar: str | Sequence[str] | None = None,
shell_complete: Callable[
[Context, "Parameter", str], list["CompletionItem"] | list[str]
]
| None = None,
) -> None:
self.name: str | None
self.opts: list[str]
self.secondary_opts: list[str]
self.name, self.opts, self.secondary_opts = self._parse_decls(
param_decls or (), expose_value
)
self.type: types.ParamType = 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: Any | Callable[[], Any] | None = default
self.is_eager = is_eager
self.metavar = metavar
self.envvar = envvar
self._custom_shell_complete = shell_complete
human_readable_name
property
¶
human_readable_name
Returns the human readable name of this parameter. This is the same as the name for options, but the metavar for arguments.
make_metavar
¶
make_metavar(ctx)
Source code in typer/_click/core.py
def make_metavar(self, ctx: Context) -> str:
if self.metavar is not None:
return self.metavar
metavar = self.type.get_metavar(param=self, ctx=ctx)
if metavar is None:
metavar = self.type.name.upper()
if self.nargs != 1:
metavar += "..."
return metavar
get_default
¶
get_default(
ctx: Context, call: Literal[True] = True
) -> Any | None
get_default(
ctx: Context, call: bool = ...
) -> Any | Callable[[], Any] | None
get_default(ctx, call=True)
Get the default for the parameter
Source code in typer/_click/core.py
def get_default(
self, ctx: Context, call: bool = True
) -> Any | Callable[[], Any] | None:
"""Get the default for the 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
add_to_parser
abstractmethod
¶
add_to_parser(parser, ctx)
Source code in typer/_click/core.py
@abstractmethod
def add_to_parser(self, parser: _OptionParser, ctx: Context) -> None:
pass # pragma: no cover
consume_value
¶
consume_value(ctx, opts)
Source code in typer/_click/core.py
def consume_value(
self, ctx: Context, opts: Mapping[str, Any]
) -> tuple[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
type_cast_value
¶
type_cast_value(ctx, value)
Convert and validate a value against the parameter's
type, multiple, and nargs.
Source code in typer/_click/core.py
def type_cast_value(self, ctx: Context, value: Any) -> Any:
"""Convert and validate a value against the parameter's
`type`, `multiple`, and `nargs`.
"""
if value is None:
return () if self.multiple or self.nargs == -1 else None
def check_iter(value: Any) -> Iterator[Any]:
assert not isinstance(value, str)
return iter(value)
# Define the conversion function based on nargs and type.
if self.nargs == 1 or self.type.is_composite:
def convert(value: Any) -> Any:
return self.type(value, param=self, ctx=ctx)
elif self.nargs == -1:
def convert(value: Any) -> Any: # tuple[t.Any, ...]
return tuple(self.type(x, self, ctx) for x in check_iter(value))
else: # nargs > 1
def convert(value: Any) -> Any: # tuple[t.Any, ...]
value = tuple(check_iter(value))
if len(value) != self.nargs:
raise BadParameter(
f"Takes {self.nargs} values but {len(value)} given.",
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)
value_is_missing
abstractmethod
¶
value_is_missing(value)
Source code in typer/_click/core.py
@abstractmethod
def value_is_missing(self, value: Any) -> bool:
pass # pragma: no cover
process_value
¶
process_value(ctx, value)
Process the value of this parameter
Source code in typer/_click/core.py
def process_value(self, ctx: Context, value: Any) -> Any:
"""Process the value of this parameter"""
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
resolve_envvar_value
¶
resolve_envvar_value(ctx)
Returns the value found in the environment variable(s) attached to this parameter.
Environment variables values are always returned as strings
<https://docs.python.org/3/library/os.html#os.environ>_.
This method returns None if:
- the
envvarproperty is not set onParameter, - the environment variable is not found in the environment,
- the variable is found in the environment but its value is empty (i.e. the environment variable is present but has an empty string).
If envvar is setup with multiple environment variables,
then only the first non-empty value is returned.
Source code in typer/_click/core.py
def resolve_envvar_value(self, ctx: Context) -> str | None:
"""Returns the value found in the environment variable(s) attached to this
parameter.
Environment variables values are `always returned as strings
<https://docs.python.org/3/library/os.html#os.environ>`_.
This method returns ``None`` if:
- the `envvar` property is not set on `Parameter`,
- the environment variable is not found in the environment,
- the variable is found in the environment but its value is empty (i.e. the
environment variable is present but has an empty string).
If `envvar` is setup with multiple environment variables,
then only the first non-empty value is returned.
"""
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)
# Return the first non-empty value of the list of environment variables.
if rv:
return rv
# Else, absence of value is interpreted as an environment variable that
# is not set, so proceed to the next one.
return None
value_from_envvar
¶
value_from_envvar(ctx)
Process the raw environment variable string for this parameter.
Returns the string as-is or splits it into a sequence of strings if the
parameter is expecting multiple values (i.e. its nargs property is set
to a value other than 1).
Source code in typer/_click/core.py
def value_from_envvar(self, ctx: Context) -> str | Sequence[str] | None:
"""Process the raw environment variable string for this parameter.
Returns the string as-is or splits it into a sequence of strings if the
parameter is expecting multiple values (i.e. its `nargs` property is set
to a value other than ``1``).
"""
rv: Any | None = self.resolve_envvar_value(ctx)
if rv is not None and self.nargs != 1:
rv = self.type.split_envvar_value(rv)
return rv
handle_parse_result
¶
handle_parse_result(ctx, opts, args)
Process the value produced by the parser from user input.
Always process the value through the Parameter's type, wherever it
comes from.
If the parameter is deprecated, this method warn the user about it. But only if the value has been explicitly set by the user (and as such, is not coming from a default).
Source code in typer/_click/core.py
def handle_parse_result(
self, ctx: Context, opts: Mapping[str, Any], args: list[str]
) -> tuple[Any, list[str]]:
"""Process the value produced by the parser from user input.
Always process the value through the Parameter's `type`, wherever it
comes from.
If the parameter is deprecated, this method warn the user about it. But only if
the value has been explicitly set by the user (and as such, is not coming from
a default).
"""
with augment_usage_errors(ctx, param=self):
value, source = self.consume_value(ctx, opts)
ctx.set_parameter_source(self.name, source) # type: ignore
# Process the value through the parameter's type.
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
get_help_record
abstractmethod
¶
get_help_record(ctx)
Source code in typer/_click/core.py
@abstractmethod
def get_help_record(self, ctx: Context) -> tuple[str, str] | None:
pass # pragma: no cover
get_usage_pieces
¶
get_usage_pieces(ctx)
Source code in typer/_click/core.py
def get_usage_pieces(self, ctx: Context) -> list[str]:
return []
get_error_hint
¶
get_error_hint(ctx)
Get a stringified version of the param for use in error messages to indicate which param caused the error.
Source code in typer/_click/core.py
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)
shell_complete
¶
shell_complete(ctx, incomplete)
Return a list of completions for the incomplete value. If a
shell_complete function was given during init, it is used.
Otherwise, the type ParamType.shell_complete function is used.
Source code in typer/_click/core.py
def shell_complete(self, ctx: Context, incomplete: str) -> 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 `type` `ParamType.shell_complete` function is used.
"""
if self._custom_shell_complete is not None:
results = self._custom_shell_complete(ctx, self, incomplete)
if results and isinstance(results[0], str):
from .shell_completion import CompletionItem
results = [CompletionItem(c) for c in results]
return cast("list[CompletionItem]", results)
return self.type.shell_complete(ctx, self, incomplete)