| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347 |
- from __future__ import annotations
- import collections.abc as cabc
- import enum
- import errno
- import inspect
- import os
- import sys
- import typing as t
- from collections import abc
- from collections import Counter
- from contextlib import AbstractContextManager
- from contextlib import contextmanager
- from contextlib import ExitStack
- from functools import update_wrapper
- from gettext import gettext as _
- from gettext import ngettext
- from itertools import repeat
- from types import TracebackType
- from . import types
- from ._utils import FLAG_NEEDS_VALUE
- from ._utils import UNSET
- from .exceptions import Abort
- from .exceptions import BadParameter
- from .exceptions import ClickException
- from .exceptions import Exit
- from .exceptions import MissingParameter
- from .exceptions import NoArgsIsHelpError
- from .exceptions import UsageError
- from .formatting import HelpFormatter
- from .formatting import join_options
- from .globals import pop_context
- from .globals import push_context
- from .parser import _OptionParser
- from .parser import _split_opt
- from .termui import confirm
- from .termui import prompt
- from .termui import style
- from .utils import _detect_program_name
- from .utils import _expand_args
- from .utils import echo
- from .utils import make_default_short_help
- from .utils import make_str
- from .utils import PacifyFlushWrapper
- if t.TYPE_CHECKING:
- from .shell_completion import CompletionItem
- F = t.TypeVar("F", bound="t.Callable[..., t.Any]")
- V = t.TypeVar("V")
- def _complete_visible_commands(
- ctx: Context, incomplete: str
- ) -> cabc.Iterator[tuple[str, Command]]:
- """List all the subcommands of a group that start with the
- incomplete value and aren't hidden.
- :param ctx: Invocation context for the group.
- :param incomplete: Value being completed. May be empty.
- """
- multi = t.cast(Group, ctx.command)
- for name in multi.list_commands(ctx):
- if name.startswith(incomplete):
- command = multi.get_command(ctx, name)
- if command is not None and not command.hidden:
- yield name, command
- def _check_nested_chain(
- base_command: Group, cmd_name: str, cmd: Command, register: bool = False
- ) -> None:
- if not base_command.chain or not isinstance(cmd, Group):
- return
- if register:
- message = (
- f"It is not possible to add the group {cmd_name!r} to another"
- f" group {base_command.name!r} that is in chain mode."
- )
- else:
- message = (
- f"Found the group {cmd_name!r} as subcommand to another group "
- f" {base_command.name!r} that is in chain mode. This is not supported."
- )
- raise RuntimeError(message)
- def batch(iterable: cabc.Iterable[V], batch_size: int) -> list[tuple[V, ...]]:
- return list(zip(*repeat(iter(iterable), batch_size), strict=False))
- @contextmanager
- def augment_usage_errors(
- ctx: Context, param: Parameter | None = None
- ) -> cabc.Iterator[None]:
- """Context manager that attaches extra information to exceptions."""
- try:
- yield
- except BadParameter as e:
- if e.ctx is None:
- e.ctx = ctx
- if param is not None and e.param is None:
- e.param = param
- raise
- except UsageError as e:
- if e.ctx is None:
- e.ctx = ctx
- raise
- def iter_params_for_processing(
- invocation_order: cabc.Sequence[Parameter],
- declaration_order: cabc.Sequence[Parameter],
- ) -> list[Parameter]:
- """Returns all declared parameters in the order they should be processed.
- The declared parameters are re-shuffled depending on the order in which
- they were invoked, as well as the eagerness of each parameters.
- The invocation order takes precedence over the declaration order. I.e. the
- order in which the user provided them to the CLI is respected.
- This behavior and its effect on callback evaluation is detailed at:
- https://click.palletsprojects.com/en/stable/advanced/#callback-evaluation-order
- """
- def sort_key(item: Parameter) -> tuple[bool, float]:
- try:
- idx: float = invocation_order.index(item)
- except ValueError:
- idx = float("inf")
- return not item.is_eager, idx
- return sorted(declaration_order, key=sort_key)
- class ParameterSource(enum.Enum):
- """This is an :class:`~enum.Enum` that indicates the source of a
- parameter's value.
- Use :meth:`click.Context.get_parameter_source` to get the
- source for a parameter by name.
- .. versionchanged:: 8.0
- Use :class:`~enum.Enum` and drop the ``validate`` method.
- .. versionchanged:: 8.0
- Added the ``PROMPT`` value.
- """
- COMMANDLINE = enum.auto()
- """The value was provided by the command line args."""
- ENVIRONMENT = enum.auto()
- """The value was provided with an environment variable."""
- DEFAULT = enum.auto()
- """Used the default specified by the parameter."""
- DEFAULT_MAP = enum.auto()
- """Used a default provided by :attr:`Context.default_map`."""
- PROMPT = enum.auto()
- """Used a prompt to confirm a default or provide a value."""
- class Context:
- """The context is a special internal object that holds state relevant
- for the script execution at every single level. It's normally invisible
- to commands unless they opt-in to getting access to it.
- The context is useful as it can pass internal objects around and can
- control special execution features such as reading data from
- environment variables.
- A context can be used as context manager in which case it will call
- :meth:`close` on teardown.
- :param command: the command class for this context.
- :param parent: the parent context.
- :param info_name: the info name for this invocation. Generally this
- is the most descriptive name for the script or
- command. For the toplevel script it is usually
- the name of the script, for commands below it it's
- the name of the script.
- :param obj: an arbitrary object of user data.
- :param auto_envvar_prefix: the prefix to use for automatic environment
- variables. If this is `None` then reading
- from environment variables is disabled. This
- does not affect manually set environment
- variables which are always read.
- :param default_map: a dictionary (like object) with default values
- for parameters.
- :param terminal_width: the width of the terminal. The default is
- inherit from parent context. If no context
- defines the terminal width then auto
- detection will be applied.
- :param max_content_width: the maximum width for content rendered by
- Click (this currently only affects help
- pages). This defaults to 80 characters if
- not overridden. In other words: even if the
- terminal is larger than that, Click will not
- format things wider than 80 characters by
- default. In addition to that, formatters might
- add some safety mapping on the right.
- :param resilient_parsing: if this flag is enabled then Click will
- parse without any interactivity or callback
- invocation. Default values will also be
- ignored. This is useful for implementing
- things such as completion support.
- :param allow_extra_args: if this is set to `True` then extra arguments
- at the end will not raise an error and will be
- kept on the context. The default is to inherit
- from the command.
- :param allow_interspersed_args: if this is set to `False` then options
- and arguments cannot be mixed. The
- default is to inherit from the command.
- :param ignore_unknown_options: instructs click to ignore options it does
- not know and keeps them for later
- processing.
- :param help_option_names: optionally a list of strings that define how
- the default help parameter is named. The
- default is ``['--help']``.
- :param token_normalize_func: an optional function that is used to
- normalize tokens (options, choices,
- etc.). This for instance can be used to
- implement case insensitive behavior.
- :param color: controls if the terminal supports ANSI colors or not. The
- default is autodetection. This is only needed if ANSI
- codes are used in texts that Click prints which is by
- default not the case. This for instance would affect
- help output.
- :param show_default: Show the default value for commands. If this
- value is not set, it defaults to the value from the parent
- context. ``Command.show_default`` overrides this default for the
- specific command.
- .. versionchanged:: 8.2
- The ``protected_args`` attribute is deprecated and will be removed in
- Click 9.0. ``args`` will contain remaining unparsed tokens.
- .. versionchanged:: 8.1
- The ``show_default`` parameter is overridden by
- ``Command.show_default``, instead of the other way around.
- .. versionchanged:: 8.0
- The ``show_default`` parameter defaults to the value from the
- parent context.
- .. versionchanged:: 7.1
- Added the ``show_default`` parameter.
- .. versionchanged:: 4.0
- Added the ``color``, ``ignore_unknown_options``, and
- ``max_content_width`` parameters.
- .. versionchanged:: 3.0
- Added the ``allow_extra_args`` and ``allow_interspersed_args``
- parameters.
- .. versionchanged:: 2.0
- Added the ``resilient_parsing``, ``help_option_names``, and
- ``token_normalize_func`` parameters.
- """
- #: The formatter class to create with :meth:`make_formatter`.
- #:
- #: .. versionadded:: 8.0
- formatter_class: type[HelpFormatter] = HelpFormatter
- def __init__(
- self,
- command: Command,
- parent: Context | None = None,
- info_name: str | None = None,
- obj: t.Any | None = None,
- auto_envvar_prefix: str | None = None,
- default_map: cabc.MutableMapping[str, t.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: t.Callable[[str], str] | None = None,
- color: bool | None = None,
- show_default: bool | None = None,
- ) -> None:
- #: the parent context or `None` if none exists.
- self.parent = parent
- #: the :class:`Command` for this context.
- self.command = command
- #: the descriptive information name
- self.info_name = info_name
- #: Map of parameter names to their parsed values. Parameters
- #: with ``expose_value=False`` are not stored.
- self.params: dict[str, t.Any] = {}
- #: the leftover arguments.
- self.args: list[str] = []
- #: protected arguments. These are arguments that are prepended
- #: to `args` when certain parsing scenarios are encountered but
- #: must be never propagated to another arguments. This is used
- #: to implement nested parsing.
- self._protected_args: 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
- #: the user object stored.
- self.obj: t.Any = obj
- self._meta: dict[str, t.Any] = getattr(parent, "meta", {})
- #: A dictionary (-like object) with defaults for parameters.
- if (
- default_map is None
- and info_name is not None
- and parent is not None
- and parent.default_map is not None
- ):
- default_map = parent.default_map.get(info_name)
- self.default_map: cabc.MutableMapping[str, t.Any] | None = default_map
- #: This flag indicates if a subcommand is going to be executed. A
- #: group callback can use this information to figure out if it's
- #: being executed directly or because the execution flow passes
- #: onwards to a subcommand. By default it's None, but it can be
- #: the name of the subcommand to execute.
- #:
- #: If chaining is enabled this will be set to ``'*'`` in case
- #: any commands are executed. It is however not possible to
- #: figure out which ones. If you require this knowledge you
- #: should use a :func:`result_callback`.
- self.invoked_subcommand: 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
- #: The maximum width of formatted content (None implies a sensible
- #: default which is 80 for most things).
- self.max_content_width: int | None = max_content_width
- if allow_extra_args is None:
- allow_extra_args = command.allow_extra_args
- #: Indicates if the context allows extra args or if it should
- #: fail on parsing.
- #:
- #: .. versionadded:: 3.0
- self.allow_extra_args = allow_extra_args
- if allow_interspersed_args is None:
- allow_interspersed_args = command.allow_interspersed_args
- #: Indicates if the context allows mixing of arguments and
- #: options or not.
- #:
- #: .. versionadded:: 3.0
- self.allow_interspersed_args: bool = allow_interspersed_args
- if ignore_unknown_options is None:
- ignore_unknown_options = command.ignore_unknown_options
- #: Instructs click to ignore options that a command does not
- #: understand and will store it on the context for later
- #: processing. This is primarily useful for situations where you
- #: want to call into external programs. Generally this pattern is
- #: strongly discouraged because it's not possibly to losslessly
- #: forward all arguments.
- #:
- #: .. versionadded:: 4.0
- self.ignore_unknown_options: bool = ignore_unknown_options
- if help_option_names is None:
- if parent is not None:
- help_option_names = parent.help_option_names
- else:
- help_option_names = ["--help"]
- #: The names for the help options.
- self.help_option_names: list[str] = help_option_names
- if token_normalize_func is None and parent is not None:
- token_normalize_func = parent.token_normalize_func
- #: An optional normalization function for tokens. This is
- #: options, choices, commands etc.
- self.token_normalize_func: t.Callable[[str], str] | None = token_normalize_func
- #: Indicates if resilient parsing is enabled. In that case Click
- #: will do its best to not cause any failures and default values
- #: will be ignored. Useful for completion.
- self.resilient_parsing: bool = resilient_parsing
- # If there is no envvar prefix yet, but the parent has one and
- # the command on this level has a name, we can expand the envvar
- # prefix automatically.
- if auto_envvar_prefix is None:
- if (
- parent is not None
- and parent.auto_envvar_prefix is not None
- and self.info_name is not None
- ):
- auto_envvar_prefix = (
- f"{parent.auto_envvar_prefix}_{self.info_name.upper()}"
- )
- else:
- auto_envvar_prefix = auto_envvar_prefix.upper()
- if auto_envvar_prefix is not None:
- auto_envvar_prefix = auto_envvar_prefix.replace("-", "_")
- self.auto_envvar_prefix: 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[t.Callable[[], t.Any]] = []
- self._depth = 0
- self._parameter_source: dict[str, ParameterSource] = {}
- self._exit_stack = ExitStack()
- @property
- def protected_args(self) -> list[str]:
- import warnings
- warnings.warn(
- "'protected_args' is deprecated and will be removed in Click 9.0."
- " 'args' will contain remaining unparsed tokens.",
- DeprecationWarning,
- stacklevel=2,
- )
- return self._protected_args
- def to_info_dict(self) -> dict[str, t.Any]:
- """Gather information that could be useful for a tool generating
- user-facing documentation. This traverses the entire CLI
- structure.
- .. code-block:: python
- with Context(cli) as ctx:
- info = ctx.to_info_dict()
- .. versionadded:: 8.0
- """
- return {
- "command": self.command.to_info_dict(self),
- "info_name": self.info_name,
- "allow_extra_args": self.allow_extra_args,
- "allow_interspersed_args": self.allow_interspersed_args,
- "ignore_unknown_options": self.ignore_unknown_options,
- "auto_envvar_prefix": self.auto_envvar_prefix,
- }
- def __enter__(self) -> Context:
- self._depth += 1
- push_context(self)
- return self
- def __exit__(
- self,
- exc_type: type[BaseException] | None,
- exc_value: BaseException | None,
- tb: TracebackType | None,
- ) -> bool | None:
- self._depth -= 1
- exit_result: bool | None = None
- if self._depth == 0:
- exit_result = self._close_with_exception_info(exc_type, exc_value, tb)
- pop_context()
- return exit_result
- @contextmanager
- def scope(self, cleanup: bool = True) -> cabc.Iterator[Context]:
- """This helper method can be used with the context object to promote
- it to the current thread local (see :func:`get_current_context`).
- The default behavior of this is to invoke the cleanup functions which
- can be disabled by setting `cleanup` to `False`. The cleanup
- functions are typically used for things such as closing file handles.
- If the cleanup is intended the context object can also be directly
- used as a context manager.
- Example usage::
- with ctx.scope():
- assert get_current_context() is ctx
- This is equivalent::
- with ctx:
- assert get_current_context() is ctx
- .. versionadded:: 5.0
- :param cleanup: controls if the cleanup functions should be run or
- not. The default is to run these functions. In
- some situations the context only wants to be
- temporarily pushed in which case this can be disabled.
- Nested pushes automatically defer the cleanup.
- """
- if not cleanup:
- self._depth += 1
- try:
- with self as rv:
- yield rv
- finally:
- if not cleanup:
- self._depth -= 1
- @property
- def meta(self) -> dict[str, t.Any]:
- """This is a dictionary which is shared with all the contexts
- that are nested. It exists so that click utilities can store some
- state here if they need to. It is however the responsibility of
- that code to manage this dictionary well.
- The keys are supposed to be unique dotted strings. For instance
- module paths are a good choice for it. What is stored in there is
- irrelevant for the operation of click. However what is important is
- that code that places data here adheres to the general semantics of
- the system.
- Example usage::
- LANG_KEY = f'{__name__}.lang'
- def set_language(value):
- ctx = get_current_context()
- ctx.meta[LANG_KEY] = value
- def get_language():
- return get_current_context().meta.get(LANG_KEY, 'en_US')
- .. versionadded:: 5.0
- """
- return self._meta
- def make_formatter(self) -> HelpFormatter:
- """Creates the :class:`~click.HelpFormatter` for the help and
- usage output.
- To quickly customize the formatter class used without overriding
- this method, set the :attr:`formatter_class` attribute.
- .. versionchanged:: 8.0
- Added the :attr:`formatter_class` attribute.
- """
- return self.formatter_class(
- width=self.terminal_width, max_width=self.max_content_width
- )
- def with_resource(self, context_manager: 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 :meth:`contextlib.ExitStack.enter_context`. It calls the
- resource's ``__enter__()`` method and returns the result. When
- the context is popped, it closes the stack, which calls the
- resource's ``__exit__()`` method.
- To register a cleanup function for something that isn't a
- context manager, use :meth:`call_on_close`. Or use something
- from :mod:`contextlib` to turn it into a context manager first.
- .. code-block:: python
- @click.group()
- @click.option("--name")
- @click.pass_context
- def cli(ctx):
- ctx.obj = ctx.with_resource(connect_db(name))
- :param context_manager: The context manager to enter.
- :return: Whatever ``context_manager.__enter__()`` returns.
- .. versionadded:: 8.0
- """
- return self._exit_stack.enter_context(context_manager)
- def call_on_close(self, f: t.Callable[..., t.Any]) -> t.Callable[..., t.Any]:
- """Register a function to be called when the context tears down.
- This can be used to close resources opened during the script
- execution. Resources that support Python's context manager
- protocol which would be used in a ``with`` statement should be
- registered with :meth:`with_resource` instead.
- :param f: The function to execute on teardown.
- """
- return self._exit_stack.callback(f)
- def close(self) -> None:
- """Invoke all close callbacks registered with
- :meth:`call_on_close`, and exit all context managers entered
- with :meth:`with_resource`.
- """
- self._close_with_exception_info(None, None, None)
- def _close_with_exception_info(
- self,
- exc_type: type[BaseException] | None,
- exc_value: BaseException | None,
- tb: TracebackType | None,
- ) -> bool | None:
- """Unwind the exit stack by calling its :meth:`__exit__` providing the exception
- information to allow for exception handling by the various resources registered
- using :meth;`with_resource`
- :return: Whatever ``exit_stack.__exit__()`` returns.
- """
- exit_result = self._exit_stack.__exit__(exc_type, exc_value, tb)
- # In case the context is reused, create a new exit stack.
- self._exit_stack = ExitStack()
- return exit_result
- @property
- def command_path(self) -> str:
- """The computed command path. This is used for the ``usage``
- information on the help page. It's automatically created by
- combining the info names of the chain of contexts to the root.
- """
- rv = ""
- if self.info_name is not None:
- rv = self.info_name
- if self.parent is not None:
- parent_command_path = [self.parent.command_path]
- if isinstance(self.parent.command, Command):
- for param in self.parent.command.get_params(self):
- parent_command_path.extend(param.get_usage_pieces(self))
- rv = f"{' '.join(parent_command_path)} {rv}"
- return rv.lstrip()
- def find_root(self) -> Context:
- """Finds the outermost context."""
- node = self
- while node.parent is not None:
- node = node.parent
- return node
- def find_object(self, object_type: 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
- def ensure_object(self, object_type: type[V]) -> V:
- """Like :meth:`find_object` but sets the innermost object to a
- new instance of `object_type` if it does not exist.
- """
- rv = self.find_object(object_type)
- if rv is None:
- self.obj = rv = object_type()
- return rv
- @t.overload
- def lookup_default(
- self, name: str, call: t.Literal[True] = True
- ) -> t.Any | None: ...
- @t.overload
- def lookup_default(
- self, name: str, call: t.Literal[False] = ...
- ) -> t.Any | t.Callable[[], t.Any] | None: ...
- def lookup_default(self, name: str, call: bool = True) -> t.Any | None:
- """Get the default for a parameter from :attr:`default_map`.
- :param name: Name of the parameter.
- :param call: If the default is a callable, call it. Disable to
- return the callable instead.
- .. versionchanged:: 8.0
- Added the ``call`` parameter.
- """
- if self.default_map is not None:
- value = self.default_map.get(name, UNSET)
- if call and callable(value):
- return value()
- return value
- return UNSET
- def fail(self, message: str) -> t.NoReturn:
- """Aborts the execution of the program with a specific error
- message.
- :param message: the error message to fail with.
- """
- raise UsageError(message, self)
- def abort(self) -> t.NoReturn:
- """Aborts the script."""
- raise Abort()
- def exit(self, code: int = 0) -> t.NoReturn:
- """Exits the application with a given exit code.
- .. versionchanged:: 8.2
- Callbacks and context managers registered with :meth:`call_on_close`
- and :meth:`with_resource` are closed before exiting.
- """
- self.close()
- raise Exit(code)
- def get_usage(self) -> str:
- """Helper method to get formatted usage string for the current
- context and command.
- """
- return self.command.get_usage(self)
- def get_help(self) -> str:
- """Helper method to get formatted help page for the current
- context and command.
- """
- return self.command.get_help(self)
- def _make_sub_context(self, command: Command) -> Context:
- """Create a new context of the same type as this context, but
- for a new command.
- :meta private:
- """
- return type(self)(command, info_name=command.name, parent=self)
- @t.overload
- def invoke(
- self, callback: t.Callable[..., V], /, *args: t.Any, **kwargs: t.Any
- ) -> V: ...
- @t.overload
- def invoke(self, callback: Command, /, *args: t.Any, **kwargs: t.Any) -> t.Any: ...
- def invoke(
- self, callback: Command | t.Callable[..., V], /, *args: t.Any, **kwargs: t.Any
- ) -> t.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.
- .. versionchanged:: 8.0
- All ``kwargs`` are tracked in :attr:`params` so they will be
- passed if :meth:`forward` is called at multiple levels.
- .. versionchanged:: 3.2
- A new context is created, and missing arguments use default values.
- """
- if isinstance(callback, Command):
- other_cmd = callback
- if other_cmd.callback is None:
- raise TypeError(
- "The given command does not have a callback that can be invoked."
- )
- else:
- callback = t.cast("t.Callable[..., V]", other_cmd.callback)
- ctx = self._make_sub_context(other_cmd)
- for param in other_cmd.params:
- if param.name not in kwargs and param.expose_value:
- kwargs[param.name] = param.type_cast_value( # type: ignore
- ctx, param.get_default(ctx)
- )
- # Track all kwargs as params, so that forward() will pass
- # them on in subsequent calls.
- ctx.params.update(kwargs)
- else:
- ctx = self
- with augment_usage_errors(self):
- with ctx:
- return callback(*args, **kwargs)
- def forward(self, cmd: Command, /, *args: t.Any, **kwargs: t.Any) -> t.Any:
- """Similar to :meth:`invoke` but fills in default keyword
- arguments from the current context if the other command expects
- it. This cannot invoke callbacks directly, only other commands.
- .. versionchanged:: 8.0
- All ``kwargs`` are tracked in :attr:`params` so they will be
- passed if ``forward`` is called at multiple levels.
- """
- # Can only forward to other commands, not direct callbacks.
- if not isinstance(cmd, Command):
- raise TypeError("Callback is not a command.")
- for param in self.params:
- if param not in kwargs:
- kwargs[param] = self.params[param]
- return self.invoke(cmd, *args, **kwargs)
- def set_parameter_source(self, name: str, source: ParameterSource) -> None:
- """Set the source of a parameter. This indicates the location
- from which the value of the parameter was obtained.
- :param name: The name of the parameter.
- :param source: A member of :class:`~click.core.ParameterSource`.
- """
- self._parameter_source[name] = source
- def get_parameter_source(self, name: str) -> 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 :attr:`~click.core.ParameterSource.DEFAULT` only if the
- value was actually taken from the default.
- :param name: The name of the parameter.
- :rtype: ParameterSource
- .. versionchanged:: 8.0
- Returns ``None`` if the parameter was not provided from any
- source.
- """
- return self._parameter_source.get(name)
- class Command:
- """Commands are the basic building block of command line interfaces in
- Click. A basic command handles command line parsing and might dispatch
- more parsing to commands nested below it.
- :param name: the name of the command to use unless a group overrides it.
- :param context_settings: an optional dictionary with defaults that are
- passed to the context object.
- :param callback: the callback to invoke. This is optional.
- :param params: the parameters to register with this command. This can
- be either :class:`Option` or :class:`Argument` objects.
- :param help: the help string to use for this command.
- :param epilog: like the help string but it's printed at the end of the
- help page after everything else.
- :param short_help: the short help to use for this command. This is
- shown on the command listing of the parent command.
- :param add_help_option: by default each command registers a ``--help``
- option. This can be disabled by this parameter.
- :param no_args_is_help: this controls what happens if no arguments are
- provided. This option is disabled by default.
- If enabled this will add ``--help`` as argument
- if no arguments are passed
- :param hidden: hide this command from help outputs.
- :param deprecated: If ``True`` or non-empty string, issues a message
- indicating that the command is deprecated and highlights
- its deprecation in --help. The message can be customized
- by using a string as the value.
- .. versionchanged:: 8.2
- This is the base class for all commands, not ``BaseCommand``.
- ``deprecated`` can be set to a string as well to customize the
- deprecation message.
- .. versionchanged:: 8.1
- ``help``, ``epilog``, and ``short_help`` are stored unprocessed,
- all formatting is done when outputting help text, not at init,
- and is done even if not using the ``@command`` decorator.
- .. versionchanged:: 8.0
- Added a ``repr`` showing the command name.
- .. versionchanged:: 7.1
- Added the ``no_args_is_help`` parameter.
- .. versionchanged:: 2.0
- Added the ``context_settings`` parameter.
- """
- #: The context class to create with :meth:`make_context`.
- #:
- #: .. versionadded:: 8.0
- context_class: type[Context] = Context
- #: the default for the :attr:`Context.allow_extra_args` flag.
- allow_extra_args = False
- #: the default for the :attr:`Context.allow_interspersed_args` flag.
- allow_interspersed_args = True
- #: the default for the :attr:`Context.ignore_unknown_options` flag.
- ignore_unknown_options = False
- def __init__(
- self,
- name: str | None,
- context_settings: cabc.MutableMapping[str, t.Any] | None = None,
- callback: t.Callable[..., t.Any] | None = None,
- params: list[Parameter] | None = None,
- help: str | None = None,
- epilog: str | None = None,
- short_help: str | None = None,
- options_metavar: str | None = "[OPTIONS]",
- add_help_option: bool = True,
- no_args_is_help: bool = False,
- hidden: bool = False,
- deprecated: bool | str = False,
- ) -> None:
- #: the name the command thinks it has. Upon registering a command
- #: on a :class:`Group` the group will default the command name
- #: with this information. You should instead use the
- #: :class:`Context`\'s :attr:`~Context.info_name` attribute.
- self.name = name
- if context_settings is None:
- context_settings = {}
- #: an optional dictionary with defaults passed to the context.
- self.context_settings: cabc.MutableMapping[str, t.Any] = context_settings
- #: the callback to execute when the command fires. This might be
- #: `None` in which case nothing happens.
- self.callback = callback
- #: the list of parameters for this command in the order they
- #: should show up in the help page and execute. Eager parameters
- #: will automatically be handled before non eager ones.
- self.params: list[Parameter] = params or []
- self.help = help
- self.epilog = epilog
- self.options_metavar = options_metavar
- self.short_help = short_help
- self.add_help_option = add_help_option
- self._help_option = None
- self.no_args_is_help = no_args_is_help
- self.hidden = hidden
- self.deprecated = deprecated
- def to_info_dict(self, ctx: Context) -> dict[str, t.Any]:
- return {
- "name": self.name,
- "params": [param.to_info_dict() for param in self.get_params(ctx)],
- "help": self.help,
- "epilog": self.epilog,
- "short_help": self.short_help,
- "hidden": self.hidden,
- "deprecated": self.deprecated,
- }
- def __repr__(self) -> str:
- return f"<{self.__class__.__name__} {self.name}>"
- def get_usage(self, ctx: Context) -> str:
- """Formats the usage line into a string and returns it.
- Calls :meth:`format_usage` internally.
- """
- formatter = ctx.make_formatter()
- self.format_usage(ctx, formatter)
- return formatter.getvalue().rstrip("\n")
- def get_params(self, ctx: Context) -> list[Parameter]:
- params = self.params
- help_option = self.get_help_option(ctx)
- if help_option is not None:
- params = [*params, help_option]
- if __debug__:
- import warnings
- opts = [opt for param in params for opt in param.opts]
- opts_counter = Counter(opts)
- duplicate_opts = (opt for opt, count in opts_counter.items() if count > 1)
- for duplicate_opt in duplicate_opts:
- warnings.warn(
- (
- f"The parameter {duplicate_opt} is used more than once. "
- "Remove its duplicate as parameters should be unique."
- ),
- stacklevel=3,
- )
- return params
- def format_usage(self, ctx: Context, formatter: HelpFormatter) -> None:
- """Writes the usage line into the formatter.
- This is a low-level method called by :meth:`get_usage`.
- """
- pieces = self.collect_usage_pieces(ctx)
- formatter.write_usage(ctx.command_path, " ".join(pieces))
- def collect_usage_pieces(self, ctx: Context) -> list[str]:
- """Returns all the pieces that go into the usage line and returns
- it as a list of strings.
- """
- rv = [self.options_metavar] if self.options_metavar else []
- for param in self.get_params(ctx):
- rv.extend(param.get_usage_pieces(ctx))
- return rv
- def get_help_option_names(self, ctx: Context) -> list[str]:
- """Returns the names for the help option."""
- all_names = set(ctx.help_option_names)
- for param in self.params:
- all_names.difference_update(param.opts)
- all_names.difference_update(param.secondary_opts)
- return list(all_names)
- def get_help_option(self, ctx: Context) -> Option | None:
- """Returns the help option object.
- Skipped if :attr:`add_help_option` is ``False``.
- .. versionchanged:: 8.1.8
- The help option is now cached to avoid creating it multiple times.
- """
- help_option_names = self.get_help_option_names(ctx)
- if not help_option_names or not self.add_help_option:
- return None
- # Cache the help option object in private _help_option attribute to
- # avoid creating it multiple times. Not doing this will break the
- # callback odering by iter_params_for_processing(), which relies on
- # object comparison.
- if self._help_option is None:
- # Avoid circular import.
- from .decorators import help_option
- # Apply help_option decorator and pop resulting option
- help_option(*help_option_names)(self)
- self._help_option = self.params.pop() # type: ignore[assignment]
- return self._help_option
- def make_parser(self, ctx: Context) -> _OptionParser:
- """Creates the underlying option parser for this command."""
- parser = _OptionParser(ctx)
- for param in self.get_params(ctx):
- param.add_to_parser(parser, ctx)
- return parser
- def get_help(self, ctx: Context) -> str:
- """Formats the help into a string and returns it.
- Calls :meth:`format_help` internally.
- """
- formatter = ctx.make_formatter()
- self.format_help(ctx, formatter)
- return formatter.getvalue().rstrip("\n")
- def get_short_help_str(self, limit: int = 45) -> str:
- """Gets short help for the command or makes it by shortening the
- long help string.
- """
- if self.short_help:
- text = inspect.cleandoc(self.short_help)
- elif self.help:
- text = make_default_short_help(self.help, limit)
- else:
- text = ""
- if self.deprecated:
- deprecated_message = (
- f"(DEPRECATED: {self.deprecated})"
- if isinstance(self.deprecated, str)
- else "(DEPRECATED)"
- )
- text = _("{text} {deprecated_message}").format(
- text=text, deprecated_message=deprecated_message
- )
- return text.strip()
- def format_help(self, ctx: Context, formatter: HelpFormatter) -> None:
- """Writes the help into the formatter if it exists.
- This is a low-level method called by :meth:`get_help`.
- This calls the following methods:
- - :meth:`format_usage`
- - :meth:`format_help_text`
- - :meth:`format_options`
- - :meth:`format_epilog`
- """
- self.format_usage(ctx, formatter)
- self.format_help_text(ctx, formatter)
- self.format_options(ctx, formatter)
- self.format_epilog(ctx, formatter)
- def format_help_text(self, ctx: Context, formatter: HelpFormatter) -> None:
- """Writes the help text to the formatter if it exists."""
- if self.help is not None:
- # truncate the help text to the first form feed
- text = inspect.cleandoc(self.help).partition("\f")[0]
- else:
- text = ""
- if self.deprecated:
- deprecated_message = (
- f"(DEPRECATED: {self.deprecated})"
- if isinstance(self.deprecated, str)
- else "(DEPRECATED)"
- )
- text = _("{text} {deprecated_message}").format(
- text=text, deprecated_message=deprecated_message
- )
- if text:
- formatter.write_paragraph()
- with formatter.indentation():
- formatter.write_text(text)
- def format_options(self, ctx: Context, formatter: HelpFormatter) -> None:
- """Writes all the options into the formatter if they exist."""
- opts = []
- for param in self.get_params(ctx):
- rv = param.get_help_record(ctx)
- if rv is not None:
- opts.append(rv)
- if opts:
- with formatter.section(_("Options")):
- formatter.write_dl(opts)
- def format_epilog(self, ctx: Context, formatter: HelpFormatter) -> None:
- """Writes the epilog into the formatter if it exists."""
- if self.epilog:
- epilog = inspect.cleandoc(self.epilog)
- formatter.write_paragraph()
- with formatter.indentation():
- formatter.write_text(epilog)
- def make_context(
- self,
- info_name: str | None,
- args: list[str],
- parent: Context | None = None,
- **extra: t.Any,
- ) -> Context:
- """This function when given an info name and arguments will kick
- off the parsing and create a new :class:`Context`. It does not
- invoke the actual command callback though.
- To quickly customize the context class used without overriding
- this method, set the :attr:`context_class` attribute.
- :param info_name: the info name for this invocation. Generally this
- is the most descriptive name for the script or
- command. For the toplevel script it's usually
- the name of the script, for commands below it's
- the name of the command.
- :param args: the arguments to parse as list of strings.
- :param parent: the parent context if available.
- :param extra: extra keyword arguments forwarded to the context
- constructor.
- .. versionchanged:: 8.0
- Added the :attr:`context_class` attribute.
- """
- for key, value in self.context_settings.items():
- if key not in extra:
- extra[key] = value
- ctx = self.context_class(self, info_name=info_name, parent=parent, **extra)
- with ctx.scope(cleanup=False):
- self.parse_args(ctx, args)
- return ctx
- def parse_args(self, ctx: Context, args: list[str]) -> list[str]:
- if not args and self.no_args_is_help and not ctx.resilient_parsing:
- raise NoArgsIsHelpError(ctx)
- parser = self.make_parser(ctx)
- opts, args, param_order = parser.parse_args(args=args)
- for param in iter_params_for_processing(param_order, self.get_params(ctx)):
- _, args = param.handle_parse_result(ctx, opts, args)
- if args and not ctx.allow_extra_args and not ctx.resilient_parsing:
- ctx.fail(
- ngettext(
- "Got unexpected extra argument ({args})",
- "Got unexpected extra arguments ({args})",
- len(args),
- ).format(args=" ".join(map(str, args)))
- )
- ctx.args = args
- ctx._opt_prefixes.update(parser._opt_prefixes)
- return args
- def invoke(self, ctx: Context) -> t.Any:
- """Given a context, this invokes the attached callback (if it exists)
- in the right way.
- """
- if self.deprecated:
- extra_message = (
- f" {self.deprecated}" if isinstance(self.deprecated, str) else ""
- )
- message = _(
- "DeprecationWarning: The command {name!r} is deprecated.{extra_message}"
- ).format(name=self.name, extra_message=extra_message)
- echo(style(message, fg="red"), err=True)
- if self.callback is not None:
- return ctx.invoke(self.callback, **ctx.params)
- def shell_complete(self, ctx: Context, incomplete: str) -> list[CompletionItem]:
- """Return a list of completions for the incomplete value. Looks
- at the names of options and chained multi-commands.
- Any command could be part of a chained multi-command, so sibling
- commands are valid at any point during command completion.
- :param ctx: Invocation context for this command.
- :param incomplete: Value being completed. May be empty.
- .. versionadded:: 8.0
- """
- from click.shell_completion import CompletionItem
- results: list[CompletionItem] = []
- if incomplete and not incomplete[0].isalnum():
- for param in self.get_params(ctx):
- if (
- not isinstance(param, Option)
- or param.hidden
- or (
- not param.multiple
- and ctx.get_parameter_source(param.name) # type: ignore
- is ParameterSource.COMMANDLINE
- )
- ):
- continue
- results.extend(
- CompletionItem(name, help=param.help)
- for name in [*param.opts, *param.secondary_opts]
- if name.startswith(incomplete)
- )
- while ctx.parent is not None:
- ctx = ctx.parent
- if isinstance(ctx.command, Group) and ctx.command.chain:
- results.extend(
- CompletionItem(name, help=command.get_short_help_str())
- for name, command in _complete_visible_commands(ctx, incomplete)
- if name not in ctx._protected_args
- )
- return results
- @t.overload
- def main(
- self,
- args: cabc.Sequence[str] | None = None,
- prog_name: str | None = None,
- complete_var: str | None = None,
- standalone_mode: t.Literal[True] = True,
- **extra: t.Any,
- ) -> t.NoReturn: ...
- @t.overload
- def main(
- self,
- args: cabc.Sequence[str] | None = None,
- prog_name: str | None = None,
- complete_var: str | None = None,
- standalone_mode: bool = ...,
- **extra: t.Any,
- ) -> t.Any: ...
- def main(
- self,
- args: cabc.Sequence[str] | None = None,
- prog_name: str | None = None,
- complete_var: str | None = None,
- standalone_mode: bool = True,
- windows_expand_args: bool = True,
- **extra: t.Any,
- ) -> t.Any:
- """This is the way to invoke a script with all the bells and
- whistles as a command line application. This will always terminate
- the application after a call. If this is not wanted, ``SystemExit``
- needs to be caught.
- This method is also available by directly calling the instance of
- a :class:`Command`.
- :param args: the arguments that should be used for parsing. If not
- provided, ``sys.argv[1:]`` is used.
- :param prog_name: the program name that should be used. By default
- the program name is constructed by taking the file
- name from ``sys.argv[0]``.
- :param complete_var: the environment variable that controls the
- bash completion support. The default is
- ``"_<prog_name>_COMPLETE"`` with prog_name in
- uppercase.
- :param standalone_mode: the default behavior is to invoke the script
- in standalone mode. Click will then
- handle exceptions and convert them into
- error messages and the function will never
- return but shut down the interpreter. If
- this is set to `False` they will be
- propagated to the caller and the return
- value of this function is the return value
- of :meth:`invoke`.
- :param windows_expand_args: Expand glob patterns, user dir, and
- env vars in command line args on Windows.
- :param extra: extra keyword arguments are forwarded to the context
- constructor. See :class:`Context` for more information.
- .. versionchanged:: 8.0.1
- Added the ``windows_expand_args`` parameter to allow
- disabling command line arg expansion on Windows.
- .. versionchanged:: 8.0
- When taking arguments from ``sys.argv`` on Windows, glob
- patterns, user dir, and env vars are expanded.
- .. versionchanged:: 3.0
- Added the ``standalone_mode`` parameter.
- """
- if args is None:
- args = sys.argv[1:]
- if os.name == "nt" and windows_expand_args:
- args = _expand_args(args)
- else:
- args = list(args)
- if prog_name is None:
- prog_name = _detect_program_name()
- # Process shell completion requests and exit early.
- self._main_shell_completion(extra, prog_name, complete_var)
- try:
- try:
- with self.make_context(prog_name, args, **extra) as ctx:
- rv = self.invoke(ctx)
- if not standalone_mode:
- return rv
- # it's not safe to `ctx.exit(rv)` here!
- # note that `rv` may actually contain data like "1" which
- # has obvious effects
- # more subtle case: `rv=[None, None]` can come out of
- # chained commands which all returned `None` -- so it's not
- # even always obvious that `rv` indicates success/failure
- # by its truthiness/falsiness
- ctx.exit()
- except (EOFError, KeyboardInterrupt) as e:
- echo(file=sys.stderr)
- raise Abort() from e
- except ClickException as e:
- if not standalone_mode:
- raise
- e.show()
- sys.exit(e.exit_code)
- except OSError as e:
- if e.errno == errno.EPIPE:
- sys.stdout = t.cast(t.TextIO, PacifyFlushWrapper(sys.stdout))
- sys.stderr = t.cast(t.TextIO, PacifyFlushWrapper(sys.stderr))
- sys.exit(1)
- else:
- raise
- except Exit as e:
- if standalone_mode:
- sys.exit(e.exit_code)
- else:
- # in non-standalone mode, return the exit code
- # note that this is only reached if `self.invoke` above raises
- # an Exit explicitly -- thus bypassing the check there which
- # would return its result
- # the results of non-standalone execution may therefore be
- # somewhat ambiguous: if there are codepaths which lead to
- # `ctx.exit(1)` and to `return 1`, the caller won't be able to
- # tell the difference between the two
- return e.exit_code
- except Abort:
- if not standalone_mode:
- raise
- echo(_("Aborted!"), file=sys.stderr)
- sys.exit(1)
- def _main_shell_completion(
- self,
- ctx_args: cabc.MutableMapping[str, t.Any],
- prog_name: str,
- complete_var: str | None = None,
- ) -> None:
- """Check if the shell is asking for tab completion, process
- that, then exit early. Called from :meth:`main` before the
- program is invoked.
- :param prog_name: Name of the executable in the shell.
- :param complete_var: Name of the environment variable that holds
- the completion instruction. Defaults to
- ``_{PROG_NAME}_COMPLETE``.
- .. versionchanged:: 8.2.0
- Dots (``.``) in ``prog_name`` are replaced with underscores (``_``).
- """
- if complete_var is None:
- complete_name = prog_name.replace("-", "_").replace(".", "_")
- complete_var = f"_{complete_name}_COMPLETE".upper()
- instruction = os.environ.get(complete_var)
- if not instruction:
- return
- from .shell_completion import shell_complete
- rv = shell_complete(self, ctx_args, prog_name, complete_var, instruction)
- sys.exit(rv)
- def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Any:
- """Alias for :meth:`main`."""
- return self.main(*args, **kwargs)
- class _FakeSubclassCheck(type):
- def __subclasscheck__(cls, subclass: type) -> bool:
- return issubclass(subclass, cls.__bases__[0])
- def __instancecheck__(cls, instance: t.Any) -> bool:
- return isinstance(instance, cls.__bases__[0])
- class _BaseCommand(Command, metaclass=_FakeSubclassCheck):
- """
- .. deprecated:: 8.2
- Will be removed in Click 9.0. Use ``Command`` instead.
- """
- class Group(Command):
- """A group is a command that nests other commands (or more groups).
- :param name: The name of the group command.
- :param commands: Map names to :class:`Command` objects. Can be a list, which
- will use :attr:`Command.name` as the keys.
- :param invoke_without_command: Invoke the group's callback even if a
- subcommand is not given.
- :param no_args_is_help: If no arguments are given, show the group's help and
- exit. Defaults to the opposite of ``invoke_without_command``.
- :param subcommand_metavar: How to represent the subcommand argument in help.
- The default will represent whether ``chain`` is set or not.
- :param chain: Allow passing more than one subcommand argument. After parsing
- a command's arguments, if any arguments remain another command will be
- matched, and so on.
- :param result_callback: A function to call after the group's and
- subcommand's callbacks. The value returned by the subcommand is passed.
- If ``chain`` is enabled, the value will be a list of values returned by
- all the commands. If ``invoke_without_command`` is enabled, the value
- will be the value returned by the group's callback, or an empty list if
- ``chain`` is enabled.
- :param kwargs: Other arguments passed to :class:`Command`.
- .. versionchanged:: 8.0
- The ``commands`` argument can be a list of command objects.
- .. versionchanged:: 8.2
- Merged with and replaces the ``MultiCommand`` base class.
- """
- allow_extra_args = True
- allow_interspersed_args = False
- #: If set, this is used by the group's :meth:`command` decorator
- #: as the default :class:`Command` class. This is useful to make all
- #: subcommands use a custom command class.
- #:
- #: .. versionadded:: 8.0
- command_class: type[Command] | None = None
- #: If set, this is used by the group's :meth:`group` decorator
- #: as the default :class:`Group` class. This is useful to make all
- #: subgroups use a custom group class.
- #:
- #: If set to the special value :class:`type` (literally
- #: ``group_class = type``), this group's class will be used as the
- #: default class. This makes a custom group class continue to make
- #: custom groups.
- #:
- #: .. versionadded:: 8.0
- group_class: type[Group] | type[type] | None = None
- # Literal[type] isn't valid, so use Type[type]
- def __init__(
- self,
- name: str | None = None,
- commands: cabc.MutableMapping[str, Command]
- | cabc.Sequence[Command]
- | None = None,
- invoke_without_command: bool = False,
- no_args_is_help: bool | None = None,
- subcommand_metavar: str | None = None,
- chain: bool = False,
- result_callback: t.Callable[..., t.Any] | None = None,
- **kwargs: t.Any,
- ) -> None:
- super().__init__(name, **kwargs)
- if commands is None:
- commands = {}
- elif isinstance(commands, abc.Sequence):
- commands = {c.name: c for c in commands if c.name is not None}
- #: The registered subcommands by their exported names.
- self.commands: cabc.MutableMapping[str, Command] = commands
- if no_args_is_help is None:
- no_args_is_help = not invoke_without_command
- self.no_args_is_help = no_args_is_help
- self.invoke_without_command = invoke_without_command
- if subcommand_metavar is None:
- if chain:
- subcommand_metavar = "COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]..."
- else:
- subcommand_metavar = "COMMAND [ARGS]..."
- self.subcommand_metavar = subcommand_metavar
- self.chain = chain
- # The result callback that is stored. This can be set or
- # overridden with the :func:`result_callback` decorator.
- self._result_callback = result_callback
- if self.chain:
- for param in self.params:
- if isinstance(param, Argument) and not param.required:
- raise RuntimeError(
- "A group in chain mode cannot have optional arguments."
- )
- def to_info_dict(self, ctx: Context) -> dict[str, t.Any]:
- info_dict = super().to_info_dict(ctx)
- commands = {}
- for name in self.list_commands(ctx):
- command = self.get_command(ctx, name)
- if command is None:
- continue
- sub_ctx = ctx._make_sub_context(command)
- with sub_ctx.scope(cleanup=False):
- commands[name] = command.to_info_dict(sub_ctx)
- info_dict.update(commands=commands, chain=self.chain)
- return info_dict
- def add_command(self, cmd: Command, name: str | None = None) -> None:
- """Registers another :class:`Command` with this group. If the name
- is not provided, the name of the command is used.
- """
- name = name or cmd.name
- if name is None:
- raise TypeError("Command has no name.")
- _check_nested_chain(self, name, cmd, register=True)
- self.commands[name] = cmd
- @t.overload
- def command(self, __func: t.Callable[..., t.Any]) -> Command: ...
- @t.overload
- def command(
- self, *args: t.Any, **kwargs: t.Any
- ) -> t.Callable[[t.Callable[..., t.Any]], Command]: ...
- def command(
- self, *args: t.Any, **kwargs: t.Any
- ) -> t.Callable[[t.Callable[..., t.Any]], Command] | Command:
- """A shortcut decorator for declaring and attaching a command to
- the group. This takes the same arguments as :func:`command` and
- immediately registers the created command with this group by
- calling :meth:`add_command`.
- To customize the command class used, set the
- :attr:`command_class` attribute.
- .. versionchanged:: 8.1
- This decorator can be applied without parentheses.
- .. versionchanged:: 8.0
- Added the :attr:`command_class` attribute.
- """
- from .decorators import command
- func: t.Callable[..., t.Any] | None = None
- if args and callable(args[0]):
- assert len(args) == 1 and not kwargs, (
- "Use 'command(**kwargs)(callable)' to provide arguments."
- )
- (func,) = args
- args = ()
- if self.command_class and kwargs.get("cls") is None:
- kwargs["cls"] = self.command_class
- def decorator(f: t.Callable[..., t.Any]) -> Command:
- cmd: Command = command(*args, **kwargs)(f)
- self.add_command(cmd)
- return cmd
- if func is not None:
- return decorator(func)
- return decorator
- @t.overload
- def group(self, __func: t.Callable[..., t.Any]) -> Group: ...
- @t.overload
- def group(
- self, *args: t.Any, **kwargs: t.Any
- ) -> t.Callable[[t.Callable[..., t.Any]], Group]: ...
- def group(
- self, *args: t.Any, **kwargs: t.Any
- ) -> t.Callable[[t.Callable[..., t.Any]], Group] | Group:
- """A shortcut decorator for declaring and attaching a group to
- the group. This takes the same arguments as :func:`group` and
- immediately registers the created group with this group by
- calling :meth:`add_command`.
- To customize the group class used, set the :attr:`group_class`
- attribute.
- .. versionchanged:: 8.1
- This decorator can be applied without parentheses.
- .. versionchanged:: 8.0
- Added the :attr:`group_class` attribute.
- """
- from .decorators import group
- func: t.Callable[..., t.Any] | None = None
- if args and callable(args[0]):
- assert len(args) == 1 and not kwargs, (
- "Use 'group(**kwargs)(callable)' to provide arguments."
- )
- (func,) = args
- args = ()
- if self.group_class is not None and kwargs.get("cls") is None:
- if self.group_class is type:
- kwargs["cls"] = type(self)
- else:
- kwargs["cls"] = self.group_class
- def decorator(f: t.Callable[..., t.Any]) -> Group:
- cmd: Group = group(*args, **kwargs)(f)
- self.add_command(cmd)
- return cmd
- if func is not None:
- return decorator(func)
- return decorator
- def result_callback(self, replace: bool = False) -> t.Callable[[F], F]:
- """Adds a result callback to the command. By default if a
- result callback is already registered this will chain them but
- this can be disabled with the `replace` parameter. The result
- callback is invoked with the return value of the subcommand
- (or the list of return values from all subcommands if chaining
- is enabled) as well as the parameters as they would be passed
- to the main callback.
- Example::
- @click.group()
- @click.option('-i', '--input', default=23)
- def cli(input):
- return 42
- @cli.result_callback()
- def process_result(result, input):
- return result + input
- :param replace: if set to `True` an already existing result
- callback will be removed.
- .. versionchanged:: 8.0
- Renamed from ``resultcallback``.
- .. versionadded:: 3.0
- """
- def decorator(f: F) -> F:
- old_callback = self._result_callback
- if old_callback is None or replace:
- self._result_callback = f
- return f
- def function(value: t.Any, /, *args: t.Any, **kwargs: t.Any) -> t.Any:
- inner = old_callback(value, *args, **kwargs)
- return f(inner, *args, **kwargs)
- self._result_callback = rv = update_wrapper(t.cast(F, function), f)
- return rv # type: ignore[return-value]
- return decorator
- def get_command(self, ctx: Context, cmd_name: str) -> Command | None:
- """Given a context and a command name, this returns a :class:`Command`
- object if it exists or returns ``None``.
- """
- return self.commands.get(cmd_name)
- def list_commands(self, ctx: Context) -> list[str]:
- """Returns a list of subcommand names in the order they should appear."""
- return sorted(self.commands)
- def collect_usage_pieces(self, ctx: Context) -> list[str]:
- rv = super().collect_usage_pieces(ctx)
- rv.append(self.subcommand_metavar)
- return rv
- def format_options(self, ctx: Context, formatter: HelpFormatter) -> None:
- super().format_options(ctx, formatter)
- self.format_commands(ctx, formatter)
- def format_commands(self, ctx: Context, formatter: HelpFormatter) -> None:
- """Extra format methods for multi methods that adds all the commands
- after the options.
- """
- commands = []
- for subcommand in self.list_commands(ctx):
- cmd = self.get_command(ctx, subcommand)
- # What is this, the tool lied about a command. Ignore it
- if cmd is None:
- continue
- if cmd.hidden:
- continue
- commands.append((subcommand, cmd))
- # allow for 3 times the default spacing
- if len(commands):
- limit = formatter.width - 6 - max(len(cmd[0]) for cmd in commands)
- rows = []
- for subcommand, cmd in commands:
- help = cmd.get_short_help_str(limit)
- rows.append((subcommand, help))
- if rows:
- with formatter.section(_("Commands")):
- formatter.write_dl(rows)
- def parse_args(self, ctx: Context, args: list[str]) -> list[str]:
- if not args and self.no_args_is_help and not ctx.resilient_parsing:
- raise NoArgsIsHelpError(ctx)
- rest = super().parse_args(ctx, args)
- if self.chain:
- ctx._protected_args = rest
- ctx.args = []
- elif rest:
- ctx._protected_args, ctx.args = rest[:1], rest[1:]
- return ctx.args
- def invoke(self, ctx: Context) -> t.Any:
- def _process_result(value: t.Any) -> t.Any:
- if self._result_callback is not None:
- value = ctx.invoke(self._result_callback, value, **ctx.params)
- return value
- if not ctx._protected_args:
- if self.invoke_without_command:
- # No subcommand was invoked, so the result callback is
- # invoked with the group return value for regular
- # groups, or an empty list for chained groups.
- with ctx:
- rv = super().invoke(ctx)
- return _process_result([] if self.chain else rv)
- ctx.fail(_("Missing command."))
- # Fetch args back out
- args = [*ctx._protected_args, *ctx.args]
- ctx.args = []
- ctx._protected_args = []
- # If we're not in chain mode, we only allow the invocation of a
- # single command but we also inform the current context about the
- # name of the command to invoke.
- if not self.chain:
- # Make sure the context is entered so we do not clean up
- # resources until the result processor has worked.
- with ctx:
- cmd_name, cmd, args = self.resolve_command(ctx, args)
- assert cmd is not None
- ctx.invoked_subcommand = cmd_name
- super().invoke(ctx)
- sub_ctx = cmd.make_context(cmd_name, args, parent=ctx)
- with sub_ctx:
- return _process_result(sub_ctx.command.invoke(sub_ctx))
- # In chain mode we create the contexts step by step, but after the
- # base command has been invoked. Because at that point we do not
- # know the subcommands yet, the invoked subcommand attribute is
- # set to ``*`` to inform the command that subcommands are executed
- # but nothing else.
- with ctx:
- ctx.invoked_subcommand = "*" if args else None
- super().invoke(ctx)
- # Otherwise we make every single context and invoke them in a
- # chain. In that case the return value to the result processor
- # is the list of all invoked subcommand's results.
- contexts = []
- while args:
- cmd_name, cmd, args = self.resolve_command(ctx, args)
- assert cmd is not None
- sub_ctx = cmd.make_context(
- cmd_name,
- args,
- parent=ctx,
- allow_extra_args=True,
- allow_interspersed_args=False,
- )
- contexts.append(sub_ctx)
- args, sub_ctx.args = sub_ctx.args, []
- rv = []
- for sub_ctx in contexts:
- with sub_ctx:
- rv.append(sub_ctx.command.invoke(sub_ctx))
- return _process_result(rv)
- def resolve_command(
- self, ctx: Context, args: list[str]
- ) -> tuple[str | None, Command | None, list[str]]:
- cmd_name = make_str(args[0])
- original_cmd_name = cmd_name
- # Get the command
- cmd = self.get_command(ctx, cmd_name)
- # If we can't find the command but there is a normalization
- # function available, we try with that one.
- if cmd is None and ctx.token_normalize_func is not None:
- cmd_name = ctx.token_normalize_func(cmd_name)
- cmd = self.get_command(ctx, cmd_name)
- # If we don't find the command we want to show an error message
- # to the user that it was not provided. However, there is
- # something else we should do: if the first argument looks like
- # an option we want to kick off parsing again for arguments to
- # resolve things like --help which now should go to the main
- # place.
- if cmd is None and not ctx.resilient_parsing:
- if _split_opt(cmd_name)[0]:
- self.parse_args(ctx, args)
- ctx.fail(_("No such command {name!r}.").format(name=original_cmd_name))
- return cmd_name if cmd else None, cmd, args[1:]
- def shell_complete(self, ctx: Context, incomplete: str) -> list[CompletionItem]:
- """Return a list of completions for the incomplete value. Looks
- at the names of options, subcommands, and chained
- multi-commands.
- :param ctx: Invocation context for this command.
- :param incomplete: Value being completed. May be empty.
- .. versionadded:: 8.0
- """
- from click.shell_completion import CompletionItem
- results = [
- CompletionItem(name, help=command.get_short_help_str())
- for name, command in _complete_visible_commands(ctx, incomplete)
- ]
- results.extend(super().shell_complete(ctx, incomplete))
- return results
- class _MultiCommand(Group, metaclass=_FakeSubclassCheck):
- """
- .. deprecated:: 8.2
- Will be removed in Click 9.0. Use ``Group`` instead.
- """
- class CommandCollection(Group):
- """A :class:`Group` that looks up subcommands on other groups. If a command
- is not found on this group, each registered source is checked in order.
- Parameters on a source are not added to this group, and a source's callback
- is not invoked when invoking its commands. In other words, this "flattens"
- commands in many groups into this one group.
- :param name: The name of the group command.
- :param sources: A list of :class:`Group` objects to look up commands from.
- :param kwargs: Other arguments passed to :class:`Group`.
- .. versionchanged:: 8.2
- This is a subclass of ``Group``. Commands are looked up first on this
- group, then each of its sources.
- """
- def __init__(
- self,
- name: str | None = None,
- sources: list[Group] | None = None,
- **kwargs: t.Any,
- ) -> None:
- super().__init__(name, **kwargs)
- #: The list of registered groups.
- self.sources: list[Group] = sources or []
- def add_source(self, group: Group) -> None:
- """Add a group as a source of commands."""
- self.sources.append(group)
- def get_command(self, ctx: Context, cmd_name: str) -> Command | None:
- rv = super().get_command(ctx, cmd_name)
- if rv is not None:
- return rv
- for source in self.sources:
- rv = source.get_command(ctx, cmd_name)
- if rv is not None:
- if self.chain:
- _check_nested_chain(self, cmd_name, rv)
- return rv
- return None
- def list_commands(self, ctx: Context) -> list[str]:
- rv: set[str] = set(super().list_commands(ctx))
- for source in self.sources:
- rv.update(source.list_commands(ctx))
- return sorted(rv)
- def _check_iter(value: t.Any) -> cabc.Iterator[t.Any]:
- """Check if the value is iterable but not a string. Raises a type
- error, or return an iterator over the value.
- """
- if isinstance(value, str):
- raise TypeError
- return iter(value)
- class Parameter:
- r"""A parameter to a command comes in two versions: they are either
- :class:`Option`\s or :class:`Argument`\s. Other subclasses are currently
- not supported by design as some of the internals for parsing are
- intentionally not finalized.
- Some settings are supported by both options and arguments.
- :param param_decls: the parameter declarations for this option or
- argument. This is a list of flags or argument
- names.
- :param type: the type that should be used. Either a :class:`ParamType`
- or a Python type. The latter is converted into the former
- automatically if supported.
- :param required: controls if this is optional or not.
- :param default: the default value if omitted. This can also be a callable,
- in which case it's invoked when the default is needed
- without any arguments.
- :param callback: A function to further process or validate the value
- after type conversion. It is called as ``f(ctx, param, value)``
- and must return the value. It is called for all sources,
- including prompts.
- :param nargs: the number of arguments to match. If not ``1`` the return
- value is a tuple instead of single value. The default for
- nargs is ``1`` (except if the type is a tuple, then it's
- the arity of the tuple). If ``nargs=-1``, all remaining
- parameters are collected.
- :param metavar: how the value is represented in the help page.
- :param expose_value: if this is `True` then the value is passed onwards
- to the command callback and stored on the context,
- otherwise it's skipped.
- :param is_eager: eager values are processed before non eager ones. This
- should not be set for arguments or it will inverse the
- order of processing.
- :param envvar: environment variable(s) that are used to provide a default value for
- this parameter. This can be a string or a sequence of strings. If a sequence is
- given, only the first non-empty environment variable is used for the parameter.
- :param shell_complete: A function that returns custom shell
- completions. Used instead of the param's type completion if
- given. Takes ``ctx, param, incomplete`` and must return a list
- of :class:`~click.shell_completion.CompletionItem` or a list of
- strings.
- :param deprecated: If ``True`` or non-empty string, issues a message
- indicating that the argument is deprecated and highlights
- its deprecation in --help. The message can be customized
- by using a string as the value. A deprecated parameter
- cannot be required, a ValueError will be raised otherwise.
- .. versionchanged:: 8.2.0
- Introduction of ``deprecated``.
- .. versionchanged:: 8.2
- Adding duplicate parameter names to a :class:`~click.core.Command` will
- result in a ``UserWarning`` being shown.
- .. versionchanged:: 8.2
- Adding duplicate parameter names to a :class:`~click.core.Command` will
- result in a ``UserWarning`` being shown.
- .. versionchanged:: 8.0
- ``process_value`` validates required parameters and bounded
- ``nargs``, and invokes the parameter callback before returning
- the value. This allows the callback to validate prompts.
- ``full_process_value`` is removed.
- .. versionchanged:: 8.0
- ``autocompletion`` is renamed to ``shell_complete`` and has new
- semantics described above. The old name is deprecated and will
- be removed in 8.1, until then it will be wrapped to match the
- new requirements.
- .. versionchanged:: 8.0
- For ``multiple=True, nargs>1``, the default must be a list of
- tuples.
- .. versionchanged:: 8.0
- Setting a default is no longer required for ``nargs>1``, it will
- default to ``None``. ``multiple=True`` or ``nargs=-1`` will
- default to ``()``.
- .. versionchanged:: 7.1
- Empty environment variables are ignored rather than taking the
- empty string value. This makes it possible for scripts to clear
- variables if they can't unset them.
- .. versionchanged:: 2.0
- Changed signature for parameter callback to also be passed the
- parameter. The old callback format will still work, but it will
- raise a warning to give you a chance to migrate the code easier.
- """
- param_type_name = "parameter"
- def __init__(
- self,
- param_decls: cabc.Sequence[str] | None = None,
- type: types.ParamType | t.Any | None = None,
- required: bool = False,
- # XXX The default historically embed two concepts:
- # - the declaration of a Parameter object carrying the default (handy to
- # arbitrage the default value of coupled Parameters sharing the same
- # self.name, like flag options),
- # - and the actual value of the default.
- # It is confusing and is the source of many issues discussed in:
- # https://github.com/pallets/click/pull/3030
- # In the future, we might think of splitting it in two, not unlike
- # Option.is_flag and Option.flag_value: we could have something like
- # Parameter.is_default and Parameter.default_value.
- default: t.Any | t.Callable[[], t.Any] | None = UNSET,
- callback: t.Callable[[Context, Parameter, t.Any], t.Any] | None = None,
- nargs: int | None = None,
- multiple: bool = False,
- metavar: str | None = None,
- expose_value: bool = True,
- is_eager: bool = False,
- envvar: str | cabc.Sequence[str] | None = None,
- shell_complete: t.Callable[
- [Context, Parameter, str], list[CompletionItem] | list[str]
- ]
- | None = None,
- deprecated: bool | str = False,
- ) -> 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 = default
- self.is_eager = is_eager
- self.metavar = metavar
- self.envvar = envvar
- self._custom_shell_complete = shell_complete
- self.deprecated = deprecated
- if __debug__:
- if self.type.is_composite and nargs != self.type.arity:
- raise ValueError(
- f"'nargs' must be {self.type.arity} (or None) for"
- f" type {self.type!r}, but it was {nargs}."
- )
- if required and deprecated:
- raise ValueError(
- f"The {self.param_type_name} '{self.human_readable_name}' "
- "is deprecated and still required. A deprecated "
- f"{self.param_type_name} cannot be required."
- )
- def to_info_dict(self) -> dict[str, t.Any]:
- """Gather information that could be useful for a tool generating
- user-facing documentation.
- Use :meth:`click.Context.to_info_dict` to traverse the entire
- CLI structure.
- .. versionchanged:: 8.3.0
- Returns ``None`` for the :attr:`default` if it was not set.
- .. versionadded:: 8.0
- """
- return {
- "name": self.name,
- "param_type_name": self.param_type_name,
- "opts": self.opts,
- "secondary_opts": self.secondary_opts,
- "type": self.type.to_info_dict(),
- "required": self.required,
- "nargs": self.nargs,
- "multiple": self.multiple,
- # We explicitly hide the :attr:`UNSET` value to the user, as we choose to
- # make it an implementation detail. And because ``to_info_dict`` has been
- # designed for documentation purposes, we return ``None`` instead.
- "default": self.default if self.default is not UNSET else None,
- "envvar": self.envvar,
- }
- def __repr__(self) -> str:
- return f"<{self.__class__.__name__} {self.name}>"
- def _parse_decls(
- self, decls: cabc.Sequence[str], expose_value: bool
- ) -> tuple[str | None, list[str], list[str]]:
- raise NotImplementedError()
- @property
- def human_readable_name(self) -> str:
- """Returns the human readable name of this parameter. This is the
- same as the name for options, but the metavar for arguments.
- """
- return self.name # type: ignore
- def make_metavar(self, 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
- @t.overload
- def get_default(
- self, ctx: Context, call: t.Literal[True] = True
- ) -> t.Any | None: ...
- @t.overload
- def get_default(
- self, ctx: Context, call: bool = ...
- ) -> t.Any | t.Callable[[], t.Any] | None: ...
- def get_default(
- self, ctx: Context, call: bool = True
- ) -> t.Any | t.Callable[[], t.Any] | None:
- """Get the default for the parameter. Tries
- :meth:`Context.lookup_default` first, then the local default.
- :param ctx: Current context.
- :param call: If the default is a callable, call it. Disable to
- return the callable instead.
- .. versionchanged:: 8.0.2
- Type casting is no longer performed when getting a default.
- .. versionchanged:: 8.0.1
- Type casting can fail in resilient parsing mode. Invalid
- defaults will not prevent showing help text.
- .. versionchanged:: 8.0
- Looks at ``ctx.default_map`` first.
- .. versionchanged:: 8.0
- Added the ``call`` parameter.
- """
- value = ctx.lookup_default(self.name, call=False) # type: ignore
- if value is UNSET:
- value = self.default
- if call and callable(value):
- value = value()
- return value
- def add_to_parser(self, parser: _OptionParser, ctx: Context) -> None:
- raise NotImplementedError()
- def consume_value(
- self, ctx: Context, opts: cabc.Mapping[str, t.Any]
- ) -> tuple[t.Any, ParameterSource]:
- """Returns the parameter value produced by the parser.
- If the parser did not produce a value from user input, the value is either
- sourced from the environment variable, the default map, or the parameter's
- default value. In that order of precedence.
- If no value is found, an internal sentinel value is returned.
- :meta private:
- """
- # Collect from the parse the value passed by the user to the CLI.
- value = opts.get(self.name, UNSET) # type: ignore
- # If the value is set, it means it was sourced from the command line by the
- # parser, otherwise it left unset by default.
- source = (
- ParameterSource.COMMANDLINE
- if value is not UNSET
- else ParameterSource.DEFAULT
- )
- if value is UNSET:
- envvar_value = self.value_from_envvar(ctx)
- if envvar_value is not None:
- value = envvar_value
- source = ParameterSource.ENVIRONMENT
- if value is UNSET:
- default_map_value = ctx.lookup_default(self.name) # type: ignore
- if default_map_value is not UNSET:
- value = default_map_value
- source = ParameterSource.DEFAULT_MAP
- if value is UNSET:
- default_value = self.get_default(ctx)
- if default_value is not UNSET:
- value = default_value
- source = ParameterSource.DEFAULT
- return value, source
- def type_cast_value(self, ctx: Context, value: t.Any) -> t.Any:
- """Convert and validate a value against the parameter's
- :attr:`type`, :attr:`multiple`, and :attr:`nargs`.
- """
- if value in (None, UNSET):
- if self.multiple or self.nargs == -1:
- return ()
- else:
- return value
- def check_iter(value: t.Any) -> cabc.Iterator[t.Any]:
- try:
- return _check_iter(value)
- except TypeError:
- # This should only happen when passing in args manually,
- # the parser should construct an iterable when parsing
- # the command line.
- raise BadParameter(
- _("Value must be an iterable."), ctx=ctx, param=self
- ) from None
- # Define the conversion function based on nargs and type.
- if self.nargs == 1 or self.type.is_composite:
- def convert(value: t.Any) -> t.Any:
- return self.type(value, param=self, ctx=ctx)
- elif self.nargs == -1:
- def convert(value: t.Any) -> t.Any: # tuple[t.Any, ...]
- return tuple(self.type(x, self, ctx) for x in check_iter(value))
- else: # nargs > 1
- def convert(value: t.Any) -> t.Any: # tuple[t.Any, ...]
- value = tuple(check_iter(value))
- if len(value) != self.nargs:
- raise BadParameter(
- ngettext(
- "Takes {nargs} values but 1 was given.",
- "Takes {nargs} values but {len} were given.",
- len(value),
- ).format(nargs=self.nargs, len=len(value)),
- ctx=ctx,
- param=self,
- )
- return tuple(self.type(x, self, ctx) for x in value)
- if self.multiple:
- return tuple(convert(x) for x in check_iter(value))
- return convert(value)
- def value_is_missing(self, value: t.Any) -> bool:
- """A value is considered missing if:
- - it is :attr:`UNSET`,
- - or if it is an empty sequence while the parameter is suppose to have
- non-single value (i.e. :attr:`nargs` is not ``1`` or :attr:`multiple` is
- set).
- :meta private:
- """
- if value is UNSET:
- return True
- if (self.nargs != 1 or self.multiple) and value == ():
- return True
- return False
- def process_value(self, ctx: Context, value: t.Any) -> t.Any:
- """Process the value of this parameter:
- 1. Type cast the value using :meth:`type_cast_value`.
- 2. Check if the value is missing (see: :meth:`value_is_missing`), and raise
- :exc:`MissingParameter` if it is required.
- 3. If a :attr:`callback` is set, call it to have the value replaced by the
- result of the callback. If the value was not set, the callback receive
- ``None``. This keep the legacy behavior as it was before the introduction of
- the :attr:`UNSET` sentinel.
- :meta private:
- """
- 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:
- # Legacy case: UNSET is not exposed directly to the callback, but converted
- # to None.
- if value is UNSET:
- value = None
- value = self.callback(ctx, self, value)
- return value
- 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 :attr:`envvar` property is not set on the :class:`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 :attr:`envvar` is setup with multiple environment variables,
- then only the first non-empty value is returned.
- .. caution::
- The raw value extracted from the environment is not normalized and is
- returned as-is. Any normalization or reconciliation is performed later by
- the :class:`Parameter`'s :attr:`type`.
- :meta private:
- """
- if not self.envvar:
- 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
- def value_from_envvar(self, ctx: Context) -> str | cabc.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 :attr:`nargs` property is set
- to a value other than ``1``).
- :meta private:
- """
- rv = self.resolve_envvar_value(ctx)
- if rv is not None and self.nargs != 1:
- return self.type.split_envvar_value(rv)
- return rv
- def handle_parse_result(
- self, ctx: Context, opts: cabc.Mapping[str, t.Any], args: list[str]
- ) -> tuple[t.Any, list[str]]:
- """Process the value produced by the parser from user input.
- Always process the value through the Parameter's :attr:`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).
- :meta private:
- """
- with augment_usage_errors(ctx, param=self):
- value, source = self.consume_value(ctx, opts)
- ctx.set_parameter_source(self.name, source) # type: ignore
- # Display a deprecation warning if necessary.
- if (
- self.deprecated
- and value is not UNSET
- and source not in (ParameterSource.DEFAULT, ParameterSource.DEFAULT_MAP)
- ):
- extra_message = (
- f" {self.deprecated}" if isinstance(self.deprecated, str) else ""
- )
- message = _(
- "DeprecationWarning: The {param_type} {name!r} is deprecated."
- "{extra_message}"
- ).format(
- param_type=self.param_type_name,
- name=self.human_readable_name,
- extra_message=extra_message,
- )
- echo(style(message, fg="red"), err=True)
- # Process the value through the parameter's type.
- try:
- value = self.process_value(ctx, value)
- except Exception:
- if not ctx.resilient_parsing:
- raise
- # In resilient parsing mode, we do not want to fail the command if the
- # value is incompatible with the parameter type, so we reset the value
- # to UNSET, which will be interpreted as a missing value.
- value = UNSET
- # Add parameter's value to the context.
- if (
- self.expose_value
- # We skip adding the value if it was previously set by another parameter
- # targeting the same variable name. This prevents parameters competing for
- # the same name to override each other.
- and self.name not in ctx.params
- ):
- # Click is logically enforcing that the name is None if the parameter is
- # not to be exposed. We still assert it here to please the type checker.
- assert self.name is not None, (
- f"{self!r} parameter's name should not be None when exposing value."
- )
- # Normalize UNSET values to None, as we're about to pass them to the
- # command function and move them to the pure-Python realm of user-written
- # code.
- ctx.params[self.name] = value if value is not UNSET else None
- return value, args
- def get_help_record(self, ctx: Context) -> tuple[str, str] | None:
- pass
- def get_usage_pieces(self, ctx: Context) -> list[str]:
- return []
- def get_error_hint(self, ctx: Context) -> str:
- """Get a stringified version of the param for use in error messages to
- indicate which param caused the error.
- """
- hint_list = self.opts or [self.human_readable_name]
- return " / ".join(f"'{x}'" for x in hint_list)
- def shell_complete(self, ctx: Context, incomplete: str) -> list[CompletionItem]:
- """Return a list of completions for the incomplete value. If a
- ``shell_complete`` function was given during init, it is used.
- Otherwise, the :attr:`type`
- :meth:`~click.types.ParamType.shell_complete` function is used.
- :param ctx: Invocation context for this command.
- :param incomplete: Value being completed. May be empty.
- .. versionadded:: 8.0
- """
- if self._custom_shell_complete is not None:
- results = self._custom_shell_complete(ctx, self, incomplete)
- if results and isinstance(results[0], str):
- from click.shell_completion import CompletionItem
- results = [CompletionItem(c) for c in results]
- return t.cast("list[CompletionItem]", results)
- return self.type.shell_complete(ctx, self, incomplete)
- class Option(Parameter):
- """Options are usually optional values on the command line and
- have some extra features that arguments don't have.
- All other parameters are passed onwards to the parameter constructor.
- :param show_default: Show the default value for this option in its
- help text. Values are not shown by default, unless
- :attr:`Context.show_default` is ``True``. If this value is a
- string, it shows that string in parentheses instead of the
- actual value. This is particularly useful for dynamic options.
- For single option boolean flags, the default remains hidden if
- its value is ``False``.
- :param show_envvar: Controls if an environment variable should be
- shown on the help page and error messages.
- Normally, environment variables are not shown.
- :param prompt: If set to ``True`` or a non empty string then the
- user will be prompted for input. If set to ``True`` the prompt
- will be the option name capitalized. A deprecated option cannot be
- prompted.
- :param confirmation_prompt: Prompt a second time to confirm the
- value if it was prompted for. Can be set to a string instead of
- ``True`` to customize the message.
- :param prompt_required: If set to ``False``, the user will be
- prompted for input only when the option was specified as a flag
- without a value.
- :param hide_input: If this is ``True`` then the input on the prompt
- will be hidden from the user. This is useful for password input.
- :param is_flag: forces this option to act as a flag. The default is
- auto detection.
- :param flag_value: which value should be used for this flag if it's
- enabled. This is set to a boolean automatically if
- the option string contains a slash to mark two options.
- :param multiple: if this is set to `True` then the argument is accepted
- multiple times and recorded. This is similar to ``nargs``
- in how it works but supports arbitrary number of
- arguments.
- :param count: this flag makes an option increment an integer.
- :param allow_from_autoenv: if this is enabled then the value of this
- parameter will be pulled from an environment
- variable in case a prefix is defined on the
- context.
- :param help: the help string.
- :param hidden: hide this option from help outputs.
- :param attrs: Other command arguments described in :class:`Parameter`.
- .. versionchanged:: 8.2
- ``envvar`` used with ``flag_value`` will always use the ``flag_value``,
- previously it would use the value of the environment variable.
- .. versionchanged:: 8.1
- Help text indentation is cleaned here instead of only in the
- ``@option`` decorator.
- .. versionchanged:: 8.1
- The ``show_default`` parameter overrides
- ``Context.show_default``.
- .. versionchanged:: 8.1
- The default of a single option boolean flag is not shown if the
- default value is ``False``.
- .. versionchanged:: 8.0.1
- ``type`` is detected from ``flag_value`` if given.
- """
- param_type_name = "option"
- def __init__(
- self,
- param_decls: cabc.Sequence[str] | None = None,
- show_default: bool | str | None = None,
- prompt: bool | str = False,
- confirmation_prompt: bool | str = False,
- prompt_required: bool = True,
- hide_input: bool = False,
- is_flag: bool | None = None,
- flag_value: t.Any = UNSET,
- multiple: bool = False,
- count: bool = False,
- allow_from_autoenv: bool = True,
- type: types.ParamType | t.Any | None = None,
- help: str | None = None,
- hidden: bool = False,
- show_choices: bool = True,
- show_envvar: bool = False,
- deprecated: bool | str = False,
- **attrs: t.Any,
- ) -> None:
- if help:
- help = inspect.cleandoc(help)
- super().__init__(
- param_decls, type=type, multiple=multiple, deprecated=deprecated, **attrs
- )
- if prompt is True:
- if self.name is None:
- raise TypeError("'name' is required with 'prompt=True'.")
- prompt_text: str | None = self.name.replace("_", " ").capitalize()
- elif prompt is False:
- prompt_text = None
- else:
- prompt_text = prompt
- if deprecated:
- deprecated_message = (
- f"(DEPRECATED: {deprecated})"
- if isinstance(deprecated, str)
- else "(DEPRECATED)"
- )
- help = help + deprecated_message if help is not None else deprecated_message
- self.prompt = prompt_text
- self.confirmation_prompt = confirmation_prompt
- self.prompt_required = prompt_required
- self.hide_input = hide_input
- self.hidden = hidden
- # The _flag_needs_value property tells the parser that this option is a flag
- # that cannot be used standalone and needs a value. With this information, the
- # parser can determine whether to consider the next user-provided argument in
- # the CLI as a value for this flag or as a new option.
- # If prompt is enabled but not required, then it opens the possibility for the
- # option to gets its value from the user.
- self._flag_needs_value = self.prompt is not None and not self.prompt_required
- # Auto-detect if this is a flag or not.
- if is_flag is None:
- # Implicitly a flag because flag_value was set.
- if flag_value is not UNSET:
- is_flag = True
- # Not a flag, but when used as a flag it shows a prompt.
- elif self._flag_needs_value:
- is_flag = False
- # Implicitly a flag because secondary options names were given.
- elif self.secondary_opts:
- is_flag = True
- # The option is explicitly not a flag. But we do not know yet if it needs a
- # value or not. So we look at the default value to determine it.
- elif is_flag is False and not self._flag_needs_value:
- self._flag_needs_value = self.default is UNSET
- if is_flag:
- # Set missing default for flags if not explicitly required or prompted.
- if self.default is UNSET and not self.required and not self.prompt:
- if multiple:
- self.default = ()
- # Auto-detect the type of the flag based on the flag_value.
- if type is None:
- # A flag without a flag_value is a boolean flag.
- if flag_value is UNSET:
- self.type = types.BoolParamType()
- # If the flag value is a boolean, use BoolParamType.
- elif isinstance(flag_value, bool):
- self.type = types.BoolParamType()
- # Otherwise, guess the type from the flag value.
- else:
- self.type = types.convert_type(None, flag_value)
- self.is_flag: bool = bool(is_flag)
- self.is_bool_flag: bool = bool(
- is_flag and isinstance(self.type, types.BoolParamType)
- )
- self.flag_value: t.Any = flag_value
- # Set boolean flag default to False if unset and not required.
- if self.is_bool_flag:
- if self.default is UNSET and not self.required:
- self.default = False
- # Support the special case of aligning the default value with the flag_value
- # for flags whose default is explicitly set to True. Note that as long as we
- # have this condition, there is no way a flag can have a default set to True,
- # and a flag_value set to something else. Refs:
- # https://github.com/pallets/click/issues/3024#issuecomment-3146199461
- # https://github.com/pallets/click/pull/3030/commits/06847da
- if self.default is True and self.flag_value is not UNSET:
- self.default = self.flag_value
- # Set the default flag_value if it is not set.
- if self.flag_value is UNSET:
- if self.is_flag:
- self.flag_value = True
- else:
- self.flag_value = None
- # Counting.
- self.count = count
- if count:
- if type is None:
- self.type = types.IntRange(min=0)
- if self.default is UNSET:
- self.default = 0
- self.allow_from_autoenv = allow_from_autoenv
- self.help = help
- self.show_default = show_default
- self.show_choices = show_choices
- self.show_envvar = show_envvar
- if __debug__:
- if deprecated and prompt:
- raise ValueError("`deprecated` options cannot use `prompt`.")
- if self.nargs == -1:
- raise TypeError("nargs=-1 is not supported for options.")
- if not self.is_bool_flag and self.secondary_opts:
- raise TypeError("Secondary flag is not valid for non-boolean flag.")
- if self.is_bool_flag and self.hide_input and self.prompt is not None:
- raise TypeError(
- "'prompt' with 'hide_input' is not valid for boolean flag."
- )
- if self.count:
- if self.multiple:
- raise TypeError("'count' is not valid with 'multiple'.")
- if self.is_flag:
- raise TypeError("'count' is not valid with 'is_flag'.")
- def to_info_dict(self) -> dict[str, t.Any]:
- """
- .. versionchanged:: 8.3.0
- Returns ``None`` for the :attr:`flag_value` if it was not set.
- """
- info_dict = super().to_info_dict()
- info_dict.update(
- help=self.help,
- prompt=self.prompt,
- is_flag=self.is_flag,
- # We explicitly hide the :attr:`UNSET` value to the user, as we choose to
- # make it an implementation detail. And because ``to_info_dict`` has been
- # designed for documentation purposes, we return ``None`` instead.
- flag_value=self.flag_value if self.flag_value is not UNSET else None,
- count=self.count,
- hidden=self.hidden,
- )
- return info_dict
- def get_error_hint(self, ctx: Context) -> str:
- result = super().get_error_hint(ctx)
- if self.show_envvar and self.envvar is not None:
- result += f" (env var: '{self.envvar}')"
- return result
- def _parse_decls(
- self, decls: cabc.Sequence[str], expose_value: bool
- ) -> tuple[str | None, list[str], list[str]]:
- opts = []
- secondary_opts = []
- name = None
- possible_names = []
- for decl in decls:
- if decl.isidentifier():
- if name is not None:
- raise TypeError(f"Name '{name}' defined twice")
- name = decl
- else:
- split_char = ";" if decl[:1] == "/" else "/"
- if split_char in decl:
- first, second = decl.split(split_char, 1)
- first = first.rstrip()
- if first:
- possible_names.append(_split_opt(first))
- opts.append(first)
- second = second.lstrip()
- if second:
- secondary_opts.append(second.lstrip())
- if first == second:
- raise ValueError(
- f"Boolean option {decl!r} cannot use the"
- " same flag for true/false."
- )
- else:
- possible_names.append(_split_opt(decl))
- opts.append(decl)
- if name is None and possible_names:
- possible_names.sort(key=lambda x: -len(x[0])) # group long options first
- name = possible_names[0][1].replace("-", "_").lower()
- if not name.isidentifier():
- name = None
- if name is None:
- if not expose_value:
- return None, opts, secondary_opts
- raise TypeError(
- f"Could not determine name for option with declarations {decls!r}"
- )
- if not opts and not secondary_opts:
- raise TypeError(
- f"No options defined but a name was passed ({name})."
- " Did you mean to declare an argument instead? Did"
- f" you mean to pass '--{name}'?"
- )
- return name, opts, secondary_opts
- def add_to_parser(self, parser: _OptionParser, ctx: Context) -> None:
- if self.multiple:
- action = "append"
- elif self.count:
- action = "count"
- else:
- action = "store"
- if self.is_flag:
- action = f"{action}_const"
- if self.is_bool_flag and self.secondary_opts:
- parser.add_option(
- obj=self, opts=self.opts, dest=self.name, action=action, const=True
- )
- parser.add_option(
- obj=self,
- opts=self.secondary_opts,
- dest=self.name,
- action=action,
- const=False,
- )
- else:
- parser.add_option(
- obj=self,
- opts=self.opts,
- dest=self.name,
- action=action,
- const=self.flag_value,
- )
- else:
- parser.add_option(
- obj=self,
- opts=self.opts,
- dest=self.name,
- action=action,
- nargs=self.nargs,
- )
- def get_help_record(self, ctx: Context) -> tuple[str, str] | None:
- if self.hidden:
- return None
- any_prefix_is_slash = False
- def _write_opts(opts: cabc.Sequence[str]) -> str:
- nonlocal any_prefix_is_slash
- rv, any_slashes = join_options(opts)
- if any_slashes:
- any_prefix_is_slash = True
- if not self.is_flag and not self.count:
- rv += f" {self.make_metavar(ctx=ctx)}"
- return rv
- rv = [_write_opts(self.opts)]
- if self.secondary_opts:
- rv.append(_write_opts(self.secondary_opts))
- help = self.help or ""
- extra = self.get_help_extra(ctx)
- extra_items = []
- if "envvars" in extra:
- extra_items.append(
- _("env var: {var}").format(var=", ".join(extra["envvars"]))
- )
- if "default" in extra:
- extra_items.append(_("default: {default}").format(default=extra["default"]))
- if "range" in extra:
- extra_items.append(extra["range"])
- if "required" in extra:
- extra_items.append(_(extra["required"]))
- if extra_items:
- extra_str = "; ".join(extra_items)
- help = f"{help} [{extra_str}]" if help else f"[{extra_str}]"
- return ("; " if any_prefix_is_slash else " / ").join(rv), help
- def get_help_extra(self, ctx: Context) -> types.OptionHelpExtra:
- extra: types.OptionHelpExtra = {}
- if self.show_envvar:
- envvar = self.envvar
- if envvar is None:
- if (
- self.allow_from_autoenv
- and ctx.auto_envvar_prefix is not None
- and self.name is not None
- ):
- envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}"
- if envvar is not None:
- if isinstance(envvar, str):
- extra["envvars"] = (envvar,)
- else:
- extra["envvars"] = tuple(str(d) for d in envvar)
- # Temporarily enable resilient parsing to avoid type casting
- # failing for the default. Might be possible to extend this to
- # help formatting in general.
- resilient = ctx.resilient_parsing
- ctx.resilient_parsing = True
- try:
- default_value = self.get_default(ctx, call=False)
- finally:
- ctx.resilient_parsing = resilient
- show_default = False
- show_default_is_str = False
- if self.show_default is not None:
- if isinstance(self.show_default, str):
- show_default_is_str = show_default = True
- else:
- show_default = self.show_default
- elif ctx.show_default is not None:
- show_default = ctx.show_default
- if show_default_is_str or (
- show_default and (default_value not in (None, UNSET))
- ):
- if show_default_is_str:
- default_string = f"({self.show_default})"
- elif isinstance(default_value, (list, tuple)):
- default_string = ", ".join(str(d) for d in default_value)
- elif isinstance(default_value, enum.Enum):
- default_string = default_value.name
- elif inspect.isfunction(default_value):
- default_string = _("(dynamic)")
- elif self.is_bool_flag and self.secondary_opts:
- # For boolean flags that have distinct True/False opts,
- # use the opt without prefix instead of the value.
- default_string = _split_opt(
- (self.opts if default_value else self.secondary_opts)[0]
- )[1]
- elif self.is_bool_flag and not self.secondary_opts and not default_value:
- default_string = ""
- elif default_value == "":
- default_string = '""'
- else:
- default_string = str(default_value)
- if default_string:
- extra["default"] = default_string
- if (
- isinstance(self.type, types._NumberRangeBase)
- # skip count with default range type
- and not (self.count and self.type.min == 0 and self.type.max is None)
- ):
- range_str = self.type._describe_range()
- if range_str:
- extra["range"] = range_str
- if self.required:
- extra["required"] = "required"
- return extra
- def prompt_for_value(self, ctx: Context) -> t.Any:
- """This is an alternative flow that can be activated in the full
- value processing if a value does not exist. It will prompt the
- user until a valid value exists and then returns the processed
- value as result.
- """
- assert self.prompt is not None
- # Calculate the default before prompting anything to lock in the value before
- # attempting any user interaction.
- default = self.get_default(ctx)
- # A boolean flag can use a simplified [y/n] confirmation prompt.
- if self.is_bool_flag:
- # If we have no boolean default, we force the user to explicitly provide
- # one.
- if default in (UNSET, None):
- default = None
- # Nothing prevent you to declare an option that is simultaneously:
- # 1) auto-detected as a boolean flag,
- # 2) allowed to prompt, and
- # 3) still declare a non-boolean default.
- # This forced casting into a boolean is necessary to align any non-boolean
- # default to the prompt, which is going to be a [y/n]-style confirmation
- # because the option is still a boolean flag. That way, instead of [y/n],
- # we get [Y/n] or [y/N] depending on the truthy value of the default.
- # Refs: https://github.com/pallets/click/pull/3030#discussion_r2289180249
- else:
- default = bool(default)
- return confirm(self.prompt, default)
- # If show_default is set to True/False, provide this to `prompt` as well. For
- # non-bool values of `show_default`, we use `prompt`'s default behavior
- prompt_kwargs: t.Any = {}
- if isinstance(self.show_default, bool):
- prompt_kwargs["show_default"] = self.show_default
- return prompt(
- self.prompt,
- # Use ``None`` to inform the prompt() function to reiterate until a valid
- # value is provided by the user if we have no default.
- default=None if default is UNSET else default,
- type=self.type,
- hide_input=self.hide_input,
- show_choices=self.show_choices,
- confirmation_prompt=self.confirmation_prompt,
- value_proc=lambda x: self.process_value(ctx, x),
- **prompt_kwargs,
- )
- def resolve_envvar_value(self, ctx: Context) -> str | None:
- """:class:`Option` resolves its environment variable the same way as
- :func:`Parameter.resolve_envvar_value`, but it also supports
- :attr:`Context.auto_envvar_prefix`. If we could not find an environment from
- the :attr:`envvar` property, we fallback on :attr:`Context.auto_envvar_prefix`
- to build dynamiccaly the environment variable name using the
- :python:`{ctx.auto_envvar_prefix}_{self.name.upper()}` template.
- :meta private:
- """
- rv = super().resolve_envvar_value(ctx)
- if rv is not None:
- return rv
- if (
- self.allow_from_autoenv
- and ctx.auto_envvar_prefix is not None
- and self.name is not None
- ):
- envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}"
- rv = os.environ.get(envvar)
- if rv:
- return rv
- return None
- def value_from_envvar(self, ctx: Context) -> t.Any:
- """For :class:`Option`, this method processes the raw environment variable
- string the same way as :func:`Parameter.value_from_envvar` does.
- But in the case of non-boolean flags, the value is analyzed to determine if the
- flag is activated or not, and returns a boolean of its activation, or the
- :attr:`flag_value` if the latter is set.
- This method also takes care of repeated options (i.e. options with
- :attr:`multiple` set to ``True``).
- :meta private:
- """
- rv = self.resolve_envvar_value(ctx)
- # Absent environment variable or an empty string is interpreted as unset.
- if rv is None:
- return None
- # Non-boolean flags are more liberal in what they accept. But a flag being a
- # flag, its envvar value still needs to be analyzed to determine if the flag is
- # activated or not.
- if self.is_flag and not self.is_bool_flag:
- # If the flag_value is set and match the envvar value, return it
- # directly.
- if self.flag_value is not UNSET and rv == self.flag_value:
- return self.flag_value
- # Analyze the envvar value as a boolean to know if the flag is
- # activated or not.
- return types.BoolParamType.str_to_bool(rv)
- # Split the envvar value if it is allowed to be repeated.
- value_depth = (self.nargs != 1) + bool(self.multiple)
- if value_depth > 0:
- multi_rv = self.type.split_envvar_value(rv)
- if self.multiple and self.nargs != 1:
- multi_rv = batch(multi_rv, self.nargs) # type: ignore[assignment]
- return multi_rv
- return rv
- def consume_value(
- self, ctx: Context, opts: cabc.Mapping[str, Parameter]
- ) -> tuple[t.Any, ParameterSource]:
- """For :class:`Option`, the value can be collected from an interactive prompt
- if the option is a flag that needs a value (and the :attr:`prompt` property is
- set).
- Additionally, this method handles flag option that are activated without a
- value, in which case the :attr:`flag_value` is returned.
- :meta private:
- """
- value, source = super().consume_value(ctx, opts)
- # The parser will emit a sentinel value if the option is allowed to as a flag
- # without a value.
- if value is FLAG_NEEDS_VALUE:
- # If the option allows for a prompt, we start an interaction with the user.
- if self.prompt is not None and not ctx.resilient_parsing:
- value = self.prompt_for_value(ctx)
- source = ParameterSource.PROMPT
- # Else the flag takes its flag_value as value.
- else:
- value = self.flag_value
- source = ParameterSource.COMMANDLINE
- # A flag which is activated always returns the flag value, unless the value
- # comes from the explicitly sets default.
- elif (
- self.is_flag
- and value is True
- and not self.is_bool_flag
- and source not in (ParameterSource.DEFAULT, ParameterSource.DEFAULT_MAP)
- ):
- value = self.flag_value
- # Re-interpret a multiple option which has been sent as-is by the parser.
- # Here we replace each occurrence of value-less flags (marked by the
- # FLAG_NEEDS_VALUE sentinel) with the flag_value.
- elif (
- self.multiple
- and value is not UNSET
- and source not in (ParameterSource.DEFAULT, ParameterSource.DEFAULT_MAP)
- and any(v is FLAG_NEEDS_VALUE for v in value)
- ):
- value = [self.flag_value if v is FLAG_NEEDS_VALUE else v for v in value]
- source = ParameterSource.COMMANDLINE
- # The value wasn't set, or used the param's default, prompt for one to the user
- # if prompting is enabled.
- elif (
- (
- value is UNSET
- or source in (ParameterSource.DEFAULT, ParameterSource.DEFAULT_MAP)
- )
- and self.prompt is not None
- and (self.required or self.prompt_required)
- and not ctx.resilient_parsing
- ):
- value = self.prompt_for_value(ctx)
- source = ParameterSource.PROMPT
- return value, source
- def type_cast_value(self, ctx: Context, value: t.Any) -> t.Any:
- if self.is_flag and not self.required:
- if value is UNSET:
- if self.is_bool_flag:
- # If the flag is a boolean flag, we return False if it is not set.
- value = False
- return super().type_cast_value(ctx, value)
- class Argument(Parameter):
- """Arguments are positional parameters to a command. They generally
- provide fewer features than options but can have infinite ``nargs``
- and are required by default.
- All parameters are passed onwards to the constructor of :class:`Parameter`.
- """
- param_type_name = "argument"
- def __init__(
- self,
- param_decls: cabc.Sequence[str],
- required: bool | None = None,
- **attrs: t.Any,
- ) -> None:
- # Auto-detect the requirement status of the argument if not explicitly set.
- if required is None:
- # The argument gets automatically required if it has no explicit default
- # value set and is setup to match at least one value.
- if attrs.get("default", UNSET) is UNSET:
- required = attrs.get("nargs", 1) > 0
- # If the argument has a default value, it is not required.
- else:
- required = False
- if "multiple" in attrs:
- raise TypeError("__init__() got an unexpected keyword argument 'multiple'.")
- super().__init__(param_decls, required=required, **attrs)
- @property
- def human_readable_name(self) -> str:
- if self.metavar is not None:
- return self.metavar
- return self.name.upper() # type: ignore
- def make_metavar(self, ctx: Context) -> str:
- if self.metavar is not None:
- return self.metavar
- var = self.type.get_metavar(param=self, ctx=ctx)
- if not var:
- var = self.name.upper() # type: ignore
- if self.deprecated:
- var += "!"
- if not self.required:
- var = f"[{var}]"
- if self.nargs != 1:
- var += "..."
- return var
- def _parse_decls(
- self, decls: cabc.Sequence[str], expose_value: bool
- ) -> tuple[str | None, list[str], list[str]]:
- if not decls:
- if not expose_value:
- return None, [], []
- raise TypeError("Argument is marked as exposed, but does not have a name.")
- if len(decls) == 1:
- name = arg = decls[0]
- name = name.replace("-", "_").lower()
- else:
- raise TypeError(
- "Arguments take exactly one parameter declaration, got"
- f" {len(decls)}: {decls}."
- )
- return name, [arg], []
- def get_usage_pieces(self, ctx: Context) -> list[str]:
- return [self.make_metavar(ctx)]
- def get_error_hint(self, ctx: Context) -> str:
- return f"'{self.make_metavar(ctx)}'"
- def add_to_parser(self, parser: _OptionParser, ctx: Context) -> None:
- parser.add_argument(dest=self.name, nargs=self.nargs, obj=self)
- def __getattr__(name: str) -> object:
- import warnings
- if name == "BaseCommand":
- warnings.warn(
- "'BaseCommand' is deprecated and will be removed in Click 9.0. Use"
- " 'Command' instead.",
- DeprecationWarning,
- stacklevel=2,
- )
- return _BaseCommand
- if name == "MultiCommand":
- warnings.warn(
- "'MultiCommand' is deprecated and will be removed in Click 9.0. Use"
- " 'Group' instead.",
- DeprecationWarning,
- stacklevel=2,
- )
- return _MultiCommand
- raise AttributeError(name)
|