mirror of
https://gitlab.com/MoonTestUse1/AdministrationItDepartmens.git
synced 2025-08-14 00:25:46 +02:00
Initial commit
This commit is contained in:
562
venv/Lib/site-packages/click/decorators.py
Normal file
562
venv/Lib/site-packages/click/decorators.py
Normal file
@@ -0,0 +1,562 @@
|
||||
import inspect
|
||||
import types
|
||||
import typing as t
|
||||
from functools import update_wrapper
|
||||
from gettext import gettext as _
|
||||
|
||||
from .core import Argument
|
||||
from .core import Command
|
||||
from .core import Context
|
||||
from .core import Group
|
||||
from .core import Option
|
||||
from .core import Parameter
|
||||
from .globals import get_current_context
|
||||
from .utils import echo
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
import typing_extensions as te
|
||||
|
||||
P = te.ParamSpec("P")
|
||||
|
||||
R = t.TypeVar("R")
|
||||
T = t.TypeVar("T")
|
||||
_AnyCallable = t.Callable[..., t.Any]
|
||||
FC = t.TypeVar("FC", bound=t.Union[_AnyCallable, Command])
|
||||
|
||||
|
||||
def pass_context(f: "t.Callable[te.Concatenate[Context, P], R]") -> "t.Callable[P, R]":
|
||||
"""Marks a callback as wanting to receive the current context
|
||||
object as first argument.
|
||||
"""
|
||||
|
||||
def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R":
|
||||
return f(get_current_context(), *args, **kwargs)
|
||||
|
||||
return update_wrapper(new_func, f)
|
||||
|
||||
|
||||
def pass_obj(f: "t.Callable[te.Concatenate[t.Any, P], R]") -> "t.Callable[P, R]":
|
||||
"""Similar to :func:`pass_context`, but only pass the object on the
|
||||
context onwards (:attr:`Context.obj`). This is useful if that object
|
||||
represents the state of a nested system.
|
||||
"""
|
||||
|
||||
def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R":
|
||||
return f(get_current_context().obj, *args, **kwargs)
|
||||
|
||||
return update_wrapper(new_func, f)
|
||||
|
||||
|
||||
def make_pass_decorator(
|
||||
object_type: t.Type[T], ensure: bool = False
|
||||
) -> t.Callable[["t.Callable[te.Concatenate[T, P], R]"], "t.Callable[P, R]"]:
|
||||
"""Given an object type this creates a decorator that will work
|
||||
similar to :func:`pass_obj` but instead of passing the object of the
|
||||
current context, it will find the innermost context of type
|
||||
:func:`object_type`.
|
||||
|
||||
This generates a decorator that works roughly like this::
|
||||
|
||||
from functools import update_wrapper
|
||||
|
||||
def decorator(f):
|
||||
@pass_context
|
||||
def new_func(ctx, *args, **kwargs):
|
||||
obj = ctx.find_object(object_type)
|
||||
return ctx.invoke(f, obj, *args, **kwargs)
|
||||
return update_wrapper(new_func, f)
|
||||
return decorator
|
||||
|
||||
:param object_type: the type of the object to pass.
|
||||
:param ensure: if set to `True`, a new object will be created and
|
||||
remembered on the context if it's not there yet.
|
||||
"""
|
||||
|
||||
def decorator(f: "t.Callable[te.Concatenate[T, P], R]") -> "t.Callable[P, R]":
|
||||
def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R":
|
||||
ctx = get_current_context()
|
||||
|
||||
obj: t.Optional[T]
|
||||
if ensure:
|
||||
obj = ctx.ensure_object(object_type)
|
||||
else:
|
||||
obj = ctx.find_object(object_type)
|
||||
|
||||
if obj is None:
|
||||
raise RuntimeError(
|
||||
"Managed to invoke callback without a context"
|
||||
f" object of type {object_type.__name__!r}"
|
||||
" existing."
|
||||
)
|
||||
|
||||
return ctx.invoke(f, obj, *args, **kwargs)
|
||||
|
||||
return update_wrapper(new_func, f)
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
def pass_meta_key(
|
||||
key: str, *, doc_description: t.Optional[str] = None
|
||||
) -> "t.Callable[[t.Callable[te.Concatenate[t.Any, P], R]], t.Callable[P, R]]":
|
||||
"""Create a decorator that passes a key from
|
||||
:attr:`click.Context.meta` as the first argument to the decorated
|
||||
function.
|
||||
|
||||
:param key: Key in ``Context.meta`` to pass.
|
||||
:param doc_description: Description of the object being passed,
|
||||
inserted into the decorator's docstring. Defaults to "the 'key'
|
||||
key from Context.meta".
|
||||
|
||||
.. versionadded:: 8.0
|
||||
"""
|
||||
|
||||
def decorator(f: "t.Callable[te.Concatenate[t.Any, P], R]") -> "t.Callable[P, R]":
|
||||
def new_func(*args: "P.args", **kwargs: "P.kwargs") -> R:
|
||||
ctx = get_current_context()
|
||||
obj = ctx.meta[key]
|
||||
return ctx.invoke(f, obj, *args, **kwargs)
|
||||
|
||||
return update_wrapper(new_func, f)
|
||||
|
||||
if doc_description is None:
|
||||
doc_description = f"the {key!r} key from :attr:`click.Context.meta`"
|
||||
|
||||
decorator.__doc__ = (
|
||||
f"Decorator that passes {doc_description} as the first argument"
|
||||
" to the decorated function."
|
||||
)
|
||||
return decorator
|
||||
|
||||
|
||||
CmdType = t.TypeVar("CmdType", bound=Command)
|
||||
|
||||
|
||||
# variant: no call, directly as decorator for a function.
|
||||
@t.overload
|
||||
def command(name: _AnyCallable) -> Command: ...
|
||||
|
||||
|
||||
# variant: with positional name and with positional or keyword cls argument:
|
||||
# @command(namearg, CommandCls, ...) or @command(namearg, cls=CommandCls, ...)
|
||||
@t.overload
|
||||
def command(
|
||||
name: t.Optional[str],
|
||||
cls: t.Type[CmdType],
|
||||
**attrs: t.Any,
|
||||
) -> t.Callable[[_AnyCallable], CmdType]: ...
|
||||
|
||||
|
||||
# variant: name omitted, cls _must_ be a keyword argument, @command(cls=CommandCls, ...)
|
||||
@t.overload
|
||||
def command(
|
||||
name: None = None,
|
||||
*,
|
||||
cls: t.Type[CmdType],
|
||||
**attrs: t.Any,
|
||||
) -> t.Callable[[_AnyCallable], CmdType]: ...
|
||||
|
||||
|
||||
# variant: with optional string name, no cls argument provided.
|
||||
@t.overload
|
||||
def command(
|
||||
name: t.Optional[str] = ..., cls: None = None, **attrs: t.Any
|
||||
) -> t.Callable[[_AnyCallable], Command]: ...
|
||||
|
||||
|
||||
def command(
|
||||
name: t.Union[t.Optional[str], _AnyCallable] = None,
|
||||
cls: t.Optional[t.Type[CmdType]] = None,
|
||||
**attrs: t.Any,
|
||||
) -> t.Union[Command, t.Callable[[_AnyCallable], t.Union[Command, CmdType]]]:
|
||||
r"""Creates a new :class:`Command` and uses the decorated function as
|
||||
callback. This will also automatically attach all decorated
|
||||
:func:`option`\s and :func:`argument`\s as parameters to the command.
|
||||
|
||||
The name of the command defaults to the name of the function with
|
||||
underscores replaced by dashes. If you want to change that, you can
|
||||
pass the intended name as the first argument.
|
||||
|
||||
All keyword arguments are forwarded to the underlying command class.
|
||||
For the ``params`` argument, any decorated params are appended to
|
||||
the end of the list.
|
||||
|
||||
Once decorated the function turns into a :class:`Command` instance
|
||||
that can be invoked as a command line utility or be attached to a
|
||||
command :class:`Group`.
|
||||
|
||||
:param name: the name of the command. This defaults to the function
|
||||
name with underscores replaced by dashes.
|
||||
:param cls: the command class to instantiate. This defaults to
|
||||
:class:`Command`.
|
||||
|
||||
.. versionchanged:: 8.1
|
||||
This decorator can be applied without parentheses.
|
||||
|
||||
.. versionchanged:: 8.1
|
||||
The ``params`` argument can be used. Decorated params are
|
||||
appended to the end of the list.
|
||||
"""
|
||||
|
||||
func: t.Optional[t.Callable[[_AnyCallable], t.Any]] = None
|
||||
|
||||
if callable(name):
|
||||
func = name
|
||||
name = None
|
||||
assert cls is None, "Use 'command(cls=cls)(callable)' to specify a class."
|
||||
assert not attrs, "Use 'command(**kwargs)(callable)' to provide arguments."
|
||||
|
||||
if cls is None:
|
||||
cls = t.cast(t.Type[CmdType], Command)
|
||||
|
||||
def decorator(f: _AnyCallable) -> CmdType:
|
||||
if isinstance(f, Command):
|
||||
raise TypeError("Attempted to convert a callback into a command twice.")
|
||||
|
||||
attr_params = attrs.pop("params", None)
|
||||
params = attr_params if attr_params is not None else []
|
||||
|
||||
try:
|
||||
decorator_params = f.__click_params__ # type: ignore
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
del f.__click_params__ # type: ignore
|
||||
params.extend(reversed(decorator_params))
|
||||
|
||||
if attrs.get("help") is None:
|
||||
attrs["help"] = f.__doc__
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
assert cls is not None
|
||||
assert not callable(name)
|
||||
|
||||
cmd = cls(
|
||||
name=name or f.__name__.lower().replace("_", "-"),
|
||||
callback=f,
|
||||
params=params,
|
||||
**attrs,
|
||||
)
|
||||
cmd.__doc__ = f.__doc__
|
||||
return cmd
|
||||
|
||||
if func is not None:
|
||||
return decorator(func)
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
GrpType = t.TypeVar("GrpType", bound=Group)
|
||||
|
||||
|
||||
# variant: no call, directly as decorator for a function.
|
||||
@t.overload
|
||||
def group(name: _AnyCallable) -> Group: ...
|
||||
|
||||
|
||||
# variant: with positional name and with positional or keyword cls argument:
|
||||
# @group(namearg, GroupCls, ...) or @group(namearg, cls=GroupCls, ...)
|
||||
@t.overload
|
||||
def group(
|
||||
name: t.Optional[str],
|
||||
cls: t.Type[GrpType],
|
||||
**attrs: t.Any,
|
||||
) -> t.Callable[[_AnyCallable], GrpType]: ...
|
||||
|
||||
|
||||
# variant: name omitted, cls _must_ be a keyword argument, @group(cmd=GroupCls, ...)
|
||||
@t.overload
|
||||
def group(
|
||||
name: None = None,
|
||||
*,
|
||||
cls: t.Type[GrpType],
|
||||
**attrs: t.Any,
|
||||
) -> t.Callable[[_AnyCallable], GrpType]: ...
|
||||
|
||||
|
||||
# variant: with optional string name, no cls argument provided.
|
||||
@t.overload
|
||||
def group(
|
||||
name: t.Optional[str] = ..., cls: None = None, **attrs: t.Any
|
||||
) -> t.Callable[[_AnyCallable], Group]: ...
|
||||
|
||||
|
||||
def group(
|
||||
name: t.Union[str, _AnyCallable, None] = None,
|
||||
cls: t.Optional[t.Type[GrpType]] = None,
|
||||
**attrs: t.Any,
|
||||
) -> t.Union[Group, t.Callable[[_AnyCallable], t.Union[Group, GrpType]]]:
|
||||
"""Creates a new :class:`Group` with a function as callback. This
|
||||
works otherwise the same as :func:`command` just that the `cls`
|
||||
parameter is set to :class:`Group`.
|
||||
|
||||
.. versionchanged:: 8.1
|
||||
This decorator can be applied without parentheses.
|
||||
"""
|
||||
if cls is None:
|
||||
cls = t.cast(t.Type[GrpType], Group)
|
||||
|
||||
if callable(name):
|
||||
return command(cls=cls, **attrs)(name)
|
||||
|
||||
return command(name, cls, **attrs)
|
||||
|
||||
|
||||
def _param_memo(f: t.Callable[..., t.Any], param: Parameter) -> None:
|
||||
if isinstance(f, Command):
|
||||
f.params.append(param)
|
||||
else:
|
||||
if not hasattr(f, "__click_params__"):
|
||||
f.__click_params__ = [] # type: ignore
|
||||
|
||||
f.__click_params__.append(param) # type: ignore
|
||||
|
||||
|
||||
def argument(
|
||||
*param_decls: str, cls: t.Optional[t.Type[Argument]] = None, **attrs: t.Any
|
||||
) -> t.Callable[[FC], FC]:
|
||||
"""Attaches an argument to the command. All positional arguments are
|
||||
passed as parameter declarations to :class:`Argument`; all keyword
|
||||
arguments are forwarded unchanged (except ``cls``).
|
||||
This is equivalent to creating an :class:`Argument` instance manually
|
||||
and attaching it to the :attr:`Command.params` list.
|
||||
|
||||
For the default argument class, refer to :class:`Argument` and
|
||||
:class:`Parameter` for descriptions of parameters.
|
||||
|
||||
:param cls: the argument class to instantiate. This defaults to
|
||||
:class:`Argument`.
|
||||
:param param_decls: Passed as positional arguments to the constructor of
|
||||
``cls``.
|
||||
:param attrs: Passed as keyword arguments to the constructor of ``cls``.
|
||||
"""
|
||||
if cls is None:
|
||||
cls = Argument
|
||||
|
||||
def decorator(f: FC) -> FC:
|
||||
_param_memo(f, cls(param_decls, **attrs))
|
||||
return f
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
def option(
|
||||
*param_decls: str, cls: t.Optional[t.Type[Option]] = None, **attrs: t.Any
|
||||
) -> t.Callable[[FC], FC]:
|
||||
"""Attaches an option to the command. All positional arguments are
|
||||
passed as parameter declarations to :class:`Option`; all keyword
|
||||
arguments are forwarded unchanged (except ``cls``).
|
||||
This is equivalent to creating an :class:`Option` instance manually
|
||||
and attaching it to the :attr:`Command.params` list.
|
||||
|
||||
For the default option class, refer to :class:`Option` and
|
||||
:class:`Parameter` for descriptions of parameters.
|
||||
|
||||
:param cls: the option class to instantiate. This defaults to
|
||||
:class:`Option`.
|
||||
:param param_decls: Passed as positional arguments to the constructor of
|
||||
``cls``.
|
||||
:param attrs: Passed as keyword arguments to the constructor of ``cls``.
|
||||
"""
|
||||
if cls is None:
|
||||
cls = Option
|
||||
|
||||
def decorator(f: FC) -> FC:
|
||||
_param_memo(f, cls(param_decls, **attrs))
|
||||
return f
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
def confirmation_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]:
|
||||
"""Add a ``--yes`` option which shows a prompt before continuing if
|
||||
not passed. If the prompt is declined, the program will exit.
|
||||
|
||||
:param param_decls: One or more option names. Defaults to the single
|
||||
value ``"--yes"``.
|
||||
:param kwargs: Extra arguments are passed to :func:`option`.
|
||||
"""
|
||||
|
||||
def callback(ctx: Context, param: Parameter, value: bool) -> None:
|
||||
if not value:
|
||||
ctx.abort()
|
||||
|
||||
if not param_decls:
|
||||
param_decls = ("--yes",)
|
||||
|
||||
kwargs.setdefault("is_flag", True)
|
||||
kwargs.setdefault("callback", callback)
|
||||
kwargs.setdefault("expose_value", False)
|
||||
kwargs.setdefault("prompt", "Do you want to continue?")
|
||||
kwargs.setdefault("help", "Confirm the action without prompting.")
|
||||
return option(*param_decls, **kwargs)
|
||||
|
||||
|
||||
def password_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]:
|
||||
"""Add a ``--password`` option which prompts for a password, hiding
|
||||
input and asking to enter the value again for confirmation.
|
||||
|
||||
:param param_decls: One or more option names. Defaults to the single
|
||||
value ``"--password"``.
|
||||
:param kwargs: Extra arguments are passed to :func:`option`.
|
||||
"""
|
||||
if not param_decls:
|
||||
param_decls = ("--password",)
|
||||
|
||||
kwargs.setdefault("prompt", True)
|
||||
kwargs.setdefault("confirmation_prompt", True)
|
||||
kwargs.setdefault("hide_input", True)
|
||||
return option(*param_decls, **kwargs)
|
||||
|
||||
|
||||
def version_option(
|
||||
version: t.Optional[str] = None,
|
||||
*param_decls: str,
|
||||
package_name: t.Optional[str] = None,
|
||||
prog_name: t.Optional[str] = None,
|
||||
message: t.Optional[str] = None,
|
||||
**kwargs: t.Any,
|
||||
) -> t.Callable[[FC], FC]:
|
||||
"""Add a ``--version`` option which immediately prints the version
|
||||
number and exits the program.
|
||||
|
||||
If ``version`` is not provided, Click will try to detect it using
|
||||
:func:`importlib.metadata.version` to get the version for the
|
||||
``package_name``. On Python < 3.8, the ``importlib_metadata``
|
||||
backport must be installed.
|
||||
|
||||
If ``package_name`` is not provided, Click will try to detect it by
|
||||
inspecting the stack frames. This will be used to detect the
|
||||
version, so it must match the name of the installed package.
|
||||
|
||||
:param version: The version number to show. If not provided, Click
|
||||
will try to detect it.
|
||||
:param param_decls: One or more option names. Defaults to the single
|
||||
value ``"--version"``.
|
||||
:param package_name: The package name to detect the version from. If
|
||||
not provided, Click will try to detect it.
|
||||
:param prog_name: The name of the CLI to show in the message. If not
|
||||
provided, it will be detected from the command.
|
||||
:param message: The message to show. The values ``%(prog)s``,
|
||||
``%(package)s``, and ``%(version)s`` are available. Defaults to
|
||||
``"%(prog)s, version %(version)s"``.
|
||||
:param kwargs: Extra arguments are passed to :func:`option`.
|
||||
:raise RuntimeError: ``version`` could not be detected.
|
||||
|
||||
.. versionchanged:: 8.0
|
||||
Add the ``package_name`` parameter, and the ``%(package)s``
|
||||
value for messages.
|
||||
|
||||
.. versionchanged:: 8.0
|
||||
Use :mod:`importlib.metadata` instead of ``pkg_resources``. The
|
||||
version is detected based on the package name, not the entry
|
||||
point name. The Python package name must match the installed
|
||||
package name, or be passed with ``package_name=``.
|
||||
"""
|
||||
if message is None:
|
||||
message = _("%(prog)s, version %(version)s")
|
||||
|
||||
if version is None and package_name is None:
|
||||
frame = inspect.currentframe()
|
||||
f_back = frame.f_back if frame is not None else None
|
||||
f_globals = f_back.f_globals if f_back is not None else None
|
||||
# break reference cycle
|
||||
# https://docs.python.org/3/library/inspect.html#the-interpreter-stack
|
||||
del frame
|
||||
|
||||
if f_globals is not None:
|
||||
package_name = f_globals.get("__name__")
|
||||
|
||||
if package_name == "__main__":
|
||||
package_name = f_globals.get("__package__")
|
||||
|
||||
if package_name:
|
||||
package_name = package_name.partition(".")[0]
|
||||
|
||||
def callback(ctx: Context, param: Parameter, value: bool) -> None:
|
||||
if not value or ctx.resilient_parsing:
|
||||
return
|
||||
|
||||
nonlocal prog_name
|
||||
nonlocal version
|
||||
|
||||
if prog_name is None:
|
||||
prog_name = ctx.find_root().info_name
|
||||
|
||||
if version is None and package_name is not None:
|
||||
metadata: t.Optional[types.ModuleType]
|
||||
|
||||
try:
|
||||
from importlib import metadata
|
||||
except ImportError:
|
||||
# Python < 3.8
|
||||
import importlib_metadata as metadata # type: ignore
|
||||
|
||||
try:
|
||||
version = metadata.version(package_name) # type: ignore
|
||||
except metadata.PackageNotFoundError: # type: ignore
|
||||
raise RuntimeError(
|
||||
f"{package_name!r} is not installed. Try passing"
|
||||
" 'package_name' instead."
|
||||
) from None
|
||||
|
||||
if version is None:
|
||||
raise RuntimeError(
|
||||
f"Could not determine the version for {package_name!r} automatically."
|
||||
)
|
||||
|
||||
echo(
|
||||
message % {"prog": prog_name, "package": package_name, "version": version},
|
||||
color=ctx.color,
|
||||
)
|
||||
ctx.exit()
|
||||
|
||||
if not param_decls:
|
||||
param_decls = ("--version",)
|
||||
|
||||
kwargs.setdefault("is_flag", True)
|
||||
kwargs.setdefault("expose_value", False)
|
||||
kwargs.setdefault("is_eager", True)
|
||||
kwargs.setdefault("help", _("Show the version and exit."))
|
||||
kwargs["callback"] = callback
|
||||
return option(*param_decls, **kwargs)
|
||||
|
||||
|
||||
class HelpOption(Option):
|
||||
"""Pre-configured ``--help`` option which immediately prints the help page
|
||||
and exits the program.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
param_decls: t.Optional[t.Sequence[str]] = None,
|
||||
**kwargs: t.Any,
|
||||
) -> None:
|
||||
if not param_decls:
|
||||
param_decls = ("--help",)
|
||||
|
||||
kwargs.setdefault("is_flag", True)
|
||||
kwargs.setdefault("expose_value", False)
|
||||
kwargs.setdefault("is_eager", True)
|
||||
kwargs.setdefault("help", _("Show this message and exit."))
|
||||
kwargs.setdefault("callback", self.show_help)
|
||||
|
||||
super().__init__(param_decls, **kwargs)
|
||||
|
||||
@staticmethod
|
||||
def show_help(ctx: Context, param: Parameter, value: bool) -> None:
|
||||
"""Callback that print the help page on ``<stdout>`` and exits."""
|
||||
if value and not ctx.resilient_parsing:
|
||||
echo(ctx.get_help(), color=ctx.color)
|
||||
ctx.exit()
|
||||
|
||||
|
||||
def help_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]:
|
||||
"""Decorator for the pre-configured ``--help`` option defined above.
|
||||
|
||||
:param param_decls: One or more option names. Defaults to the single
|
||||
value ``"--help"``.
|
||||
:param kwargs: Extra arguments are passed to :func:`option`.
|
||||
"""
|
||||
kwargs.setdefault("cls", HelpOption)
|
||||
return option(*param_decls, **kwargs)
|
Reference in New Issue
Block a user