Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
core.py3477 linesDownload Raw Back to click
1from __future__ import annotations2 3import collections.abc as cabc4import enum5import errno6import inspect7import os8import sys9import typing as t10from collections import abc11from collections import Counter12from contextlib import AbstractContextManager13from contextlib import contextmanager14from contextlib import ExitStack15from functools import update_wrapper16from gettext import gettext as _17from gettext import ngettext18from itertools import repeat19from types import TracebackType20 21from . import types22from ._utils import FLAG_NEEDS_VALUE23from ._utils import UNSET24from .exceptions import Abort25from .exceptions import BadParameter26from .exceptions import ClickException27from .exceptions import Exit28from .exceptions import MissingParameter29from .exceptions import NoArgsIsHelpError30from .exceptions import UsageError31from .formatting import HelpFormatter32from .formatting import join_options33from .globals import pop_context34from .globals import push_context35from .parser import _OptionParser36from .parser import _split_opt37from .termui import confirm38from .termui import prompt39from .termui import style40from .utils import _detect_program_name41from .utils import _expand_args42from .utils import echo43from .utils import make_default_short_help44from .utils import make_str45from .utils import PacifyFlushWrapper46 47if t.TYPE_CHECKING:48    from .shell_completion import CompletionItem49 50F = t.TypeVar("F", bound="t.Callable[..., t.Any]")51V = t.TypeVar("V")52 53 54def _complete_visible_commands(55    ctx: Context, incomplete: str56) -> cabc.Iterator[tuple[str, Command]]:57    """List all the subcommands of a group that start with the58    incomplete value and aren't hidden.59 60    :param ctx: Invocation context for the group.61    :param incomplete: Value being completed. May be empty.62    """63    multi = t.cast(Group, ctx.command)64 65    for name in multi.list_commands(ctx):66        if name.startswith(incomplete):67            command = multi.get_command(ctx, name)68 69            if command is not None and not command.hidden:70                yield name, command71 72 73def _check_nested_chain(74    base_command: Group, cmd_name: str, cmd: Command, register: bool = False75) -> None:76    if not base_command.chain or not isinstance(cmd, Group):77        return78 79    if register:80        message = (81            f"It is not possible to add the group {cmd_name!r} to another"82            f" group {base_command.name!r} that is in chain mode."83        )84    else:85        message = (86            f"Found the group {cmd_name!r} as subcommand to another group "87            f" {base_command.name!r} that is in chain mode. This is not supported."88        )89 90    raise RuntimeError(message)91 92 93def batch(iterable: cabc.Iterable[V], batch_size: int) -> list[tuple[V, ...]]:94    return list(zip(*repeat(iter(iterable), batch_size), strict=False))95 96 97@contextmanager98def augment_usage_errors(99    ctx: Context, param: Parameter | None = None100) -> cabc.Iterator[None]:101    """Context manager that attaches extra information to exceptions."""102    try:103        yield104    except BadParameter as e:105        if e.ctx is None:106            e.ctx = ctx107        if param is not None and e.param is None:108            e.param = param109        raise110    except UsageError as e:111        if e.ctx is None:112            e.ctx = ctx113        raise114 115 116def iter_params_for_processing(117    invocation_order: cabc.Sequence[Parameter],118    declaration_order: cabc.Sequence[Parameter],119) -> list[Parameter]:120    """Returns all declared parameters in the order they should be processed.121 122    The declared parameters are re-shuffled depending on the order in which123    they were invoked, as well as the eagerness of each parameters.124 125    The invocation order takes precedence over the declaration order. I.e. the126    order in which the user provided them to the CLI is respected.127 128    This behavior and its effect on callback evaluation is detailed at:129    https://click.palletsprojects.com/en/stable/advanced/#callback-evaluation-order130    """131 132    def sort_key(item: Parameter) -> tuple[bool, float]:133        try:134            idx: float = invocation_order.index(item)135        except ValueError:136            idx = float("inf")137 138        return not item.is_eager, idx139 140    return sorted(declaration_order, key=sort_key)141 142 143class ParameterSource(enum.IntEnum):144    """This is an :class:`~enum.IntEnum` that indicates the source of a145    parameter's value.146 147    Use :meth:`click.Context.get_parameter_source` to get the148    source for a parameter by name.149 150    Members are ordered from most explicit to least explicit source.151    This allows comparison to check if a value was explicitly provided:152 153    .. code-block:: python154 155        source = ctx.get_parameter_source("port")156        if source < click.ParameterSource.DEFAULT_MAP:157            ...  # value was explicitly set158 159    .. versionchanged:: 8.3.3160        Use :class:`~enum.IntEnum` and reorder members from most to161        least explicit. Supports comparison operators.162 163    .. versionchanged:: 8.0164        Use :class:`~enum.Enum` and drop the ``validate`` method.165 166    .. versionchanged:: 8.0167        Added the ``PROMPT`` value.168    """169 170    PROMPT = enum.auto()171    """Used a prompt to confirm a default or provide a value."""172    COMMANDLINE = enum.auto()173    """The value was provided by the command line args."""174    ENVIRONMENT = enum.auto()175    """The value was provided with an environment variable."""176    DEFAULT_MAP = enum.auto()177    """Used a default provided by :attr:`Context.default_map`."""178    DEFAULT = enum.auto()179    """Used the default specified by the parameter."""180 181 182class Context:183    """The context is a special internal object that holds state relevant184    for the script execution at every single level.  It's normally invisible185    to commands unless they opt-in to getting access to it.186 187    The context is useful as it can pass internal objects around and can188    control special execution features such as reading data from189    environment variables.190 191    A context can be used as context manager in which case it will call192    :meth:`close` on teardown.193 194    :param command: the command class for this context.195    :param parent: the parent context.196    :param info_name: the info name for this invocation.  Generally this197                      is the most descriptive name for the script or198                      command.  For the toplevel script it is usually199                      the name of the script, for commands below it it's200                      the name of the script.201    :param obj: an arbitrary object of user data.202    :param auto_envvar_prefix: the prefix to use for automatic environment203                               variables.  If this is `None` then reading204                               from environment variables is disabled.  This205                               does not affect manually set environment206                               variables which are always read.207    :param default_map: a dictionary (like object) with default values208                        for parameters.209    :param terminal_width: the width of the terminal.  The default is210                           inherit from parent context.  If no context211                           defines the terminal width then auto212                           detection will be applied.213    :param max_content_width: the maximum width for content rendered by214                              Click (this currently only affects help215                              pages).  This defaults to 80 characters if216                              not overridden.  In other words: even if the217                              terminal is larger than that, Click will not218                              format things wider than 80 characters by219                              default.  In addition to that, formatters might220                              add some safety mapping on the right.221    :param resilient_parsing: if this flag is enabled then Click will222                              parse without any interactivity or callback223                              invocation.  Default values will also be224                              ignored.  This is useful for implementing225                              things such as completion support.226    :param allow_extra_args: if this is set to `True` then extra arguments227                             at the end will not raise an error and will be228                             kept on the context.  The default is to inherit229                             from the command.230    :param allow_interspersed_args: if this is set to `False` then options231                                    and arguments cannot be mixed.  The232                                    default is to inherit from the command.233    :param ignore_unknown_options: instructs click to ignore options it does234                                   not know and keeps them for later235                                   processing.236    :param help_option_names: optionally a list of strings that define how237                              the default help parameter is named.  The238                              default is ``['--help']``.239    :param token_normalize_func: an optional function that is used to240                                 normalize tokens (options, choices,241                                 etc.).  This for instance can be used to242                                 implement case insensitive behavior.243    :param color: controls if the terminal supports ANSI colors or not.  The244                  default is autodetection.  This is only needed if ANSI245                  codes are used in texts that Click prints which is by246                  default not the case.  This for instance would affect247                  help output.248    :param show_default: Show the default value for commands. If this249        value is not set, it defaults to the value from the parent250        context. ``Command.show_default`` overrides this default for the251        specific command.252 253    .. versionchanged:: 8.2254        The ``protected_args`` attribute is deprecated and will be removed in255        Click 9.0. ``args`` will contain remaining unparsed tokens.256 257    .. versionchanged:: 8.1258        The ``show_default`` parameter is overridden by259        ``Command.show_default``, instead of the other way around.260 261    .. versionchanged:: 8.0262        The ``show_default`` parameter defaults to the value from the263        parent context.264 265    .. versionchanged:: 7.1266       Added the ``show_default`` parameter.267 268    .. versionchanged:: 4.0269        Added the ``color``, ``ignore_unknown_options``, and270        ``max_content_width`` parameters.271 272    .. versionchanged:: 3.0273        Added the ``allow_extra_args`` and ``allow_interspersed_args``274        parameters.275 276    .. versionchanged:: 2.0277        Added the ``resilient_parsing``, ``help_option_names``, and278        ``token_normalize_func`` parameters.279    """280 281    #: The formatter class to create with :meth:`make_formatter`.282    #:283    #: .. versionadded:: 8.0284    formatter_class: type[HelpFormatter] = HelpFormatter285 286    def __init__(287        self,288        command: Command,289        parent: Context | None = None,290        info_name: str | None = None,291        obj: t.Any | None = None,292        auto_envvar_prefix: str | None = None,293        default_map: cabc.MutableMapping[str, t.Any] | None = None,294        terminal_width: int | None = None,295        max_content_width: int | None = None,296        resilient_parsing: bool = False,297        allow_extra_args: bool | None = None,298        allow_interspersed_args: bool | None = None,299        ignore_unknown_options: bool | None = None,300        help_option_names: list[str] | None = None,301        token_normalize_func: t.Callable[[str], str] | None = None,302        color: bool | None = None,303        show_default: bool | None = None,304    ) -> None:305        #: the parent context or `None` if none exists.306        self.parent = parent307        #: the :class:`Command` for this context.308        self.command = command309        #: the descriptive information name310        self.info_name = info_name311        #: Map of parameter names to their parsed values. Parameters312        #: with ``expose_value=False`` are not stored.313        self.params: dict[str, t.Any] = {}314        #: the leftover arguments.315        self.args: list[str] = []316        #: protected arguments.  These are arguments that are prepended317        #: to `args` when certain parsing scenarios are encountered but318        #: must be never propagated to another arguments.  This is used319        #: to implement nested parsing.320        self._protected_args: list[str] = []321        #: the collected prefixes of the command's options.322        self._opt_prefixes: set[str] = set(parent._opt_prefixes) if parent else set()323 324        if obj is None and parent is not None:325            obj = parent.obj326 327        #: the user object stored.328        self.obj: t.Any = obj329        self._meta: dict[str, t.Any] = getattr(parent, "meta", {})330 331        #: A dictionary (-like object) with defaults for parameters.332        if (333            default_map is None334            and info_name is not None335            and parent is not None336            and parent.default_map is not None337        ):338            default_map = parent.default_map.get(info_name)339 340        self.default_map: cabc.MutableMapping[str, t.Any] | None = default_map341 342        #: This flag indicates if a subcommand is going to be executed. A343        #: group callback can use this information to figure out if it's344        #: being executed directly or because the execution flow passes345        #: onwards to a subcommand. By default it's None, but it can be346        #: the name of the subcommand to execute.347        #:348        #: If chaining is enabled this will be set to ``'*'`` in case349        #: any commands are executed.  It is however not possible to350        #: figure out which ones.  If you require this knowledge you351        #: should use a :func:`result_callback`.352        self.invoked_subcommand: str | None = None353 354        if terminal_width is None and parent is not None:355            terminal_width = parent.terminal_width356 357        #: The width of the terminal (None is autodetection).358        self.terminal_width: int | None = terminal_width359 360        if max_content_width is None and parent is not None:361            max_content_width = parent.max_content_width362 363        #: The maximum width of formatted content (None implies a sensible364        #: default which is 80 for most things).365        self.max_content_width: int | None = max_content_width366 367        if allow_extra_args is None:368            allow_extra_args = command.allow_extra_args369 370        #: Indicates if the context allows extra args or if it should371        #: fail on parsing.372        #:373        #: .. versionadded:: 3.0374        self.allow_extra_args = allow_extra_args375 376        if allow_interspersed_args is None:377            allow_interspersed_args = command.allow_interspersed_args378 379        #: Indicates if the context allows mixing of arguments and380        #: options or not.381        #:382        #: .. versionadded:: 3.0383        self.allow_interspersed_args: bool = allow_interspersed_args384 385        if ignore_unknown_options is None:386            ignore_unknown_options = command.ignore_unknown_options387 388        #: Instructs click to ignore options that a command does not389        #: understand and will store it on the context for later390        #: processing.  This is primarily useful for situations where you391        #: want to call into external programs.  Generally this pattern is392        #: strongly discouraged because it's not possibly to losslessly393        #: forward all arguments.394        #:395        #: .. versionadded:: 4.0396        self.ignore_unknown_options: bool = ignore_unknown_options397 398        if help_option_names is None:399            if parent is not None:400                help_option_names = parent.help_option_names401            else:402                help_option_names = ["--help"]403 404        #: The names for the help options.405        self.help_option_names: list[str] = help_option_names406 407        if token_normalize_func is None and parent is not None:408            token_normalize_func = parent.token_normalize_func409 410        #: An optional normalization function for tokens.  This is411        #: options, choices, commands etc.412        self.token_normalize_func: t.Callable[[str], str] | None = token_normalize_func413 414        #: Indicates if resilient parsing is enabled.  In that case Click415        #: will do its best to not cause any failures and default values416        #: will be ignored. Useful for completion.417        self.resilient_parsing: bool = resilient_parsing418 419        # If there is no envvar prefix yet, but the parent has one and420        # the command on this level has a name, we can expand the envvar421        # prefix automatically.422        if auto_envvar_prefix is None:423            if (424                parent is not None425                and parent.auto_envvar_prefix is not None426                and self.info_name is not None427            ):428                auto_envvar_prefix = (429                    f"{parent.auto_envvar_prefix}_{self.info_name.upper()}"430                )431        else:432            auto_envvar_prefix = auto_envvar_prefix.upper()433 434        if auto_envvar_prefix is not None:435            auto_envvar_prefix = auto_envvar_prefix.replace("-", "_")436 437        self.auto_envvar_prefix: str | None = auto_envvar_prefix438 439        if color is None and parent is not None:440            color = parent.color441 442        #: Controls if styling output is wanted or not.443        self.color: bool | None = color444 445        if show_default is None and parent is not None:446            show_default = parent.show_default447 448        #: Show option default values when formatting help text.449        self.show_default: bool | None = show_default450 451        self._close_callbacks: list[t.Callable[[], t.Any]] = []452        self._depth = 0453        self._parameter_source: dict[str, ParameterSource] = {}454        self._exit_stack = ExitStack()455 456    @property457    def protected_args(self) -> list[str]:458        import warnings459 460        warnings.warn(461            "'protected_args' is deprecated and will be removed in Click 9.0."462            " 'args' will contain remaining unparsed tokens.",463            DeprecationWarning,464            stacklevel=2,465        )466        return self._protected_args467 468    def to_info_dict(self) -> dict[str, t.Any]:469        """Gather information that could be useful for a tool generating470        user-facing documentation. This traverses the entire CLI471        structure.472 473        .. code-block:: python474 475            with Context(cli) as ctx:476                info = ctx.to_info_dict()477 478        .. versionadded:: 8.0479        """480        return {481            "command": self.command.to_info_dict(self),482            "info_name": self.info_name,483            "allow_extra_args": self.allow_extra_args,484            "allow_interspersed_args": self.allow_interspersed_args,485            "ignore_unknown_options": self.ignore_unknown_options,486            "auto_envvar_prefix": self.auto_envvar_prefix,487        }488 489    def __enter__(self) -> Context:490        self._depth += 1491        push_context(self)492        return self493 494    def __exit__(495        self,496        exc_type: type[BaseException] | None,497        exc_value: BaseException | None,498        tb: TracebackType | None,499    ) -> bool | None:500        self._depth -= 1501        exit_result: bool | None = None502        if self._depth == 0:503            exit_result = self._close_with_exception_info(exc_type, exc_value, tb)504        pop_context()505 506        return exit_result507 508    @contextmanager509    def scope(self, cleanup: bool = True) -> cabc.Iterator[Context]:510        """This helper method can be used with the context object to promote511        it to the current thread local (see :func:`get_current_context`).512        The default behavior of this is to invoke the cleanup functions which513        can be disabled by setting `cleanup` to `False`.  The cleanup514        functions are typically used for things such as closing file handles.515 516        If the cleanup is intended the context object can also be directly517        used as a context manager.518 519        Example usage::520 521            with ctx.scope():522                assert get_current_context() is ctx523 524        This is equivalent::525 526            with ctx:527                assert get_current_context() is ctx528 529        .. versionadded:: 5.0530 531        :param cleanup: controls if the cleanup functions should be run or532                        not.  The default is to run these functions.  In533                        some situations the context only wants to be534                        temporarily pushed in which case this can be disabled.535                        Nested pushes automatically defer the cleanup.536        """537        if not cleanup:538            self._depth += 1539        try:540            with self as rv:541                yield rv542        finally:543            if not cleanup:544                self._depth -= 1545 546    @property547    def meta(self) -> dict[str, t.Any]:548        """This is a dictionary which is shared with all the contexts549        that are nested.  It exists so that click utilities can store some550        state here if they need to.  It is however the responsibility of551        that code to manage this dictionary well.552 553        The keys are supposed to be unique dotted strings.  For instance554        module paths are a good choice for it.  What is stored in there is555        irrelevant for the operation of click.  However what is important is556        that code that places data here adheres to the general semantics of557        the system.558 559        Example usage::560 561            LANG_KEY = f'{__name__}.lang'562 563            def set_language(value):564                ctx = get_current_context()565                ctx.meta[LANG_KEY] = value566 567            def get_language():568                return get_current_context().meta.get(LANG_KEY, 'en_US')569 570        .. versionadded:: 5.0571        """572        return self._meta573 574    def make_formatter(self) -> HelpFormatter:575        """Creates the :class:`~click.HelpFormatter` for the help and576        usage output.577 578        To quickly customize the formatter class used without overriding579        this method, set the :attr:`formatter_class` attribute.580 581        .. versionchanged:: 8.0582            Added the :attr:`formatter_class` attribute.583        """584        return self.formatter_class(585            width=self.terminal_width, max_width=self.max_content_width586        )587 588    def with_resource(self, context_manager: AbstractContextManager[V]) -> V:589        """Register a resource as if it were used in a ``with``590        statement. The resource will be cleaned up when the context is591        popped.592 593        Uses :meth:`contextlib.ExitStack.enter_context`. It calls the594        resource's ``__enter__()`` method and returns the result. When595        the context is popped, it closes the stack, which calls the596        resource's ``__exit__()`` method.597 598        To register a cleanup function for something that isn't a599        context manager, use :meth:`call_on_close`. Or use something600        from :mod:`contextlib` to turn it into a context manager first.601 602        .. code-block:: python603 604            @click.group()605            @click.option("--name")606            @click.pass_context607            def cli(ctx):608                ctx.obj = ctx.with_resource(connect_db(name))609 610        :param context_manager: The context manager to enter.611        :return: Whatever ``context_manager.__enter__()`` returns.612 613        .. versionadded:: 8.0614        """615        return self._exit_stack.enter_context(context_manager)616 617    def call_on_close(self, f: t.Callable[..., t.Any]) -> t.Callable[..., t.Any]:618        """Register a function to be called when the context tears down.619 620        This can be used to close resources opened during the script621        execution. Resources that support Python's context manager622        protocol which would be used in a ``with`` statement should be623        registered with :meth:`with_resource` instead.624 625        :param f: The function to execute on teardown.626        """627        return self._exit_stack.callback(f)628 629    def close(self) -> None:630        """Invoke all close callbacks registered with631        :meth:`call_on_close`, and exit all context managers entered632        with :meth:`with_resource`.633        """634        self._close_with_exception_info(None, None, None)635 636    def _close_with_exception_info(637        self,638        exc_type: type[BaseException] | None,639        exc_value: BaseException | None,640        tb: TracebackType | None,641    ) -> bool | None:642        """Unwind the exit stack by calling its :meth:`__exit__` providing the exception643        information to allow for exception handling by the various resources registered644        using :meth;`with_resource`645 646        :return: Whatever ``exit_stack.__exit__()`` returns.647        """648        exit_result = self._exit_stack.__exit__(exc_type, exc_value, tb)649        # In case the context is reused, create a new exit stack.650        self._exit_stack = ExitStack()651 652        return exit_result653 654    @property655    def command_path(self) -> str:656        """The computed command path.  This is used for the ``usage``657        information on the help page.  It's automatically created by658        combining the info names of the chain of contexts to the root.659        """660        rv = ""661        if self.info_name is not None:662            rv = self.info_name663        if self.parent is not None:664            parent_command_path = [self.parent.command_path]665 666            if isinstance(self.parent.command, Command):667                for param in self.parent.command.get_params(self):668                    parent_command_path.extend(param.get_usage_pieces(self))669 670            rv = f"{' '.join(parent_command_path)} {rv}"671        return rv.lstrip()672 673    def find_root(self) -> Context:674        """Finds the outermost context."""675        node = self676        while node.parent is not None:677            node = node.parent678        return node679 680    def find_object(self, object_type: type[V]) -> V | None:681        """Finds the closest object of a given type."""682        node: Context | None = self683 684        while node is not None:685            if isinstance(node.obj, object_type):686                return node.obj687 688            node = node.parent689 690        return None691 692    def ensure_object(self, object_type: type[V]) -> V:693        """Like :meth:`find_object` but sets the innermost object to a694        new instance of `object_type` if it does not exist.695        """696        rv = self.find_object(object_type)697        if rv is None:698            self.obj = rv = object_type()699        return rv700 701    def _default_map_has(self, name: str | None) -> bool:702        """Check if :attr:`default_map` contains a real value for ``name``.703 704        Returns ``False`` when the key is absent, the map is ``None``,705        ``name`` is ``None``, or the stored value is the internal706        :data:`UNSET` sentinel.707        """708        return (709            name is not None710            and self.default_map is not None711            and name in self.default_map712            and self.default_map[name] is not UNSET713        )714 715    @t.overload716    def lookup_default(717        self, name: str, call: t.Literal[True] = True718    ) -> t.Any | None: ...719 720    @t.overload721    def lookup_default(722        self, name: str, call: t.Literal[False] = ...723    ) -> t.Any | t.Callable[[], t.Any] | None: ...724 725    def lookup_default(self, name: str, call: bool = True) -> t.Any | None:726        """Get the default for a parameter from :attr:`default_map`.727 728        :param name: Name of the parameter.729        :param call: If the default is a callable, call it. Disable to730            return the callable instead.731 732        .. versionchanged:: 8.0733            Added the ``call`` parameter.734        """735        if not self._default_map_has(name):736            return None737 738        # Assert to make the type checker happy.739        assert self.default_map is not None740        value = self.default_map[name]741 742        if call and callable(value):743            return value()744 745        return value746 747    def fail(self, message: str) -> t.NoReturn:748        """Aborts the execution of the program with a specific error749        message.750 751        :param message: the error message to fail with.752        """753        raise UsageError(message, self)754 755    def abort(self) -> t.NoReturn:756        """Aborts the script."""757        raise Abort()758 759    def exit(self, code: int = 0) -> t.NoReturn:760        """Exits the application with a given exit code.761 762        .. versionchanged:: 8.2763            Callbacks and context managers registered with :meth:`call_on_close`764            and :meth:`with_resource` are closed before exiting.765        """766        self.close()767        raise Exit(code)768 769    def get_usage(self) -> str:770        """Helper method to get formatted usage string for the current771        context and command.772        """773        return self.command.get_usage(self)774 775    def get_help(self) -> str:776        """Helper method to get formatted help page for the current777        context and command.778        """779        return self.command.get_help(self)780 781    def _make_sub_context(self, command: Command) -> Context:782        """Create a new context of the same type as this context, but783        for a new command.784 785        :meta private:786        """787        return type(self)(command, info_name=command.name, parent=self)788 789    @t.overload790    def invoke(791        self, callback: t.Callable[..., V], /, *args: t.Any, **kwargs: t.Any792    ) -> V: ...793 794    @t.overload795    def invoke(self, callback: Command, /, *args: t.Any, **kwargs: t.Any) -> t.Any: ...796 797    def invoke(798        self, callback: Command | t.Callable[..., V], /, *args: t.Any, **kwargs: t.Any799    ) -> t.Any | V:800        """Invokes a command callback in exactly the way it expects.  There801        are two ways to invoke this method:802 803        1.  the first argument can be a callback and all other arguments and804            keyword arguments are forwarded directly to the function.805        2.  the first argument is a click command object.  In that case all806            arguments are forwarded as well but proper click parameters807            (options and click arguments) must be keyword arguments and Click808            will fill in defaults.809 810        .. versionchanged:: 8.0811            All ``kwargs`` are tracked in :attr:`params` so they will be812            passed if :meth:`forward` is called at multiple levels.813 814        .. versionchanged:: 3.2815            A new context is created, and missing arguments use default values.816        """817        if isinstance(callback, Command):818            other_cmd = callback819 820            if other_cmd.callback is None:821                raise TypeError(822                    "The given command does not have a callback that can be invoked."823                )824            else:825                callback = t.cast("t.Callable[..., V]", other_cmd.callback)826 827            ctx = self._make_sub_context(other_cmd)828 829            for param in other_cmd.params:830                if param.name not in kwargs and param.expose_value:831                    default_value = param.get_default(ctx)832                    # We explicitly hide the :attr:`UNSET` value to the user, as we833                    # choose to make it an implementation detail. And because ``invoke``834                    # has been designed as part of Click public API, we return ``None``835                    # instead. Refs:836                    # https://github.com/pallets/click/issues/3066837                    # https://github.com/pallets/click/issues/3065838                    # https://github.com/pallets/click/pull/3068839                    if default_value is UNSET:840                        default_value = None841                    kwargs[param.name] = param.type_cast_value(  # type: ignore842                        ctx, default_value843                    )844 845            # Track all kwargs as params, so that forward() will pass846            # them on in subsequent calls.847            ctx.params.update(kwargs)848        else:849            ctx = self850 851        with augment_usage_errors(self):852            with ctx:853                return callback(*args, **kwargs)854 855    def forward(self, cmd: Command, /, *args: t.Any, **kwargs: t.Any) -> t.Any:856        """Similar to :meth:`invoke` but fills in default keyword857        arguments from the current context if the other command expects858        it.  This cannot invoke callbacks directly, only other commands.859 860        .. versionchanged:: 8.0861            All ``kwargs`` are tracked in :attr:`params` so they will be862            passed if ``forward`` is called at multiple levels.863        """864        # Can only forward to other commands, not direct callbacks.865        if not isinstance(cmd, Command):866            raise TypeError("Callback is not a command.")867 868        for param in self.params:869            if param not in kwargs:870                kwargs[param] = self.params[param]871 872        return self.invoke(cmd, *args, **kwargs)873 874    def set_parameter_source(self, name: str, source: ParameterSource) -> None:875        """Set the source of a parameter. This indicates the location876        from which the value of the parameter was obtained.877 878        :param name: The name of the parameter.879        :param source: A member of :class:`~click.core.ParameterSource`.880        """881        self._parameter_source[name] = source882 883    def get_parameter_source(self, name: str) -> ParameterSource | None:884        """Get the source of a parameter. This indicates the location885        from which the value of the parameter was obtained.886 887        This can be useful for determining when a user specified a value888        on the command line that is the same as the default value. It889        will be :attr:`~click.core.ParameterSource.DEFAULT` only if the890        value was actually taken from the default.891 892        :param name: The name of the parameter.893        :rtype: ParameterSource894 895        .. versionchanged:: 8.0896            Returns ``None`` if the parameter was not provided from any897            source.898        """899        return self._parameter_source.get(name)900 901 902class Command:903    """Commands are the basic building block of command line interfaces in904    Click.  A basic command handles command line parsing and might dispatch905    more parsing to commands nested below it.906 907    :param name: the name of the command to use unless a group overrides it.908    :param context_settings: an optional dictionary with defaults that are909                             passed to the context object.910    :param callback: the callback to invoke.  This is optional.911    :param params: the parameters to register with this command.  This can912                   be either :class:`Option` or :class:`Argument` objects.913    :param help: the help string to use for this command.914    :param epilog: like the help string but it's printed at the end of the915                   help page after everything else.916    :param short_help: the short help to use for this command.  This is917                       shown on the command listing of the parent command.918    :param add_help_option: by default each command registers a ``--help``919                            option.  This can be disabled by this parameter.920    :param no_args_is_help: this controls what happens if no arguments are921                            provided.  This option is disabled by default.922                            If enabled this will add ``--help`` as argument923                            if no arguments are passed924    :param hidden: hide this command from help outputs.925    :param deprecated: If ``True`` or non-empty string, issues a message926                        indicating that the command is deprecated and highlights927                        its deprecation in --help. The message can be customized928                        by using a string as the value.929 930    .. versionchanged:: 8.2931        This is the base class for all commands, not ``BaseCommand``.932        ``deprecated`` can be set to a string as well to customize the933        deprecation message.934 935    .. versionchanged:: 8.1936        ``help``, ``epilog``, and ``short_help`` are stored unprocessed,937        all formatting is done when outputting help text, not at init,938        and is done even if not using the ``@command`` decorator.939 940    .. versionchanged:: 8.0941        Added a ``repr`` showing the command name.942 943    .. versionchanged:: 7.1944        Added the ``no_args_is_help`` parameter.945 946    .. versionchanged:: 2.0947        Added the ``context_settings`` parameter.948    """949 950    #: The context class to create with :meth:`make_context`.951    #:952    #: .. versionadded:: 8.0953    context_class: type[Context] = Context954 955    #: the default for the :attr:`Context.allow_extra_args` flag.956    allow_extra_args = False957 958    #: the default for the :attr:`Context.allow_interspersed_args` flag.959    allow_interspersed_args = True960 961    #: the default for the :attr:`Context.ignore_unknown_options` flag.962    ignore_unknown_options = False963 964    def __init__(965        self,966        name: str | None,967        context_settings: cabc.MutableMapping[str, t.Any] | None = None,968        callback: t.Callable[..., t.Any] | None = None,969        params: list[Parameter] | None = None,970        help: str | None = None,971        epilog: str | None = None,972        short_help: str | None = None,973        options_metavar: str | None = "[OPTIONS]",974        add_help_option: bool = True,975        no_args_is_help: bool = False,976        hidden: bool = False,977        deprecated: bool | str = False,978    ) -> None:979        #: the name the command thinks it has.  Upon registering a command980        #: on a :class:`Group` the group will default the command name981        #: with this information.  You should instead use the982        #: :class:`Context`\'s :attr:`~Context.info_name` attribute.983        self.name = name984 985        if context_settings is None:986            context_settings = {}987 988        #: an optional dictionary with defaults passed to the context.989        self.context_settings: cabc.MutableMapping[str, t.Any] = context_settings990 991        #: the callback to execute when the command fires.  This might be992        #: `None` in which case nothing happens.993        self.callback = callback994        #: the list of parameters for this command in the order they995        #: should show up in the help page and execute.  Eager parameters996        #: will automatically be handled before non eager ones.997        self.params: list[Parameter] = params or []998        self.help = help999        self.epilog = epilog1000        self.options_metavar = options_metavar1001        self.short_help = short_help1002        self.add_help_option = add_help_option1003        self._help_option = None1004        self.no_args_is_help = no_args_is_help1005        self.hidden = hidden1006        self.deprecated = deprecated1007 1008    def to_info_dict(self, ctx: Context) -> dict[str, t.Any]:1009        return {1010            "name": self.name,1011            "params": [param.to_info_dict() for param in self.get_params(ctx)],1012            "help": self.help,1013            "epilog": self.epilog,1014            "short_help": self.short_help,1015            "hidden": self.hidden,1016            "deprecated": self.deprecated,1017        }1018 1019    def __repr__(self) -> str:1020        return f"<{self.__class__.__name__} {self.name}>"1021 1022    def get_usage(self, ctx: Context) -> str:1023        """Formats the usage line into a string and returns it.1024 1025        Calls :meth:`format_usage` internally.1026        """1027        formatter = ctx.make_formatter()1028        self.format_usage(ctx, formatter)1029        return formatter.getvalue().rstrip("\n")1030 1031    def get_params(self, ctx: Context) -> list[Parameter]:1032        params = self.params1033        help_option = self.get_help_option(ctx)1034 1035        if help_option is not None:1036            params = [*params, help_option]1037 1038        if __debug__:1039            import warnings1040 1041            opts = [opt for param in params for opt in param.opts]1042            opts_counter = Counter(opts)1043            duplicate_opts = (opt for opt, count in opts_counter.items() if count > 1)1044 1045            for duplicate_opt in duplicate_opts:1046                warnings.warn(1047                    (1048                        f"The parameter {duplicate_opt} is used more than once. "1049                        "Remove its duplicate as parameters should be unique."1050                    ),1051                    stacklevel=3,1052                )1053 1054        return params1055 1056    def format_usage(self, ctx: Context, formatter: HelpFormatter) -> None:1057        """Writes the usage line into the formatter.1058 1059        This is a low-level method called by :meth:`get_usage`.1060        """1061        pieces = self.collect_usage_pieces(ctx)1062        formatter.write_usage(ctx.command_path, " ".join(pieces))1063 1064    def collect_usage_pieces(self, ctx: Context) -> list[str]:1065        """Returns all the pieces that go into the usage line and returns1066        it as a list of strings.1067        """1068        rv = [self.options_metavar] if self.options_metavar else []1069 1070        for param in self.get_params(ctx):1071            rv.extend(param.get_usage_pieces(ctx))1072 1073        return rv1074 1075    def get_help_option_names(self, ctx: Context) -> list[str]:1076        """Returns the names for the help option."""1077        all_names = set(ctx.help_option_names)1078        for param in self.params:1079            all_names.difference_update(param.opts)1080            all_names.difference_update(param.secondary_opts)1081        return list(all_names)1082 1083    def get_help_option(self, ctx: Context) -> Option | None:1084        """Returns the help option object.1085 1086        Skipped if :attr:`add_help_option` is ``False``.1087 1088        .. versionchanged:: 8.1.81089            The help option is now cached to avoid creating it multiple times.1090        """1091        help_option_names = self.get_help_option_names(ctx)1092 1093        if not help_option_names or not self.add_help_option:1094            return None1095 1096        # Cache the help option object in private _help_option attribute to1097        # avoid creating it multiple times. Not doing this will break the1098        # callback odering by iter_params_for_processing(), which relies on1099        # object comparison.1100        if self._help_option is None:1101            # Avoid circular import.1102            from .decorators import help_option1103 1104            # Apply help_option decorator and pop resulting option1105            help_option(*help_option_names)(self)1106            self._help_option = self.params.pop()  # type: ignore[assignment]1107 1108        return self._help_option1109 1110    def make_parser(self, ctx: Context) -> _OptionParser:1111        """Creates the underlying option parser for this command."""1112        parser = _OptionParser(ctx)1113        for param in self.get_params(ctx):1114            param.add_to_parser(parser, ctx)1115        return parser1116 1117    def get_help(self, ctx: Context) -> str:1118        """Formats the help into a string and returns it.1119 1120        Calls :meth:`format_help` internally.1121        """1122        formatter = ctx.make_formatter()1123        self.format_help(ctx, formatter)1124        return formatter.getvalue().rstrip("\n")1125 1126    def get_short_help_str(self, limit: int = 45) -> str:1127        """Gets short help for the command or makes it by shortening the1128        long help string.1129        """1130        if self.short_help:1131            text = inspect.cleandoc(self.short_help)1132        elif self.help:1133            text = make_default_short_help(self.help, limit)1134        else:1135            text = ""1136 1137        if self.deprecated:1138            deprecated_message = (1139                f"(DEPRECATED: {self.deprecated})"1140                if isinstance(self.deprecated, str)1141                else "(DEPRECATED)"1142            )1143            text = _("{text} {deprecated_message}").format(1144                text=text, deprecated_message=deprecated_message1145            )1146 1147        return text.strip()1148 1149    def format_help(self, ctx: Context, formatter: HelpFormatter) -> None:1150        """Writes the help into the formatter if it exists.1151 1152        This is a low-level method called by :meth:`get_help`.1153 1154        This calls the following methods:1155 1156        -   :meth:`format_usage`1157        -   :meth:`format_help_text`1158        -   :meth:`format_options`1159        -   :meth:`format_epilog`1160        """1161        self.format_usage(ctx, formatter)1162        self.format_help_text(ctx, formatter)1163        self.format_options(ctx, formatter)1164        self.format_epilog(ctx, formatter)1165 1166    def format_help_text(self, ctx: Context, formatter: HelpFormatter) -> None:1167        """Writes the help text to the formatter if it exists."""1168        if self.help is not None:1169            # truncate the help text to the first form feed1170            text = inspect.cleandoc(self.help).partition("\f")[0]1171        else:1172            text = ""1173 1174        if self.deprecated:1175            deprecated_message = (1176                f"(DEPRECATED: {self.deprecated})"1177                if isinstance(self.deprecated, str)1178                else "(DEPRECATED)"1179            )1180            text = _("{text} {deprecated_message}").format(1181                text=text, deprecated_message=deprecated_message1182            )1183 1184        if text:1185            formatter.write_paragraph()1186 1187            with formatter.indentation():1188                formatter.write_text(text)1189 1190    def format_options(self, ctx: Context, formatter: HelpFormatter) -> None:1191        """Writes all the options into the formatter if they exist."""1192        opts = []1193        for param in self.get_params(ctx):1194            rv = param.get_help_record(ctx)1195            if rv is not None:1196                opts.append(rv)1197 1198        if opts:1199            with formatter.section(_("Options")):1200                formatter.write_dl(opts)

Showing the first 1,200 of 3477 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai