click_extra package¶
Expose package-wide elements.
- exception click_extra.Abort[source]¶
Bases:
RuntimeErrorAn internal signalling exception that signals Click to abort.
- class click_extra.AccessibleOption(param_decls=None, is_flag=True, default=False, is_eager=True, expose_value=False, help='Accessibility mode: disable colors and render tables in a borderless, screen-reader-friendly format.', **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured
--accessibleswitch.Turning it on (either via the flag or the
ACCESSIBLEenvironment variable) is equivalent to passing--no-color --no-progress --table-format plain, and additionally streamsecho_via_pager()output without a pager and turnsclear()into a no-op: it strips ANSI codes, silences progress spinners and bars, renders tables without box-drawing characters, and avoids interactive screen takeovers.Note
It is a one-way flag with no
--no-accessiblecounterpart: to opt back out, pass the explicit--color/--table-formatyou want, which take precedence anyway (see below). A negation flag would also be the widest option label in the help screen, pushing every other optionâs description column to the right.The switch only adjusts the defaults of the
--colorand--table-formatoptions, through the contextâsdefault_map. An explicit--color/--table-formaton the command line (or in a configuration file) therefore keeps precedence over--accessible.This option is eager so it lands its defaults before
--colorand--table-formatare resolved.Note
The values are injected with
dict.setdefault(), so they never clobber a colorization or table format already requested by the user. Combined with theChainMapthatConfigOptionlayers on top ofdefault_map, this yields the precedence: command line > configuration file >--accessible> built-in defaults.- set_accessible(ctx, param, value)[source]¶
Publish the accessibility intent and lower color/progress/table defaults.
Reconciles
--accessiblewith theACCESSIBLEenvironment variable, stores the result atACCESSIBLEfor output helpers (clear(),echo_via_pager()) to read, then lowers the--color/--progress/--table-formatdefaults when active. A CLI that never sees--accessible(norACCESSIBLE) keeps every default untouched.Note
The global
ACCESSIBLEenvironment variable is read here rather than wired through the optionâsenvvar. Click would otherwise list it alongside the auto-generated<CLI>_ACCESSIBLEvariable in the--paramstable, making the combined string the widest cell of the env-var column and pushing every other rowâs padding out. This mirrors howColorOptionreadsNO_COLORand friends.- Return type:
- class click_extra.Argument(*args, help=None, **attrs)[source]¶
Bases:
_ParameterMixin,ArgumentWrap
cloup.Argument, itself inheriting fromclick.Argument.Inherits first from
_ParameterMixinto allow future overrides of ClickâsParametermethods.
- exception click_extra.BadArgumentUsage(message, ctx=None)[source]¶
Bases:
UsageErrorRaised if an argument is generally supplied but the use of the argument was incorrect. This is for instance raised if the number of values for an argument is not correct.
Added in version 6.0.
- exception click_extra.BadOptionUsage(option_name, message, ctx=None)[source]¶
Bases:
UsageErrorRaised if an option is generally supplied but the use of the option was incorrect. This is for instance raised if the number of arguments for an option is not correct.
Added in version 4.0.
- Parameters:
option_name (str) â the name of the option being used incorrectly.
- exception click_extra.BadParameter(message, ctx=None, param=None, param_hint=None)[source]¶
Bases:
UsageErrorAn exception that formats out a standardized error message for a bad parameter. This is useful when thrown from a callback or type as Click will attach contextual information to it (for instance, which parameter it is).
Added in version 2.0.
- Parameters:
param (Parameter | None) â the parameter object that caused this error. This can be left out, and Click will attach this info itself if possible.
param_hint (cabc.Sequence[str] | str | None) â a string that shows up as parameter name. This can be used as alternative to
paramin cases where custom validation should happen. If it is a string itâs used as such, if itâs a list then each item is quoted and separated.
- class click_extra.CLITestCase(cli_parameters=<factory>, env=<factory>, unset_env=<factory>, skip_platforms=<factory>, only_platforms=<factory>, timeout=None, exit_code=None, strip_ansi=False, output_contains=<factory>, stdout_contains=<factory>, stderr_contains=<factory>, output_regex_matches=<factory>, stdout_regex_matches=<factory>, stderr_regex_matches=<factory>, output_regex_fullmatch=None, stdout_regex_fullmatch=None, stderr_regex_fullmatch=None, execution_trace=None)[source]¶
Bases:
objectA single CLI test case: how to invoke the command and what to expect.
Each case runs the command-under-test once with
cli_parametersappended, then checks the captured result against the expectation directives below. A case with no expectation only asserts the command ran (plusexit_code, if set).- cli_parameters: tuple[str, ...] | str¶
Arguments and options appended to the command-under-test.
A plain string is split into arguments (on spaces on Windows, with
shlexelsewhere); a list or tuple is used as-is.
- env: dict[str, str]¶
Environment variables set on the command, over the inherited environment.
The second input surface of a CLI, and the only way to reach a variable-only feature from a suite: an option can be typed as a
cli_parametersflag, a variable cannot. Values must be strings, so a number or a boolean is quoted ("1", not1): an environment holds strings only, and coercing would have to pick betweenTrueandtrueon the authorâs behalf.Applied to that one child process, never to the suite runnerâs own environment, so cases stay independent under
--jobs. Seeunset_envto take a variable away instead.
- unset_env: tuple[str, ...] | str¶
Environment variables removed from the inherited environment.
The half
envcannot express. Assigning the empty string leaves a variable set, and a flag read by bare presence (NO_COLORand its family) counts that as activation, so hiding one from the command means removing it. This is what keeps a case from answering to whatever the shell running the suite happens to export.A separate directive rather than a
nullvalue inenvbecause TOML has no null literal, and a suite is as likely to be written in TOML as in YAML. Removing a variable that is not set is a no-op.
- skip_platforms: Trait | Group | str | None | Iterable[Trait | Group | str | None | Iterable[_TNestedReferences]]¶
Platforms (or platform-group IDs) on which to skip this case.
Accepts
extra_platformsidentifiers such aslinux,macos,windows, in any case, mixed freely with group IDs.
- only_platforms: Trait | Group | str | None | Iterable[Trait | Group | str | None | Iterable[_TNestedReferences]]¶
Restrict this case to these platforms; skip it everywhere else.
The mirror image of
skip_platforms, using the same identifiers.
- timeout: float | str | None = None¶
Seconds before the command is killed and the case fails as a timeout.
Falls back to the commandâs
--timeoutdefault, then to no limit.
- output_contains: tuple[str, ...] | str¶
Substrings that must all be present in the combined output.
The combined output interleaves stdout and stderr in the order the command wrote them, matching what a user sees in a terminal. The
output_*directives are mutually exclusive with thestdout_*/stderr_*ones: a single subprocess run captures either the merged stream or the separate ones, not both.
- output_regex_matches: tuple[Pattern | str, ...] | str¶
Regexes that must each match somewhere in the combined output (searched,
re.DOTALL). Seeoutput_containsfor the merged-stream semantics.
- stdout_regex_matches: tuple[Pattern | str, ...] | str¶
Regexes that must each match somewhere in stdout (searched,
re.DOTALL).
- stderr_regex_matches: tuple[Pattern | str, ...] | str¶
Regexes that must each match somewhere in stderr (searched,
re.DOTALL).
- output_regex_fullmatch: Pattern | str | None = None¶
Regex that must fully match the combined output, line by line. See
output_containsfor the merged-stream semantics.
- stdout_regex_fullmatch: Pattern | str | None = None¶
Regex that must fully match stdout, line by line.
- stderr_regex_fullmatch: Pattern | str | None = None¶
Regex that must fully match stderr, line by line.
- execution_trace: str | None = None¶
Rendering of the command execution and its output.
Populated after the case runs, for inspection on failure; not a directive you set in a test suite.
- property has_merged_output_directives: bool¶
Whether any
output_*directive (merged stream) is set.
- property has_separate_stream_directives: bool¶
Whether any
stdout_*orstderr_*directive (separate streams) is set.
- run_cli_test(command, additional_skip_platforms, default_timeout, work_directory=None)[source]¶
Run a CLI command and check its output against the test case.
The provided
commandcan be either:a path to a binary or script to execute;
a command name to be searched in the
PATH,a command line with arguments to be parsed and executed by the shell.
The caseâs
envandunset_envdirectives are layered over the inherited environment for this child process only.work_directoryis the directory the command runs in, defaulting to the one the runner itself is in.commandis resolved to an absolute path before it takes effect, so moving the target elsewhere never changes which binary is executed, only what a relative path inside the command resolves against.- Return type:
- class click_extra.Choice(choices, case_sensitive=True)[source]¶
Bases:
ParamType[_ValueT_co],Generic[_ValueT_co]The choice type allows a value to be checked against a fixed set of supported values.
You may pass any iterable value which will be converted to a tuple and thus will only be iterated once.
The resulting value will always be one of the originally passed choices. See
normalize_choice()for more info on the mapping of strings to choices. See Choice for an example.- Parameters:
case_sensitive (
bool) â Set to false to make choices case insensitive. Defaults to true.
Changed in version 8.4.0: Now generic in the choice value type. Parameterize with the type of the choice values (
Choice[HashType]for an enum,Choice[str]for plain strings) to enable type-checked consumers.Changed in version 8.2.0: Non-
strchoicesare now supported. It can additionally be any iterable. Before you were not recommended to pass anything but a list or tuple.Added in version 8.2.0: Choice normalization can be overridden via
normalize_choice().- to_info_dict()[source]¶
Gather information that could be useful for a tool generating user-facing documentation.
Use
click.Context.to_info_dict()to traverse the entire CLI structure.Added in version 8.0.
- Return type:
ChoiceInfoDict[TypeVar(_ValueT_co, covariant=True)]
- normalize_choice(choice, ctx)[source]¶
Normalize a choice value, used to map a passed string to a choice. Each choice must have a unique normalized value.
By default uses
Context.token_normalize_func()and if not case sensitive, convert it to a casefolded value.Added in version 8.2.0.
- Return type:
str
- get_metavar(param, ctx)[source]¶
Returns the metavar default for this param if it provides one.
- Return type:
str | None
- get_missing_message(param, ctx)[source]¶
Message shown when no choice is passed.
Changed in version 8.2.0: Added
ctxargument.- Return type:
str
- convert(value, param, ctx)[source]¶
For a given value from the parser, normalize it and find its matching normalized value in the list of choices. Then return the matched âoriginalâ choice.
- Return type:
_ValueT_co
- get_invalid_choice_message(value, ctx)[source]¶
Get the error message when the given choice is invalid.
- Parameters:
value (t.Any) â The invalid value.
Added in version 8.2.
- Return type:
str
- shell_complete(ctx, param, incomplete)[source]¶
Complete choices that start with the incomplete value.
- Parameters:
ctx (Context) â Invocation context for this command.
param (Parameter) â The parameter that is requesting completion.
incomplete (str) â Value being completed. May be empty.
Added in version 8.0.
- Return type:
list[CompletionItem]
- class click_extra.ChoiceSource(*values)[source]¶
Bases:
EnumSource of choices for
EnumChoice.- KEY = 'key'¶
- NAME = 'name'¶
- VALUE = 'value'¶
- STR = 'str'¶
- class click_extra.CliRunner(charset='utf-8', env=None, echo_stdin=False, catch_exceptions=True, capture='sys')[source]¶
Bases:
CliRunnerAugment
click.testing.CliRunnerwith extra features and bug fixes.- invoke(cli, *args, input=None, env=None, catch_exceptions=True, color=None, **extra)[source]¶
Same as
click.testing.CliRunner.invoke()with extra features.The first positional parameter is the CLI to invoke. The remaining positional parameters of the function are the CLI arguments. All other parameters are required to be named.
The CLI arguments can be nested iterables of arbitrary depth. This is useful for argument composition of test cases with @pytest.mark.parametrize.
Allow forcing of the
colorproperty at the class-level viaforce_colorattribute.Adds a special case in the form of
color="forced"parameter, which allows colored output to be kept, while forcing the initialization ofContext.color = True. This is not allowed in current implementation ofclick.testing.CliRunner.invoke()because of colliding parameters.Strips all ANSI codes from results if
colorwas explicitly set toFalse.Always prints a simulation of the CLI execution as the user would see it in its terminal. Including colors.
Pretty-prints a formatted exception traceback if the command fails.
- Parameters:
cli (
Command) â CLI to invoke.args (
str|Path|None|Iterable[str|Path|None|Iterable[Iterable[str|Path|None|Iterable[TNestedArgs]]]]) â can be nested iterables composed ofstr,pathlib.Pathobjects andNonevalues. The nested structure will be flattened andNonevalues will be filtered out. Then all elements will be cast tostr. Seeargs_cleanup()for details.input (
str|bytes|IO|None) â same asclick.testing.CliRunner.invoke().env (
Mapping[str,str|None] |None) â same asclick.testing.CliRunner.invoke().catch_exceptions (
bool) â same asclick.testing.CliRunner.invoke().color (
bool|Literal['forced'] |None) â If a boolean, the parameter will be passed as-is toclick.testing.CliRunner.isolation(). If"forced", the parameter will be passed asTruetoclick.testing.CliRunner.isolation()and an extracolor=Trueparameter will be passed to the invoked CLI.extra (
Any) â same asclick.testing.CliRunner.invoke(), but colliding parameters are allowed and properly passed on to the invoked CLI.
- Return type:
- exception click_extra.ClickException(message)[source]¶
Bases:
ExceptionAn exception that Click can handle and show to the user.
- class click_extra.Color[source]¶
Bases:
FrozenSpaceColors accepted by
Styleandclick.style().- black = 'black'¶
- red = 'red'¶
- green = 'green'¶
- yellow = 'yellow'¶
- blue = 'blue'¶
- magenta = 'magenta'¶
- cyan = 'cyan'¶
- white = 'white'¶
- reset = 'reset'¶
- bright_black = 'bright_black'¶
- bright_red = 'bright_red'¶
- bright_green = 'bright_green'¶
- bright_yellow = 'bright_yellow'¶
- bright_blue = 'bright_blue'¶
- bright_magenta = 'bright_magenta'¶
- bright_cyan = 'bright_cyan'¶
- bright_white = 'bright_white'¶
- class click_extra.ColorOption(param_decls=None, is_flag=False, flag_value='always', default='auto', is_eager=True, expose_value=False, help='Colorize the output. A bare --color is the same as --color=always.', **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured
--color[=WHEN]tri-state option.Mirrors the GNU coreutils convention:
WHENis one ofCOLOR_WHEN(auto,alwaysornever), and a bare--color(no value) meansalways. The negative alias--no-coloris carried by the separateNoColorOption, because Click forbids attaching/--no-xsecondary flags to a value option.The resolved tri-state lands on
ctx.color, the Click-standard attribute thatecho()reads through itsresolve_color_default()âshould_strip_ansi()chain:Truekeeps ANSI codes,Falsestrips them,None(auto) defers to the output streamâs TTY status.This option is eager by default, so other eager options (like
--version) are rendered with the resolved color state.Note
--coloris deliberately not wired to anenvvar. The color environment variables (NO_COLOR,FORCE_COLOR, âŠ) are read manually throughresolve_color_env(). Letting Click manage them would dump the wholeCOLOR_ENVVARSset into the--paramsenv-var column, and only bind one variable per option anyway.- add_to_parser(parser, ctx)[source]¶
Register the option, then teach the parser GNU optional-argument rules.
Clickâs optional-value parser binds
--colorto the next token whenever it does not look like an option, somycli --color subcommandwould consumesubcommandas the color value and fail. GNU instead binds an optional argument only when it is attached with=.This wraps the parserâs long-option matcher so a bare
--colorreplays as--color=<flag_value>(always) and leaves the following argument untouched, while--color=<when>keeps working. The wrapper stays inert for every option that does not carry_gnu_optional_value, so it is safe to install on the shared parser.- Return type:
- set_color(ctx, param, value)[source]¶
Resolve
--color=<WHEN>against the environment and pinctx.color.Precedence, highest first:
An explicit
--coloron the command line.The color environment variables, but only when the value comes from the built-in default. A configuration file or
--accessible(both seen here as a non-DEFAULTsource) therefore wins over the environment, matchingAccessibleOption.A color state already pinned by
--no-color, a forced test runner, or an explicitContext(color=...): preserved when this option only resolves toautofrom its default.The
autodefault, leavingctx.coloratNonefor TTY detection.
Whatever branch settles it, the resolution is mirrored process-wide by
publish_invocation_color()so output produced from background threads honors it too.Stays dormant under resilient parsing, like every other eager callback: an introspection context (
make_resilient_context(), behind the man-page, tree and completion-spec exporters) is never closed, so publishing from one would leave the process-wide mirror pinned to that contextâs environment resolution. ANO_COLORbuild environment would then strip the output of every later CLI carrying no color option of its own.- Return type:
- class click_extra.ColumnsOption(param_decls=None, columns=None, type=None, default=(), expose_value=False, is_eager=True, help='Restrict and reorder table columns, SQL SELECT-style. Comma-separated list of column IDs. Default: all columns in canonical order.', **kwargs)[source]¶
Bases:
ExtraOptionA
--columnsoption that lets users restrict and reorder table columns.Accepts a comma-separated list of column IDs, SQL-
SELECT-style:$ my-cli --columns id,spec,value --params
The selection is stored in
ctx.meta[click_extra.context.COLUMNS]and consumed by table-rendering callbacks (likeclick_extra.parameters.ShowParamsOption) to project rows + headers before rendering.Pass
columns=at construction time with the column registry the option should advertise: the help text then lists the accepted IDs and the default selection, and the callback validates the user input against that registry so unknown IDs fail fast with aclick.UsageError. Withoutcolumns=, the option stays generic: it parses any IDs and leaves validation to the downstream consumer.Empty / unset means render every column in canonical order: the default behavior, indistinguishable from not passing
--columnsat all.- columns: tuple[ColumnSpec, ...]¶
Column registry this option advertises and validates against (may be empty).
- class click_extra.Command(*args, version_fields=None, config_schema=None, config_strict=False, schema_strict=False, fallback_sections=(), config_validators=(), included_params=None, excluded_params=None, extra_option_at_end=True, option_priorities=None, populate_auto_envvars=True, extra_keywords=None, excluded_keywords=None, examples=(), **kwargs)[source]¶
Bases:
_HelpColorsMixin,CommandLike
cloup.command, with sane defaults and extra help screen colorization.List of extra parameters:
- Parameters:
version_fields (
dict[str,Any] |None) â dictionary ofVersionOptiontemplate field overrides forwarded to the version option. Accepts any field fromVersionOption.template_fields(likeprog_name,version,git_branch). Lets you customize--versionoutput from the command decorator without replacing the defaultparamslist.config_strict (
bool) â forwarded to the defaultConfigOptionâsstrictsetting: configuration keys not matching any CLI parameter raise an error instead of being silently ignored. Like the otherconfig_*and*_paramsforwards, it spares you from replacing the whole defaultparamslist to customize the config option.excluded_params (
Sequence[str] |None) â additional parameter IDs to block from configuration files, merged into the defaultConfigOptionâsexcluded_paramsblocklist. Additive, unlike the option-levelexcluded_paramswhich replaces the default blocklist entirely. Items are fully-qualified parameter IDs (likemycli.mail_sources). Mutually exclusive withincluded_params.extra_keywords (
HelpKeywords|None) â aHelpKeywordsinstance whose entries are merged into the auto-collected keyword set. Use this to inject additional strings for help screen highlighting.excluded_keywords (
HelpKeywords|None) â aHelpKeywordsinstance whose entries are removed from the auto-collected keyword set. Use this to suppress highlighting of specific strings.examples (
Sequence[Sequence[str]]) â a sequence of(description, command)string pairs showing the command in use. They are rendered in anExamples:section of the help screen, in the man page, and in every âhelp-format rendering. A malformed pair raisesTypeErrorhere, at command construction, rather than on the first--helpa user runs.extra_option_at_end (
bool) â reorders all parameters attached to the command, by moving all instances ofExtraOptionat the end of the parameter list. The original order of the options is preserved among themselves.option_priorities (
Mapping[str,float] |None) â maps an option to its priority in the help screen, relative toDEFAULT_PRIORITY, lowest shown first. Keys are matched against each parameterâs long and short flags first, then its destination name, so the--config/--no-configpair (which shares theconfigdestination) stays addressable one flag at a time. Presentation only:self.params, and with it the order callbacks are evaluated in, is left alone. Positional arguments are never reordered, their sequence being part of the commandâs grammar.populate_auto_envvars (
bool) â forces all parameters to have their auto-generated environment variables registered. This address the shortcoming ofclickwhich only evaluates them dynamically. By forcing their registration, the auto-generated environment variables gets displayed in the help screen, fixing click#2483 issue. On Windows, environment variable names are case-insensitive, so we normalize them to uppercase.
By default, these Click context settings are applied:
auto_envvar_prefix = self.name(Click feature)Auto-generate environment variables for all options, using the command ID as prefix. The prefix is normalized to be uppercased and all non-alphanumerics replaced by underscores.
help_option_names = ("--help", "-h")(Click feature)Allow help screen to be invoked with either âhelp or -h options.
show_default = True(Click feature)Show all default values in help screen.
Additionally, these Cloup context settings are set:
align_option_groups = False(Cloup feature)show_constraints = True(Cloup feature)show_subcommand_aliases = True(Cloup feature)
Click Extra also adds its own
context_settings:show_choices = None(Click Extra feature)If set to
TrueorFalse, will force that value on all options, so we can globally show or hide choices when prompting a user for input. Only makes sense for options whosepromptproperty is set.Defaults to
None, which will leave all options untouched, and let them decide of their ownshow_choicessetting.show_envvar = None(Click Extra feature)If set to
TrueorFalse, will force that value on all options, so we can globally enable or disable the display of environment variables in help screen.Defaults to
None, which will leave all options untouched, and let them decide of their ownshow_envvarsetting. The rationale being that discoverability of environment variables is enabled by the--paramsoption, which is active by default on extra commands. So there is no need to surcharge the help screen.This addresses the click#2313 issue.
To override these defaults, you can pass your own settings with the
context_settingsparameter:@command( context_settings={ "show_default": False, ... } )
- examples: tuple[tuple[str, str], ...] = ()¶
(description, command)pairs showing the command in use.Normalized from the
examplesconstructor argument bynormalize_examples(). Declared here so the attribute exists on every command, whether or not its author passed any: the renderers reading it (help screen, man page, and everyHELP_FORMATSbackend) then need no guard.
- param_priority(param)[source]¶
Priority of param in the help screen.
Defaults to
DEFAULT_PRIORITY, and is otherwise resolved againstoption_prioritiesby trying each of the parameterâs flags in turn, then its destination name.Important
This orders the help screen alone. The order of
self.paramsdecides when each callback fires:click.core.iter_params_for_processingsorts on(not is_eager, position on the command line), and every eager option the user did not type ties on that second key, leaving declaration order as the tie-break. That is what puts--timeahead of everything it measures and--accessibleahead of the--colordefault it lowers, so the two orders have to be free to disagree.Positional arguments always resolve to the default: their sequence is part of the commandâs grammar, not a matter of presentation.
- Return type:
- main(args=None, prog_name=None, **kwargs)[source]¶
Pre-invocation step that is instantiating the context, then call
invoke()within it.Caution
During context instantiation, each optionâs callbacks are called. These might break the execution flow (like
--helpor--version).Sets the default CLIâs
prog_nameto the commandâs name if not provided, instead of relying on Clickâs auto-detection via the_detect_program_name()method. This is to avoid the CLI being calledpython -m <module_name>, which is not very user-friendly.- Return type:
- make_context(info_name, args, parent=None, **extra)[source]¶
Intercept the call to the original
click.core.Command.make_contextso we can keep a copy of the raw, pre-parsed arguments provided to the CLI.The result are passed to our own
Contextconstructor which is able to initialize the contextâsmetaproperty under our ownclick_extra.context.RAW_ARGSentry. This will be used inShowParamsOption.print_params()to print the table of parameters fed to the CLI.See also
See
click_extra.context.RAW_ARGSfor the full rationale and the upstream-proposal notes (related: click#1279).- Return type:
- format_examples(ctx, formatter)[source]¶
Write an
Examples:section listing the commandâsexamples.Each entry renders its description, then the command line it describes, indented behind a
$prompt. A command declaring none writes nothing at all, so a help screen only grows the section when it has something to put in it.The command lines go out verbatim rather than through
formatter.write_text(): an example exists to be copied, and Clickâs text wrapper would fold a long one onto a second line mid-token. This is the same call the\bno-rewrap marker makes for help prose.Nothing here styles anything. The lines land in the formatterâs buffer, which
getvalue()runs through keyword highlighting on its way out, so the option names, subcommands and CLI names inside an example are painted by the same pass that paints them everywhere else.- Return type:
- format_epilog(ctx, formatter)[source]¶
Insert the examples section ahead of the epilog.
Places it after the options and subcommands, which is where a reader arrives once they know what the command accepts, and keeps the authorâs own epilog as the last word on the screen.
- Return type:
- parse_args(ctx, args)[source]¶
Like parentâs
parse_argsbut with better error messages for single-dash multi-character tokens.Also settles the presentation options before delegating, so
--color,--no-color,--accessibleand--themereach the eager help and version screens regardless of their position on the command line. See_resolve_presentation_eagerly.
- class click_extra.CommandCollection(name=None, sources=None, **kwargs)[source]¶
Bases:
GroupA
Groupthat 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.- Parameters:
Changed in version 8.2: This is a subclass of
Group. Commands are looked up first on this group, then each of its sources.
- class click_extra.CommandDoc(name, short_help='', section='1', synopsis_pieces=(), description='', operands=(), option_groups=(), subcommands=(), environment=(), files=(), exit_status=(('0', 'Success.'), ('1', 'A runtime error, or an aborted prompt (Ctrl-C, a declined confirmation).'), ('2', 'A usage error: unknown option, invalid value, missing operand, or an unparsable configuration file.')), examples=(), version=None, date='', manual=None, authors=None, copyright=None)[source]¶
Bases:
objectA whole man page in structured form, ready to render to roff.
One
CommandDocmaps to one command (or subcommand). Its fields are the man-pages(7) sections, in the order Man-page documents them. Build it withextract_command_doc()and serialize withto_roff().- synopsis_pieces: tuple[str, ...] = ()¶
Usage metavars after the command name (
[OPTIONS],CITY, âŠ).
- option_groups: tuple[DocOptionGroup, ...] = ()¶
The OPTIONS entries, partitioned into one or more groups. A command without explicit option groups carries a single untitled group.
- subcommands: tuple[tuple[str, str], ...] = ()¶
For groups:
(name, short_help)pairs for the COMMANDS section.
- exit_status: tuple[tuple[str, str], ...] = (('0', 'Success.'), ('1', 'A runtime error, or an aborted prompt (Ctrl-C, a declined confirmation).'), ('2', 'A usage error: unknown option, invalid value, missing operand, or an unparsable configuration file.'))¶
EXIT STATUS entries as
(code, meaning)pairs.
- examples: tuple[tuple[str, str], ...] = ()¶
EXAMPLES entries as
(description, command_line)pairs.Collected from the commandâs own
examplesattribute (seeclick_extra.commands.Command.examples). Empty for a command that declares none, in which case every backend omits the section entirely.
- to_markdown()[source]¶
Render the whole document as Markdown.
Same sections as
to_roff(), in the same order, minus the roff.THheader, whose date, section number and manual name describe a man page rather than the command. The version survives, as a line under the title.- Return type:
- to_dict()[source]¶
Render the whole document as a JSON-serializable mapping.
Subcommands are listed by name and one-line description only, never recursively: a consumer walking a deep tree asks for the child it cares about instead of paying for the whole tree at once.
render_help()exposes the recursive variant separately, for the consumers that do want everything.
- class click_extra.ConfigOption(param_decls=None, metavar='CONFIG_PATH', type=UNPROCESSED, help='Location of the configuration file. Supports local path with glob patterns or remote URL.', is_eager=True, expose_value=False, file_format_patterns=None, file_pattern_flags=4104, roaming=True, force_posix=False, search_pattern_flags=285504, search_parents=False, stop_at=Sentinel.VCS, cascade=False, excluded_params=None, included_params=None, strict=False, config_schema=None, schema_strict=False, fallback_sections=(), config_validators=(), **kwargs)[source]¶
Bases:
ExtraOption,ParamStructureA pre-configured option adding
--config CONFIG_PATH.Takes as input a path to a file or folder, a glob pattern, or an URL.
is_eageris active by default so thecallbackgets the opportunity to set thedefault_mapof the CLI before any other parameter is processed.defaultis set to the value returned byself.default_pattern(), which is a pattern combining the default configuration folder for the CLI (as returned byclick.get_app_dir()) and all supported file formats.Attention
Default search pattern must follow the syntax of wcmatch.glob.
excluded_paramsare parameters which, if present in the configuration file, will be ignored and not applied to the CLI. Items are expected to be the fully-qualified ID of the parameter, as produced in the output of--params. Will default to the value ofDEFAULT_EXCLUDED_PARAMS, plus the CLIâs--helpoption, resolved at runtime.included_paramsis the inverse ofexcluded_params: only the listed parameters will be loaded from the configuration file. Cannot be used together withexcluded_params.
- file_format_patterns: dict[ConfigFormat, tuple[str, ...]]¶
Mapping of
ConfigFormatto their associated file patterns.Can be a string or a sequence of strings. This defines which configuration file formats are supported, and which file patterns are used to search for them.
Note
All formats depending on third-party dependencies that are not installed will be ignored.
Attention
File patterns must follow the syntax of wcmatch.fnmatch.
- file_pattern_flags¶
Flags provided to all calls of
wcmatch.fnmatch.Applies to the matching of file names against supported format patterns specified in
file_format_patterns.Important
The
SPLITflag is always forced, as our multi-pattern design relies on it.
- force_posix¶
Configuration for default folder search.
roamingandforce_posixare fed to click.get_app_dir() to determine the location of the default configuration folder.
- search_pattern_flags¶
Flags provided to all calls of
wcmatch.glob.Applies to both the default pattern and any user-provided pattern.
Important
The
BRACEflag is always forced, so that multi-format default patterns using{pat1,pat2,...}syntax expand correctly.The
NODIRflag is always forced, to optimize the search for files only.
- search_parents¶
Indicates whether to walk back the tree of parent folders when searching for configuration files.
- stop_at¶
Boundary for parent directory walking.
None: walk up to filesystem root.VCS: stop at the nearest VCS root, whichever system marks it (seeVCS_DIRS) (default).A
Pathorstr: stop at that directory.
- cascade¶
Merge every discovered configuration file instead of stopping at the first parseable one.
When
True, all files found by auto-discovery (the app-dir search, including the parent walk whensearch_parents=True, plus thepyproject.tomlCWD search when enabled) are loaded and layered into the contextâsdefault_mapvia a~collections.ChainMap. The most local file wins on key lookup: apyproject.tomlfound near the CWD overrides the app-dir config, which overrides files found higher up the parent walk.An explicit
--configvalue never cascades: it pins a single source, whatever the pattern matches.Defaults to
False, which preserves the historical behavior of the first successfully parsed file winning.
- extra_excluded_params: frozenset[str]¶
Additional exclusions merged into the dynamic
excluded_paramsdefault.Populated by
Commandâsexcluded_paramsforwarding, which is additive: the default blocklist (--config,--version,--help, âŠ) is preserved and the forwarded IDs are unioned into it when the property resolves. Ignored when an explicitexcluded_paramswas frozen on the instance, as the property is then never consulted.
- strict¶
Defines the strictness of the configuration loading.
If
True, raise an error if the configuration file contain parameters not recognized by the CLI.If
False, silently ignore unrecognized parameters.
- config_schema¶
Optional schema for structured access to configuration values.
When set, the appâs configuration section is extracted from the parsed config file, normalized (hyphens replaced with underscores), flattened (nested dicts joined with
_), and passed to this callable to produce a typed configuration object.Supports:
Dataclass types: detected via
__dataclass_fields__. Keys are normalized, nested dicts are flattened, and the result is filtered to known fields before instantiation. This allows nested config sections (like[tool.myapp.sub-section]) to map directly to flat dataclass fields (likesub_section_key).Any callable
dict â T: called directly with the raw dict. Works with PydanticâsModel.model_validate, attrs, or custom factory functions. The caller is responsible for key normalization and flattening.
The resulting object is stored in
ctx.meta[click_extra.context.TOOL_CONFIG]and can be retrieved viaget_tool_config.
- schema_strict¶
Strictness for schema validation (separate from
strict).If
True, raiseValueErrorwhen the config section contains keys that do not match any dataclass field (after normalization and flattening). Only applies whenconfig_schemais a dataclass.If
False, ignore unrecognized keys. When the section is schema-only (included_params=()), a warning still names them: seewarn_unknowninmake_schema_callable().
Note
This is distinct from
strict, which controls whethermerge_default_maprejects config keys not matching CLI parameters.schema_strictvalidates against dataclass fields instead.
- fallback_sections: Sequence[str]¶
Legacy section names to try when the appâs own section is empty.
Useful when a CLI tool has been renamed: old configuration files that still use
[tool.old-name](TOML),old-name:(YAML), or{"old-name": âŠ}(JSON) are recognized with a deprecation warning. Works with all configuration formats.
- schema_warn_unknown: bool¶
Warn on config keys unknown to the schema, in lax mode.
Inferred, not user-supplied: an explicitly empty
included_paramsmeans no CLI parameter is merged from the appâs config section, so the section is schema-only and any key the schema does not know is a typo worth a warning. Forwarded tomake_schema_callable()and the validation pipeline aswarn_unknown.
- config_validators: tuple[ConfigValidator, ...]¶
Extension validators for sub-trees of the configuration file.
Each
ConfigValidatortargets a dottedextension_pathrelative to the app section. Validators run after click-extraâs built-in CLI-parameter strict check (during--validate-config) and after the schema callable produces the typed configuration object (during normal config loading).The list is seeded with click-extraâs built-in validators (currently the one for
[tool.<cli>.themes.<name>]tables, seeclick_extra.theme.validate_themes_config()); user-supplied validators are appended after them. App code that registers its own validator on the sameextension_pathsimply runs alongside the built-in: both validators are called, both sets of errors surface.
- property excluded_params: frozenset[str][source]¶
Generates the default list of fully-qualified IDs to exclude.
Danger
It is only called once to produce the default exclusion list if the user did not provided its own.
It was not implemented in the constructor but made as a property, to allow for a just-in-time call within the current context. Without this trick we could not have fetched the CLI name.
- property file_pattern: str[source]¶
Compile all file patterns from the supported formats.
Uses
,(comma) notation to combine multiple patterns, suitable forwcmatchbrace expansion ({pat1,pat2,...}).Returns a single pattern string.
- default_pattern()[source]¶
Returns the default pattern used to search for the configuration file.
Defaults to
<app_dir>/{*.toml,*.json,*.ini}. Where<app_dir>is produced by the click.get_app_dir() method. The result depends on OS and is influenced by theroamingandforce_posixproperties.Multiple file format patterns are wrapped with
{âŠ}brace-expansion syntax so thatwcmatch.globcorrectly applies the directory prefix to every sub-pattern.Todo
Use platformdirs for more advanced configuration folder detection?
- Return type:
- get_help_extra(ctx)[source]¶
Replaces the default value of the configuration option.
Display a pretty path that is relative to the userâs home directory:
~/folder/my_cli/{*.toml,*.json,*.ini}Instead of the full absolute path:
/home/user/folder/my_cli/{*.toml,*.json,*.ini}- Return type:
OptionHelpExtra
Caution
This only applies when the
GLOBTILDEflag is set insearch_pattern_flags.
- parent_patterns(pattern)[source]¶
Generate
(root_dir, file_pattern)pairs for searching.Each yielded pair can be passed directly to
glob.iglob(file_pattern, root_dir=root_dir)so that every sub-pattern (whether fromBRACEorSPLITexpansion) is correctly scoped to the same directory.root_dirisNonefor entirely magic patterns that will be evaluated relative to the current working directory.Stops when reaching the root folder, the
stop_atboundary, or an inaccessible directory.
- search_and_read_file(pattern)[source]¶
Search filesystem or URL for files matching the
pattern.If
patternis an URL, download its content. A pattern is considered an URL only if it validates as one and starts withhttp://orhttps://. All other patterns are considered glob patterns for local filesystem search.Returns an iterator of
(location, content, media_type)triples, for each one matching the pattern.locationis normalized andcontentraw.media_typeis the baretype/subtypethe server advertised in itsContent-Typeheader, and isNonefor a local file, whose format is derived from its name. Only files are returned, directories are silently skipped.This method returns the raw content of all matching patterns, without trying to parse them. If the content is empty, it is still returned as-is.
Also includes lookups into parents directories if
self.search_parentsisTrue.Raises
FileNotFoundErrorif no file was found after searching all locations.
- parse_conf(content, formats, location=None)[source]¶
Parse the
contentwith the givenformats.Tries to parse the given raw
contentstring with each of the givenformats, in order. Yields the resulting data structure for each successful parse.locationis the path thecontentwas read from. It is only needed by formats that cannot be parsed from a text payload, likeSQLITE, which is read straight from its file, and the binary variant ofPLIST, which only exists on disk. Such formats are skipped whenlocationis missing or is not a local file.Attention
Formats whose parsing raises an exception or does not return a
dictare considered a failure and are skipped.This follows the parse, donât validate principle.
- read_and_parse_all_conf(pattern)[source]¶
Search for every parseable configuration file matching
pattern.Yields
(location, parsed_conf)pairs in discovery order, which is the most local first: the original search location, then each parent directory when parent search is enabled. Files already yielded (as matched by their resolved location) are skipped, as are files that parse to an empty configuration.Raises
FileNotFoundErrorif no file at all matched the pattern.
- read_and_parse_conf(pattern)[source]¶
Search for a parseable configuration file.
Returns the location and data structure of the first configuration matching the
pattern.Only return the first match that:
exists,
is a file,
is not empty,
match file format patterns,
can be parsed successfully, and
produce a non-empty data structure.
Raises
FileNotFoundErrorif no configuration file was found matching the criteria above.Returns
(None, None)if files were found but none could be parsed.
- load_ini_config(content)[source]¶
Utility method to parse INI configuration file.
Internal convention is to use a dot (
., as set byPARAM_PATH_SEP) in section IDs as a separator between levels. This is a workaround the limitation ofINIformat which doesnât allow for sub-sections.Returns a ready-to-use data structure.
- load_argfile_config(content)[source]¶
Utility method to parse a plain-text argfile configuration file.
The file holds command-line tokens, one option per line, in the style of
mpvâs andyt-dlpâs configuration files:# Comments start with a hash sign. --option-name some value --flag
Tokens are split with
shlex.split(), so shell quoting rules apply and a#starts a comment. Each option is matched against the CLIâs root-level parameter declarations, and its value is converted to the parameterâs Python type, likeload_ini_config()does. A boolean flag needs no value: its primary declaration sets it toTrue, its secondary one (--no-*) toFalse. An option flaggedmultipleaccumulates one list item per occurrence. Unknown options are kept under a normalized key so the strict check can reject them like any other unrecognized configuration key, while positional tokens are skipped; subcommand options cannot be addressed from an argfile.Returns a ready-to-use data structure, wrapped in the appâs section name like the
[my-cli]section of the other formats.- Raises:
ValueError â the content cannot be tokenized, or an option is missing its value.
- Return type:
- load_sqlite_config(path)[source]¶
Utility method to parse a SQLite configuration database.
The database holds a single
SQLITE_CONFIG_TABLEtable ofkey/valuerows. Keys are parameter paths, with a dot (., as set byPARAM_PATH_SEP) separating each level, likemy-cli.default.int_param. Values are JSON-encoded, which carries every type the other formats do: booleans, numbers, strings, lists and nested objects alike.Returns a ready-to-use data structure.
- load_plist_config(path)[source]¶
Utility method to parse a
plistconfiguration file.The file is read as raw bytes and handed to the standard libraryâs
plistlib, which transparently decodes both the XML and the binary variants of the format. The XML variant also parses from a text payload throughparse_content(), which is how aplistfetched overhttp://orhttps://is loaded.Returns a ready-to-use data structure.
- merge_default_map(ctx, user_conf)[source]¶
Save the user configuration into the contextâs
default_map.Merge the user configuration into the pre-computed template structure, which filters out all unrecognized options not supported by the command, then hand the result to
_install_default_map().Opaque sub-trees declared by the schema or by registered
ConfigValidatorinstances are stripped from the conf before the CLI-parameter strict check, so user-controlled keys (like mappings whose keys are data, not flag names) donât tripstrict=True.Note
This recomputes the filtered config that
run_config_validation()already produces asmerged_conf.load_conf()installs that result directly and skips this method; it stays as the standalone entry point for external callers.- Return type:
- load_conf(ctx, param, path_pattern)[source]¶
Fetch parameter values from a configuration file and set them as defaults.
User configuration is merged to the contextâs default_map, like Click does.
By relying on Clickâs
default_map, we make sure that precedence is respected. Direct CLI parameters, environment variables or interactive prompts take precedence over any values from the config file.Hint
Once loading is complete, the resolved file path and its full parsed content are stored in
ctx.meta[click_extra.context.CONF_SOURCE]andctx.meta[click_extra.context.CONF_FULL]respectively. This is the recommended way to identify which configuration file was loaded.We intentionally do not add a custom
ParameterSource.CONFIG_FILEenum member:ParameterSourceis a closed enum in Click, and monkeypatching it would be fragile. Besides, config values end up indefault_map, so Click already reports them asParameterSource.DEFAULT_MAP, which is accurate.- Return type:
- class click_extra.ConstraintMixin(*args, constraints=(), show_constraints=None, **kwargs)[source]¶
Bases:
objectProvides support for constraints.
- Parameters:
constraints (
Sequence[BoundConstraintSpec|BoundConstraint]) â sequence of constraints bound to specific groups of parameters. Note that constraints applied to option groups are collected from the option groups themselves, so they donât need to be included in this argument.show_constraints (
bool|None) â whether to include a âConstraintâ section in the command help. This is also available as a context setting having a lower priority than this attribute.args (
Any) â positional arguments forwarded to the next class in the MROkwargs (
Any) â keyword arguments forwarded to the next class in the MRO
- optgroup_constraints¶
Constraints applied to
OptionGroupinstances.
- param_constraints: Tuple[BoundConstraint, ...]¶
Constraints registered using
@constraint(or equivalent method).
- all_constraints¶
All constraints applied to parameter/option groups of this command.
- class click_extra.Context(*args, meta=None, sort_subcommands=None, **kwargs)[source]¶
Bases:
ContextLike
cloup._context.Context, but with the ability to populate the contextâsmetaproperty at instantiation.Also defaults
colortoTruefor root contexts (those without a parent), so help screens are always colorized, even when piped. Clickâs own default isNone(auto-detect via TTY), which strips colors in non-interactive contexts.Parent-to-child color inheritance is handled by Click itself at
Context.__init__time, so no property override is needed.When the
POSIXLY_CORRECTenvironment variable is set, this context forcesallow_interspersed_argstoFalseso option parsing stops at the first positional argument, as GNU getopt-based tools do. SeePOSIXLY_CORRECT_ENVVAR.Carries the
sort_subcommandssetting read byclick_extra.commands.Group.must_sort_subcommands(), so a whole command tree can settle its subcommand listings in one place.Todo
Propose addition of
metakeyword upstream to Click.Like parentâs context but with an extra
metakeyword-argument.Also pre-seed
colorfrom the color environment variables for a parentless context when the user did not provide it, and forceallow_interspersed_argstoFalsewhenPOSIXLY_CORRECTis set in the environment.- Parameters:
sort_subcommands (
bool|None) â whether groups list their subcommands alphabetically. Inherited from the parent context when left toNone, the way Cloup inheritsalign_sections, so declaring it once on the root group settles every subgroup below it.
- formatter_class¶
alias of
HelpFormatter
- render_table(table_data, headers=None, table_format=None, sort_key=None, **kwargs)[source]¶
Render a table honoring the invocationâs table options, and return it.
Same contract as
click_extra.table.render_table(), withtable_formatandsort_keydefaulting to the values resolved by the--table-formatand--sort-byoptions (read fromTABLE_FORMATandTABLE_SORT_KEY).ctx.metais shared along the context chain, so this works from any subcommand without reaching for the root context. Without those options in the chain, falls back to the default format and no sort.- Return type:
- print_table(table_data, headers=None, table_format=None, sort_key=None, **kwargs)[source]¶
Render a table honoring the invocationâs table options, and print it.
The printing counterpart of
render_table(): same defaulting oftable_formatandsort_keyfrom the contextâs sharedmeta, delegating toclick_extra.table.print_table()(which also handles ANSI translation and colorization policy).- Return type:
- class click_extra.DateTime(formats=None)[source]¶
-
The DateTime type converts date strings into
datetimeobjects.The format strings which are checked are configurable, but default to some common (non-timezone aware) ISO 8601 formats.
When specifying DateTime formats, you should only pass a list or a tuple. Other iterables, like generators, may lead to surprising results.
The format strings are processed using
datetime.strptime, and this consequently defines the format strings which are allowed.Parsing is tried using each format, in order, and the first format which parses successfully is used.
- Parameters:
formats (
Sequence[str] |None) â A list or tuple of date format strings, in the order in which they should be tried. Defaults to'%Y-%m-%d','%Y-%m-%dT%H:%M:%S','%Y-%m-%d %H:%M:%S'.
- to_info_dict()[source]¶
Gather information that could be useful for a tool generating user-facing documentation.
Use
click.Context.to_info_dict()to traverse the entire CLI structure.Added in version 8.0.
- Return type:
DateTimeInfoDict
- get_metavar(param, ctx)[source]¶
Returns the metavar default for this param if it provides one.
- Return type:
str
- convert(value, param, ctx)[source]¶
Convert the value to the correct type. This is not called if the value is
None(the missing value).This must accept string values from the command line, as well as values that are already the correct type. It may also convert other compatible types.
The
paramandctxarguments may beNonein certain situations, such as when converting prompt input.If the value cannot be converted, call
fail()with a descriptive message.- Parameters:
value (t.Any) â The value to convert.
param (Parameter | None) â The parameter that is using this type to convert its value. May be
None.ctx (Context | None) â The current context that arrived at this value. May be
None.
- Return type:
datetime
- class click_extra.Duration[source]¶
Bases:
ParamTypeParse a duration or an age into a
datetime.timedelta.Accepts three input shapes:
Friendly duration:
7 days,1 week,12h,30m,45s, or a bare number of days like7. Case-insensitive.ISO 8601 duration:
P7D,PT12H,P1WT6H. Case-insensitive.RFC 3339 absolute timestamp:
2024-05-01T00:00:00Zor with an offset like+02:00. Converted at parse time to its age,now - timestamp.
Some inputs parse to
Noneinstead of atimedelta: a zero duration, an empty string, and a timestamp in the future. Cutoff options (cooldowns, timeouts, retention windows, cache TTLs) readNoneas âno cutoffâ, so a0on the command line disables the gate and overrides a value set in a configuration file.To parse outside a Click parameter (classifying a value read from a file, say), reach for the soft
parse_duration()family, which returnsNoneinstead of raising on an unrecognized value.Note
Durations resolve to a fixed number of seconds, assuming a day is 24 hours. The local time zone, DST transitions, and calendar boundaries are ignored. Calendar units (months, years) are rejected for the same reason: 28-31 days and 365-366 days make them unsuitable for a precise cutoff. Use
daysorweeksinstead.
- class click_extra.EnumChoice(choices, case_sensitive=False, choice_source=ChoiceSource.STR, show_aliases=False, transform=None)[source]¶
Bases:
ChoiceChoice type for
Enum.Allows to select which part of the members to use as choice strings, by setting the
choice_sourceparameter to one of:ChoiceSource.KEYorChoiceSource.NAMEto use the key (thenameproperty),ChoiceSource.VALUEto use thevalue,ChoiceSource.STRto use thestr()string representation, orA custom callable that takes an
Enummember and returns a string.
Defaults to
ChoiceSource.STR, which only requires you to define the__str__()method on yourEnumto produce beautiful choice strings.The
transformparameter takes a callable reshaping the string produced by the source. It composes with every source, and is the only way to spell choices in a CLI-friendly case whileshow_aliasesis on: aliases are reachable throughChoiceSource.KEY,ChoiceSource.NAMEandChoiceSource.VALUEalone, which are stuck on raw Python identifiers.Same as
click.Choice, but takes anEnumaschoices.Also defaults to case-insensitive matching.
- choices: tuple[str, ...]¶
The strings available as choice.
Hint
Contrary to the parent
Choiceclass, we store choices directly as strings, not theEnummembers themselves. That way there is no surprises when displaying them to the user.This trick bypass
Enum-specific code path in the Click library. Because, after all, a terminal environment only deals with strings: arguments, parameters, parsing, help messages, environment variables, etc.
- get_choice_string(member)[source]¶
Derive the choice string from the given
Enumâsmember.The string produced by the choice source is passed through
transform.- Return type:
- normalize_choice(choice, ctx)[source]¶
Expand the parentâs
normalize_choice()to acceptEnummembers as input.An
Enummember is mapped to its choice string first; any other value is passed to the parent untouched.- Return type:
- shell_complete(ctx, param, incomplete)[source]¶
Return completion items with choices normalized via
normalize_choice().Overrides the parent to ensure
normalize_choice()is always called on each candidate, fixing Click 8.4.0 whereshell_complete()returned raw (unnormalized) choice strings forChoiceSource.KEY.Note
On Click 8.4.1+ this override is a no-op: the parent already calls
normalize_choice(), and re-normalizing is idempotent (casefold(casefold(s)) == casefold(s)).- Return type:
- class click_extra.ExportConfigOption(param_decls=None, type=None, metavar='FORMAT', is_eager=True, expose_value=False, help='Export the configuration in the selected format to <stdout>, then exit.', **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured option adding
--export-config FORMAT.Resolves the CLIâs current parameter values following Clickâs precedence chain (command line, then environment variables, then configuration file, then defaults), renders them as a configuration file in the requested format on
<stdout>, and exits.Hint
Combine the flag with other options or environment variables to capture them in the generated configuration. For example,
mycli --verbosity DEBUG --export-config toml``emits a configuration whose``verbosityis already set toDEBUG.Like
ValidateConfigOption, it relies on a siblingConfigOptionto provide the parameter structure and theexcluded_params/included_paramsfilter, so the export contains exactly the parameters that can be loaded back from a configuration file.Note
The accepted formats are those
serialize_content()can write (SERIALIZABLE_FORMATS).INI,Argfileandpyproject.tomlhave no serializer and cannot be dumped.- build_config(ctx, config_option)[source]¶
Resolve every config-eligible parameter into a dumpable tree.
Walks the sibling
ConfigOptionâs parameter structure, resolves each parameterâs effective value by replayingRAW_ARGS(falling back to defaults when the command did not capture them), drops theexcluded_params, and layers the coerced values into the{cli-name: {param: value, ...}}shape a configuration file uses. Parameter keys are rendered in their kebab-case spelling, the canonical presentation for configuration files; either spelling loads back to the same parameter.Parameters without a default are kept as
Noneleaves so the export names every key a configuration file can set: serializers render them asnull, except TOML which comments them out (see_serialize_toml_with_unset()). Loadingnullback is harmless:ConfigOption._install_default_map()cleans blank values out of the merged result.
- class click_extra.ExtraOption(*args, group=None, **attrs)[source]¶
Bases:
OptionDedicated to option implemented by
click-extraitself.Provides a way to identify Click Extraâs own options with certainty, and restores the pre-Click-8.4.0 contract that a callback (or a typeâs
convert()) can introspect its own parameter source from within itself.Note
This is the one click-extra class that deliberately keeps the
Extraprefix. The8.0.0cleanup dropped it everywhere else (ExtraCommandbecameCommand,ExtraContextbecameContext, and so on), shadowing the matching Cloup or Click class. Here the plainOptionname is already taken by the user-facing enhanced wrapper this class subclasses, so the prefix is not legacy baggage but a real distinction:ExtraOptionmarks click-extraâs own built-in options. That marker is load-bearing, sinceCommandsorts parameters withisinstance(param, ExtraOption)to push the built-in options to the end.Note
Bracket fields (envvar, default, range, required) cannot be pre-styled in
get_help_record()because Clickâs text wrapper splits lines after the record is returned, which would break ANSI codes that span wrapped boundaries. Styling is instead applied post-wrapping inHelpFormatter._style_bracket_fields(), which uses the structured data fromOption.get_help_extra()to identify each field by its label.Note
Built-in option subclasses share a common shape: their
__init__defaultsparam_declsto the optionâs canonical flags and wires an eager callback viakwargs.setdefault("callback", self.<callback>). Every callback name encodes its role with a verb prefix. The common roles are:set_<key>publishes a resolved value toctx.meta(set_color,set_no_color,set_theme,set_telemetry,set_progress,set_accessible,set_zero_exit, the verbosity optionsâset_level);init_<system>additionally installs actxhelper or records a snapshot (init_timer,init_formatter,init_columns,init_sort);validate_<thing>coerces and validates the raw input (validate_jobs,validate_config);print_*renders output and exits (print_man,print_params,print_and_exit).
A few options own a richer operation and name it with its own verb rather than forcing one of the above.
ConfigOptionwiresload_confto read, parse, and merge a configuration file, andNoConfigOptionwirescheck_sibling_config_optionto assert that a sibling--configoption exists.- handle_parse_result(ctx, opts, args)[source]¶
Record the parameter source before delegating to the base implementation.
Warning
Click
8.4.0(PR pallets/click#3404) reorderedParameter.handle_parse_resultsoctx.set_parameter_sourceruns afterprocess_value. Callbacks that introspect their own provenance viactx.get_parameter_source(self.name)therefore readNoneinstead of the actual source.ColorOption,ConfigOption, andShowParamsOptionrely on this introspection (from their eager callback) to decide whether an env var should override the default (--color), whether the--configpath was user-supplied, and what to render in theSourcecolumn of--params.JobsOptionrelies on the same introspection from its typeâs non-eagerconvert()(JobCount), to decide whether anauto/maxcollapsing to a single job logs as a warning (explicit request) or at info level (the optionâs own default).Click
8.4.1restored the pre-8.4.0contract upstream (PR pallets/click#3484), so this override only matters for Click8.4.0itself, which sits inside click-extraâs supported>= 8.3.1range. Pre-recording the source here, for every option regardless of eagerness, keeps that contract on every supported Click.super().handle_parse_resultre-records the same value at the canonical time, so the slot arbitration logic introduced by #3404 is unaffected:slot_emptyis computed fromctx.params, not from_parameter_source.consume_valueruns twice as a side effect: once here and once insuper. Both calls are pure for click-extraâs existing options (no env var side effects, no prompt):consume_valueonly resolves the raw value and its source, it never invokes the parameterâstype.convert(), so this pre-record cannot itself trigger a callbackâs or a typeâs logging or validation twice. Should a future subclass need prompt behavior, this override would need to cache the result instead.The pre-record is skipped when the slot already carries a source from an earlier option sharing the same
name(Clickâs feature-switch pattern), so the arbitration logic insuperstill sees the originalexisting_sourcerather than a stale rewrite from this option.
- class click_extra.File(mode='r', encoding=None, errors='strict', lazy=None, atomic=False)[source]¶
-
Declares a parameter to be a file for reading or writing. The file is automatically closed once the context tears down (after the command finished working).
Files can be opened for reading or writing. The special value
-indicates stdin or stdout depending on the mode.By default, the file is opened for reading text data, but it can also be opened in binary mode or for writing. The encoding parameter can be used to force a specific encoding.
The
lazyflag controls if the file should be opened immediately or upon first IO. The default is to be non-lazy for standard input and output streams as well as files opened for reading,lazyotherwise. When opening a file lazily for reading, it is still opened temporarily for validation, but will not be held open until first IO. lazy is mainly useful when opening for writing to avoid creating the file until it is needed.Files can also be opened atomically in which case all writes go into a separate file in the same folder and upon completion the file will be moved over to the original location. This is useful if a file regularly read by other users is modified.
See File Arguments for more information.
Changed in version 2.0: Added the
atomicparameter.- envvar_list_splitter: ClassVar[str] = ':'¶
if a list of this type is expected and the value is pulled from a string environment variable, this is what splits it up.
Nonemeans any whitespace. For all parameters the general rule is that whitespace splits them up. The exception are paths and files which are split byos.path.pathsepby default (â:â on Unix and â;â on Windows).
- to_info_dict()[source]¶
Gather information that could be useful for a tool generating user-facing documentation.
Use
click.Context.to_info_dict()to traverse the entire CLI structure.Added in version 8.0.
- Return type:
FileInfoDict
- convert(value, param, ctx)[source]¶
Convert the value to the correct type. This is not called if the value is
None(the missing value).This must accept string values from the command line, as well as values that are already the correct type. It may also convert other compatible types.
The
paramandctxarguments may beNonein certain situations, such as when converting prompt input.If the value cannot be converted, call
fail()with a descriptive message.- Parameters:
value (str | os.PathLike[str] | t.IO[t.Any]) â The value to convert.
param (Parameter | None) â The parameter that is using this type to convert its value. May be
None.ctx (Context | None) â The current context that arrived at this value. May be
None.
- Return type:
t.IO[t.Any]
- shell_complete(ctx, param, incomplete)[source]¶
Return a special completion marker that tells the completion system to use the shell to provide file path completions.
- Parameters:
ctx (Context) â Invocation context for this command.
param (Parameter) â The parameter that is requesting completion.
incomplete (str) â Value being completed. May be empty.
Added in version 8.0.
- Return type:
list[CompletionItem]
- exception click_extra.FileError(filename, hint=None)[source]¶
Bases:
ClickExceptionRaised if a file cannot be opened.
- class click_extra.FloatRange(min=None, max=None, min_open=False, max_open=False, clamp=False)[source]¶
Bases:
_NumberRangeBase[float,float],FloatParamTypeRestrict a
click.FLOATvalue to a range of accepted values. See Int and Float Ranges.If
minormaxare not passed, any value is accepted in that direction. Ifmin_openormax_openare enabled, the corresponding boundary is not included in the range.If
clampis enabled, a value outside the range is clamped to the boundary instead of failing. This is not supported if either boundary is markedopen.Changed in version 8.0: Added the
min_openandmax_openparameters.
- class click_extra.Formatter(fmt=None, datefmt=None, style='%', validate=True, *, defaults=None)[source]¶
Bases:
FormatterClick Extraâs default log formatter.
Initialize the formatter with specified format strings.
Initialize the formatter either with the specified format string, or a default as described above. Allow for specialized date formatting with the optional datefmt argument. If datefmt is omitted, you get an ISO8601-like (or RFC 3339-like) format.
Use a style parameter of â%â, â{â or â$â to specify that you want to use one of %-formatting,
str.format()({}) formatting orstring.Templateformatting in your format string.Changed in version 3.2: Added the
styleparameter.- formatMessage(record)[source]¶
Colorize the recordâs log level name before calling the standard formatter.
Colors are sourced from a
click_extra.theme.HelpTheme, resolved per-invocation viaclick_extra.theme.get_current_theme().A record carrying a
labelattribute (each linerun_cli()streams from a subprocess is tagged with its caller-provided label) renders it glued to the level name, styled like an invoked command:debug:mas: Warning: .... The tag stays out of the message text itself, so a foreign formatter is free to renderrecord.labelits own way.The recordâs
levelnameis restored afterwards: a record may be formatted more than once (several handlers, a captured then re-rendered record), and must not accumulate styling or glued labels.- Return type:
- class click_extra.Group(*args, help_command=True, sort_subcommands=None, subcommand_priorities=None, **kwargs)[source]¶
Bases:
Command,GroupLike
cloup.Group, with sane defaults and extra help screen colorization.Like
Command.__init__, but auto-injects ahelpsubcommand.- Parameters:
help_command (
bool) â whenTrue(the default), ahelpsubcommand is automatically registered. Set toFalseto suppress it, or register your ownhelpsubcommand to override it.sort_subcommands (
bool|None) â how subcommands sharing a priority are broken apart.Truelists them alphabetically,Falsein the order they were registered.None(the default) defers to thesort_subcommandscontext setting, then toTrue. Seemust_sort_subcommands().subcommand_priorities (
Mapping[str,float] |None) â maps a subcommand name to its priority relative toDEFAULT_PRIORITY, lowest listed first. Names left out keep the default priority, so numbering a few subcommands moves only those.
- must_sort_subcommands(ctx)[source]¶
Resolve whether subcommand listings are alphabetical.
Reads the groupâs own
sort_subcommands, then the context setting of the same name, then falls back toTrue. This is the resolution order Cloup uses foralign_sections, and it is what lets a singlecontext_settings={"sort_subcommands": False}on the root group reach every subgroup below it instead of being repeated on each.- Return type:
- subcommand_priority(name)[source]¶
Priority of the name subcommand.
Defaults to
DEFAULT_PRIORITY.- Return type:
- list_commands(ctx)[source]¶
Subcommand names in presentation order.
Sorted on
subcommand_prioritiesfirst, then broken apart bymust_sort_subcommands(): alphabetically, or by registration order. With no priority declared every subcommand ties, leaving the tie-break as the only ordering, which is Clickâs plain alphabetical listing.In registration order the auto-injected
helpsubcommand is listed last, wherever it happens to have been registered:Group.__init__appends it before any@cli.command()decorator runs, while acommands=[âŠ]constructor argument lands it after, so its natural position says nothing about the authorâs intent. Mirrors whatextra_option_at_enddoes to options.
- list_sections(ctx, include_default_section=True)[source]¶
Like
cloup.Group.list_sections, but ordering the default section.Cloup hard-codes the default section to
Section.sorted(âŠ), which is why overridinglist_commands()alone leaves the help screen alphabetical: the screen is rendered from sections and never calls it. Rebuild that section fromlist_commands()instead, and hand it over already ordered.Note
Sections the author declared themselves are returned untouched. Cloupâs own
Section(is_sorted=âŠ)already governs those, and a user holding aSectioninstance should not have it rewritten underneath them. Priorities andsort_subcommandstherefore address the default section and the flat listings (--tree, man pages, completion specs), not the contents of an explicit section.
- add_command(cmd, name=None, **kwargs)[source]¶
Like
cloup.Group.add_command, but replaces an auto-injectedHelpCommandwhen the user registers their ownhelpsubcommand.- Return type:
- invoke(ctx)[source]¶
Inject
_default_subcommandsand_prepend_subcommandsfrom config.If the user has not provided any subcommands explicitly, and the loaded configuration contains a
_default_subcommandslist for this group, those subcommands are injected intoctx.protected_argsso that Clickâs normalGroup.invoke()dispatches them._prepend_subcommandsalways prepends subcommands to the invocation, regardless of whether CLI subcommands were provided. Only works withchain=Truegroups.- Return type:
- class click_extra.HelpCommand(name, context_settings=None, callback=None, params=None, help=None, epilog=None, short_help=None, options_metavar='[OPTIONS]', add_help_option=True, no_args_is_help=False, hidden=False, deprecated=False)[source]¶
Bases:
ColorizedCommandSynthetic subcommand that displays help for the parent group or a subcommand.
Auto-injected into every
Group. Supports nested resolution:mycli help subgroup subcmdshows the help forsubcmdwithinsubgroup.
- class click_extra.HelpFormatOption(param_decls=None, expose_value=False, is_eager=True, help='Render the command in the given format and exit.', **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured
--help-formatoption printing the command in one of theHELP_FORMATSand exiting.Eager and value-taking, unlike its
--manneighbour, which is the same renderer reached through a bare flag:--manis exactly--help-format roff, kept because a runtime manual flag has its own tradition (seeManOption).Note
One option carrying a format, rather than one flag per format. A CLIâs option list is the most expensive real estate in its help screen, and every reader pays for it whether or not they will ever export anything: a family of
--help-json,--help-markdownand--help-carapaceflags would widen the label column of every screen, forever, one line per format anyone ever adds. Here a new format costs an entry inHELP_FORMATSand nothing on screen.Note
The rendered output is deliberately colorless whatever
--colorsays. Every format here is meant to be piped into something (a file, a parser, a model), and ANSI escapes in a JSON string or a Markdown fence are noise to all of them.--helpremains the colorized human view.
- class click_extra.HelpFormatter(*args, **kwargs)[source]¶
Bases:
HelpFormatterExtends Cloupâs custom HelpFormatter to highlights options, choices, metavars and default values.
This is being discussed for upstream integration at:
Forces theme to the active one for the current Click context.
Also transform Cloupâs standard
HelpThemeto our ownHelpTheme.Resolves the active theme via
click_extra.theme.get_current_theme(), which reads the per-invocation pick from the Click context (set byThemeOption) and falls back to the module-level default when no context is active.- keywords: HelpKeywords¶
Keywords to highlight, collected from the rendered commandâs context.
Instance state, initialized per formatter:
_HelpColorsMixin.format_helpfills it before rendering, andhighlight_extra_keywords()mutates it (see theexcluded_keywordssubtraction), so a shared class-level default would leak keywords across formatters.
- excluded_keywords: HelpKeywords | None¶
Keywords subtracted from the cross-reference passes, or
None.
- write_usage(prog, args='', prefix=None)[source]¶
ANSI-aware override of
cloup.HelpFormatter.write_usage.On Click
8.3.x,click.formatting.wrap_textmeasures line length with rawlen(), counting every byte of the ANSI escape sequences embedded ininitial_indent(the styledUsage:heading + invoked-command name). With 24-bit RGB themes (like Solarized Dark, Dracula, Nord, Monokai), each styled token carries 17+ extra bytes of escape, which inflates the measured line beyond the width budget and causes premature wraps mid-token:[OPTIONS\n ].Cloup styles
prefixandprogthen delegates to clickâsHelpFormatter.write_usage(), inheriting the bug. This override re-applies the same styling, then bypasseswrap_textwhenever the visible content fits on a single line: the common case for short usage strings where wrapping is unnecessary. Lines that genuinely overflow the visible width fall back to clickâs implementation: the wrap point may still be sub-optimal but the output stays syntactically valid.Note
Click
8.4.0(PR pallets/click#3420) madeclick.formatting.TextWrapperANSI-aware by counting visible width instead of raw bytes, so this override is a no-op fast path on Click>= 8.4.0and only fixes wrapping on the Click8.3.xreleases click-extra still supports.Todo
Drop this override once the minimum supported Click rises to
8.4.0(which includespallets/click#3420). Theterm_len-based visible-width check below becomes redundant once Clickâs own wrapper counts visible width.- Return type:
- highlight_extra_keywords(help_text)[source]¶
Highlight extra keywords in help screens based on the theme.
Uses the
highlight()function for all keyword categories. Each category is processed as a batch of regex patterns with a single styling function, which handles overlapping matches and prevents double-styling.- Return type:
- class click_extra.HelpKeywords(cli_names=<factory>, subcommands=<factory>, command_aliases=<factory>, arguments=<factory>, long_options=<factory>, short_options=<factory>, choices=<factory>, choice_metavars=<factory>, metavars=<factory>, envvars=<factory>, defaults=<factory>)[source]¶
Bases:
objectStructured collection of keywords extracted from a Click context for help screen highlighting.
Each field corresponds to a semantic category with its own styling.
- class click_extra.HelpSection(heading, definitions, help=None, constraint=None)[source]¶
Bases:
objectA container for a help section data.
- class click_extra.HelpTheme(invoked_command=<function identity>, command_help=<function identity>, heading=<function identity>, constraint=<function identity>, section_help=<function identity>, col1=<function identity>, col2=<function identity>, alias=<function identity>, alias_secondary=None, epilog=<function identity>, critical=<function identity>, error=<function identity>, warning=<function identity>, info=<function identity>, debug=<function identity>, option=<function identity>, subcommand=<function identity>, choice=<function identity>, metavar=<function identity>, bracket=<function identity>, envvar=<function identity>, default=<function identity>, range_label=<function identity>, required=<function identity>, argument=<function identity>, deprecated=<function identity>, search=<function identity>, success=<function identity>, cross_ref_highlight=True, subheading=<function identity>)[source]¶
Bases:
HelpThemeExtends
cloup.HelpThemewith slots for log levels and the structural elements Click Extra highlights in help screens.Each slot below documents what it colors. The built-in themes shipped in
BUILTIN_THEMESprovide the visual styling by setting the relevant slots; user-defined themes can be authored as plain mappings and loaded viafrom_dict().- critical()¶
Style applied to the
CRITICALlevel name in log records.Example:
CRITICAL: Database connection lost.- Return type:
TypeVar(T)
- error()¶
Style applied to the
ERRORlevel name in log records.Example:
ERROR: Configuration file not found.- Return type:
TypeVar(T)
- warning()¶
Style applied to the
WARNINGlevel name in log records.Example:
WARNING: Requested 16 jobs exceeds the 8 logical CPUs: honored, but pays only for I/O-bound work.- Return type:
TypeVar(T)
- info()¶
Style applied to the
INFOlevel name in log records.Usually left at
identity:INFOis the default verbosity and shouldnât stand out from regular output.- Return type:
TypeVar(T)
- debug()¶
Style applied to the
DEBUGlevel name in log records.Example:
DEBUG: Resolved /etc/myapp/config.toml.- Return type:
TypeVar(T)
- option()¶
Style applied to option names (
--config,-v,--color/--no-color) wherever they appear: synopsis column, free-form descriptions, and docstrings (whencross_ref_highlightis enabled).- Return type:
TypeVar(T)
- subcommand()¶
Style applied to subcommand names: in a groupâs command list and wherever they are referenced in prose.
- Return type:
TypeVar(T)
- choice()¶
Style applied to each individual value inside a
click.Choicemetavar (likejson,csv,xmlwithin[json|csv|xml]) and to those values referenced in option descriptions.- Return type:
TypeVar(T)
- metavar()¶
Style applied to type metavars (
INTEGER,TEXT,PATH,FILE, âŠ) that follow an option name in the synopsis column.- Return type:
TypeVar(T)
- bracket()¶
Style applied to the literal bracket characters and label prefixes of trailing fields:
[,],default:,env var:, and the field separators between them. Also acts as the fallback for the four inner bracket-field slots (envvar,default,required,range_label) whenever any of them is left atidentity. A theme that only setsbrackettherefore renders the whole bracket field with a single uniform style; richer themes layer specific colors on top by setting the inner slots.- Return type:
TypeVar(T)
- envvar()¶
Style applied to environment-variable values inside
[env var: ...]bracket fields, and to envvar names mentioned in option descriptions. Falls back tobracketwhen left atidentity, so a theme that only stylesbracketstill gets a consistent rendering inside bracket fields.- Return type:
TypeVar(T)
- default()¶
Style applied to the default-value content inside
[default: ...]bracket fields. Falls back tobracketwhen left atidentity.- Return type:
TypeVar(T)
- range_label()¶
Style applied to range expressions (
0<=x<=9,x>=1024,0<=x<100) that appear inside bracket fields forIntRangeandFloatRangeoptions. Falls back tobracketwhen left atidentity.- Return type:
TypeVar(T)
- required()¶
Style applied to the
requiredlabel inside bracket fields on mandatory options. Falls back tobracketwhen left atidentity.- Return type:
TypeVar(T)
- argument()¶
Style applied to argument metavars (positional parameter names like
MY_ARG,SCRIPT,[FILENAMES]...) in the synopsis column and when referenced in prose.- Return type:
TypeVar(T)
- deprecated()¶
Style applied to
(DEPRECATED)/(Deprecated: reason)markers appended to options and commands.- Return type:
TypeVar(T)
- search()¶
Style applied to substring matches in <cli> help --search output, so users can spot where their query matched.
- Return type:
TypeVar(T)
- success()¶
Style applied to success glyphs in pre-rendered UI elements (the
âinOK_GLYPH) and any text passed through this slot by downstream code.- Return type:
TypeVar(T)
- cross_ref_highlight: bool = True¶
Highlight options, choices, arguments, metavars and CLI names in free-form text (descriptions, docstrings).
When
False, only structural elements are styled: bracket fields ([default: ...],[env var: ...], ranges,[required]), deprecated messages, and subcommand names in definition lists.
- subheading()¶
Style for sub-section headings inside log output or inline help.
Distinct from
heading(which styles the top-level help-screen section titles):subheadingis intended for downstream code that wants a second styling level for its own narrative output.See also
Used by mail-deduplicate to style
⌠N mails sharing hash âŠlog lines.- Return type:
TypeVar(T)
- with_(**kwargs)[source]¶
Derives a new theme from the current one, with some styles overridden.
Returns the same instance if the provided styles are the same as the current.
- Return type:
- to_dict()[source]¶
Serialize the theme to a plain dict suitable for TOML/JSON/YAML.
Each
Styleslot is emitted viaStyle.to_dict. Slots left at their default (identityorNone) are omitted, so the output only carries what the theme actually overrides. Pair withfrom_dict()to round-trip.
- classmethod from_dict(data)[source]¶
Build a theme from the plain dict produced by
to_dict().Each value is interpreted by field type: a mapping becomes a
StyleviaStyle.from_dict, whilecross_ref_highlightis read as a plainbool. Unknown keys raiseTypeErrorso typos surface immediately.- Return type:
- cascade(base)[source]¶
Layer this themeâs set slots on top of base.
Mirrors
Style.cascadeat the slot level: this themeâs non-default slots win, base fills the rest. Useful for layering a sparse override (typically parsed from a config fileâs[tool.<cli>.themes.<name>]table) on top of a full built-in palette.
- class click_extra.IntRange(min=None, max=None, min_open=False, max_open=False, clamp=False)[source]¶
Bases:
_NumberRangeBase[int,int],IntParamTypeRestrict an
click.INTvalue to a range of accepted values. See Int and Float Ranges.If
minormaxare not passed, any value is accepted in that direction. Ifmin_openormax_openare enabled, the corresponding boundary is not included in the range.If
clampis enabled, a value outside the range is clamped to the boundary instead of failing.Changed in version 8.0: Added the
min_openandmax_openparameters.
- class click_extra.JobsOption(param_decls=None, default='auto', expose_value=False, show_default=True, type=<click_extra.execution.JobCount object>, help="Number of parallel jobs. Accepts an integer, 'auto' (the host's logical CPUs minus one) or 'max' (all logical CPUs). 0 runs sequentially.", **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured
--jobsoption to control parallel execution.Accepts an integer or one of two keywords resolved by
JobCount:auto(the default: one fewer than the available logical CPU cores, leaving a core free for the main process and system tasks, except on hosts with fewer than three logical CPUs, where reserving one would leave a single worker) andmax(every available logical CPU core). A value of0disables parallelism and runs sequentially.The core count is the number of logical CPUs (hardware threads) available to the process, not physical cores: see
CPU_COUNT. On a host with a single logical CPU,auto/maxresolve to a single job andJobCountlogs that execution will be sequential: as a warning when the keyword was requested explicitly, at info level when it came from the optionâs own default.The resolved value is stored as an
intinctx.meta[click_extra.context.JOBS].Warning
JobsOptiononly resolves and publishes the job count: it does not drive any concurrency by itself. Pass it torun_jobs()(which reads the resolvedctx.meta[click_extra.context.JOBS]count), or read that value yourself and act on it.- validate_jobs(ctx, param, value)[source]¶
Validate the resolved job count and store it in context metadata.
JobCounthas already resolved anyauto/maxkeyword to an integer by the time this runs. A value of0disables parallelism: it is rounded up to1(sequential execution) with a warning. Negative values are likewise clamped to1. A count above the available cores is honored: the pool is aThreadPoolExecutor, and oversubscription is how I/O- and subprocess-bound work overlaps, so the warning only flags the CPU-bound case where extra threads just contend for the GIL. The resolved count is then logged at info level next to the hostâs logical CPU count (CPU_COUNT), so a CLIâs parallelism is visible under--verbosity INFO.- Return type:
- class click_extra.LazyGroup(*args, lazy_subcommands=None, **kwargs)[source]¶
Bases:
GroupA
Groupthat supports lazy loading of subcommands.Hint
This implementation is based on the snippet from Clickâs documentation: Defining the lazy group.
It has been extended to work with Click Extraâs
config_optionin click_extra#1332 issue.lazy_subcommandsmaps command names to their import paths.Tip
lazy_subcommandsis a map of the form:{"<command-name>": "<module-name>.<command-object-name>"}
For example:
{"mycmd": "my_cli.commands.mycmd"}
A subcommand needing registration settings on top of its import path is declared with a
LazySubcommandinstead of a bare string:{"mycmd": LazySubcommand("my_cli.commands.mycmd", section=my_section)}
Every section declared that way is registered on the group here, so the help screen orders its sections as the author declared them. Waiting for each subcommand to be imported would instead order them by import, which is alphabetical and says nothing about intent.
- lazy_subcommands: dict[str, LazySubcommand]¶
- class click_extra.LazySubcommand(import_path, section=None, fallback_to_default_section=True)[source]¶
Bases:
objectDeclaration of a lazily-imported subcommand of a
LazyGroup.Carries the registration settings
cloup.Group.add_command()accepts, which a bare import path cannot express. A subcommand needing none of them is declared as a plain string instead.- section: Section | None = None¶
Help-screen section the subcommand is filed under, once imported.
A section declared here is registered on the group right away, so the help screen orders its sections as they are declared, not as their subcommands happen to be imported. The same
Sectioninstance can be shared with eagerly-registered subcommands.
- fallback_to_default_section: bool = True¶
Whether to file the subcommand under the default section when
sectionisNone.Set to
Falseto leave the subcommand out of every section, which hides it from the help screen while keeping it invocable. Cloup calls this an escape hatch for internal code: do not disable it unless you know what you are doing.
- class click_extra.ManOption(param_decls=None, is_flag=True, expose_value=False, is_eager=True, help="Read the command's manual page and exit.", **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured
--manflag that typesets the commandâs manual, pages it, and exits.Eager and value-less, like
ShowParamsOption. Part of the default option set injected bydefault_params(), so every@commandand@groupexposes it. Use@man_optionto add it to a plain Click CLI.Note
The flag is named
--man, not--show-manor--man-page.In the POSIX, GNU and BSD traditions a program does not emit its own man page through a flag: the page is a separate file read with
man <prog>, either hand-written (BSDmdoc) or generated at build time from--helpoutput (GNUhelp2man). Click Extra already covers that build-time path withwrite_manpages(), itshelp2manequivalent.The one ecosystem that exposes a runtime flag is Perlâs
Pod::Usage, whose convention is--helpfor the brief usage and bare--manfor the full manual.--manalso lines up with the neighbouring--helpand--versioninformational flags, which use bare nouns with noshow-prefix.--show-manand--man-pagehave no precedent outside Click Extra.Note
That Perl convention is about reading a manual, and this flag used to print roff source instead, which nobody reads: it was a build artifact wearing a readerâs name. It now typesets the page and sends it to the pager, the way
manitself does, so the flag does what its tradition says.The source did not go away, it moved to where a build step looks for it:
--help-format man, beside every other artifact this module renders. The two are one question apart. Do you want to read the manual, or to ship it?
- exception click_extra.MissingParameter(message=None, ctx=None, param=None, param_hint=None, param_type=None)[source]¶
Bases:
BadParameterRaised if click required an option or argument but it was not provided when invoking the script.
Added in version 4.0.
- Parameters:
param_type (str | None) â a string that indicates the type of the parameter. The default is to inherit the parameter type from the given
param. Valid values are'parameter','option'or'argument'.
- class click_extra.MultiChoice(choices=(), separator=',', case_sensitive=True)[source]¶
Bases:
ParamTypeComma-separated multi-pick from a fixed set of values.
The pick-many counterpart to
click.Choice. Accepts a single token containing several values joined by a configurableseparator(defaults to,), parses it into atuple[str, ...]and validates each value againstchoiceswhen that set is non-empty.The rendered metavar is
[a,b,c](separator-joined, parallel toChoiceâs[a|b|c]):click_extra.highlight._HelpColorsMixinauto-detects the separator and highlights each individual value the same way it does forChoice.Note
Click does not ship a built-in equivalent. The closest idiomatic approach is
click.Choice([...]) + multiple=True, which requires the flag to be repeated (--tag a --tag b --tag c) rather than comma-separated. The lack of a single-token, separator-based variant upstream has been raised in:pallets/click#2771 (open): request for
nargs=-1with a non-whitespace separator, covering exactly this use case.pallets/click#2537 (closed as not planned): earlier request for space-separated multi values via
nargs=-1on options.
Maintainers have leaned on the orthogonality argument:
multiple=Truealready exists, separator conventions vary across communities (,vs.:vs.;), and escaping breaks down when a value contains the chosen separator.MultiChoiceships the convention anyway because SQL-styleSELECT a, b, csyntax reads more naturally for the tabular use casesclick-extrasupports (click_extra.table.ColumnsOptionis the headline consumer).Initialize the type.
- Parameters:
choices (
Sequence[str]) â the accepted values. When non-empty,convert()rejects unknown tokens withfail. When empty, the type behaves as a pure separator-aware parser and leaves validation to the consumer.separator (
str) â the token boundary. Use any single character; this also drives the metavar rendering ([a<sep>b<sep>c]).case_sensitive (
bool) â whenFalse, tokens matchchoicescase-insensitively and the returned tuple holds the canonical (original-case) values fromchoices.
- get_metavar(param, ctx=None)[source]¶
Render
[a<sep>b<sep>c]whenchoicesis set,Noneotherwise.Nonefalls back to Clickâs default rendering (the uppercasedname, likeMULTI).
- class click_extra.MulticallGroup(*args, personalities=None, personalities_command=True, **kwargs)[source]¶
Bases:
GroupA
Groupdispatching on its invocation name, BusyBox-style.When the name the binary was invoked under matches a personality, the group steps aside entirely and runs the matching subcommand as a standalone command: the personality carries the groupâs options merged into the subcommandâs, parses them in one flat pass with no positional ordering constraint, and renders its own usage line and help screen. Any other invocation name falls through to regular group behavior.
The invocation name is, in precedence order:
an explicit
prog_namepassed tomain()(whatclick_extra.testing.CliRunneruses to simulate a symlink),else the unresolved basename of
sys.argv[0].
The basename is used unresolved: resolving through
os.path.realpath()would return the symlinkâs target and destroy the personality. A trailingWINDOWS_EXE_SUFFIXis stripped for Windows console-script shims. Clickâs own_detect_program_name()is deliberately not used: it reads__main__.__package__and answerspython -m âŠin the module case. Seeclick_extra.cli_wrapper.invoke_target()for the full trap. A name matching no personality is not an error: it falls through, which is also what keeps the feature inert under test runners, whereargv[0]is the runnerâs own binary.Like
Group.__init__, but with multicall dispatch.- Parameters:
personalities (
Mapping[str,str|Sequence[str]] |None) â maps an invocation name to the tokens it invokes: a bare subcommand name ("chill") or a token sequence (("chill", "--hours", "1")) whose extra tokens are prepended to the userâs arguments. Left toNone, every non-hidden, non-synthetic subcommand is its own personality.personalities_command (
bool) â whenTrue(the default), apersonalitiessubcommand is auto-registered on the group, listing every invocation name the binary answers to. Register your ownpersonalitiessubcommand to override it.
- resolve_invocation_name(prog_name=None)[source]¶
The name this binary was invoked under.
An explicit prog_name wins: it is what makes the feature testable without symlinks on disk. Otherwise the unresolved basename of
sys.argv[0]is used, with a trailing.exestripped on Windows.
- list_personalities()[source]¶
Every personality name mapped to the tokens it invokes.
The explicit
personalitiesmapping when one was declared, else every non-hidden, non-synthetic subcommand mapped to itself.
- main(args=None, prog_name=None, **kwargs)[source]¶
Dispatch on the invocation name before any argument parsing.
A matching personality runs as a standalone command, the groupâs own options merged into it, its extra tokens prepended to the arguments. Anything else delegates to the regular group
main().- Return type:
- build_personality(name, tokens)[source]¶
Synthesize the standalone command the name personality runs as.
The personality is a fresh instance of the subcommandâs own class, re-instantiated over the groupâs parameters merged with the subcommandâs, not a copy whose
paramsattribute is patched after the fact. Two reasons make the re-instantiation mandatory:Cloup computes its help layout (
arguments,option_groups,ungrouped_options) fromparamsinside__init__, so a patched copy parses every merged option but only renders the subcommandâs own on its help screen.Click Extraâs own
Command.__init__does work that must run over the merged set:extra_option_at_endreordering, option priorities, auto envvar population and help-keyword collection.
Every parameter is deep-copied, because
Command.__init__re-runspopulate_auto_envvarsover the merged set under the personalityâs ownauto_envvar_prefix: sharing instances would rewrite the groupâs and subcommandâsenvvarattributes and leak that back into group mode. This is the same class of leaky statedefault_params()warns about.- Return type:
- class click_extra.NoColorOption(param_decls=None, is_flag=True, default=False, is_eager=True, expose_value=False, help='Disable colorization (alias of --color=never).', **kwargs)[source]¶
Bases:
ExtraOption--no-colorflag that forces--color=never.Click rejects
/--no-xsecondary flags on a value option, so the negative alias of the tri-stateColorOptioncannot live on it and is provided here as a standalone boolean flag. When set, it pinsctx.colortoFalse; when absent it is a no-op, leaving the resolution toColorOption.Shown on its own line directly below
--color(mirroring--no-configbelow--config), since every other negative in the default option set is visible too. Eager by default, likeColorOption, so the color state is settled before other eager options render.- set_no_color(ctx, param, value)[source]¶
Force
ctx.coloroff when a negative alias is passed; no-op otherwise.Dormant under resilient parsing, for the same reason as
ColorOption.set_color(): a never-closed introspection context must not publish the process-wide color mirror.- Return type:
- class click_extra.NoConfigOption(param_decls=None, type=UNPROCESSED, help='Ignore all configuration files and only use command line parameters and environment variables.', is_flag=True, flag_value=Sentinel.NO_CONFIG, is_eager=True, expose_value=False, **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured option adding
--no-config.This option is supposed to be used alongside the
--configoption (ConfigOption) to allow users to explicitly disable the use of any configuration file.This is especially useful to debug side-effects caused by autodetection of configuration files.
flag_value=NO_CONFIGis theSentinelenum member that signals âskip configuration loadingâ toConfigOption. Click8.4.0(PR pallets/click#3363) auto-detectstype=UNPROCESSEDfor non-basicflag_valuetypes, but click-extra still supports Click8.3.xwhere that auto-detection is absent, so thetype=UNPROCESSEDoverride is kept explicit to let the sentinel pass throughOptionunchanged on every supported Click.See also
An alternative implementation of this class would be to create a custom click.ParamType instead of a custom
Optionsubclass. Here is for example.
- exception click_extra.NoSuchCommand(command_name, message=None, possibilities=None, ctx=None)[source]¶
Bases:
UsageErrorRaised if Click attempted to handle a command that does not exist.
Added in version 8.4.0.
- exception click_extra.NoSuchOption(option_name, message=None, possibilities=None, ctx=None)[source]¶
Bases:
UsageErrorRaised if Click attempted to handle an option that does not exist.
Added in version 4.0.
- class click_extra.OperationTrail(*, label='', unit='', total=0, jobs=1, spinner=None, progress_bar=False, timer=None, clock='elapsed', enabled=None, echo_sequential=True, delay=0.0, stream=None)[source]¶
Bases:
objectA
â/âprogress trail and finisher for a batch of operations.Where
Spinnernarrates one long-running call,OperationTrailreports a batch of them: each completed operation leaves a persistenttrail_line()on screen, a runningdone/totaltally keeps the batchâs pulse visible, andfinish()closes with a persistent summary line. The natural reporting companion of the concurrency primitivesrun_jobs()andrun_lanes(), rendered one of three ways:sequential (
jobs <= 1): echo each outcome as it lands, with no aggregate indicator (each operation is free to keep its own per-callSpinner).finish()appends the elapsed time.concurrent (
jobs > 1): drive one aggregateSpinner(per-call spinners would collide on the shared stream), buffering outcomes until it first draws, then streaming the rest live above it. Pick the animation from theSPINNERScatalog withspinner=.progress bar (
progress_bar=True): drive one aggregate determinate bar carrying the{done}/:total:` tally, with outcomes streaming above it. Serves sequential and concurrent batches alike, and needs a known `total.
All render only on an interactive stream unless
enabledforces the matter, so pipes, CI logs and captured test buffers stay clean. The runningâtally is kept as outcomes land (ok_count), so a caller computes no counts of its own.Thread-safe:
mark()may be called from worker threads. Use it as a context manager whenever it may run concurrently, to bound the aggregate spinnerâs life; a purely sequential caller may construct it bare.from click_extra.execution import run_jobs from click_extra.spinner import OperationTrail with OperationTrail(label="Fetching", unit="feeds", total=len(feeds), jobs=jobs) as trail: def fetch(feed): trail.mark(*pull(feed)) # pull() returns (ok, message). list(run_jobs(fetch, feeds, jobs=jobs)) trail.finish( trail.ok_count == len(feeds), f"Fetched {trail.ok_count}/{len(feeds)} feeds", )
Configure (but do not start) the trail.
- Parameters:
label (
str) â present-tense verb for the running aggregate indicator ("Fetching"), composed into its{label} {done}/{total} {unit}tally.unit (
str) â the noun counted in the tally ("files","feeds").total (
int) â how many outcomes are expected, for thedone/totalcount.jobs (
int) â the batchâs worker count;> 1selects the concurrent rendering (one aggregate spinner),<= 1the sequential one (plain echoed lines).spinner (
SpinnerPreset|None) â aSpinnerPresetfrom theSPINNERScatalog (spinner=SPINNERS["moon"]) for the concurrent aggregate spinner. Ignored by the sequential and progress-bar renderings, and mutually exclusive withprogress_bar.progress_bar (
bool) â render the aggregate indicator as a determinateclick.progressbar()instead of a spinner, for a sequential or concurrent batch alike. Requires a positivetotal(a bar needs a length) and is mutually exclusive withspinner.timer (
bool|Callable[[float],str] |None) â append each operationâs and the batchâs elapsed time to the trail lines and the finisher.None(the default) follows the CLIâs--time/--no-timeflag;Trueforces timing on withformat_duration()âs compact clock, a callable(seconds: float) -> strforces it on with a custom format, andFalseforces it off. Per-operation times come from asecondsargument tomark(), filled in automatically by anoperation()handle.clock (
Literal['elapsed','eta']) â whether a running aggregate indicator shows elapsed time ("elapsed", the default: a stopwatch counting up, visible from the start) or remaining time ("eta": an estimate from the batchâs rate, appearing only once an outcome lets it be computed). Both the progress bar and the concurrent spinner honor"eta"(the spinner reuses Clickâs progress-bar estimate, since the trail knows itstotal). Per-operation and finisher times are always elapsed.enabled (
bool|None) â force the trail on or off.None(the default) auto-detects: the sequential echo renders only on an interactive stream, and the aggregate indicator applies its own TTY gate.echo_sequential (
bool) â whether a sequential batch echoes its outcome lines and finisher at all. Turn it off when the batch has another output that is the real product (a result table) and the trail would be noise; an aggregate indicator is unaffected.delay (
float) â seconds before the aggregate indicator first draws: a fast batch then completes without ever flashing one.stream (
IO[str] |None) â where to render; defaults tosys.stderrso the trail never mixes intostdoutdata.
- Raises:
ValueError â if
progress_baris set without a positivetotal, or together withspinner, or ifclockis neither"elapsed"nor"eta".
- mark(ok, message, seconds=None)[source]¶
Record one
â/âoutcome: tally it and render its trail line.- Parameters:
seconds (
float|None) â the operationâs own elapsed time. Whentimeris on it is formatted and appended tomessageas(2.3s). Anoperation()handle fills this in from when it was created; pass it yourself when you already hold a duration.- Return type:
- finish(ok, summary)[source]¶
Render the persistent
â/â{summary}finisher.With an aggregate indicator, it becomes the indicatorâs kept line (a spinnerâs
Spinner.ok()/Spinner.fail()line, or the barâs replacement line); sequential without one, a plain echoed line. The batchâs elapsed time since construction is appended whentimeris on (the default).- Return type:
- operation()[source]¶
Start a timed operation, returning a handle to record its outcome.
The handle captures the current time; call
_Operation.mark()when the work finishes to record itsâ/âoutcome with the elapsed time appended (whentimeris on). This is how a batch reports per-operation timings under concurrency, where the trail itself never sees when an operation began:def fetch(feed): op = trail.operation() ok, message = pull(feed) op.mark(ok, message)
- Return type:
_Operation
- class click_extra.Option(*args, group=None, **attrs)[source]¶
Bases:
_ParameterMixin,OptionWrap
cloup.Option, itself inheriting fromclick.Option.Inherits first from
_ParameterMixinto allow future overrides of ClickâsParametermethods.
- class click_extra.OptionGroup(title, help=None, constraint=None, hidden=False)[source]¶
Bases:
objectContains the information of an option group and identifies it. Note that, as far as the clients of this library are concerned, an
OptionGroupsacts as a âmarkerâ for options, not as a container for related options. When you call@optgroup.option(...)you are not adding an option to a container, you are just adding an option marked with this option group.Added in version 0.8.0: The
hiddenparameter.
- class click_extra.OptionGroupMixin(*args, align_option_groups=None, **kwargs)[source]¶
Bases:
objectImplements support for:
option groups
the âPositional argumentsâ help section; this section is shown only if at least one of your arguments has non-empty
help.
Important
In order to check the constraints defined on the option groups, a command must inherits from
cloup.ConstraintMixintoo!Added in version 0.14.0: added the âPositional argumentsâ help section.
Changed in version 0.8.0: this mixin now relies on
cloup.HelpFormatterto align help sections. If aclick.HelpFormatteris used with aTypeErroris raised.Changed in version 0.8.0: removed
format_option_group. Addedget_default_option_groupandmake_option_group_help_section.Added in version 0.5.0.
- Parameters:
align_option_groups (
bool|None) â whether to align the columns of all option groupsâ help sections. This is also available as a context setting having a lower priority than this attribute. Given that this setting should be consistent across all you commands, you should probably use the context setting only.args (
Any) â positional arguments forwarded to the next class in the MROkwargs (
Any) â keyword arguments forwarded to the next class in the MRO
- option_groups¶
List of all option groups, except the âdefault option groupâ.
- ungrouped_options¶
List of options not explicitly assigned to an user-defined option group. These options will be included in the âdefault option groupâ. Note: this list does not include options added automatically by Click based on context settings, like the
--helpoption; use theget_ungrouped_options()method if you need the real full list (which needs aContextobject).
- get_ungrouped_options(ctx)[source]¶
Return options not explicitly assigned to an option group (eventually including the
--helpoption), i.e. options that will be part of the âdefault option groupâ.
- make_option_group_help_section(group, ctx)[source]¶
Return a
HelpSectionfor anOptionGroup, i.e. an object containing the title, the optional description and the optionsâ definitions for this option group.Added in version 0.8.0.
- Return type:
- must_align_option_groups(ctx, default=True)[source]¶
Return
Trueif the help sections of all options groups should have their columns aligned.Added in version 0.8.0.
- Return type:
- class click_extra.ParamStructure[source]¶
Bases:
objectUtilities to introspect CLI options and commands structure.
Structures are represented by a tree-like
dict.Access to a node is available using a serialized path string composed of the keys to descend to that node, separated by a dot
..- excluded_params: frozenset[str]¶
Fully-qualified IDs of the parameters to block from the structure.
Set by subclasses:
ShowParamsOptionfreezes an empty set, whileConfigOptionresolves a dynamic default (or the user-provided list) within the active context. The two filters are mutually exclusive, a constraint each subclass enforces in its own constructor.
- included_params: frozenset[str] | None¶
Allowlist of parameter IDs, mutually exclusive with
excluded_params.Nonedisables the allowlist. It is resolved intoexcluded_paramsbybuild_param_trees(), once every parameter ID is known.
- static init_tree_dict(*path, leaf=None)[source]¶
Utility method to recursively create a nested dict structure whose keys are provided by
pathlist and at the end is populated by a copy ofleaf.- Return type:
- static get_tree_value(tree_dict, *path)[source]¶
Get in the
tree_dictthe value located at thepath.Raises
KeyErrorif no item is found at the providedpath.- Return type:
- walk_params()[source]¶
Generate an unfiltered list of all CLI parameters.
Everything is included, from top-level groups to subcommands, and from options to arguments.
- Yields a 2-element tuple:
a tuple of keys leading to the parameter;
the parameter object itself.
Thin adapter over
walk_command_params(): it resolves the root CLI from the active context and drops the per-parameter context that the free function also yields.
- TYPE_MAP: ClassVar[dict[type[ParamType], type[str | int | float | bool | list]]] = {<class 'click.types.BoolParamType'>: <class 'bool'>, <class 'click.types.Choice'>: <class 'str'>, <class 'click.types.DateTime'>: <class 'str'>, <class 'click.types.File'>: <class 'str'>, <class 'click.types.FloatParamType'>: <class 'float'>, <class 'click.types.FloatRange'>: <class 'float'>, <class 'click.types.IntParamType'>: <class 'int'>, <class 'click.types.IntRange'>: <class 'int'>, <class 'click.types.Path'>: <class 'str'>, <class 'click.types.StringParamType'>: <class 'str'>, <class 'click.types.Tuple'>: <class 'list'>, <class 'click.types.UUIDParameterType'>: <class 'str'>, <class 'click.types.UnprocessedParamType'>: <class 'str'>}¶
Map Click types to their Python equivalent.
Keys are subclasses of
click.types.ParamType. Values are expected to be simple builtins Python types.This mapping can be seen as a reverse of the
click.types.convert_type()method.
- static map_click_type(click_type)[source]¶
Map a Click parameter type instance to its Python equivalent.
Returns
strfor unrecognised custom types, since command-line parameters are strings by default.See the list of custom types provided by Click.
- static get_param_type(param)[source]¶
Get the Python type of a Click parameter.
Returns
strfor unrecognised custom types, since command-line parameters are strings by default.See the list of custom types provided by Click.
- build_param_trees()[source]¶
Build and return the parameters tree structure.
This removes parameters whose fully-qualified IDs are in the
excluded_paramsblocklist.If
included_paramswas provided, it is resolved intoexcluded_paramshere, where all parameter IDs are available.
- class click_extra.ParamType[source]¶
Bases:
Generic[_ValueT_co],ABCRepresents the type of a parameter. Validates and converts values from the command line or Python into the correct type.
To implement a custom type, subclass and implement at least the following:
The
nameclass attribute must be set.Calling an instance of the type with
Nonemust returnNone. This is already implemented by default.convert()must convert string values to the correct type.convert()must accept values that are already the correct type.It must be able to convert a value if the
ctxandparamarguments areNone. This can occur when converting prompt input.
Changed in version 8.4.0: Now a generic abstract base class. Parameterize with the converted value type (
ParamType[int]for an integer-returning type) so thatconvert()and downstream consumers carry the narrowed return type.- envvar_list_splitter: ClassVar[str | None] = None¶
if a list of this type is expected and the value is pulled from a string environment variable, this is what splits it up.
Nonemeans any whitespace. For all parameters the general rule is that whitespace splits them up. The exception are paths and files which are split byos.path.pathsepby default (â:â on Unix and â;â on Windows).
- to_info_dict()[source]¶
Gather information that could be useful for a tool generating user-facing documentation.
Use
click.Context.to_info_dict()to traverse the entire CLI structure.Added in version 8.0.
- Return type:
ParamTypeInfoDict
- get_metavar(param, ctx)[source]¶
Returns the metavar default for this param if it provides one.
- Return type:
str | None
- get_missing_message(param, ctx)[source]¶
Optionally might return extra information about a missing parameter.
Added in version 2.0.
- Return type:
str | None
- convert(value, param, ctx)[source]¶
Convert the value to the correct type. This is not called if the value is
None(the missing value).This must accept string values from the command line, as well as values that are already the correct type. It may also convert other compatible types.
The
paramandctxarguments may beNonein certain situations, such as when converting prompt input.If the value cannot be converted, call
fail()with a descriptive message.- Parameters:
value (t.Any) â The value to convert.
param (Parameter | None) â The parameter that is using this type to convert its value. May be
None.ctx (Context | None) â The current context that arrived at this value. May be
None.
- Return type:
_ValueT_co
- split_envvar_value(rv)[source]¶
Given a value from an environment variable this splits it up into small chunks depending on the defined envvar list splitter.
If the splitter is set to
None, which means that whitespace splits, then leading and trailing whitespace is ignored. Otherwise, leading and trailing splitters usually lead to empty items being included.
- fail(message, param=None, ctx=None)[source]¶
Helper method to fail with an invalid value message.
- Return type:
t.NoReturn
- shell_complete(ctx, param, incomplete)[source]¶
Return a list of
CompletionItemobjects for the incomplete value. Most types do not provide completions, but some do, and this allows custom types to provide custom completions as well.- Parameters:
ctx (Context) â Invocation context for this command.
param (Parameter) â The parameter that is requesting completion.
incomplete (str) â Value being completed. May be empty.
Added in version 8.0.
- Return type:
list[CompletionItem]
- class click_extra.Parameter(param_decls=None, type=None, required=False, default=Sentinel.UNSET, callback=None, nargs=None, multiple=False, metavar=None, expose_value=True, is_eager=False, envvar=None, shell_complete=None, deprecated=False)[source]¶
Bases:
ABCA parameter to a command comes in two versions: they are either
Options orArguments. 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.
- Parameters:
param_decls (cabc.Sequence[str] | None) â the parameter declarations for this option or argument. This is a list of flags or argument names.
type (types.ParamType[t.Any] | t.Any | None) â the type that should be used. Either a
ParamTypeor a Python type. The latter is converted into the former automatically if supported.required (bool) â controls if this is optional or not.
default (t.Any | t.Callable[[], t.Any] | None) â 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.
callback (t.Callable[[Context, Parameter, t.Any], t.Any] | None) â 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.nargs (int | None) â the number of arguments to match. If not
1the return value is a tuple instead of single value. The default for nargs is1(except if the type is a tuple, then itâs the arity of the tuple). Ifnargs=-1, all remaining parameters are collected.metavar (str | None) â how the value is represented in the help page.
expose_value (bool) â if this is
Truethen the value is passed onwards to the command callback and stored on the context, otherwise itâs skipped.is_eager (bool) â eager values are processed before non eager ones. This should not be set for arguments or it will inverse the order of processing.
envvar (str | cabc.Sequence[str] | None) â 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.
shell_complete (t.Callable[[Context, Parameter, str], list[CompletionItem] | list[str]] | None) â A function that returns custom shell completions. Used instead of the paramâs type completion if given. Takes
ctx, param, incompleteand must return a list ofCompletionItemor a list of strings.deprecated (bool | str) â If
Trueor 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.
Changed in version 8.2.0: Introduction of
deprecated.Changed in version 8.2: Adding duplicate parameter names to a
Commandwill result in aUserWarningbeing shown.Changed in version 8.2: Adding duplicate parameter names to a
Commandwill result in aUserWarningbeing shown.Changed in version 8.0:
process_valuevalidates required parameters and boundednargs, and invokes the parameter callback before returning the value. This allows the callback to validate prompts.full_process_valueis removed.Changed in version 8.0:
autocompletionis renamed toshell_completeand 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.Changed in version 8.0: For
multiple=True, nargs>1, the default must be a list of tuples.Changed in version 8.0: Setting a default is no longer required for
nargs>1, it will default toNone.multiple=Trueornargs=-1will default to().Changed in version 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.
Changed in version 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'¶
- type: types.ParamType[t.Any]¶
- to_info_dict()[source]¶
Gather information that could be useful for a tool generating user-facing documentation.
Use
click.Context.to_info_dict()to traverse the entire CLI structure.Changed in version 8.3.0: Returns
Nonefor thedefaultif it was not set.Added in version 8.0.
- property human_readable_name: str¶
Returns the human readable name of this parameter. This is the same as the name for options, but the metavar for arguments.
- get_default(ctx, call=True)[source]¶
Get the default for the parameter. Tries
Context.lookup_default()first, then the local default.- Overloads:
self, ctx (Context), call (t.Literal[True]) â t.Any | None
self, ctx (Context), call (bool) â t.Any | t.Callable[[], t.Any] | None
- Parameters:
Changed in version 8.0.2: Type casting is no longer performed when getting a default.
Changed in version 8.0.1: Type casting can fail in resilient parsing mode. Invalid defaults will not prevent showing help text.
Changed in version 8.0: Looks at
ctx.default_mapfirst.Changed in version 8.0: Added the
callparameter.
- type_cast_value(ctx, value)[source]¶
Convert and validate a value against the parameterâs
type,multiple, andnargs.- Return type:
- get_error_hint(ctx)[source]¶
Get a stringified version of the param for use in error messages to indicate which param caused the error.
Changed in version 8.4.0:
ctxcan beNone.- Return type:
- shell_complete(ctx, incomplete)[source]¶
Return a list of completions for the incomplete value. If a
shell_completefunction was given during init, it is used. Otherwise, thetypeshell_complete()function is used.- Parameters:
ctx (Context) â Invocation context for this command.
incomplete (str) â Value being completed. May be empty.
Added in version 8.0.
- Return type:
list[CompletionItem]
- class click_extra.ParameterSource(*values)[source]¶
Bases:
IntEnumThis is an
IntEnumthat indicates the source of a parameterâs value.Use
click.Context.get_parameter_source()to get the source for a parameter by name.Members are ordered from most explicit to least explicit source. This allows comparison to check if a value was explicitly provided:
source = ctx.get_parameter_source("port") if source < click.ParameterSource.DEFAULT_MAP: ... # value was explicitly set
Changed in version 8.3.3: Use
IntEnumand reorder members from most to least explicit. Supports comparison operators.Changed in version 8.0: Use
Enumand drop thevalidatemethod.Changed in version 8.0: Added the
PROMPTvalue.- PROMPT = 1¶
Used a prompt to confirm a default or provide a value.
- COMMANDLINE = 2¶
The value was provided by the command line args.
- ENVIRONMENT = 3¶
The value was provided with an environment variable.
- DEFAULT_MAP = 4¶
Used a default provided by
Context.default_map.
- DEFAULT = 5¶
Used the default specified by the parameter.
- class click_extra.Path(exists=False, file_okay=True, dir_okay=True, writable=False, readable=True, resolve_path=False, allow_dash=False, path_type=None, executable=False)[source]¶
Bases:
ParamType[str|bytes|PathLike[str]]The
Pathtype is similar to theFiletype, but returns the filename instead of an open file. Various checks can be enabled to validate the type of file and permissions.- Parameters:
exists (
bool) â The file or directory needs to exist for the value to be valid. If this is not set toTrue, and the file does not exist, then all further checks are silently skipped.file_okay (
bool) â Allow a file as a value.dir_okay (
bool) â Allow a directory as a value.readable (
bool) â if true, a readable check is performed.writable (
bool) â if true, a writable check is performed.executable (
bool) â if true, an executable check is performed.resolve_path (
bool) â Make the value absolute and resolve any symlinks. A~is not expanded, as this is supposed to be done by the shell only.allow_dash (
bool) â Allow a single dash as a value, which indicates a standard stream (but does not open it). Useopen_file()to handle opening this value.path_type (
type|None) â Convert the incoming path value to this type. IfNone, keep Pythonâs default, which isstr. Useful to convert topathlib.Path.
Changed in version 8.1: Added the
executableparameter.Changed in version 8.0: Allow passing
path_type=pathlib.Path.Changed in version 6.0: Added the
allow_dashparameter.- envvar_list_splitter: ClassVar[str] = ':'¶
if a list of this type is expected and the value is pulled from a string environment variable, this is what splits it up.
Nonemeans any whitespace. For all parameters the general rule is that whitespace splits them up. The exception are paths and files which are split byos.path.pathsepby default (â:â on Unix and â;â on Windows).
- to_info_dict()[source]¶
Gather information that could be useful for a tool generating user-facing documentation.
Use
click.Context.to_info_dict()to traverse the entire CLI structure.Added in version 8.0.
- Return type:
PathInfoDict
- convert(value, param, ctx)[source]¶
Convert the value to the correct type. This is not called if the value is
None(the missing value).This must accept string values from the command line, as well as values that are already the correct type. It may also convert other compatible types.
The
paramandctxarguments may beNonein certain situations, such as when converting prompt input.If the value cannot be converted, call
fail()with a descriptive message.- Parameters:
value (str | os.PathLike[str]) â The value to convert.
param (Parameter | None) â The parameter that is using this type to convert its value. May be
None.ctx (Context | None) â The current context that arrived at this value. May be
None.
- Return type:
str | bytes | os.PathLike[str]
- shell_complete(ctx, param, incomplete)[source]¶
Return a special completion marker that tells the completion system to use the shell to provide path completions for only directories or any paths.
- Parameters:
ctx (Context) â Invocation context for this command.
param (Parameter) â The parameter that is requesting completion.
incomplete (str) â Value being completed. May be empty.
Added in version 8.0.
- Return type:
list[CompletionItem]
- class click_extra.ProgressOption(param_decls=None, is_flag=True, default=True, is_eager=True, expose_value=False, help='Show progress indicators during long operations. Disabled for non-interactive output (pipes, dumb terminals, CI) and by --accessible.', **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured
--progress/--no-progressflag gating spinner display.Resolves to a single boolean published at
ctx.meta[click_extra.context.PROGRESS], which a CLI reads to decide whether to start aSpinner. The default isTrue;--accessiblelowers it toFalse(viadefault_map) so a screen reader is never handed a spinning glyph.Note
Spinner display is intentionally decoupled from color, even though both emit ANSI. A spinner is an interactivity concern, not a color one: it is built from cursor-control codes (hide-cursor, carriage return, clear-line), which the NO_COLOR standard explicitly does not govern â it âonly signals the userâs intention regarding adding ANSI color to text outputâ. So
--no-color/NO_COLORstrip the spinnerâs colors but never hide it.This matches how the wider ecosystem treats the two axes as orthogonal: cargo, npm, pip, Rich, indicatif and ora all gate progress on the terminal (and a dedicated
--progress/--quietknob), whileNO_COLORonly affects color. Rich usesTERM=dumbâ notNO_COLORâ as the signal to drop cursor-moving features like progress bars.The spinner is therefore silenced by two things only, neither of them color:
non-interactive output â a pipe, file, CI log, or
TERM=dumbterminal that cannot move the cursor (seeSpinner._resolve_enabled);explicit intent â
--no-progressor--accessible.
This option is eager. It no longer reads
ctx.color, so its position relative toColorOptionis not load-bearing.- set_progress(ctx, param, value)[source]¶
Publish whether progress spinners may be shown.
Stores the resolved
--progressflag atPROGRESS. Deliberately independent of color: see theProgressOptionnote for why a spinner is gated on interactivity (TTY /TERM=dumb) and--accessible, never on--no-color/NO_COLOR.- Return type:
- class click_extra.QuietOption(param_decls=None, **kwargs)[source]¶
Bases:
_CounterOption--quiet/-qoption to lower the log level of_VerbosityOptionby one step per repetition.The symmetric counterpart of
VerboseOption: where-vraises the verbosity oneLogLevelstep at a time,-qlowers it. Starting fromVerbosityOption.default(WARNINGby default):-qlowers the level toERROR,-qqlowers the level toCRITICAL,any further repetition is clamped at the quietest level, so
-qqqqqfor example resolves toCRITICAL.
-qshares a single signed counter withVerboseOptionâs-v, so the two cancel out:-v -qleaves the level unchanged. See_VerbosityOption.resolve_levelfor the full reconciliation rule with--verbosity.Set up a verbosity-altering option.
- Parameters:
default_logger â If a
logging.Loggerobject is provided, thatâs the instance to which we will set the level to. If the parameter is a string and is found in the global registry, we will use it as the loggerâs ID. Otherwise, we will create a new logger withnew_logger()Default to the globalrootlogger.
- class click_extra.Result(runner, stdout_bytes, stderr_bytes, output_bytes, return_value, exit_code, exception, exc_info=None)[source]¶
Bases:
ResultA
Resultsubclass with automatic traceback formatting.Enhances
__repr__so that pytest assertion failures show the full traceback instead of just the exception type.
- class click_extra.SchemaFieldInfo(key: str, type_hint: str, default: Any, summary: str, description: str)[source]¶
Bases:
NamedTupleDocumentation record for one option of a configuration schema.
Produced by
schema_field_infos(). Consumed by theclick:configSphinx directive, and by CLIs building their own configuration reference (ashow-configtable, say) from the same introspection.Create new instance of SchemaFieldInfo(key, type_hint, default, summary, description)
- key: str¶
Dotted configuration path of the option.
Field names are kebab-cased (
setup_guideâsetup-guide) unless the field pins an explicit path throughclick_extra.config.schema.CONFIG_PATH_METADATA_KEY. Nested dataclass fields contribute one segment per nesting level (test-suite.timeout).
- summary: str¶
First paragraph of the fieldâs attribute docstring, collapsed onto a single line. Empty when the field has no docstring or the class source is unavailable (see
field_docstrings()).
- class click_extra.Section(title, commands=(), is_sorted=False)[source]¶
Bases:
objectA group of (sub)commands to show in the same help section of a
MultiCommand. You can use sections with anyCommandthat inherits fromSectionMixin.Changed in version 0.6.0: removed the deprecated old name
GroupSection.Changed in version 0.5.0: introduced the new name
Sectionand deprecated the oldGroupSection.- Parameters:
- commands: OrderedDict[str, Command]¶
- class click_extra.SectionMixin(*args, commands=None, sections=(), align_sections=None, **kwargs)[source]¶
Bases:
objectAdds to a
click.MultiCommandthe possibility of organizing its subcommands into multiple help sections.Sections can be specified in the following ways:
passing a list of
Sectionobjects to the constructor setting the argumentsectionsusing
add_section()to add a single sectionusing
add_command()with the argumentsectionset
Commands not assigned to any user-defined section are added to the âdefault sectionâ, whose title is âCommandsâ or âOther commandsâ depending on whether it is the only section or not. The default section is the last shown section in the help and its commands are listed in lexicographic order.
Changed in version 0.8.0: this mixin now relies on
cloup.HelpFormatterto align help sections. If aclick.HelpFormatteris used with aTypeErroris raised.Changed in version 0.8.0: removed
format_section. Addedmake_commands_help_section.Added in version 0.5.0.
- Parameters:
align_sections (
bool|None) â whether to align the columns of all subcommandsâ help sections. This is also available as a context setting having a lower priority than this attribute. Given that this setting should be consistent across all you commands, you should probably use the context setting only.args (
Any) â positional arguments forwarded to the next class in the MROkwargs (
Any) â keyword arguments forwarded to the next class in the MRO
- add_section(section)[source]¶
Add a
Sectionto this group. You can add the same section object only a single time.- Return type:
- See Also:
- section(title, *commands, **attrs)[source]¶
Create a new
Section, adds it to this group and returns it.- Return type:
- add_command(cmd, name=None, section=None, fallback_to_default_section=True)[source]¶
Add a subcommand to this
Group.Implementation note:
fallback_to_default_sectionlooks not very clean but, even if itâs not immediate to see (it wasnât for me), I chose it over apparently cleaner options.- Parameters:
cmd (
Command)section (
Section|None) â aSectioninstance. The command must not be in the section already.fallback_to_default_section (
bool) â ifsectionis None and this option is enabled, the command is added to the âdefault sectionâ. If disabled, the command is not added to any section unlesssectionis provided. This is useful for internal code and subclasses. Donât disable it unless you know what you are doing.
- Return type:
- list_sections(ctx, include_default_section=True)[source]¶
Return the list of all sections in the âcorrect orderâ.
If
include_default_section=Trueand the default section is non-empty, it will be included at the end of the list.
- format_subcommand_name(ctx, name, cmd)[source]¶
Used to format the name of the subcommands. This method is useful when you combine this extension with other click extensions that override
format_commands(). Most of these, like click-default-group, just add something to the name of the subcommands, which is exactly what this method allows you to do without overriding bigger methods.- Return type:
- class click_extra.ShowParamsOption(param_decls=None, is_flag=True, expose_value=False, is_eager=True, help='Show all CLI parameters, their provenance, defaults and value, then exit.', **kwargs)[source]¶
Bases:
ExtraOption,ParamStructureA pre-configured option adding a
--paramsoption.Between configuration files, default values and environment variables, it might be hard to guess under which set of parameters the CLI will be executed. This option print information about the parameters that will be fed to the CLI.
Note
The flag is named
--params, not--show-params. It names the view it prints, matching the neighbouring bare-noun informational flags (--help,--version,--man,--tree), none of which carry ashow-verb prefix. The class and@show_params_optiondecorator keep their historical names: the class is named for what it does (show the parameters), while the flag and the parameterâs ID use the bare noun.- TABLE_HEADERS: ClassVar[tuple[_ColumnSpec, ...]] = (ColumnSpec(id='id', label='ID', description='Fully-qualified parameter path (`cli.subcommand.param_name`) derived from the [`click.Command`](https://click.palletsprojects.com/en/stable/api/#click.Command) tree. Doubles as the key used to address the parameter from a configuration file, which also accepts the kebab-case spelling of the last segment.', max_width=None, optional=False), ColumnSpec(id='spec', label='Spec.', description='Option/argument specification string (like `-v, --verbose`) extracted from [`click.Parameter.get_help_record()`](https://click.palletsprojects.com/en/stable/api/#click.Parameter).', max_width=None, optional=False), ColumnSpec(id='help', label='Help', description="The parameter's own help text, as written by the CLI author. Opt-in: it is the only column carrying free-form prose, so it stays out of the default table and is selected by ID (`--columns id,spec,help`). Structured formats are its main audience: it turns a `--params` dump into a self-describing inventory a tool or an agent can read without also parsing the rendered `--help` screen.", max_width=None, optional=True), ColumnSpec(id='class', label='Class', description="Fully-qualified class of the parameter: a subclass of [`click.Option`](https://click.palletsprojects.com/en/stable/api/#click.Option), [`click.Argument`](https://click.palletsprojects.com/en/stable/api/#click.Argument), [`cloup.Option`](https://cloup.readthedocs.io/en/stable/autoapi/cloup/index.html#cloup.Option), or one of Click Extra's own wrappers ([`click_extra.parameters.Option`](#click_extra.parameters.Option), [`click_extra.parameters.Argument`](#click_extra.parameters.Argument), [`click_extra.parameters.ExtraOption`](#click_extra.parameters.ExtraOption)).", max_width=None, optional=False), ColumnSpec(id='param_type', label='Param type', description='Click value converter class: a subclass of [`click.ParamType`](https://click.palletsprojects.com/en/stable/api/#click.ParamType) like [`click.IntRange`](https://click.palletsprojects.com/en/stable/api/#click.IntRange), [`click.Choice`](https://click.palletsprojects.com/en/stable/api/#click.Choice), or a Click Extra type.', max_width=None, optional=False), ColumnSpec(id='python_type', label='Python type', description='Python built-in type the parsed value resolves to: [`str`](https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str), [`int`](https://docs.python.org/3/library/functions.html#int), [`float`](https://docs.python.org/3/library/functions.html#float), [`bool`](https://docs.python.org/3/library/functions.html#bool), or [`list`](https://docs.python.org/3/library/stdtypes.html#list). Computed by [`ParamStructure.get_param_type()`](#click_extra.parameters.ParamStructure.get_param_type) from the Click `Param type`.', max_width=None, optional=False), ColumnSpec(id='hidden', label='Hidden', description="Reflects [`click.Option`'s `hidden`](https://click.palletsprojects.com/en/stable/api/#click.Option) constructor argument: the option is omitted from `--help` output. Empty for [`click.Argument`](https://click.palletsprojects.com/en/stable/api/#click.Argument), which does not support hiding.", max_width=None, optional=False), ColumnSpec(id='exposed', label='Exposed', description="Reflects [`click.Parameter`'s `expose_value`](https://click.palletsprojects.com/en/stable/api/#click.Parameter) constructor argument: whether the parsed value is forwarded to the command callback. Eager options like `--params` and `--help` typically run a callback and exit, so they are not exposed.", max_width=None, optional=False), ColumnSpec(id='allowed_in_conf', label='Allowed in conf?', description='Click Extra-specific: whether the parameter is reachable from a configuration file. Controlled by [`ParamStructure.excluded_params`](#click_extra.parameters.ParamStructure.excluded_params) and [`included_params`](#click_extra.parameters.ParamStructure.included_params). Empty when the CLI has no [`--config` option](config.md).', max_width=None, optional=False), ColumnSpec(id='envvars', label='Env. vars.', description="Environment variables read for this parameter: the explicit [`click.Parameter`'s `envvar`](https://click.palletsprojects.com/en/stable/api/#click.Parameter) plus the auto-resolved IDs documented in [Environment variables](envvar.md).", max_width=None, optional=False), ColumnSpec(id='default', label='Default', description='Default value returned by [`click.Parameter.get_default()`](https://click.palletsprojects.com/en/stable/api/#click.Parameter.get_default), rendered as its Python `repr()`.', max_width=None, optional=False), ColumnSpec(id='is_flag', label='Is flag', description="Reflects [`click.Option`'s `is_flag`](https://click.palletsprojects.com/en/stable/api/#click.Option): whether the option behaves as a flag (no value taken from the command line). Empty for [`click.Argument`](https://click.palletsprojects.com/en/stable/api/#click.Argument).", max_width=None, optional=False), ColumnSpec(id='flag_value', label='Flag value', description="Reflects [`click.Option`'s `flag_value`](https://click.palletsprojects.com/en/stable/api/#click.Option): the Python value substituted for the option when its flag is used. Defaults to `True` for boolean flags, can be any value for flag-value style options (like `@option('--upper', 'transform', flag_value='upper')`).", max_width=None, optional=False), ColumnSpec(id='is_bool_flag', label='Is bool flag', description='Reflects `click.Option.is_bool_flag` (set internally by Click when `flag_value` is `True` or `False`): the option is a *true* boolean flag, as opposed to a flag-value style option.', max_width=None, optional=False), ColumnSpec(id='multiple', label='Multiple', description="Reflects [`click.Parameter`'s `multiple`](https://click.palletsprojects.com/en/stable/api/#click.Parameter): the parameter can be repeated on the command line, collecting values into a tuple.", max_width=None, optional=False), ColumnSpec(id='nargs', label='Nargs', description="Reflects [`click.Parameter`'s `nargs`](https://click.palletsprojects.com/en/stable/api/#click.Parameter): the number of CLI tokens the parameter consumes. `1` is the default; `-1` denotes a variadic argument.", max_width=None, optional=False), ColumnSpec(id='prompt', label='Prompt', description="Reflects [`click.Option`'s `prompt`](https://click.palletsprojects.com/en/stable/api/#click.Option): the text shown to the user when the option is not provided on the command line. Empty when no prompt is configured.", max_width=None, optional=False), ColumnSpec(id='confirmation_prompt', label='Confirmation prompt', description="Reflects [`click.Option`'s `confirmation_prompt`](https://click.palletsprojects.com/en/stable/api/#click.Option): whether the user is asked to enter the value twice for confirmation.", max_width=None, optional=False), ColumnSpec(id='value', label='Value', description='Current value of the parameter at invocation time, computed by [`click.Parameter.consume_value()`](https://click.palletsprojects.com/en/stable/api/#click.Parameter) from the merged sources (CLI, environment, config file, default).', max_width=None, optional=False), ColumnSpec(id='source', label='Source', description='Provenance of the resolved value: a [`click.core.ParameterSource`](https://click.palletsprojects.com/en/stable/api/#click.core.ParameterSource) enum member such as `COMMANDLINE`, `ENVIRONMENT`, `DEFAULT_MAP`, or `DEFAULT`.', max_width=None, optional=False), ColumnSpec(id='config_file', label='Config file', description='The configuration file the effective value was loaded from, when `Source` reports `DEFAULT_MAP`. With [`cascade=True`](config.md#cascading-configuration-files) several files are layered and this column names the one that won the parameter; with a single loaded file, every config-sourced parameter names that file. Empty for every other source and when no configuration file was loaded. Opt-in, like `help`: paths are wide and stay redundant with `Source` until several files take part.', max_width=None, optional=True))¶
Rich column registry for the
--paramstable.Each entry is a
click_extra.table.ColumnSpeccarrying the columnâs stableid(used by--columnsand as structured-format key), its displaylabel, and a MyST/Markdowndescriptionconsumed by the documentationâs auto-generated Available columns section. Iteration yields columns in canonical display order.
- classmethod column_labels()[source]¶
Return just the display labels of
TABLE_HEADERS(in order).
- classmethod column_ids()[source]¶
Return just the stable IDs of
TABLE_HEADERS(in order).
- classmethod default_columns()[source]¶
Return the columns rendered when
--columnsasks for no projection.Every column but the
optionalones, which stay addressable by ID and out of the way until named.- Return type:
tuple[_ColumnSpec, âŠ]
- classmethod default_column_ids()[source]¶
Return the stable IDs of
default_columns()(in order).
- classmethod default_column_labels()[source]¶
Return the display labels of
default_columns()(in order).
- classmethod find_column(column_id)[source]¶
Return the
ColumnSpecmatchingcolumn_id.Raises
KeyErrorif no column has this ID; callers should convert the error into aclick.UsageErrorwhen surfaced to a user.
- classmethod render_doc_table()[source]¶
Render
TABLE_HEADERSas a Markdown table for documentation.Used by the
show_params_columns_tableMyST substitution indocs/conf.pyto feed the Available columns section ofdocs/parameters.md: editing a description here automatically rebuilds the docs table on the nextsphinx-build.- Return type:
- excluded_params¶
Deactivates the blocking of any parameter.
- included_params¶
No allowlist filter; show all parameters.
- print_params(ctx, param, value)[source]¶
Introspect the current CLI and print its parameter metadata table.
Thin wrapper over
render_params_table(), the shared rendering core also drivingclick-extra wrap --paramsfor foreign CLIs. The live invocation context carries everything the core needs: the capturedRAW_ARGS(attached byCommand/Group) for value and source resolution, plus any sibling--table-format/--columnsoptions.- Return type:
- exception click_extra.SkippedTest[source]¶
Bases:
ExceptionRaised when a test case should be skipped.
- class click_extra.SortByOption(*header_defs, param_decls=None, columns=None, default=None, expose_value=False, cell_key=None, help='Sort table by this column. Repeat to set priority.', **kwargs)[source]¶
Bases:
ExtraOptionA
--sort-byoption whose choices are derived from column definitions.Stores the selected column IDs in
ctx.meta[click_extra.context.SORT_BY]and publishes the derived row sort key inctx.meta[click_extra.context.TABLE_SORT_KEY], whichctx.print_tablepicks up so that table output is automatically sorted, without changing its(table_data, headers)call contract. The option acceptsmultiple=True, so users can repeat--sort-byto define a multi-column sort priority.Column definitions may be
ColumnSpecinstances or raw(label, column_id)tuples, passed positionally or via thecolumns=keyword. Passing aColumnSpecregistry viacolumns=lets the same tuple drive bothColumnsOption(--columns) and--sort-by, so the two options stay in sync from a single source of truth.COLUMNS = ( ColumnSpec("package_id", "Package ID"), ColumnSpec("package_name", "Name"), ColumnSpec("manager_id", "Manager"), ) @command @table_format_option @columns_option(columns=COLUMNS) @sort_by_option(columns=COLUMNS) @pass_context def my_cmd(ctx): ctx.print_table(rows, [col.label for col in COLUMNS])
Definitions may instead be bare column ID strings, declaring a field vocabulary untied to any single table layout. This fits a
--sort-bydeclared once on a group whose subcommands render heterogeneous tables: no sort key is published since no layout is known up front. The selection is resolved per table byprint_table(), from the column IDs its headers carry â each table sorts by the selected fields it knows (remaining columns breaking ties left to right) and keeps its original row order when it knows none.@group @sort_by_option("package_id", "package_name", "manager_id") def my_cli(): pass @my_cli.command def installed(): print_table(rows, [("Package ID", "package_id"), ("Manager", "manager_id")]) @my_cli.command def managers(): print_table(rows, [("Manager", "manager_id"), ("Path", None)])
- field_vocabulary¶
Whether definitions are bare column IDs, untied to any table layout.
In this mode
init_sort()only publishes the selection on the context: the sort is resolved per table atprint_table()time.
- init_sort(ctx, param, sort_columns)[source]¶
Publish the row sort key on the contextâs shared
meta.Builds the sort key from this optionâs column definitions and the selected
sort_columns, then stores it underctx.meta[click_extra.context.TABLE_SORT_KEY], wherectx.print_tablepicks it up. The call contract is the same sorted or not:ctx.print_table(table_data, headers).In field-vocabulary mode no table layout is known at declaration time, so no key is published: only the selection lands on the context (
ctx.metais shared with every subcommand), resolved per table byprint_table()from the column IDs its headers carry.- Return type:
- class click_extra.Spinner(label='', *, frames=None, spinner=None, reverse=False, interval=None, delay=0.0, style=None, timer=False, stream=None, enabled=None, hide_cursor=True, beep=False)[source]¶
Bases:
objectA thread-animated, indeterminate progress spinner usable as a context manager.
The animation runs on a background daemon thread, leaving the calling thread free to block on the actual work. Entering the context (or calling
start()) begins the animation; leaving it (or callingstop()) halts the thread and erases the spinner line so it never lingers above the next output.Note
A single
Spinnerinstance drives one animation at a time. mpm and similar tools run their subprocesses sequentially, so one shared instance whoselabelis reassigned between steps is enough; for concurrent work, use one instance per thread.Configure (but do not start) the spinner.
- Parameters:
label (
str|Callable[...,Any]) â text shown after the spinner glyph. As a special case, a bare@Spinnerdecorator passes the wrapped function here instead; it is detected and the label defaults to empty.frames (
Sequence[str] |None) â the animation frames, cycled in order. Defaults toSPINNER_FRAMES, or thespinnerpresetâs frames when given.spinner (
SpinnerPreset|None) â aSpinnerPresetfrom theSPINNERScatalog (spinner=SPINNERS["moon"]), supplying both frames and a tuned interval. An explicitframesorintervalstill overrides it.reverse (
bool) â cycle the frames backwards, spinning the animation the other way. Set it when the rotation runs counter to what you expect; it composes with any customframes.interval (
float|None) â seconds between two frames. Defaults to0.1, or thespinnerpresetâs interval when given.delay (
float) â seconds to wait before drawing the first frame. A non-zero delay keeps the spinner silent for calls that finish quickly, so it only surfaces once an operation is genuinely slow.style (
Style|None) â aStyleapplied to the spinner glyph, label and timer (Style(fg="cyan", bold=True)). Color is decoupled from animation:--no-color/NO_COLORstrip it while the spinner keeps spinning (seeProgressOption).timer (
bool|Callable[[float],str]) â append the elapsed wall-clock time to the spinner, and to any finalok()/fail()line.Trueusesformat_duration()for the default compact format (2.3s,1:05, then1:02:03). Pass a callable(seconds: float) -> strto format the duration yourself, liketimer=lambda s: f"{s / 60:.0f}m"for whole minutes.stream (
IO[str] |None) â where to draw; defaults tosys.stderrso the spinner never mixes intostdoutdata.enabled (
bool|None) â force the spinner on or off.None(the default) auto-detects, animating only whenstreamis a TTY.hide_cursor (
bool) â hide the text cursor while spinning and restore it on stop.beep (
bool) â ring the terminal bell once when the spinner stops. It fires only when the spinner was active, so a disabled or redirected spinner stays silent.
- Raises:
ValueError â if
stylecarries a color or attribute that cannot be rendered.
- label: str¶
Text drawn after the spinner glyph.
Reassign it at any time while the spinner runs to reflect the current step; the animation thread reads it afresh on every frame.
- property elapsed_time: float¶
Seconds elapsed since
start(), frozen oncestop()is called.Returns
0.0before the spinner has started.
- property shown: bool¶
Whether the spinner has drawn at least one frame to its stream.
Trueonly once an animation frame was actually rendered. It staysFalsefor a disabled spinner (off a TTY, on aTERM=dumbterminal, or withenabled=False) and for a call that finishes withindelay, before the first frame. Reset bystart().Use it to gate output that should mirror the spinnerâs visibility.
ok()andfail()write their line unconditionally, so an outcome is still recorded in a pipe or log; guard them withshownwhen you only want the finisher on screen after a spinner the user actually saw:with Spinner("Baking bread") as spinner: bake() if spinner.shown: spinner.ok()
- start()[source]¶
Begin animating on a background thread, unless the spinner is disabled.
A disabled spinner (non-TTY stream, or
enabled=False) returns at once without spawning a thread or emitting anything (but still records the start time, so a laterok()/fail()can report a duration).- Return type:
- stop()[source]¶
Halt the animation and erase the spinner line.
Idempotent and safe to call when the spinner never started. Restores the cursor and clears the line only if the animation actually drew to the terminal.
- Return type:
- echo(message='')[source]¶
Print
messageon its own line above the running spinner.Clickâs
click.progressbar()and a bareprintboth fight the animation: a frame drawn between the cursor returns and the text mangles the line.echo()takes the same draw lock as the animation thread, erases the in-progress frame, writesmessagefollowed by a newline, and lets the next tick redraw the spinner underneath. It is safe to call from another thread while the spinner runs.Output goes to the spinnerâs own
stream(stderrby default), so results written tostdoutnever need it. When the spinner is not animating (disabled, or a non-TTY stream), it degrades to a plain write ofmessagewith no control codes.- Return type:
- ok(symbol=None, *, style=None)[source]¶
Stop the spinner and leave a persistent success line on screen.
Where
stop()erases the spinner,ok()replaces the final frame withsymbolfollowed by the current label (and the elapsed time whentimeris set), then keeps that line.symboldefaults to the themed success glyphOK_GLYPH(â), painted with the active themeâssuccessslot unlessstyleoverrides it. Color is stripped under--no-color/NO_COLOR; the glyph stays.- Return type:
- class click_extra.SpinnerPreset(frames: tuple[str, ...], interval: float)[source]¶
Bases:
NamedTupleA named spinner animation: its frames and the interval they look best at.
The
SPINNERScatalog is ported from cli-spinners, with intervals converted from milliseconds to seconds. Pass one toSpinnervia itsspinnerargument.Create new instance of SpinnerPreset(frames, interval)
- class click_extra.StreamHandler(stream=None)[source]¶
Bases:
StreamHandlerA handler to output logs to the console.
Wraps
logging.StreamHandler, but useclick.echo()to support color printing.Only
<stderr>or<stdout>are allowed as output stream.If stream is not specified,
<stderr>is used by defaultInitialize the handler.
If stream is not specified, sys.stderr is used.
- property stream: IO[Any]¶
The stream to which logs are written.
A proxy of the parent
logging.StreamHandlerâs stream attribute.Redefined here to enforce checks on the stream value.
- emit(record)[source]¶
Use
click.echo()to print to the console.Cooperates with any live terminal line currently drawing on the same stream (a
Spinner, or anOperationTrailprogress bar): the record is then printed through itsecho, which erases the in-progress render first, so a log line emitted mid-draw lands on its own line instead of garbling the indicator (and vice versa).The color tri-state is resolved through
invocation_color()rather than left toclick.echo()âs own context lookup: a record emitted from a background thread (a subprocess stream reader, a fan-out worker) has no reachable Click context, and would otherwise ignore--no-colorand keep its ANSI codes on a TTY.- Return type:
- class click_extra.Style(fg=None, bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None)[source]¶
Bases:
Stylecloup.Stylewith extra ergonomics.See the module docstring for the full list of additions. The runtime contract (calling the instance to apply styling, equality, hashing,
with_()) is otherwise identical tocloup.Style.- fg: str | tuple[int, int, int] | int | None = None¶
Foreground color: named ANSI string,
#rrggbbhex, RGB tuple, or palette index.
- bg: str | tuple[int, int, int] | int | None = None¶
Background color: named ANSI string,
#rrggbbhex, RGB tuple, or palette index.
- cascade(base)[source]¶
Return a copy with
Nonefields filled in from base.The instanceâs own non-
Nonevalues always win:cascadeonly fills gaps. Useful for theme inheritance:derived.cascade(parent)keepsderivedâs overrides and inherits the rest fromparent.- Return type:
- to_dict()[source]¶
Serialize to a plain dict with only the set fields.
RGB tuples are emitted as
#rrggbbstrings so the result round-trips through TOML/JSON/YAML untouched. Pair withfrom_dict()to rebuild aStyle.
- classmethod from_dict(data)[source]¶
Build a
Stylefrom the plain dict produced byto_dict().Validates that every key in data names a known
Stylefield and raisesTypeErrorotherwise. Pair withto_dict()to round-trip through TOML/JSON/YAML.- Return type:
- to_css()[source]¶
Render the style as a semicolon-separated CSS declaration list.
Style(fg="#f1fa8c", bold=True).to_css()returns"color: #f1fa8c; font-weight: bold". Suitable for inlinestyle="..."attributes on HTML spans.- Return type:
- classmethod from_ansi(escape)[source]¶
Parse one or more consecutive ANSI SGR escapes into a
Style.Supports the standard 8/16-color codes (30â37, 40â47, 90â97, 100â107), the
38;5;n/48;5;n256-color extension, and the38;2;r;g;b/48;2;r;g;b24-bit extension. Reset codes (the full0reset, its parameter-less\x1b[mform included, and selective resets like22,39or49) are ignored, so parsing the full output of a style call (trailing reset included) recovers that style. Multiple back-to-back escapes (as click emits when combining colors with attributes:\x1b[31m\x1b[1m) are merged into a singleStyle.To tokenize a string mixing text and escapes, with resets honored, see
split_ansi().- Return type:
- contrast_ratio(other)[source]¶
Return the WCAG 2.x contrast ratio between this fg and otherâs fg.
Result is in
[1, 21]: 1 = identical colors (no contrast), 21 = maximum contrast (black on white). WCAG AA requires 4.5+ for normal text, 3.0+ for large text; AAA wants 7.0+ and 4.5+ respectively.- Return type:
- class click_extra.TableFormat(*values)[source]¶
Bases:
EnumEnumeration of supported table formats.
Hard-coded to be in alphabetical order. Content of this enum is checked in unit tests.
Warning
The
youtrackformat is missing in action from any official JetBrains documentation. It will be removed in python-tabulate v0.11.- ALIGNED = 'aligned'¶
- ASCIIDOC = 'asciidoc'¶
- COLON_GRID = 'colon-grid'¶
- CSV = 'csv'¶
- CSV_EXCEL = 'csv-excel'¶
- CSV_EXCEL_TAB = 'csv-excel-tab'¶
- CSV_UNIX = 'csv-unix'¶
- DOUBLE_GRID = 'double-grid'¶
- DOUBLE_OUTLINE = 'double-outline'¶
- FANCY_GRID = 'fancy-grid'¶
- FANCY_OUTLINE = 'fancy-outline'¶
- GITHUB = 'github'¶
- GRID = 'grid'¶
- HEAVY_GRID = 'heavy-grid'¶
- HEAVY_OUTLINE = 'heavy-outline'¶
- HJSON = 'hjson'¶
- HTML = 'html'¶
- JIRA = 'jira'¶
- JSON = 'json'¶
- JSON5 = 'json5'¶
- JSONC = 'jsonc'¶
- LATEX = 'latex'¶
- LATEX_BOOKTABS = 'latex-booktabs'¶
- LATEX_LONGTABLE = 'latex-longtable'¶
- LATEX_RAW = 'latex-raw'¶
- MEDIAWIKI = 'mediawiki'¶
- MIXED_GRID = 'mixed-grid'¶
- MIXED_OUTLINE = 'mixed-outline'¶
- MOINMOIN = 'moinmoin'¶
- ORGTBL = 'orgtbl'¶
- OUTLINE = 'outline'¶
- PIPE = 'pipe'¶
- PLAIN = 'plain'¶
- PRESTO = 'presto'¶
- PRETTY = 'pretty'¶
- PSQL = 'psql'¶
- ROUNDED_GRID = 'rounded-grid'¶
- ROUNDED_OUTLINE = 'rounded-outline'¶
- RST = 'rst'¶
- SIMPLE = 'simple'¶
- SIMPLE_GRID = 'simple-grid'¶
- SIMPLE_OUTLINE = 'simple-outline'¶
- TEXTILE = 'textile'¶
- TOML = 'toml'¶
- TSV = 'tsv'¶
- UNSAFEHTML = 'unsafehtml'¶
- VERTICAL = 'vertical'¶
- XML = 'xml'¶
- YAML = 'yaml'¶
- YOUTRACK = 'youtrack'¶
- property is_markup: bool¶
Whether this format is a markup rendering.
ANSI codes never reach a markup rendering raw: they are either translated to the formatâs native styling (see
supports_styling) or stripped from cell values. Forcing--coloron the command line preserves them as-is in the markup formats without styling support.
- property supports_styling: bool¶
Whether ANSI codes are translated to this formatâs native styling.
See
STYLED_FORMATSfor the registry, and the rationale behind each excluded markup format.
- property is_wrappable: bool¶
Whether this format renders a cell wrapped onto several lines.
See
WRAPPABLE_FORMATSfor the registry, and the rationale behind each excluded format.
- class click_extra.TableFormatOption(param_decls=None, type=EnumChoice('aligned', 'asciidoc', 'colon-grid', 'csv', 'csv-excel', 'csv-excel-tab', 'csv-unix', 'double-grid', 'double-outline', 'fancy-grid', 'fancy-outline', 'github', 'grid', 'heavy-grid', 'heavy-outline', 'hjson', 'html', 'jira', 'json', 'json5', 'jsonc', 'latex', 'latex-booktabs', 'latex-longtable', 'latex-raw', 'mediawiki', 'mixed-grid', 'mixed-outline', 'moinmoin', 'orgtbl', 'outline', 'pipe', 'plain', 'presto', 'pretty', 'psql', 'rounded-grid', 'rounded-outline', 'rst', 'simple', 'simple-grid', 'simple-outline', 'textile', 'toml', 'tsv', 'unsafehtml', 'vertical', 'xml', 'yaml', 'youtrack'), default=TableFormat.ROUNDED_OUTLINE, expose_value=False, is_eager=True, help='Rendering style of tables.', **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured option that is adding a
--table-formatflag to select the rendering style of a table.The selected table format ID is made available in the context in
ctx.meta[click_extra.context.TABLE_FORMAT], where therender_table()andprint_table()context methods pick it up as their default format.ctx.metais shared along the context chain, so declaring this option on a group makes the selected format reach every subcommand:ctx.render_table(table_data, headers, **kwargs): renders and returns the table as a string,ctx.print_table(table_data, headers, **kwargs): renders and prints the table to the console.
Where:
table_datais a 2-dimensional iterable of iterables for rows and cells values,headersis a list of string to be used as column headers,**kwargsare any extra keyword arguments supported by the underlying table formatting function.
- init_formatter(ctx, param, table_format)[source]¶
Save the resolved
table_formatin the contextâs sharedmeta.The
render_table()andprint_table()context methods read it back at call time.- Return type:
- class click_extra.TelemetryOption(param_decls=None, default=False, expose_value=False, envvar=None, show_envvar=True, help='Collect telemetry and usage data.', **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured
--telemetry/--no-telemetryoption flag.Respects the proposed DO_NOT_TRACK environment variable as a unified standard to opt-out of telemetry for TUI/console apps: a truthy
DO_NOT_TRACKforces telemetry off, overriding the user-defined environment variables, the auto-generated values, and configuration files. Only an explicit--telemetryon the command line outranks it.The resolved value is stored in
ctx.meta[click_extra.context.TELEMETRY], aligning with every other Click Extra optionâs per-invocation context-meta storage pattern.See also
- set_telemetry(ctx, param, value)[source]¶
Reconcile the flag with
DO_NOT_TRACKand store the result onctx.meta.An explicit
--telemetry/--no-telemetryon the command line wins. Otherwise a truthyDO_NOT_TRACK(bare presence, or any value not parseable as false, in the permissive spirit of the color environment variables) forces telemetry off. Read viaclick_extra.context.get(ctx, click_extra.context.TELEMETRY).Note
DO_NOT_TRACKis read here rather than wired through the optionâsenvvar: Clickâs environment plumbing feeds the raw value straight to the boolean flag, soDO_NOT_TRACK=1would enable telemetry, inverting the convention. Reading it manually keeps the opt-out meaning, mirroring howColorOptionreadsNO_COLORand friends.- Return type:
- class click_extra.ThemeOption(param_decls=None, default='dark', is_eager=True, expose_value=False, query_background=False, help='Color theme used for help screens.', **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured option that adds
--themeto select the help-screen palette.Accepts any name registered in
theme_registryor in the per-invocation overrides loaded byConfigOptionfrom[tool.<cli>.themes.<name>]. Validation goes throughThemeChoice, which reads the live registry at parse time, so config-defined themes appear as valid choices and in the--helpmetavar without any further wiring.The resolved
HelpThemelands on the Click context underclick_extra.context.THEMEand applies for the duration of the current invocation only.A user who never passes the flag can still pick a palette by exporting
THEME_ENVVAR(CLICK_EXTRA_THEME), which is honored by every Click Extra CLI at once. Seeset_theme()for how it ranks against the flag, the<CLI>_THEMEvariable and the configuration file.The reserved value
AUTO_THEME(--theme=auto) is also accepted on every CLI: it resolves the palette from the terminal background viaresolve_auto_theme()instead of naming a registered theme. Background detection reads environment variables by default; passquery_background=Trueto additionally allow the live OSC 11 terminal query (query_osc_background()), which is opt-in because it reads stdin.- set_theme(ctx, param, value)[source]¶
Resolve the chosen theme name and store it on the Click context.
ThemeChoicehas already validated value against the live registry (or accepted theAUTO_THEMEdirective) by the time this fires. A plain palette name is looked up unconditionally;autois resolved from the terminal background viaresolve_auto_theme(), leavingctx.metauntouched when no palette can be resolved soget_current_theme()keeps its default.Before that,
THEME_ENVVARis consulted when the value still comes from the optionâs own default, which yields the precedence:--theme><CLI>_THEME> configuration file >CLICK_EXTRA_THEME> built-in default. The global variable therefore only names the palette of the CLIs nothing else has an opinion about.Note
The variable is read here rather than wired through the optionâs
envvar. Click resolves an explicitenvvarbefore the auto-generated<CLI>_THEME, which would let the machine-wide preference outrank the CLI-specific one, and would list both names in the--paramstable, making the combined string the widest cell of its column. This mirrors howAccessibleOptionreadsACCESSIBLEandColorOptionreadsNO_COLOR.An unparsable palette name is a warning, not an error: a typo in a shell profile would otherwise break every Click Extra CLI on the machine at once, including the ones needed to fix it.
- Return type:
- class click_extra.TimerOption(param_decls=None, default=False, expose_value=False, is_eager=True, help='Measure and print elapsed execution time.', **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured option that is adding a
--time/--no-timeflag to print elapsed time at the end of CLI execution.The start time is made available in the context in
ctx.meta[click_extra.context.START_TIME].- print_timer()[source]¶
Compute and print elapsed execution time.
Always prints, even when a sibling eager option (
--version,--params,--show-configâŠ) short-circuited the command body viactx.exit(). That makes--timea usable probe for the cost of Click Extraâs own machinery (option parsing, config loading, eager callbacks), not just user command bodies.- Return type:
- init_timer(ctx, param, value)[source]¶
Set up the execution-timer machinery for the current invocation.
Captures
time.perf_counter()as the start time, stores it onctx.metaunderclick_extra.context.START_TIME, and queuesprint_timer()as a context-close callback so the elapsed duration is printed even when a sibling eager option (--version,--paramsâŠ) short-circuits the command body.- Return type:
- class click_extra.TreeOption(param_decls=None, is_flag=True, expose_value=False, is_eager=True, help='Show the tree of nested subcommands and exit.', **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured
--treeflag that prints the hierarchy of nested subcommands and exits.Eager and value-less, like
ManOption. Part of the default option set injected bydefault_params(), so every@commandand@groupexposes it. Use@tree_optionto add it to a plain Click CLI.Note
The flag is named
--tree, not--show-treeor--commands.Rendering a hierarchy as a tree is conventionally named
treeacross ecosystems:eza --tree,lsblk --tree,poetry show --tree,cargo tree,pstree(1)andtree(1)itself (ps --forestbeing the lone dissenter).--commandswould suggest the flat listing--helpalready provides.The bare noun also lines up with the neighbouring
--man,--versionand--helpinformational flags;--paramsis the historical outlier, not the pattern. A flag was preferred over a registeredtreesubcommand, which could collide with the userâs own command namespace.
- class click_extra.Tuple(types)[source]¶
Bases:
CompositeParamType[tuple[Any, âŠ]]The default behavior of Click is to apply a type on a value directly. This works well in most cases, except for when
nargsis set to a fixed count and different types should be used for different items. In this case theTupletype can be used. This type can only be used ifnargsis set to a fixed number.For more information see Multi Value Options as Tuples.
This can be selected by using a Python tuple literal as a type.
- Parameters:
types (
Sequence[type[Any] |ParamType[Any]]) â a list of types that should be used for the tuple items.
- to_info_dict()[source]¶
Gather information that could be useful for a tool generating user-facing documentation.
Use
click.Context.to_info_dict()to traverse the entire CLI structure.Added in version 8.0.
- Return type:
TupleInfoDict
- property arity: int¶
int([x]) -> integer int(x, base=10) -> integer
Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.__int__(). For floating-point numbers, this truncates towards zero.
If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by â+â or â-â and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal. >>> int(â0b100â, base=0) 4
- convert(value, param, ctx)[source]¶
Convert the value to the correct type. This is not called if the value is
None(the missing value).This must accept string values from the command line, as well as values that are already the correct type. It may also convert other compatible types.
The
paramandctxarguments may beNonein certain situations, such as when converting prompt input.If the value cannot be converted, call
fail()with a descriptive message.- Parameters:
value (t.Any) â The value to convert.
param (Parameter | None) â The parameter that is using this type to convert its value. May be
None.ctx (Context | None) â The current context that arrived at this value. May be
None.
- Return type:
tuple[t.Any, âŠ]
- exception click_extra.UsageError(message, ctx=None)[source]¶
Bases:
ClickExceptionAn internal exception that signals a usage error. This typically aborts any further handling.
- Parameters:
message (str) â the error message to display.
ctx (Context | None) â optionally the context that caused this error. Click will fill in the context automatically in some situations.
- class click_extra.ValidateConfigOption(param_decls=None, type=<click.types.Path object>, is_eager=True, expose_value=False, help='Validate the configuration file and exit.', **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured option adding
--validate-config CONFIG_PATH.Loads the config file at the given path, validates it against the CLIâs parameter structure in strict mode, reports results, and exits.
- validate_config(ctx, param, value)[source]¶
Load, parse, and validate the configuration file, then exit.
Validation runs three checks in order, every one of them under the same
ValidationErrorshape so the reported path is always rooted at the configuration file:CLI-parameter strict check on the non-opaque part of the document.
Schema processing, if a
config_schemais configured: catches type errors and unknown keys inside the dataclass-described section.Each registered
ConfigValidatorruns against its declared opaque sub-tree.
Every detected error is emitted before exiting, so a single
--validate-configrun surfaces the full list of fixes the user needs to apply.- Return type:
- exception click_extra.ValidationError(path, message, code=None)[source]¶
Bases:
ExceptionRaised when a configuration file fails validation.
A single, structured exception type that uniformly carries the dotted
pathof the offending key, a human-readablemessage, and an optionalcodefor programmatic handling. Used by click-extraâs built-in strict-mode check and by every user-registeredConfigValidator, so downstream apps and--validate-configsee the same error shape regardless of who detected the problem.- Parameters:
path (
str) â Dotted path to the offending key, relative to the configuration file root (like"my-cli.managers.winget.cli_searchpath"). An empty string means the error applies to the document as a whole.message (
str) â Human-readable description of the failure. Should be a single sentence, no trailing punctuation, no path repeated.code (
str|None) â Optional machine-readable error code (like"unknown_field") for callers that want to dispatch on error type without parsing the message string.
- class click_extra.ValidationReport(schema_instance, opaque_subtrees, errors, merged_conf=None)[source]¶
Bases:
objectOutcome of one pass through
run_config_validation().Bundles everything a caller needs after validating a parsed configuration document: the typed schema instance, the extracted opaque sub-trees, the template-filtered config ready for
default_map, and every error detected across all validation stages.Note
The report holds references to the parsed sub-trees, not copies, so building it is cheap regardless of document size.
- schema_instance: Any | None¶
Typed object produced by the configured schema callable.
Nonewhen no schema is configured, or when the schema stage raised (in which case the failure is recorded inerrors).
- opaque_subtrees: dict[str, dict[str, Any]]¶
Extracted extension sub-trees, keyed by dotted path relative to the app section. Only paths actually present in the document appear here, so callers can re-route them to per-path validators or stash them on
ctx.meta.
- errors: tuple[ValidationError, ...]¶
Every
ValidationErrordetected, in stage order (unknown CLI-flag keys first, then schema errors, then validator failures). Empty on success.With
collect_all=Falsethis holds at most one error: the first failure short-circuits the remaining stages.
- merged_conf: dict[str, Any] | None = None¶
The CLI-flag-bound configuration merged onto
params_template: the payload_install_default_map()layers into the contextâsdefault_map.Nonewhenparams_templatewasNone(no strict check) or the strict check raised. Read it only on a successful report: it is the same valuemerge_default_map()would recompute, so reusing it avoids a second normalize/strip/merge pass.
- class click_extra.VerboseOption(param_decls=None, **kwargs)[source]¶
Bases:
_CounterOption--verbose/-voption to raise the log level of_VerbosityOptionby one step per repetition.Each
-vraises the verbosity by oneLogLevelstep. The option can be repeated, so-vv(or-v -v) raises it by two steps.The base level the counter starts from is sourced from
VerbosityOption.default. So with--verbosityâs default left atWARNING:-vraises the level toINFO,-vvraises the level toDEBUG,any further repetition is clamped at the loudest level, so
-vvvvvfor example resolves toDEBUG.
-vshares a single signed counter withQuietOptionâs-q, so the two cancel out:-v -qleaves the level unchanged. See_VerbosityOption.resolve_levelfor the full reconciliation rule with--verbosity.Set up a verbosity-altering option.
- Parameters:
default_logger â If a
logging.Loggerobject is provided, thatâs the instance to which we will set the level to. If the parameter is a string and is found in the global registry, we will use it as the loggerâs ID. Otherwise, we will create a new logger withnew_logger()Default to the globalrootlogger.
- class click_extra.VerbosityOption(param_decls=None, default_logger='root', default=LogLevel.WARNING, metavar='LEVEL', type=EnumChoice('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'), help='Either CRITICAL, ERROR, WARNING, INFO, DEBUG.', **kwargs)[source]¶
Bases:
_VerbosityOption--verbosity LEVELoption to set the log level of_VerbosityOption.Set up a verbosity-altering option.
- Parameters:
default_logger (
Logger|str) â If alogging.Loggerobject is provided, thatâs the instance to which we will set the level to. If the parameter is a string and is found in the global registry, we will use it as the loggerâs ID. Otherwise, we will create a new logger withnew_logger()Default to the globalrootlogger.
- class click_extra.VersionOption(param_decls=None, message=None, fields=None, styles=None, message_style=None, screen=None, is_flag=True, expose_value=False, is_eager=True, help='Show the version and exit.', **kwargs)[source]¶
Bases:
ExtraOptionGather CLI metadata and prints a colored version string.
Note
This started as a copy of the standard @click.version_option() decorator, but is no longer a drop-in replacement. Hence the
Extraprefix.This address the following Click issues:
click#2324, to allow its use with the declarative
params=argument.click#2331, by distinguishing the module from the package.
click#1756, by allowing path and Python version.
Preconfigured as a
--versionoption flag.- Parameters:
message (
str|None) â the message template to print, in format string syntax. Defaults to{prog_name}, version {version}.fields (
Mapping[str,Any] |None) â mapping of template field name to a forced value, overriding the value auto-computed for that field. Keys must be members oftemplate_fields(for example{"version": "1.2.3"}).styles (
Mapping[str,Callable[[str],str] |None] |None) â mapping of template field name to itsStyle, merged overdefault_styles. PassNoneas a value to clear a fieldâs default style. Keys must be members oftemplate_fields.message_style (
Callable[[str],str] |None) â fallback style for the message literals and for any field that has no style of its own.screen (
VersionScreen|None) â aVersionScreento draw instead of the one-line message, whenever the terminal can take it. Left unset,--versionbehaves exactly as it always has.
- template_fields: tuple[str, ...] = ('module', 'module_name', 'module_file', 'module_version', 'package_name', 'package_version', 'author', 'license', 'exec_name', 'version', 'git_repo_path', 'git_branch', 'git_long_hash', 'git_short_hash', 'git_date', 'git_tag', 'git_tag_sha', 'git_distance', 'git_dirty', 'prog_name', 'env_info')¶
List of field IDs recognized by the message template.
- default_styles: ClassVar[dict[str, IStyle]] = {'env_info': Style(fg='bright_black'), 'exec_name': <function theme_slot.<locals>.apply>, 'git_branch': Style(fg='cyan'), 'git_date': Style(fg='bright_black'), 'git_dirty': Style(fg='red'), 'git_distance': <function theme_slot.<locals>.apply>, 'git_long_hash': Style(fg='yellow'), 'git_repo_path': Style(fg='bright_black'), 'git_short_hash': Style(fg='yellow'), 'git_tag': Style(fg='cyan'), 'git_tag_sha': Style(fg='yellow'), 'module_name': <function theme_slot.<locals>.apply>, 'module_version': <function theme_slot.<locals>.apply>, 'package_name': <function theme_slot.<locals>.apply>, 'package_version': <function theme_slot.<locals>.apply>, 'prog_name': <function theme_slot.<locals>.apply>, 'version': <function theme_slot.<locals>.apply>}¶
Default style for each template field.
Fields absent from this mapping render with no style of their own and fall back to
message_style(or no color when that is unset). User-providedstylesare merged over these defaults.The name and version fields defer to the active palette through
theme_slot()rather than naming a color. Both slots render exactly what the literals they replaced did under thedarkdefault âinvoked_commandis bright white bold,successis green â so nothing moves for a CLI that never touches--theme, while one that does finally gets a version message to match.
- message: str = '{prog_name}, version {version}'¶
Default message template used to render the version string.
- static cli_frame()[source]¶
Returns the frame in which the CLI is implemented.
Inspects the execution stack frames to find the package in which the userâs CLI is implemented.
Returns the frame itself.
- Return type:
- property module: ModuleType[source]¶
Returns the module in which the CLI resides.
- property module_version: str | None[source]¶
Returns the string found in the local
__version__variable.Hint
__version__is an old pattern from early Python packaging. It is not a standard variable and is not defined in the packaging PEPs.You should prefer using the
package_versionproperty below instead, which uses the standard libraryimportlib.metadataAPI.Weâre still supporting it for backward compatibility with existing codebases, as Click removed it in version 8.2.0.
- property package_version: str | None[source]¶
Returns the package version if installed.
Resolved from the distribution name (see
_distribution_name) viaimportlib.metadata.version(). ReturnsNoneif the package is not installed or cannot be resolved.
- property author: str | None[source]¶
Returns the package author(s) from its core metadata.
Delegates to
resolve_author(): prefers theAuthorfield, then theMaintainerfield, then the display name parsed out of theAuthor-email/Maintainer-emailfields (Name <email>). ReturnsNoneif no author can be determined.
- property license: str | None[source]¶
Returns the package license from its core metadata.
Delegates to
resolve_license(): prefers the SPDXLicense-Expressionfield, falls back to the human-readable name of the firstLicense ::trove classifier, then to the free-formLicensefield. ReturnsNoneif no license can be determined.
- property exec_name: str[source]¶
User-friendly name of the executed CLI.
Returns the module name. But if the later is
__main__, returns the package name.If not packaged, the CLI is assumed to be a simple standalone script, and the returned name is the scriptâs file name (including its extension).
- property version: str | None[source]¶
Return the version of the CLI.
Returns the module version if a
__version__variable is set alongside the CLI in its module.Else returns the package version if the CLI is implemented in a package, using importlib.metadata.version().
For development versions (containing
.dev), automatically appends the Git short hash as a PEP 440 local version identifier, producing versions like1.2.3.dev0+abc1234. This helps identify the exact commit a dev build was produced from. If Git is unavailable, the plain dev version is returned.Versions that already contain a
+(a pre-baked local version identifier, typically set at build time by CI pipelines) are returned as-is to avoid producing invalid double-suffixed versions like1.2.3.dev0+abc1234+xyz5678.
- property git_branch: str | None[source]¶
Returns the current Git branch name.
Checks for a pre-baked
__git_branch__dunder first, thengit rev-parse --abbrev-ref HEAD, then.git_archival.json.
- property git_long_hash: str | None[source]¶
Returns the full Git commit hash.
Checks for a pre-baked
__git_long_hash__dunder first, thengit rev-parse HEAD, then.git_archival.json.
- property git_short_hash: str | None[source]¶
Returns the short Git commit hash.
Checks for a pre-baked
__git_short_hash__dunder first, thengit rev-parse --short HEAD, then.git_archival.json(where it is derived from the first 7 characters of the full hash).Hint
The short hash is usually the first 7 characters of the full hash, but this is not guaranteed to be the case.
But it is at least guaranteed to be unique within the repository, and a minimum of 4 characters.
- property git_date: str | None[source]¶
Returns the commit date in ISO format:
YYYY-MM-DD HH:MM:SS +ZZZZ.Checks for a pre-baked
__git_date__dunder first, thengit show -s --format=%ci HEAD, then.git_archival.json(whosenode-dateis strict ISO 8601, like2021-01-01T12:00:00+00:00).
- property git_tag: str | None[source]¶
Returns the Git tag pointing at HEAD, if any.
Checks for a pre-baked
__git_tag__dunder first, thengit describe --tags --exact-match HEAD, then.git_archival.json.Returns
Noneif HEAD is not at a tagged commit.
- property git_tag_sha: str | None[source]¶
Returns the commit SHA that the current tag points at.
Checks for a pre-baked
__git_tag_sha__dunder first, thengit rev-list -1on the tag returned bygit_tag, then.git_archival.json. ReturnsNoneif HEAD is not at a tag.
- property git_distance: str | None[source]¶
Number of commits since the most recent tag, or
None.Checks for a pre-baked
__git_distance__dunder first, then parsesgit describe --tags --long, then falls back to.git_archival.json.Nonewhen no tag is reachable or Git is unavailable.
- property git_dirty: str | None[source]¶
Work-tree state:
"dirty","clean"orNone.Checks for a pre-baked
__git_dirty__dunder first, then runsgit status --porcelain.Nonewhen not in a Git repository or Git is unavailable. There is no.git_archival.jsonfallback: an archive has no work tree, so its state is unknowable.
- property prog_name: str | None¶
Return the name of the CLI, from Clickâs point of view.
Get the info_name of the root command.
Note
Unlike its siblings, this field is resolved on every access instead of being cached on the instance: it is the one template field whose value legitimately varies between invocations of the same option instance sharing a process.
multicalldispatch relies on that, running one CLI under many names in sequence, and aprog_namepassed tomain()varies it without any multicall at all. A cached value would pin the first name seen forever.
- property env_info: dict[str, Any][source]¶
Various environment info.
Returns the data produced by boltons.ecoutils.get_profile().
- field_style(field_id=None)[source]¶
Style painting the field_id segment of a rendered message.
A field carrying no style of its own falls back to
message_style, and one left unset by the caller too renders bare. Call with nofield_idfor the style of the templateâs literal segments, which ismessage_stylealone.
- colored_template(template=None)[source]¶
Insert ANSI styles to a message template.
Accepts a custom
templateas parameter, otherwise uses the default message defined on the Option instance.This step is necessary because we need to linearize the template to apply the ANSI codes on the string segments. This is a consequence of the nature of ANSI, directives which cannot be encapsulated within another (unlike markup tags like HTML).
- Return type:
- render_message(template=None)[source]¶
Render the version string from the provided template.
Accepts a custom
templateas parameter, otherwise uses the defaultself.colored_template()produced by the instance.A CLI carrying a
VersionScreengets that drawn instead, whenever three conditions hold. Failing any one of them falls back to the plain template unchanged, which is a deliberate guarantee rather than a default: that form is the one every machine reader parses.Color reaches the output. Not because a mark needs it â a good one survives having its escapes stripped â but because it is the one lever a caller already has. A redirected
--version, or one run under--no-coloror NO_COLOR, is asking for something parseable.The terminal is wide enough to seat the facts beside the mark without wrapping them.
Accessible mode is off. A mark read out character by character is noise to a screen reader, so
--accessiblekeeps the plain message.
- Return type:
- print_debug_message()[source]¶
Render in debug logs all template fields in color.
A field resolving to a nested structure is dumped as indented JSON under its own label, instead of the single-line
repra template would produce for it. Only:env_info:is built that way today, and it alone accounts for two thirds of this listing: a thousand characters on one line is what a bug report carries otherwise. Upstream reads its profile the same way, through boltons.ecoutils.get_profile_json(indent=True).- Return type:
- class click_extra.ZeroExitOption(param_decls=None, default=False, expose_value=False, is_flag=True, help='Always exit with a status code of 0, even when problems are found.', **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured
-0/--zero-exitoption flag.Follows the convention popularized by linters and static analysers, which exit with a non-zero code whenever they report findings so that automation can gate on it. Setting this flag flips that behavior: the CLI returns
0as long as it ran to completion, reserving non-zero codes for actual execution failures.The resolved value is stored in
ctx.meta[click_extra.context.ZERO_EXIT], aligning with every other Click Extra optionâs per-invocation context-meta storage pattern.Warning
This option is a placeholder: it does not alter the CLIâs exit code by itself. Downstream code must read
ctx.meta[click_extra.context.ZERO_EXIT]and act on it.- set_zero_exit(ctx, param, value)[source]¶
Store the resolved zero-exit flag on the contextâs
metadict.Read via
click_extra.context.get(ctx, click_extra.context.ZERO_EXIT).- Return type:
- click_extra.accessible_option(param_decls: Sequence[str] | None = None, is_flag=True, default=False, is_eager=True, expose_value=False, help='Accessibility mode: disable colors and render tables in a borderless, screen-reader-friendly format.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.ansi_to_html(text)[source]¶
Translate ANSI styling in text to inline-styled HTML
<span>tags.\x1b[34mSummer\x1b[0mbecomes<span style="color: blue">Summer</span>. The spans are self-contained (no stylesheet needed) and also valid in markups accepting inline HTML, like MediaWiki.- Return type:
- click_extra.ansi_to_jira(text)[source]¶
Translate ANSI styling in text to Jira wiki markup.
\x1b[34;1mSummer\x1b[0mbecomes{color:blue}*Summer*{color}.- Return type:
- click_extra.ansi_to_latex(text)[source]¶
Translate ANSI styling in text to LaTeX macros.
\x1b[34;1mSummer\x1b[0mbecomes\textcolor{blue}{\textbf{Summer}}. The colored macros require\usepackage{xcolor}in the document preamble.- Return type:
- click_extra.ansi_to_textile(text)[source]¶
Translate ANSI styling in text to Textile spans.
\x1b[34;1mSummer\x1b[0mbecomes%{color: blue; font-weight: bold}Summer%.- Return type:
- click_extra.args_cleanup(*args)[source]¶
Flatten recursive iterables, remove all
None, and cast each element to strings.Helps serialize
pathlib.Pathand other objects.It also allows for nested iterables and
Nonevalues as CLI arguments for convenience. We just need to flatten and filters them out.
- click_extra.argument(*args, help=None, **attrs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.basicConfig(*, filename=None, filemode='a', format='{levelname}: {message}', datefmt=None, style='{', level=None, stream=None, handlers=None, force=False, encoding=None, errors='backslashreplace', stream_handler_class=<class 'click_extra.logging.StreamHandler'>, file_handler_class=<class 'logging.FileHandler'>, formatter_class=<class 'click_extra.logging.Formatter'>)[source]¶
Configure the global
rootlogger.This function is a wrapper around Python standard libraryâs
logging.basicConfig(), but with additional parameters and tweaked defaults.It sets up the global
rootlogger, and optionally adds a file or stream handler to it.Differences in default values:
Argument
basicConfig()defaultlogging.basicConfig()defaultstyle{%format{levelname}: {message}%(levelname)s:%(name)s:%(message)sThis function takes the same parameters as
logging.basicConfig(), but require them to be all passed as explicit keywords arguments.- Parameters:
filename (
str|None) â Specifies that alogging.FileHandlerbe created, using the specified filename, rather than anStreamHandler.filemode (
str) âIf filename is specified, open the file in this
mode.Defaults to
a.Use the specified format string for the handler.
Defaults to
{levelname}: {message}.datefmt (
str|None) â Use the specified date/time format, as accepted bytime.strftime().style (
Literal['%','{','$']) âIf format is specified, use this style for the format string:
%for printf-style,{forstr.format(),$forstring.Template.
Defaults to
{.level (
int|str|None) â Set therootlogger level to the specified level.stream (
IO[Any] |None) â Use the specified stream to initialize theStreamHandler. Note that this argument is incompatible with filename - if both are present, aValueErroris raised.handlers (
Iterable[Handler] |None) â If specified, this should be an iterable of already created handlers to add to therootlogger. Any handlers which donât already have a formatter set will be assigned the default formatter created in this function. Note that this argument is incompatible with filename or stream - if both are present, aValueErroris raised.force (
bool) â If this argument is specified asTrue, any existing handlers attached to therootlogger are removed and closed, before carrying out the configuration as specified by the other arguments.encoding (
str|None) â Name of the encoding used to decode or encode the file. To be specified along with filename, and passed tologging.FileHandlerfor opening the output file.errors (
str|None) â Optional string that specifies how encoding and decoding errors are to be handled by thelogging.FileHandler. Defaults tobackslashreplace. Note that ifNoneis specified, it will be passed as such toopen().
- Return type:
Important
Always keep the signature of this function, the default values of its parameters and its documentation in sync with the one from Pythonâs standard library.
These new arguments are available for better configurability:
- Parameters:
stream_handler_class (
type[Handler]) â Alogging.Handlerclass that will be used inlogging.basicConfig()to create a default stream-based handler. Defaults toStreamHandler.file_handler_class (
type[Handler]) â Alogging.Handlerclass that will be used inlogging.basicConfig()to create a default file-based handler. Defaults tologging.FileHandler.formatter_class (
type[Formatter]) â Alogging.Formatterclass of the formatter that will be used inlogging.basicConfig()to setup the default formatter. Defaults toFormatter.
Note
I donât like the camel-cased name of this function and would have called it
basic_config(), but itâs kept this way for consistency with Pythonâs standard librarylogging.basicConfig().
- click_extra.cases_from_data(data)[source]¶
Build
CLITestCaseinstances from already-parsed suite data.The in-memory counterpart to
parse_test_suite()(which parses a string) andload_test_suite()(which reads a file): feed it a suite that is already a Python object, such as the nativecasesmappings declared in a[tool.<cli>.test-suite]config section.A suite is a list of case mappings, each keyed by
CLITestCasedirective names. Formats with no bare top-level array (TOML) carry that list under a top-levelcaseskey, so a mapping is unwrapped here.- Raises:
ValueError â the suite is empty, a mapping suite omits
cases, or a case uses unknown directives.TypeError â the suite is not a list, or a case is not a mapping.
- Return type:
- click_extra.clear()[source]¶
Drop-in for
click.clear()that becomes a no-op under--accessible.Clearing the screen wipes the scrollback a screen reader relies on and carries no meaning in a linear stream, so accessibility mode skips it entirely. Outside accessibility mode (or with no active context) it defers to
click.clear(), which already no-ops when stdout is not a terminal.- Return type:
- click_extra.color_option(param_decls: Sequence[str] | None = None, is_flag=False, flag_value='always', default='auto', is_eager=True, expose_value=False, help='Colorize the output. A bare --color is the same as --color=always.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.column_sort_key(header_defs, sort_columns=None, cell_key=None)[source]¶
Build a row sort key from the
sort_columnsa table actually carries.header_defsdescribes the rendered columns:ColumnSpecinstances or(label, column_id)tuples, withcolumn_id=Nonefor columns that cannot be sorted on. The requestedsort_columnsthe table carries drive the comparison first, de-duplicated and in request order; the remaining columns follow in their natural left-to-right order for tie-breaking.Returns
Nonewhen the table carries none of the requested columns, signalling that rows should keep their original order. This is what lets one--sort-byselection apply across subcommands rendering heterogeneous tables: each table sorts by the requested fields it knows, and a table knowing none of them is left untouched.
- click_extra.columns_option(param_decls: Sequence[str] | None = None, columns: Sequence[ColumnSpec] | None = None, type=None, default: Sequence[str] | None = (), expose_value: bool = False, is_eager: bool = True, help: str = 'Restrict and reorder table columns, SQL SELECT-style. Comma-separated list of column IDs. Default: all columns in canonical order.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.command(*args, **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.config_option(param_decls: Sequence[str] | None = None, metavar='CONFIG_PATH', type=UNPROCESSED, help='Location of the configuration file. Supports local path with glob patterns or remote URL.', is_eager: bool = True, expose_value: bool = False, file_format_patterns: dict[ConfigFormat, Sequence[str] | str] | Iterable[ConfigFormat] | ConfigFormat | None = None, file_pattern_flags: int = 4104, roaming: bool = True, force_posix: bool = False, search_pattern_flags: int = 285504, search_parents: bool = False, stop_at: Path | str | Literal[Sentinel.VCS] | None = Sentinel.VCS, cascade: bool = False, excluded_params: Iterable[str] | None = None, included_params: Iterable[str] | None = None, strict: bool = False, config_schema: type | Callable[[dict[str, Any]], Any] | None = None, schema_strict: bool = False, fallback_sections: Sequence[str] = (), config_validators: Sequence[ConfigValidator] = (), **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.config_table_to_flags(table)[source]¶
Translate a mapping of configuration keys into long-form CLI flags.
For tools whose command-line options mirror their configuration keys but which cannot read the table themselves (no
--configsupport, no native config file). Follows the conventional mapping:key = Trueâ--keykey = "value"(or a number) â--key=valuekey = ["a", "b"]â--key=a --key=b(one flag per item)key = Falseis skipped: there is no universal--no-<key>form.
Keys keep their spelling, so hyphenated keys map straight onto long options, and flags follow the mappingâs iteration order.
- click_extra.confirm(text, default=False, abort=False, prompt_suffix=': ', show_default=True, err=False)[source]¶
Prompts for confirmation (yes/no question).
If the user aborts the input by sending a interrupt signal this function will catch it and raise a
Abortexception.- Parameters:
text (
str) â the question to ask.default (
bool|None) â The default value to use when no input is given. IfNone, repeat until input is given.abort (
bool) â if this is set toTruea negative answer aborts the exception by raisingAbort.prompt_suffix (
str) â a suffix that should be added to the prompt.show_default (
bool) â shows or hides the default value in the prompt.err (
bool) â if set to true the file defaults tostderrinstead ofstdout, the same as with echo.
Changed in version 8.3.1: A space is no longer appended to the prompt.
Changed in version 8.0: Repeat until input is given if
defaultisNone.Added in version 4.0: Added the
errparameter.- Return type:
- click_extra.confirmation_option(*param_decls, **kwargs)[source]¶
Add a
--yesoption which shows a prompt before continuing if not passed. If the prompt is declined, the program will exit.
- click_extra.constrained_params(constr, *param_adders)[source]¶
Return a decorator that adds the given parameters and applies a constraint to them. Equivalent to:
@param_adders[0] ... @param_adders[-1] @constraint(constr, <param names>)
This decorator saves you to manually (re)type the parameter names. It can also be used inside
@option_group.Instead of using this decorator, you can also call the constraint itself:
@constr(*param_adders)
but remember that:
Python 3.9 is the first that allows arbitrary expressions on the right of
@;using a long conditional/composite constraint as decorator may be less readable.
In these cases, you may consider using
@constrained_params.Added in version 0.9.0.
- click_extra.constraint(constr, params)[source]¶
Register a constraint on a list of parameters specified by (destination) name (e.g. the default name of
--input-fileisinput_file).
- click_extra.convert_apidoc_rst_to_myst(content)[source]¶
Convert
sphinx-apidocRST to MyST markdown with{eval-rst}blocks.
- click_extra.convert_directory(directory)[source]¶
Convert all Python files in a directory from reST to MyST docstrings.
- click_extra.convert_file(filepath)[source]¶
Apply all conversions to a single Python file.
Returns
Trueif the file was modified.- Return type:
- click_extra.convert_rst_files_in_directory(directory)[source]¶
Convert
sphinx-apidocRST files to MyST markdown in the given directory.For each
.rstfile containing.. automodule::directives:If a
.mdfile with the same stem exists, delete the.rst(the existing markdown takes precedence).Otherwise, convert the RST content to MyST and write a
.mdfile, then delete the.rst.
- click_extra.convert_source(source)[source]¶
Convert reST markup to MyST in a Python moduleâs docstrings and comments.
Docstrings get the full pipeline, in an order that matters: inline constructs (cross-references, links, inline code) run before directives so that directive bodies are already converted when they are dedented into fences. Comments get the inline conversions only, except consecutive full-line
#:comments, whose directives are also converted throughconvert_comment_blocks(). Everything outside docstrings and comments passes through byte-for-byte.- Return type:
- click_extra.detect_source_package(pyproject_path=None)[source]¶
Locate the projectâs single source package from its script entry points.
Reads
[project.scripts]frompyproject.tomland derives the top-level package of each entry point target ("pkg.cli:main"givespkg), so theconvert-to-mystcommand can run bare from a project root.- Parameters:
pyproject_path (
Path|None) â Path of thepyproject.tomlto inspect. Defaults to the one in the current working directory.- Return type:
- Returns:
Path of the single detected package directory.
- Raises:
ValueError â When
pyproject.tomlis missing, declares no script entry point, or several distinct packages are detected.
- click_extra.dir_path(*, path_type=<class 'pathlib.Path'>, exists=False, readable=True, writable=False, executable=False, resolve_path=False, allow_dash=False)[source]¶
Shortcut for
click.Pathwithfile_okay=False, path_type=pathlib.Path.- Return type:
- click_extra.echo(message=None, file=None, nl=True, err=False, color=None)[source]¶
Print a message and newline to stdout or a file. This should be used instead of
print()because it provides better support for different data, files, and environments.Compared to
print(), this does the following:Ensures that the output encoding is not misconfigured on Linux.
Supports Unicode in the Windows console.
Supports writing to binary outputs, and supports writing bytes to text outputs.
Supports colors and styles on Windows.
Removes ANSI color and style codes if the output does not look like an interactive terminal.
Always flushes the output.
- Parameters:
message (
object) â The string or bytes to output. Other objects are converted to strings.file (
IO[Any] |None) â The file to write to. Defaults tostdout.err (
bool) â Write tostderrinstead ofstdout.nl (
bool) â Print a newline after the message. Enabled by default.color (
bool|None) â Force showing or hiding colors and other styles. By default Click will remove color if the output does not look like an interactive terminal.
Changed in version 6.0: Support Unicode output on the Windows console. Click does not modify
sys.stdout, sosys.stdout.write()andprint()will still not support Unicode.Changed in version 4.0: Added the
colorparameter.Added in version 3.0: Added the
errparameter.Changed in version 2.0: Support colors on Windows if colorama is installed.
- Return type:
- click_extra.echo_via_pager(text_or_generator, color=None)[source]¶
Drop-in for
click.echo_via_pager()that streams plainly under âaccessible.A pager is a full-screen, cursor-driven TUI: it traps output behind its own keybindings, hostile to a screen reader consuming a linear stream. Under
--accessiblethe text is written straight to stdout viaclick.echo()instead. Outside accessibility mode (or with no active context) it defers toclick.echo_via_pager(), which already falls back to a plain write when stdout is not a terminal.The argument is normalized exactly as
click.echo_via_pager()does (a generator function is called, a string is emitted as-is, anything else is iterated), so the two behave identically on their inputs.- Return type:
- click_extra.edit(text=None, editor=None, env=None, require_save=True, extension='.txt', filename=None)[source]¶
Edits the given text in the defined editor. If an editor is given (should be the full path to the executable but the regular operating system search path is used for finding the executable) it overrides the detected editor. Optionally, some environment variables can be used. If the editor is closed without changes,
Noneis returned. In case a file is edited directly the return value is alwaysNoneandrequire_saveandextensionare ignored.- Overloads:
text (bytes | bytearray), editor (str | None), env (cabc.Mapping[str, str] | None), require_save (bool), extension (str) â bytes | None
text (str), editor (str | None), env (cabc.Mapping[str, str] | None), require_save (bool), extension (str) â str | None
text (None), editor (str | None), env (cabc.Mapping[str, str] | None), require_save (bool), extension (str), filename (str | cabc.Iterable[str] | None) â None
If the editor cannot be opened a
UsageErroris raised.Note for Windows: to simplify cross-platform usage, the newlines are automatically converted from POSIX to Windows and vice versa. As such, the message here will have
\nas newline markers.- Parameters:
editor (
str|None) â optionally the editor to use. Defaults to automatic detection.env (
Mapping[str,str] |None) â environment variables to forward to the editor.require_save (
bool) â if this is true, then not saving in the editor will make the return value becomeNone.extension (
str) â the extension to tell the editor about. This defaults to.txtbut changing this might change syntax highlighting.filename (
str|Iterable[str] |None) â if provided it will edit this file instead of the provided text contents. It will not use a temporary file as an indirection in that case. If the editor supports editing multiple files at once, a sequence of files may be passed as well. Invokeclick.fileonce per file instead if multiple files cannot be managed at once or editing the files serially is desired.
Changed in version 8.2.0:
filenamenow accepts anyIterable[str]in addition to astrif theeditorsupports editing multiple files at once.
- click_extra.export_config_option(param_decls: Sequence[str] | None = None, type: click.ParamType | Any = None, metavar: str = 'FORMAT', is_eager: bool = True, expose_value: bool = False, help: str = 'Export the configuration in the selected format to <stdout>, then exit.', **kwargs: Any)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.field_docstrings(cls)[source]¶
Extract attribute docstrings from a class body, keyed by field name.
Attribute docstrings are string literals immediately following an annotated assignment in a class body (the PEP 257 convention used by Sphinxâs autodoc). Python discards them at runtime, so they are recovered by parsing the class source with
ast. Each docstring is cleaned up withinspect.cleandoc(), preserving paragraph breaks.Caution
Returns an empty mapping when the class source is unavailable, as for classes defined in an
exec-ed code block (an interactive session, or the body of aclick:sourceSphinx directive). Import the schema from a real module to get its docstrings documented.
- click_extra.file_path(*, path_type=<class 'pathlib.Path'>, exists=False, readable=True, writable=False, executable=False, resolve_path=False, allow_dash=False)[source]¶
Shortcut for
click.Pathwithdir_okay=False, path_type=pathlib.Path.- Return type:
- click_extra.flatten_config_keys(conf, sep='_', opaque_keys=frozenset({}), _prefix='')[source]¶
Flatten nested dicts into a single level by joining keys with a separator.
Useful for mapping nested configuration structures (like TOML sub-tables) to flat Python dataclass fields. After normalization with
normalize_config_keys, the flattened keys match dataclass field names directly:>>> from click_extra.config import ( ... flatten_config_keys, ... normalize_config_keys, ... ) >>> raw = {"dependency-graph": {"all-groups": True, "output": "deps.mmd"}} >>> flatten_config_keys(normalize_config_keys(raw)) {'dependency_graph_all_groups': True, 'dependency_graph_output': 'deps.mmd'}
- Parameters:
sep (
str) â Separator used to join parent and child keys. Defaults to"_"which produces valid Python identifiers when combined withnormalize_config_keys.opaque_keys (
frozenset[str]) â Fully-qualified key names where flattening stops. When the accumulated key matches an entry in this set, the dict value is kept as-is instead of being recursively flattened. This is useful for fields typed asdict[str, X]where the dict keys are data (like GitHub Actions matrix axis names), not config structure._prefix (
str) â Internal parameter for tracking the accumulated key path during recursion. Callers should not set this.
- Return type:
- click_extra.format_cli_prompt(cmd_args, extra_env=None, theme=None, prompt=None)[source]¶
Render the shell prompt simulating a CLI invocation, for logs and dry-runs.
Prefixes
PROMPTto anyextra_envassignments and the command line. Each token family is styled with the theme slot (get_current_theme()) it holds elsewhere in a CLIâs output, so the line reads like the help screens do:the prompt sigil with
bracket, the structural-token style;each environment assignment as
envvarname, plain=,defaultvalue;the programâs binary name with
invoked_command, its directory plain (seehighlight_bin_name());the
-/--flags withoption; other arguments stay plain.
Useful to print a copy-pasteable command trace in debug logs, dry-runs and test output.
- Parameters:
extra_env (
Mapping[str,str|None] |None) â environment assignments to prefix it with.theme (
HelpTheme|None) â palette to style the line with. Defaults to the theme the current invocation runs under, which is what a CLI printing its own trace wants. A caller drawing the line onto a surface of its own choosing (a light capture, say) passes the one that surface can show.prompt (
str|None) â sigil to draw before the command, when the shell being pictured is not the one running. A capture mimicking a Windows terminal passesPS C:\>;NonekeepsPROMPT, which is this platformâs.
- Return type:
- Returns:
the styled prompt line.
- click_extra.format_duration(duration)[source]¶
Render an elapsed duration compactly:
2.3s,1:05, then1:02:03.Below a minute the duration reads as one-decimal seconds (
2.3s). From a minute up it switches to a clock layout, growing an hours field only once it reaches an hour:1:05under an hour,1:02:03at or above.The reverse direction, parsing a human-written duration back into a
timedelta, lives inclick_extra.types(seeDuration).
- click_extra.format_filename(filename, shorten=False)[source]¶
Format a filename as a string for display. Ensures the filename can be displayed by replacing any invalid bytes or surrogate escapes in the name with the replacement character
ïżœ.Invalid bytes or surrogate escapes will raise an error when written to a stream with
errors="strict". This will typically happen withstdoutwhen the locale is something likeen_GB.UTF-8.Many scenarios are safe to write surrogates though, due to PEP 538 and PEP 540, including:
Writing to
stderr, which useserrors="backslashreplace".The system has
LANG=C.UTF-8,C, orPOSIX. Python opens stdout and stderr witherrors="surrogateescape".None of
LANG/LC_*are set. Python assumesLANG=C.UTF-8.Python is started in UTF-8 mode with
PYTHONUTF8=1or-X utf8. Python opens stdout and stderr witherrors="surrogateescape".
- click_extra.format_from_mime(mime_type, formats=None)[source]¶
Return the configuration format a media type designates.
The counterpart of
format_from_path()for a configuration fetched over HTTP, whose URL often carries no usable file extension: theContent-Typeheader is then the only thing typing the payload. The media type is matched against each formatâsmime_types, soapplication/tomlresolves toTOMLandtext/yamltoYAML.formatsrestricts and orders the candidates (the first match wins); it defaults to everyConfigFormat.Parameters are stripped, so a raw
application/yaml; charset=utf-8header value can be passed as-is, and matching is case-insensitive.Note
A RFC 6839 structured syntax suffix is honored, so the
application/vnd.acme.settings+jsona private API answers with resolves toJSON. An exact match wins over a suffix.Returns
Nonefor a media type no format claims, which covers the generictext/plainandapplication/octet-streama server falls back to for an extension it does not recognize.- Return type:
- click_extra.format_from_path(path, formats=None)[source]¶
Return the configuration format whose patterns match a file name.
The name is matched against each formatâs
patterns, soapp.tomlresolves toTOMLandapp.ymltoYAML.formatsrestricts and orders the candidates (the first match wins); it defaults to everyConfigFormat.- Return type:
- click_extra.format_manpage(roff, width=None)[source]¶
Typeset roff into readable terminal text, or
Noneif nothing can.Tries each entry of
MAN_FORMATTERSin turn and returns the output of the first that succeeds. ReturnsNonewhen none of them is installed, which the caller is expected to degrade on rather than fail: a CLI that cannot find a typesetter is a CLI running somewhere that never had man pages to begin with (Windows, a slim container), and that is no reason for--manto error.
- click_extra.format_param_row(param, ctx, path, is_structured)[source]¶
Compute the structural table cells for a Click parameter.
Returns a
dict[column_id, cell]covering every column that can be derived from the parameter object alone (no runtime invocation state or config-file context). Specifically:id,spec,class,param_type,python_type,hidden,exposed,envvars,default,is_flag,flag_value,is_bool_flag,multiple,nargs,prompt, andconfirmation_prompt.Attributes only defined on
click.Option(hidden,is_flag,flag_value,is_bool_flag,prompt,confirmation_prompt) yieldNoneforclick.Argumentparameters: empty cell in visual formats,nullin structured ones.For structured formats (JSON, YAML, etc.), values are native Python types. For visual formats, values are themed strings matching help-screen styling.
The remaining table columns (
allowed_in_conf,value,source,config_file) require live context and are filled in byrender_params_table().
- click_extra.format_size(size, *, units='iec', precision=1)[source]¶
Render a byte count as a compact, human-readable string.
- Parameters:
size (
float) â The number of bytes. A negative value keeps a leading-.units (
Literal['iec','si','jedec']) â The unit system to render in, one of_UNIT_SYSTEMS:iec(the default) for binary powers with the unambiguousKiB/MiBsymbols,sifor decimal powers withkB/MB, orjedecfor binary powers with the customary but impreciseKB/MB.precision (
int) â Number of fractional digits for every unit above bytes. A byte count is always rendered as a whole number.
- Return type:
- Returns:
The size followed by a space and its unit, like
1.5 KiB. The integer part is grouped with thousands separators.- Raises:
ValueError â If units is not a known unit system.
- click_extra.get_app_dir(app_name, roaming=True, force_posix=False)[source]¶
Returns the config folder for the application. The default behavior is to return whatever is most appropriate for the operating system.
To give you an idea, for an app called
"Foo Bar", something like the following folders could be returned:- Mac OS X:
~/Library/Application Support/Foo Bar- Mac OS X (POSIX):
~/.foo-bar- Unix:
~/.config/foo-bar- Unix (POSIX):
~/.foo-bar- Windows (roaming):
C:\Users\<user>\AppData\Roaming\Foo Bar- Windows (not roaming):
C:\Users\<user>\AppData\Local\Foo Bar
Added in version 2.0.
- Parameters:
app_name (
str) â the application name. This should be properly capitalized and can contain whitespace.roaming (
bool) â controls if the folder should be roaming or not on Windows. Has no effect otherwise.force_posix (
bool) â if this is set toTruethen on any POSIX system the folder will be stored in the home folder with a leading dot instead of the XDG config home or darwinâs application support folder.
- Return type:
- click_extra.get_current_context(silent=False)[source]¶
Equivalent to
click.get_current_context()but casts the returnedclick.Contextobject tocloup.Context(which is safe when using cloup commands classes and decorators).- Overloads:
â Context
silent (bool) â Optional[Context]
- click_extra.get_current_theme()[source]¶
Return the theme active for the current CLI invocation.
Resolution order:
The theme stored on the active Click context under
click_extra.context.THEME(set byThemeOptionfrom--theme).The process-wide fallback returned by
get_default_theme()(the dark default, or whateverpatch_click()set at process start).
Falling back through the active context (instead of reading a module attribute) keeps
--themescoped to the invocation that received it, so a second invocation in the same process starts from the default again.- Return type:
- click_extra.get_default_theme()[source]¶
Return the process-wide fallback theme.
Read by
get_current_theme()when no Click context is active or when the active context has no theme set. The default is the built-indarkpalette;patch_click()overrides it viaset_default_theme()for the duration of a patched session.Resolved through a function rather than a module attribute so callers always observe the current value: capturing
default_themeas a default function parameter (the previous pattern) would freeze whatever was set at import time.- Return type:
- click_extra.get_pager_file(color=None)[source]¶
Context manager.
Yields a writable file-like object which can be used as an output pager.
Added in version 8.4.0.
- click_extra.get_param_spec(param, ctx)[source]¶
Extract the option-spec string (like
-v, --verbose) from a parameter.Temporarily unhides hidden options so their help record can be produced.
Note
The
hiddenproperty is only supported byOption, notArgument.Todo
Submit a PR to Click to separate production of param spec and help record. That way we can always produce the param spec even if the parameter is hidden. See: https://github.com/kdeldycke/click-extra/issues/689
- click_extra.get_text_stream(name, encoding=None, errors='strict')[source]¶
Returns a system stream for text processing. This usually returns a wrapped stream around a binary stream returned from
get_binary_stream()but it also can take shortcuts for already correctly configured streams.
- click_extra.get_tool_config(ctx=None)[source]¶
Retrieve the typed tool configuration from the context.
Returns the object stored under
click_extra.context.TOOL_CONFIGbyConfigOptionwhen aconfig_schemais set, orNoneif no schema was configured or no configuration was loaded.
- click_extra.getchar(echo=False)[source]¶
Fetches a single character from the terminal and returns it. This will always return a unicode character and under certain rare circumstances this might return more than one character. The situations which more than one character is returned is when for whatever reason multiple characters end up in the terminal buffer or standard input was not actually a terminal.
Note that this will always read from the terminal, even if something is piped into the standard input.
Note for Windows: in rare cases when typing non-ASCII characters, this function might wait for a second character and then return both at once. This is because certain Unicode characters look like special-key markers.
Added in version 2.0.
- click_extra.group(*args, **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.help_format_option(param_decls: tuple[str, ...] | None = None, expose_value: bool = False, is_eager: bool = True, help: str = 'Render the command in the given format and exit.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.help_option(*args, **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.highlight_bin_name(program, theme=None)[source]¶
Style the binaryâs own name inside
program, leaving its directory plain./opt/homebrew/bin/masrenders with onlymasin the active themeâsinvoked_commandstyle, so the part of the path the eye scans for stands out from the noise of its location. A bare name (no separator) is styled whole. Both POSIX and Windows separators are recognized, whichever comes last.- Parameters:
program (
str) â the command, path and all.theme (
HelpTheme|None) â palette to style with. Defaults to the theme the current invocation runs under, seeformat_cli_prompt().
- Return type:
- Returns:
the styled command.
- click_extra.install_interrupt_handler(ctx)[source]¶
Make the first Ctrl+C terminate in-flight subprocesses, then abort as usual.
Installs a
SIGINThandler for the duration of the CLI run that callsterminate_live_processes()before re-raisingKeyboardInterrupt(exactly what Pythonâs default handler raises). The abort then proceeds normally, but a concurrent fan-out no longer hangs on surviving children. The previous handler is restored whenctxcloses.Must run in the main thread:
signal.signal()refuses to install a handler from any other, so a non-main-thread caller (embedded use, some tests) is a no-op that keeps the default Ctrl+C behavior.A signal handler is required here rather than a
try/except KeyboardInterruptaround the fan-out: Python delivers Ctrl+C only to the main thread, so worker threads never see the interrupt, and the exception unwinds through the executorâs blockingshutdown(wait=True)teardown before anyexceptin the caller could run. The children must be killed at signal-delivery time, ahead of that teardown.- Return type:
- click_extra.install_manpages(command, prog_name=None, **overrides)[source]¶
Write the command treeâs man pages where
mancan find them.Targets
$XDG_DATA_HOME/man/man1when that variable is set, elseMAN_INSTALL_DIR. Returns the written paths.The environment is read here rather than at import time, so a caller that sets
XDG_DATA_HOMEfor one invocation (a test, a packaging script staging into a build root) is honored. This mirrorsinstall_carapace_spec(), whose spec directory resolves the same way.
- click_extra.is_stdout(path)[source]¶
Return
Truewhen path is the stdout sentinel-.Guards against accidentally creating a file literally named
-in the current directory.- Return type:
- click_extra.jobs_option(param_decls: Sequence[str] | None = None, default='auto', expose_value=False, show_default=True, type=<click_extra.execution.JobCount object>, help="Number of parallel jobs. Accepts an integer, 'auto' (the host's logical CPUs minus one) or 'max' (all logical CPUs). 0 runs sequentially.", **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.last_param(params, klass)[source]¶
Return the last parameter of exactly
klassin params, orNone.Unlike
search_params(), this matches the exactklass(no subclasses) and tolerates duplicates: when an option is declared more than once (like an explicit@verbosity_optionstacked on a Click Extra command that already ships one), Click keeps the last occurrence, so this mirrors that here instead of erroring out on the ambiguity.
- click_extra.launch(url, wait=False, locate=False)[source]¶
This function launches the given URL (or filename) in the default viewer application for this file type. If this is an executable, it might launch the executable in a new session. The return value is the exit code of the launched application. Usually,
0indicates success.Examples:
click.launch('https://click.palletsprojects.com/') click.launch('/my/downloaded/file', locate=True)
Added in version 2.0.
- Parameters:
url (
str) â URL or filename of the thing to launch.wait (
bool) â Wait for the program to exit before returning. This only works if the launched program blocks. In particular,xdg-openon Linux does not block.locate (
bool) â if this is set toTruethen instead of launching the application associated with the URL it will attempt to launch a file manager with the file located. This might have weird effects if the URL does not point to the filesystem.
- Return type:
- click_extra.lazy_group(*args, **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.load_test_suite(path)[source]¶
Read a test suite file and parse it by the format of its extension.
The format is resolved from
pathâs name over the list-capableSUITE_FORMATS(sosuite.tomlparses as TOML,suite.yamlas YAML). Reading and format detection are delegated toclick_extra.config.formats.read_file().- Raises:
ValueError â the file extension matches no suite format.
ImportError â the matched formatâs optional parser is not installed.
- Return type:
- click_extra.make_pass_decorator(object_type, ensure=False)[source]¶
Given an object type this creates a decorator that will work similar to
pass_obj()but instead of passing the object of the current context, it will find the innermost context of typeobject_type().This generates a decorator that works roughly like this:
from functools import update_wrapper def decorator(f): @pass_context def new_func(ctx, *args, **kwargs): obj = ctx.find_object(object_type) return ctx.invoke(f, obj, *args, **kwargs) return update_wrapper(new_func, f) return decorator
- Parameters:
object_type (type[T]) â the type of the object to pass.
ensure (bool) â if set to
True, a new object will be created and remembered on the context if itâs not there yet.
- Return type:
t.Callable[[t.Callable[te.Concatenate[T, P], R]], t.Callable[P, R]]
- click_extra.make_schema_callable(schema, *, strict=False, normalize=True, warn_unknown=False)[source]¶
Wrap a schema type into a callable that accepts a raw config dict.
Dataclass types (detected via
dataclasses.is_dataclass) are auto-wrapped: keys are normalized (hyphens to underscores), nested dicts are flattened, and the result is filtered to known fields before instantiation. Three schema-aware features refine this process:Type-aware flattening. Fields typed as
dict[str, X]are treated as opaque:flatten_config_keysstops at their boundary so the dict value is kept intact.Field metadata. Dataclass fields may carry
click_extra.config_path(a dotted TOML path like"test-matrix.replace") andclick_extra.normalize_keys(Falseto skip key normalization on the extracted value). Fields with an explicit path are extracted from the raw config before normalization and flattening.Nested dataclass support. Fields whose resolved type is itself a dataclass are recursively processed with the same logic.
Any other callable is returned as-is. The caller is responsible for key normalization if needed.
NonereturnsNone.
- Parameters:
strict (
bool) â IfTrue, raiseValueErrorwhen the config contains keys that do not match any dataclass field (after normalization and flattening).warn_unknown (
bool) â IfTrue(andstrictisFalse), log a warning naming those same unknown keys instead of silently dropping them. Meant for configs whose section is schema-only (no CLI parameter is merged from it, i.e.included_params=()), where any unrecognized key can only be a typo. Applies recursively to nested dataclasses.normalize (
bool) â IfFalse, skipnormalize_config_keyson the remaining config dict. Used internally when recursing into nested dataclasses whose parent opted out of normalization viaclick_extra.normalize_keys = False.
- Return type:
- click_extra.man_option(param_decls: tuple[str, ...] | None = None, is_flag: bool = True, expose_value: bool = False, is_eager: bool = True, help: str = "Read the command's manual page and exit.", **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.multicall_group(*args, **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.new_logger(name='root', *, propagate=False, force=True, **kwargs)[source]¶
Setup a logger in the style of Click Extra.
By default, this helper will:
Fetch the loggerregistered under thenameparameter, or creates a new one with that name if it doesnât exist,Set the loggerâs
propagateattribute toFalse,Force removal of any existing handlers and formatters attached to the logger,
Attach a new
StreamHandlerwithFormatter,Return the logger object.
This function is a wrapper around
basicConfig()and takes the same keywords arguments.- Parameters:
name (
str) â ID of the logger to setup. IfNone, Pythonâsrootlogger will be used. If a logger with the provided name is not found in the global registry, a new logger with that name will be created.propagate (
bool) â Sets the loggerâspropagateattribute. Defaults toFalse.force (
bool) â Same as the force parameter fromlogging.basicConfig()andbasicConfig(). Defaults toTrue.kwargs â Any other keyword parameters supported by
logging.basicConfig()andbasicConfig().
- Return type:
- click_extra.no_color_option(param_decls: Sequence[str] | None = None, is_flag=True, default=False, is_eager=True, expose_value=False, help='Disable colorization (alias of --color=never).', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.no_config_option(param_decls: Sequence[str] | None = None, type=UNPROCESSED, help='Ignore all configuration files and only use command line parameters and environment variables.', is_flag=True, flag_value=Sentinel.NO_CONFIG, is_eager=True, expose_value=False, **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.normalize_config_keys(conf, opaque_keys=frozenset({}), _prefix='')[source]¶
Normalize configuration keys to valid Python identifiers.
Recursively replaces hyphens with underscores in all dict keys, using the same
str.replace("-", "_")transform that Click applies internally when deriving parameter names from option declarations (--foo-barbecomesfoo_bar). Click does not expose this as a public function, so we replicate the one-liner here.Handles the convention mismatch between configuration formats (TOML, YAML, JSON all commonly use kebab-case) and Python identifiers. Works with all configuration formats supported by
ConfigOption.- Parameters:
opaque_keys (
frozenset[str]) â Fully-qualified key names (using"_"as separator) where recursion stops. The key itself is still normalized, but its dict value is kept as-is. Used in tandem withflatten_config_keysâsopaque_keysto protect data dicts (like GitHub Actions matrix axes) from normalization._prefix (
str) â Internal parameter for tracking the accumulated key path during recursion. Callers should not set this.
Todo
Propose upstream to Click to extract the inline
name.replace("-", "_")into a private_normalize_param_namehelper, so downstream projects like Click Extra can reuse it instead of duplicating the transform.
- click_extra.open_file(filename, mode='r', encoding=None, errors='strict', lazy=False, atomic=False)[source]¶
Open a file, with extra behavior to handle
'-'to indicate a standard stream, lazy open on write, and atomic write. Similar to the behavior of theFileparam type.If
'-'is given to openstdoutorstdin, the stream is wrapped so that using it in a context manager will not close it. This makes it possible to use the function without accidentally closing a standard stream:with open_file(filename) as f: ...
- Parameters:
filename (
str|PathLike[str]) â The name or Path of the file to open, or'-'forstdin/stdout.mode (
str) â The mode in which to open the file.encoding (
str|None) â The encoding to decode or encode a file opened in text mode.lazy (
bool) â Wait to open the file until it is accessed. For read mode, the file is temporarily opened to raise access errors early, then closed until it is read again.atomic (
bool) â Write to a temporary file and replace the given file on close.
Added in version 3.0.
- click_extra.option(*args, group=None, **attrs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.option_group(title, *args, **kwargs)[source]¶
Return a decorator that annotates a function with an option group.
- Overloads:
title (str), help (str), options (Decorator), constraint (Optional[Constraint]), hidden (bool) â Callable[[F], F]
title (str), options (Decorator), help (Optional[str]), constraint (Optional[Constraint]), hidden (bool) â Callable[[F], F]
The
helpargument is an optional description and can be provided either as keyword argument or as 2nd positional argument after thenameof the group:# help as keyword argument @option_group(name, *options, help=None, ...) # help as 2nd positional argument @option_group(name, help, *options, ...)
Changed in version 0.9.0: in order to support the decorator
cloup.constrained_params(),@option_groupnow allows each input decorators to add multiple options.- Parameters:
title (
str) â title of the help section describing the option group.help â an optional description shown below the name; can be provided as keyword argument or 2nd positional argument.
options â an arbitrary number of decorators like
click.option, which attach one or multiple options to the decorated command function.constraint â an optional instance of
Constraint(see Constraints for more info); a description of the constraint will be shown between squared brackets aside the option group title (or below it if too long).hidden â if
True, the option group and all its options are hidden from the help page (all contained options will have theirhiddenattribute set toTrue).
- click_extra.parse_content(fmt, content)[source]¶
Parse content with a single stateless format.
INI is excluded: it needs the CLI parameter structure for type coercion and is handled by ConfigOption.load_ini_config. ARGFILE is excluded for the same reason: it maps command-line tokens to the CLIâs parameters and is handled by ConfigOption.load_argfile_config. SQLITE is excluded too: it is a binary format, read from its file path by ConfigOption.load_sqlite_config instead of a text payload.
PLISTparses here from its XML variant, the only one expressible as a text payload; the binary variant is read from its file path by ConfigOption.load_plist_config.Note
Optional third-party parsers are imported lazily, at the point of use, rather than at module load. Only enabled formats reach this function (disabled ones are filtered out of
ConfigOption.file_format_patterns), so the import always resolves for the formats actually parsed here.- Return type:
- click_extra.parse_duration(value, *, now=None)[source]¶
Parse a friendly, ISO 8601 or RFC 3339 duration into a
timedelta.The soft, library-friendly counterpart of the
Durationparameter type: it accepts the same three input shapes but returnsNoneinstead of raising when value matches none of them, so it suits classifying values read from files or other machine sources. UnlikeDuration, it does not collapse a zero duration toNone:parse_duration("0")istimedelta(0), letting callers tell a zero duration from an unparsable value.Noneis returned only for an empty value, a future timestamp, or a value matching no known form.- Parameters:
- Return type:
- Returns:
The parsed
timedelta(possibly zero), orNone.
- click_extra.parse_friendly_duration(value)[source]¶
Parse only a friendly duration (
7 days,12h, a bare number of days).Returns the parsed
timedelta(possibly zero, so"0 days"istimedelta(0)), orNonefor anything that is not a friendly duration: ISO 8601 forms, calendar units (months, years), and empty or unrecognized values. Seeparse_duration()for the format-detecting umbrella.
- click_extra.parse_iso8601_duration(value)[source]¶
Parse only an ISO 8601 duration (
P7D,PT12H,P1WT6H).Returns the parsed
timedelta(possibly zero, so"PT0S"istimedelta(0)), orNonefor anything that is not an ISO 8601 duration: friendly forms, calendar (year or month) components, and empty or unrecognized values. Seeparse_duration()for the format-detecting umbrella.
- click_extra.parse_test_suite(suite_string, fmt=ConfigFormat.YAML)[source]¶
Parse a serialized test suite string into
CLITestCaseinstances.fmtselects the serialization format, one ofSUITE_FORMATS; it defaults to YAML for string sources with no extension to key on, such as an environment variable.load_test_suite()is the file-based counterpart.- Raises:
ValueError â the suite is empty,
fmtcannot express a suite, a mapping suite omitscases, or a case uses unknown directives.TypeError â the suite is not a list, or a case is not a mapping.
ImportError â the formatâs optional parser is not installed.
- Return type:
- click_extra.pass_context(func)[source]¶
Mark a callback as wanting the active
Contextas its first argument.Clickâs own
click.pass_context()is typed for the baseclick.Context. A handler annotated with click-extraâs enhancedContext(to reach its extra helpers likectx.print_table) therefore fails static type checking: function parameters are contravariant, soCallable[[Context], R]is not assignable where aCallable[[click.Context], R]is expected.This drop-in is typed for the enhanced
Contextand still accepts handlers typed for the baseclick.Context(a wider first parameter is allowed), so both type-check. At runtime it forwards the active context unchanged, exactly likeclick.pass_context().
- click_extra.pass_obj(f)[source]¶
Similar to
pass_context(), but only pass the object on the context onwards (Context.obj). This is useful if that object represents the state of a nested system.- Return type:
t.Callable[P, R]
- click_extra.password_option(*param_decls, **kwargs)[source]¶
Add a
--passwordoption which prompts for a password, hiding input and asking to enter the value again for confirmation.
- click_extra.path(*, path_type=<class 'pathlib.Path'>, exists=False, file_okay=True, dir_okay=True, readable=True, writable=False, executable=False, resolve_path=False, allow_dash=False)[source]¶
Shortcut for
click.Pathwithpath_type=pathlib.Path.- Return type:
- click_extra.pause(info=None, err=False)[source]¶
This command stops execution and waits for the user to press any key to continue. This is similar to the Windows batch âpauseâ command. If the program is not run through a terminal, this command will instead do nothing.
Added in version 2.0.
Added in version 4.0: Added the
errparameter.
- click_extra.prep_path(path)[source]¶
Open path for writing as UTF-8 text, or return stdout for
-.Always yields a UTF-8 stream, stdout included, sidestepping the
UnicodeEncodeErrora non-ASCII payload triggers on Windows, where the console defaults tocp1252. For a real path, missing parent directories are created first, absorbing themkdir -pa caller would otherwise need.Note
When stdout is an in-memory capture with no backing file descriptor (Clickâs test runner, the Sphinx
{click:run}directive that live-renders CLI output in the docs),fileno()raises and the existing stream is returned as-is. Such streams are already Python text objects, so the Windowscp1252concern does not apply: that only bites a real terminal, which always has a descriptor.
- click_extra.print_data(data, table_format, *, default=None, root_element='records', package='click-extra', **kwargs)[source]¶
Serialize arbitrary Python data and print it to the console.
Wraps
serialize_data()with user-friendly error handling for missing optional dependencies.- Parameters:
data (
Any) â Arbitrary data to serialize.table_format (
TableFormat) â Target serialization format.default (
Callable|None) â Fallback serializer for custom types. Defaults tostr.root_element (
str) â Root element name for XML output.package (
str) â Package name for install instructions in error messages.kwargs â Extra keyword arguments forwarded to the underlying serializer.
- Return type:
- click_extra.print_table(table_data, headers=None, table_format=None, sort_key=None, max_column_widths=None, **kwargs)[source]¶
Render a table and print it to the console.
headersentries carrying a column ID (ColumnSpecinstances or(label, column_id)pairs) plug the table into the active--sort-byselection: when no explicitsort_keyis given, rows sort by the selected columns this table carries, and keep their original order when it carries none. Seecolumn_sort_key()for the exact semantics.ANSI codes carried by cell values and headers depend on the format:
Markup formats with native styling support (see
STYLED_FORMATS) get them translated to the formatâs own styling markup, unless color output is disabled (--no-color,NO_COLOR, âŠ).Other markup formats get them stripped from cell values before rendering, unless
--coloris explicitly forced on the command line.Plain-text formats keep them raw, and defer to
echo()âs sensitivity to the global colorization settings.
- Parameters:
sort_key (
Callable[[Sequence[str|None]],Any] |None) â Optional callable passed tosorted()as thekeyargument. When provided, rows are sorted before rendering.max_column_widths (
Sequence[int|Literal['auto'] |None] |int|Literal['auto'] |None) â Width limits, as one entry per column or a single value for all of them. Each entry is a character count,"auto"to absorb the width left on the terminal, orNonefor no limit. Defaults to themax_widthdeclared byColumnSpecheaders. Silently dropped by formats outsideWRAPPABLE_FORMATS.
- Return type:
- click_extra.progressbar(iterable=None, length=None, label=None, hidden=None, show_eta=None, **kwargs)[source]¶
Drop-in for
click.progressbar()honoring--progressand--time.Clickâs own progress bar is determinate, the counterpart to the indeterminate
Spinner. This thin wrapper gates its visibility on the samePROGRESSflag the spinner uses, so a single--no-progress(or--accessible, which lowers theprogressdefault) silences both, and gates its estimated-time display on--time.- Parameters:
hidden (
bool|None) â tri-state. Left at its defaultNone, the bar follows the resolved--progressflag: hidden when the user (or--accessible) turned progress off, shown otherwise. An explicitTrueorFalseforces the bar regardless, mirroring how an explicitcolor=argument overridesctx.coloronclick.echo(). With no active context (the bar used outside a Click command) it defaults to shown.show_eta (
bool|None) â tri-state, likehidden. Left at its defaultNone, the estimated-time-remaining display follows the--time/--no-timeflag: shown under--time, hidden otherwise (its default, or outside a command). An explicitTrueorFalseforces it, keeping a bare barâs timing in step with anOperationTrailâstimer. Clickâs own default isTrue.
- Return type:
ProgressBar[TypeVar(V)]
Note
The
--progressflag gates visibility and--timethe ETA. Color is already handled upstream: Click renders the bar throughclick.echo(), whosecolor=Noneresolves againstctx.color, so--no-color/NO_COLORstrip the barâs ANSI without any work from this wrapper.
- click_extra.prompt(text, default=None, hide_input=False, confirmation_prompt=False, type=None, value_proc=None, prompt_suffix=': ', show_default=True, err=False, show_choices=True)[source]¶
Prompts a user for input. This is a convenience function that can be used to prompt a user for input later.
If the user aborts the input by sending an interrupt signal, this function will catch it and raise a
Abortexception.- Parameters:
text (
str) â the text to show for the prompt.default (
Any|None) â the default value to use if no input happens. If this is not given it will prompt until itâs aborted.hide_input (
bool) â if this is set to true then the input value will be hidden.confirmation_prompt (
bool|str) â Prompt a second time to confirm the value. Can be set to a string instead ofTrueto customize the message.type (
ParamType[Any] |Any|None) â the type to use to check the value against.value_proc (
Callable[[str],Any] |None) â if this parameter is provided itâs a function that is invoked instead of the type conversion to convert a value.prompt_suffix (
str) â a suffix that should be added to the prompt.show_default (
bool|str) â shows or hides the default value in the prompt. If this value is a string, it shows that string in parentheses instead of the actual value.err (
bool) â if set to true the file defaults tostderrinstead ofstdout, the same as with echo.show_choices (
bool) â Show or hide choices if the passed type is a Choice. For example if type is a Choice of either day or week, show_choices is true and text is âGroup byâ then the prompt will be âGroup by (day, week): â.
Changed in version 8.3.3:
show_defaultcan be a string to show a custom value instead of the actual default, matching the help text behavior.Changed in version 8.3.1: A space is no longer appended to the prompt.
Added in version 8.0:
confirmation_promptcan be a custom string.Added in version 7.0: Added the
show_choicesparameter.Added in version 6.0: Added unicode support for cmd.exe on Windows.
Added in version 4.0: Added the
errparameter.- Return type:
- click_extra.quiet_option(param_decls: Sequence[str] | None = None, **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.read_file(path, formats=None)[source]¶
Read a file and parse it, picking the format from its name.
The format is resolved with
format_from_path()overformats(everyConfigFormatby default), then the content is parsed withparse_content().- Raises:
ValueError â the file name matches none of the candidate
formats.ImportError â the matched formatâs optional parser is not installed.
- Return type:
- click_extra.read_manpage(command, ctx=None)[source]¶
Typeset a commandâs manual and send it to the pager.
The reading counterpart of
--help-format man, which emits the roff source a packager installs. Falls back to printing that source, with a warning naming what to install, when no typesetter is available: something on screen beats an error, and the source still carries every word of the manual.Under
--accessiblethe emphasis is stripped and the pager bypassed (echo_via_pager()streams instead). Both matter to the same reader: a pager is a cursor-driven takeover, and overstrike is worse than the ANSI codes accessible mode already removes, since a screen reader voicesN\x08NA\x08AM\x08ME\x08Erather than skipping it.- Return type:
- click_extra.register_theme(name, theme)[source]¶
Register a named theme in the module-level
theme_registry.
- click_extra.render_ansi(text, emitter)[source]¶
Rebuild text, replacing each ANSI-styled run by emitterâs markup.
Unstyled runs pass through verbatim, so any markup surrounding the styled runs (table borders, tags produced by another renderer) is preserved byte for byte. Styled runs are handed to emitter one line at a time: runs are split on newlines so no markup wrapper ever crosses a line boundary, which keeps line-oriented markup (LaTeX rows, wiki tables) well-formed even when a style spans multiple lines.
- Return type:
- click_extra.render_columns_markdown_table(columns)[source]¶
Render an iterable of
ColumnSpecas a 2-column Markdown table.Output shape:
| Column | Description | | :--- | :--- | | ``Label`` | description | ...
Suitable for inlining into MyST documents via
myst_substitutionsso the Available columns reference can be auto-generated from a single source of truth.- Return type:
- click_extra.render_command_tree(command, prog_name=None, ctx=None, width=None)[source]¶
Render the hierarchy rooted at
commandas a tree with descriptions.Reuses
ctxwhen given (like the live invocation context), otherwise builds a throwaway one withresilient_parsing=True. The root line is labeled withprog_namewhen given, else the contextâs command path.Each node carries the command name, its aliases, its operand metavars (mirroring the usage line) and a column-aligned description from
full_short_help(), so deprecated commands carry their(Deprecated)marker. Everything is styled with the same theme slots as help screens (invoked_commandfor the root,subcommandandaliasfor children,metavarfor operands), so the tree follows--themeand--color. The rail switches from box-drawing to ASCII when accessibility mode is active on the context (seeACCESSIBLE).Descriptions wrap at
width, resolved like help screens when not given (ctx.make_formatter(), honoring theterminal_widthandmax_content_widthcontext settings). Wrapped lines keep the tree rail running through the description column. A label wider than the column (typically a long script path as the root, underwrap --tree) keeps its line to itself and hangs its description underneath, at the column.Note
The tree is a point-in-time snapshot: groups computing their subcommands from external state (plugins, scanned directories) render exactly what
click.Group.list_commands()returns at that moment, in listing order. Cloup section groupings are not rendered.Caution
A non-group command renders as a single root line: valid, just not very interesting. Like a man page, the output stays meaningful for every command type.
- Return type:
- click_extra.render_help(command, help_format, prog_name=None, ctx=None, **overrides)[source]¶
Render command in one of the
HELP_FORMATS.Reuses
ctxwhen given (like the live invocation context), otherwise builds a throwaway one withresilient_parsing=True, exactly likerender_manpage(). Keyword overrides are passed through toextract_command_doc(), and ignored by thecarapaceformat, which carries no version or authorship of its own.- Raises:
ValueError â on an unknown format, listing the known ones.
- Return type:
- click_extra.render_manpage(command, prog_name=None, ctx=None, **overrides)[source]¶
Render a single commandâs man page as a roff string.
Reuses
ctxwhen given (like the live invocation context), otherwise builds a throwaway one withresilient_parsing=True. Keyword overrides (version,date,manual,authors,copyright) are passed through toextract_command_doc().- Return type:
- click_extra.render_manpages(command, prog_name=None, **overrides)[source]¶
Render the whole command tree, one man page per (sub)command.
Returns an ordered mapping of
{filename: roff}where each filename is the command path joined by hyphens plus the section suffix (likeweather-forecast.1).
- click_extra.render_table(table_data, headers=None, table_format=None, sort_key=None, max_column_widths=None, **kwargs)[source]¶
Render a table and return it as a string.
headersentries carrying a column ID (ColumnSpecinstances or(label, column_id)pairs) plug the table into the active--sort-byselection: when no explicitsort_keyis given, rows sort by the selected columns this table carries, and keep their original order when it carries none. Seecolumn_sort_key()for the exact semantics.- Parameters:
sort_key (
Callable[[Sequence[str|None]],Any] |None) â Optional callable passed tosorted()as thekeyargument. When provided, rows are sorted before rendering.max_column_widths (
Sequence[int|Literal['auto'] |None] |int|Literal['auto'] |None) â Width limits, as one entry per column or a single value for all of them. Each entry is a character count,"auto"to absorb the width left on the terminal, orNonefor no limit. Defaults to themax_widthdeclared byColumnSpecheaders. Silently dropped by formats outsideWRAPPABLE_FORMATS.
- Return type:
- click_extra.require_sibling_param(params, requester, klass)[source]¶
Return the sibling klass parameter declared on the same command, or raise.
Some options are inert on their own: they drive machinery owned by a sibling option.
--no-configand--validate-config, for instance, both depend on the--configoption (ConfigOption). This helper centralizes the lookup so every such option raises the sameRuntimeErrorwhen its required sibling is missing, naming the offending flag.- Parameters:
- Return type:
- click_extra.resolve_jobs(ctx, count, *, serial_at_debug=False)[source]¶
Resolve how many worker threads to use for a batch of
countitems.Returns the number of items to process in parallel;
1means run sequentially in the calling thread. This is the policy shared byrun_jobs()andrun_lanes(), exposed on its own for callers that must know the resolved count before they fan out (for example to pick a progress-rendering mode). It collapses to sequential when:there is no active CLI context (programmatic or test use),
a single item leaves nothing to parallelize, or
the resolved
JobsOptioncount (ctx.meta[click_extra.context.JOBS]) is1or less.
Otherwise that count wins, capped at
count: there is no point spinning up more workers than there are items.- Parameters:
ctx (
Context|None) â the active Click context, read for the resolved--jobscount (and, withserial_at_debug, the verbosity).Noneforces sequential.count (
int) â how many items are about to be scheduled.serial_at_debug (
bool) â when set, also collapse to sequential atDEBUGverbosity, where coherent per-worker log narration matters more than the speed-up (interleaved threads would scramble it). Off by default.
- Return type:
- click_extra.run_cli(args, *, extra_env=None, cwd=None, timeout=None, label=None, merge_streams=False, errors='replace', windows_creation_flags=0, start_new_session=False, command_level=20, output_level=10, log=None)[source]¶
Run a CLI in a subprocess, disclosing the call and streaming its output live.
A
subprocess.run()work-alike for CLI-wrapping tools, with observability built in:the invocation is logged before the spawn, as the copy-pasteable
$ ENV=value command argsline offormat_cli_prompt(), so a user can reproduce by hand what the tool runs on their system;each line of the childâs output is forwarded to the logger as it is produced (ANSI-stripped, tagged with
label), instead of being held back until the child exits, so a long-running command narrates its progress live;the child is registered in the live-process registry for the duration of the call, so
terminate_live_processes()(wired to Ctrl+C byinstall_interrupt_handler()) can abort it.
Contract mirrored from
subprocess.run():returns a
subprocess.CompletedProcesswith the full capturedstdoutandstderrdecoded as UTF-8;raises
subprocess.TimeoutExpired(with the partial capture attached) when the child, or the draining of its output, outlivestimeout. The child is killed first â its whole process tree on Windows (see_kill_windows_process_tree()), its whole POSIX process group when spawned withstart_new_session, the direct child alone otherwise;a
KeyboardInterruptmid-run kills the child (with the same tree, group or direct scope), then propagates.
The child reads from
subprocess.DEVNULLso it can never block onstdin, and never opens a console window on Windows.Note
The pipes are opened in universal-newlines text mode, so a bare
\r(a child redrawing a progress bar in place) terminates a line just like\n: each redraw is streamed as its own log line, and the captured text normalizes both to\n, exactly assubprocess.Popen.communicate()does.- Parameters:
args (
str|Path|None|Iterable[str|Path|None|Iterable[Iterable[str|Path|None|Iterable[TNestedArgs]]]]) â the command line. Nested iterables are flattened,Nonevalues dropped, and every element (Path, versions, âŠ) cast to a string; seeargs_cleanup().extra_env (
Mapping[str,str|None] |None) â environment variables forced over the inherited environment for this call (seeenv_copy()). They are part of the disclosed prompt line, since reproducing the call requires them.cwd (
Path|str|None) â directory to run the child in.Noneinherits the callerâs, which issubprocess.run()âs own default. A relativeargs[0]is resolved by the OS against this directory, not the callerâs, so pass an absolute path (or a name on thePATH) when moving the child elsewhere.timeout (
float|None) â seconds before the child is killed.Nonewaits forever.label (
str|None) â tag identifying this call on each streamed output line, for when several children interleave in one log. Carried as the recordâslabelattribute, whichclick_extra.logging.Formatterrenders glued to the level name and styled like an invoked command (debug:mas: Warning: ...); a foreign formatter can readrecord.labelitself. Applied to the output lines only, never the prompt line.merge_streams (
bool) â route the childâsstderrintostdoutso the OS interleaves both in write order. The resultâsstderris thenNone, like asubprocess.run()call withstderr=STDOUT.errors (
str) â decoding error handler for the childâs output. The default"replace"swaps undecodable bytes forïżœ; pass"backslashreplace"to keep them inspectable as escapes.windows_creation_flags (
int) â extra Windows process-creation flags, OR-ed with the always-onCREATE_NO_WINDOW. No-op off Windows.start_new_session (
bool) â make the child lead its own POSIX session and process group (subprocess.Popenâs parameter of the same name). Every kill path â thetimeoutoverrun, a mid-runKeyboardInterrupt, andterminate_live_processes()â then signals the whole group, so a grandchild spawned by the child (a shim re-executing the real binary, an installer helper) is reaped along with it instead of surviving as an orphan holding the output pipes open. Off by default, and to be left off when a descendant must keep the controlling terminal: a new session detaches from it, so an interactive prompt raised from inside the child (sudoreading/dev/tty) would fail, andsudoâs tty-keyed credential cache would no longer match. No-op on Windows, where the timeout path already kills the full tree. Only the reaping half of this flag has that Windows equivalent, and the other half has none: a POSIX session also detaches the child from the controlling terminal, where a Windows child keeps sharing the parentâs console and can still reach back into it. A subprocess-heavy test suite is where that surfaces âmeta-package-managerâs Windows CI saw a package managerâs own teardown land in the parentpytestprocess as a mid-runKeyboardInterrupt, which a console control event on the shared console explains and which no POSIX runner showed. The lever there iswindows_creation_flags(CREATE_NEW_PROCESS_GROUP), left to the caller because it also changes how a real Ctrl-C reaches the child.command_level (
int) â logging level of the invocation-disclosure line. Defaults tologging.INFO; lower it tologging.DEBUGfor internal probes not worth narrating.output_level (
int) â logging level of the streamed output lines. Defaults tologging.DEBUG.log (
Logger|None) â destination logger. Defaults to the root logger, whose level theVerbosityOptionfamily manages.
- Return type:
- click_extra.run_config_validation(user_conf, *, app_name, params_template, config_schema=None, config_validators=(), fallback_sections=(), schema_strict=False, schema_warn_unknown=False, strict=False, blocked_params=(), collect_all=True)[source]¶
Validate a parsed configuration document in one schema-driven pass.
This is the module-level entry point that unifies click-extraâs three historical validation paths (CLI-parameter strict check, dataclass schema, and app-registered
ConfigValidatorhooks) behind a single function yielding a single error type. It is deliberately not namedvalidate_config: that name belongs tovalidate_config(), the callback powering the--validate-configflag.Stages, in order:
Normalize. Strip reserved keys and expand dotted keys.
Partition. Split opaque sub-trees (schema extension fields plus every registered validatorâs
extension_path) from the CLI-flag-bound content. Extracted sub-trees land inValidationReport.opaque_subtrees.Strict-check the CLI-flag-bound part against
params_template, keeping the merged result asValidationReport.merged_conf(skipped whenparams_templateisNone).Schema-build the app section through the configured callable, producing
ValidationReport.schema_instance.Validate every opaque sub-tree through its registered validator.
- Parameters:
user_conf (
dict[str,Any]) â The full parsed configuration document.app_name (
str) â Name of the appâs section (used to resolve the section and to root opaque paths and error paths at the document level).params_template (
dict[str,Any] |None) â The CLI-parameter template the strict check runs against. PassNoneto skip the strict check entirely (for example, for a schema-only validation).config_schema (
type|Callable[[dict[str,Any]],Any] |None) â Dataclass type or callable describing the typed configuration, orNone.config_validators (
Sequence[ConfigValidator]) â Extension validators to run against opaque sub-trees.fallback_sections (
Sequence[str]) â Legacy section names to try whenapp_nameis absent or empty.schema_strict (
bool) â Reject keys the dataclass schema does not recognize.schema_warn_unknown (
bool) â In lax mode, log a warning naming keys the dataclass schema does not recognize (seewarn_unknowninmake_schema_callable()). Ignored whenschema_strictrejects them outright.strict (
bool) â Reject keys the CLI-parameter template does not recognize.blocked_params (
Iterable[str]) â Fully-qualified IDs of parameters excluded from configuration files, used to sharpen strict-mode error messages (a blocked parameter is reported as such, not as unknown).collect_all (
bool) â WhenTrue(default), run every stage and collect all errors. WhenFalse, the first error short-circuits the rest.
- Return type:
- Returns:
A
ValidationReport.ValidationErroris the single error type recorded by every stage;ValueError/TypeErrorraised by the strict check or schema callable are wrapped into it.
- click_extra.run_jobs(func, items, *, jobs=None, serial_at_debug=False)[source]¶
Run
funcoveritems, parallelized per the resolved--jobscount.The worker count is taken from
jobswhen given, else resolved from the active commandâsJobsOptionvalue byresolve_jobs(), else1. With a single worker (or at most one item) the items run sequentially and lazily, so a caller can stop early on the first result (for example to abort on the first failure); otherwise they run in a thread pool. Either way results are yielded in submission order, likemap().This is the single-task-per-item special case of
run_lanes()(every item is its own lane). Reach forrun_lanes()when some items must run serially relative to one another while others run concurrently.The pool is thread-based, which suits the I/O- and subprocess-bound work CLI tools usually parallelize (each child releases the GIL). The count is a number of logical CPUs: see
CPU_COUNT.itemsis never materialized: only a bounded window of tasks is queued at a time, so an unbounded or expensive-to-produce stream stays memory-flat and is read no further than the caller consumes.- Parameters:
func (
Callable[[TypeVar(T)],TypeVar(R)]) â Called once per item; its return value is yielded.items (
Iterable[TypeVar(T)]) â The work items. Read lazily, a window at a time.jobs (
int|None) â Override the worker count instead of reading it from the context.1or fewer forces sequential execution.serial_at_debug (
bool) â forwarded toresolve_jobs()whenjobsis not given: collapse to sequential atDEBUGverbosity.
- Return type:
- Returns:
An iterator over
funcâs results, in the order ofitems.
- click_extra.run_lanes(func, lanes, *, jobs=None, serial_at_debug=False)[source]¶
Run
funcover grouped items: serial within a lane, concurrent across.Each lane is an iterable of items.
funcis mapped over every item, but a laneâs own items run serially and in order on a single worker, while distinct lanes run concurrently up to the resolved--jobscount. This is the right primitive when some work must be serialized relative to itself (a shared lock, a rate limit, one mailbox file, one package-manager backend) yet still overlap with unrelated work.run_jobs()is the degenerate case where every lane holds a single item. Concurrency is sized by the number of lanes (one worker per lane), since a lane never splits across workers.Results are yielded in lane-submission order, a laneâs items in order, like
map(). The run stays lazy at any worker count: a lane is materialized only when it is about to be scheduled, and only a bounded window of lanes is in flight, so a caller can break early and the lanes behind it are never read. A lane runs entirely on one worker, so a stateful resource bound to the lane (a per-lane cache, a connection) is touched by only that one thread and needs no lock.- Parameters:
func (
Callable[[TypeVar(T)],TypeVar(R)]) â Called once per item; its return value is yielded.lanes (
Iterable[Iterable[TypeVar(T)]]) â The lanes, each an iterable of items. Read lazily, a window of lanes at a time; a laneâs own items are materialized when it is scheduled.jobs (
int|None) â Override the worker count instead of reading it from the context.1or fewer forces fully sequential execution.serial_at_debug (
bool) â forwarded toresolve_jobs()whenjobsis not given: collapse to sequential atDEBUGverbosity.
- Return type:
- Returns:
An iterator over
funcâs results, lane by lane in submission order.
- click_extra.run_test_suite(command, cases, *, jobs=1, select_test=None, skip_platform=None, timeout=None, work_directory=None, exit_on_error=False, show_trace_on_error=True, stats=True, show_progress=True)[source]¶
Run a list of test cases against a target command and tally the results.
Cases are parallelized per
jobs(seeclick_extra.execution.run_jobs()): at one worker they run sequentially and lazily, soexit_on_errorcan stop before the rest start; otherwise they run in a thread pool and every case runs to completion. Either way outcomes are tallied in submission order. On an interactive terminal aclick_extra.spinner.Spinnerreports progress unlessshow_progressis false.- Parameters:
command (
Path|str) â The target to test: a command name, a command line, or a path to a binary or script.cases (
Sequence[CLITestCase]) â The test cases to run.jobs (
int) â Number of parallel workers;1runs sequentially.select_test (
Sequence[int] |None) â 1-based case numbers to run; others are skipped.skip_platform (
Trait|Group|str|None|Iterable[Trait|Group|str|None|Iterable[Trait|Group|str|None|Iterable[Trait|Group|str|None|Iterable[_TNestedReferences]]]]) â Extra platforms (or group IDs) to skip every case on.timeout (
float|None) â Default per-case timeout in seconds when a case sets none.work_directory (
Path|str|None) â Directory every case runs its command in, defaulting to the runnerâs own. It moves the target, never the runner: the suite file is read before any case starts, andcommandis resolved to an absolute path first, so neither is looked up relative to it.exit_on_error (
bool) â Stop at the first failure (sequential runs only).show_trace_on_error (
bool) â Echo the execution trace of each failed case.stats (
bool) â Echo a one-line worker summary up front and a result tally.show_progress (
bool) â Allow the progress spinner on an interactive terminal.
- Return type:
- Returns:
A
collections.Counterwithtotal,skipped, andfailedkeys. A non-zerofailedcount signals the caller to exit with an error.
- click_extra.schema_field_infos(schema)[source]¶
Walk a configuration schema dataclass into per-option records.
Introspects the dataclass fields, their type annotations, defaults, and attribute docstrings. Nested dataclass fields expand recursively into dotted keys (
test-suite.timeout), honoringclick_extra.config.schema.CONFIG_PATH_METADATA_KEYat every level. Records are sorted by key, segment-wise, so a sub-tableâs options stay contiguous even when another tableâs name shares their prefix (workflow.syncsorts beforeworkflow-pins.sync).Defaults are read off a pristine
schema()instance, so every field must carry a default: configuration schemas are default-complete by construction, sincemake_schema_callable()instantiates them from partial user data.- Raises:
TypeError â when
schemais not a dataclass type.- Return type:
- click_extra.search_params(params, klass, include_subclasses=True, unique=True)[source]¶
Search a particular class of parameter in a list and return them.
- Parameters:
params (
Iterable[Parameter]) â list of parameter instances to search in.klass (
type[Parameter]) â the class of the parameters to look for.include_subclasses (
bool) â ifTrue, includes in the results all parameters subclassing the providedklass. IfFalse, only matches parameters which are strictly instances ofklass. Defaults toTrue.unique (
bool) â ifTrue, raise an error if more than one parameter of the providedklassis found. Defaults toTrue.
- Return type:
- click_extra.secho(message=None, file=None, nl=True, err=False, color=None, **styles)[source]¶
This function combines
echo()andstyle()into one call. As such the following two calls are the same:click.secho('Hello World!', fg='green') click.echo(click.style('Hello World!', fg='green'))
All keyword arguments are forwarded to the underlying functions depending on which one they go with.
Non-string types will be converted to
str. However,bytesare passed directly toecho()without applying style. If you want to style bytes that represent text, callbytes.decode()first.Changed in version 8.0: A non-string
messageis converted to a string. Bytes are passed through without style applied.Added in version 2.0.
- Return type:
- click_extra.select_columns(columns, selected_ids)[source]¶
Filter and reorder
columnsaccording toselected_ids.Returns
columnsunchanged whenselected_idsis falsy (no projection). Otherwise yields the matchingColumnSpecin the orderselected_idsspecifies, SQL-SELECT-style. RaisesKeyErrorfor unknown IDs so the caller can convert it into aclick.UsageError.- Return type:
- click_extra.select_row(row, selected_ids, canonical_ids)[source]¶
Build a positional row by reading cells from
rowin the selection order.Falls back to
canonical_idswhenselected_idsis empty / unset, so the row preserves its canonical column order in the absence of any user selection.- Return type:
- click_extra.serialize_content(fmt, data, **kwargs)[source]¶
Serialize a Python object to a string in the given format.
The dumping counterpart to
parse_content(). Per-format defaults can be overridden throughkwargs(forwarded to the underlying serializer). JSON5 and JSONC are emitted as plain JSON, a valid subset of both.Caution
Not every format round-trips:
TOML,XMLandPLISThave no null type (plistlibeven raises onNonevalues), andXMLexpects a single root mapping, so the caller is responsible for shapingdataaccordingly.INI,SQLITEandpyproject.tomlhave no serializer here.Note
Optional third-party serializers are imported lazily, at the point of use. Writing
TOMLusestomlkit(the[toml]extra), unlike reading which relies on the built-intomllib.- Raises:
ValueError â the format has no serializer.
- Return type:
- click_extra.serialize_data(data, table_format, *, default=None, root_element='records', **kwargs)[source]¶
Serialize arbitrary Python data to a structured format.
Unlike
render_table()which expects tabular rows and headers, this function accepts any JSON-compatible data structure (dicts, lists, nested combinations) and serializes it to the requested format.Only formats in
SERIALIZATION_FORMATSare supported.- Parameters:
data (
Any) â Arbitrary data to serialize (dicts, lists, scalars).table_format (
TableFormat) â Target serialization format.default (
Callable|None) â Fallback serializer for types not natively supported. Defaults tostr, soPathand similar types are stringified automatically. Set to a custom callable for different behavior.root_element (
str) â Root element name for XML output.kwargs â Extra keyword arguments forwarded to the underlying serializer (like
sort_keysorindentfor JSON).
- Raises:
ValueError â If the format is not a serialization format.
- Return type:
- click_extra.set_default_theme(theme)[source]¶
Override the process-wide fallback theme.
ThemeOptionwrites its picked theme toctx.metarather than calling this helper, so per-invocation choices do not leak across invocations sharing the same process. Use this only for genuinely process-wide overrides:patch_click()is the canonical caller.- Return type:
- click_extra.show_params_option(param_decls: Sequence[str] | None = None, is_flag=True, expose_value=False, is_eager=True, help='Show all CLI parameters, their provenance, defaults and value, then exit.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.sort_by_option(*header_defs, cls=<class 'click_extra.table.SortByOption'>, group=None, **kwargs)[source]¶
Attach a
SortByOptionto a command.Forwards the positional
header_defs((label, column_id)pairs) straight to the option constructor and registers a regular CloupOption, so the--sort-byoption composes with@option_groupand@constraintlike any other option decorator.Note
Hand-written instead of produced by
decorator_factory()becauseSortByOptionaccepts its column definitions as positional arguments, which conflicts with theparam_decls-first convention the factory relies on.
- click_extra.split_ansi(text)[source]¶
Split text into
(style, text)runs at ANSI SGR escape boundaries.A stateful SGR stream parser: each escape updates the current style state (with full and selective resets honored, unlike
Style.from_ansi()), and every maximal run of text sharing the same state is yielded with itsStyle. Unstyled text is yielded with an emptyStyle. Consecutive runs with equal styles are merged and empty runs are dropped, so wrapping each yielded run produces minimal markup.Non-SGR escapes carry no style information and are removed from the yielded text, per
_strip_unsupported_ansi().
- click_extra.style(text, fg=None, bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, reset=True)[source]¶
Styles a text with ANSI styles and returns the new string. By default the styling is self contained which means that at the end of the string a reset code is issued. This can be prevented by passing
reset=False.Examples:
click.echo(click.style('Hello World!', fg='green')) click.echo(click.style('ATTENTION!', blink=True)) click.echo(click.style('Some things', reverse=True, fg='cyan')) click.echo(click.style('More colors', fg=(255, 12, 128), bg=117))
Supported color names:
black(might be a gray)redgreenyellow(might be an orange)bluemagentacyanwhite(might be light gray)bright_blackbright_redbright_greenbright_yellowbright_bluebright_magentabright_cyanbright_whitereset(reset the color code only)
If the terminal supports it, color may also be specified as:
An integer in the interval [0, 255]. The terminal must support 8-bit/256-color mode.
An RGB tuple of three integers in [0, 255]. The terminal must support 24-bit/true-color mode.
See https://en.wikipedia.org/wiki/ANSI_color and https://gist.github.com/XVilka/8346728 for more information.
- Parameters:
text (
Any) â the string to style with ansi codes.fg (
int|tuple[int,int,int] |str|None) â if provided this will become the foreground color.bg (
int|tuple[int,int,int] |str|None) â if provided this will become the background color.bold (
bool|None) â if provided this will enable or disable bold mode.dim (
bool|None) â if provided this will enable or disable dim mode. This is badly supported.underline (
bool|None) â if provided this will enable or disable underline.overline (
bool|None) â if provided this will enable or disable overline.italic (
bool|None) â if provided this will enable or disable italic.blink (
bool|None) â if provided this will enable or disable blinking.reverse (
bool|None) â if provided this will enable or disable inverse rendering (foreground becomes background and the other way round).strikethrough (
bool|None) â if provided this will enable or disable striking through text.reset (
bool) â by default a reset-all code is added at the end of the string which means that styles do not carry over. This can be disabled to compose styles.
Changed in version 8.0: A non-string
messageis converted to a string.Changed in version 8.0: Added support for 256 and RGB color codes.
Changed in version 8.0: Added the
strikethrough,italic, andoverlineparameters.Changed in version 7.0: Added support for bright colors.
Added in version 2.0.
- Return type:
- click_extra.table_format_option(param_decls: Sequence[str] | None = None, type=EnumChoice('aligned', 'asciidoc', 'colon-grid', 'csv', 'csv-excel', 'csv-excel-tab', 'csv-unix', 'double-grid', 'double-outline', 'fancy-grid', 'fancy-outline', 'github', 'grid', 'heavy-grid', 'heavy-outline', 'hjson', 'html', 'jira', 'json', 'json5', 'jsonc', 'latex', 'latex-booktabs', 'latex-longtable', 'latex-raw', 'mediawiki', 'mixed-grid', 'mixed-outline', 'moinmoin', 'orgtbl', 'outline', 'pipe', 'plain', 'presto', 'pretty', 'psql', 'rounded-grid', 'rounded-outline', 'rst', 'simple', 'simple-grid', 'simple-outline', 'textile', 'toml', 'tsv', 'unsafehtml', 'vertical', 'xml', 'yaml', 'youtrack'), default=TableFormat.ROUNDED_OUTLINE, expose_value=False, is_eager=True, help='Rendering style of tables.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.telemetry_option(param_decls: Sequence[str] | None = None, default=False, expose_value=False, envvar=None, show_envvar=True, help='Collect telemetry and usage data.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.terminate_live_processes()[source]¶
Send
SIGTERMto every subprocess currently running throughrun_cli().Called from the main threadâs
SIGINThandler (seeinstall_interrupt_handler()) so a concurrent fan-out aborts promptly: terminating the children unblocks the worker threads parked inrun_cli(), letting the thread pool drain instead of hanging on a child that ignored the terminalâs process-groupSIGINT.A child spawned with
start_new_sessionnever receives the terminalâsSIGINTat all (it left the foreground process group), so its whole group is signalled here, descendants included.Uses
SIGTERMrather thanSIGKILLso a child still gets to clean up, notably to restore terminal state asudopassword prompt may have altered. The registry is snapshotted under the lock, then signalled outside it, becauserun_cli()may be discarding its own entries from other threads at the same time.- Return type:
- click_extra.theme_option(param_decls: Sequence[str] | None = None, default: str = 'dark', is_eager: bool = True, expose_value: bool = False, query_background: bool = False, help: str = 'Color theme used for help screens.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.timer_option(param_decls: Sequence[str] | None = None, default=False, expose_value=False, is_eager=True, help='Measure and print elapsed execution time.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.tree_option(param_decls: tuple[str, ...] | None = None, is_flag: bool = True, expose_value: bool = False, is_eager: bool = True, help: str = 'Show the tree of nested subcommands and exit.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.unstyle(text)[source]¶
Removes ANSI styling information from a string. Usually itâs not necessary to use this function as Clickâs echo function will automatically remove styling if necessary.
Added in version 2.0.
- click_extra.validate_config_option(param_decls: Sequence[str] | None = None, type: click.ParamType | Any = <click.types.Path object>, is_eager: bool = True, expose_value: bool = False, help: str = 'Validate the configuration file and exit.', **kwargs: Any)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.verbose_option(param_decls: Sequence[str] | None = None, **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.verbosity_option(param_decls: Sequence[str] | None = None, default_logger: Logger | str = 'root', default: LogLevel = LogLevel.WARNING, metavar='LEVEL', type=EnumChoice('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'), help='Either CRITICAL, ERROR, WARNING, INFO, DEBUG.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.version_option(version=None, *param_decls, cls=<class 'click_extra.version.VersionOption'>, group=None, **kwargs)[source]¶
Attach a
VersionOptionto a command.Drop-in compatible with Clickâs
@version_option: the first positional argument may be an explicit version string. click-extra otherwise auto-detects the version and treats positional arguments as option flags (like every other option decorator), so the two are disambiguated by their leading character: a value starting with-is a flag declaration, anything else is a Click-style version string forwarded into theversiontemplate field.@command @version_option("1.2.3") # Click idiom: pins the displayed version. def my_cmd(): ...
Note
Hand-written instead of produced by
decorator_factory()because Clickâs leadingversionpositional conflicts with theparam_decls-first convention the factory relies on.
- click_extra.wrap_ansi(text, width)[source]¶
Wrap text to width visible columns, preserving its ANSI styling.
textwrap.wrap()counts every byte of an ANSI escape toward the line length, so a styled string wraps far earlier than its visible width warrants. Line breaks are computed here on the plain text, then mapped back onto the styled runs ofsplit_ansi(). Likerender_ansi(), no escape sequence crosses a line boundary: each returned line carries the styling it needs, opened and closed within the line.Returns a list of lines, empty text yielding a single empty one.
Note
Where the breaks fall is still
textwrap.wrap()âs decision, so long-word breaking and whitespace handling match it exactly. It measures in characters, which means a run of double-width characters occupies more terminal columns than width, as it does everywhere else Click wraps text.
- click_extra.wrap_text(text, width=78, initial_indent='', subsequent_indent='', preserve_paragraphs=False)[source]¶
A helper function that intelligently wraps text. By default, it assumes that it operates on a single paragraph of text but if the
preserve_paragraphsparameter is provided it will intelligently handle paragraphs (defined by two empty lines).If paragraphs are handled, a paragraph can be prefixed with an empty line containing the
\bcharacter (\x08) to indicate that no rewrapping should happen in that block.- Parameters:
text (
str) â the text that should be rewrapped.width (
int) â the maximum width for the text.initial_indent (
str) â the initial indent that should be placed on the first line as a string.subsequent_indent (
str) â the indent string that should be placed on each consecutive line.preserve_paragraphs (
bool) â if this flag is set then the wrapping will intelligently handle paragraphs.
Changed in version 8.4.0: Width is measured in visible characters. ANSI escape sequences in
text,initial_indent, orsubsequent_indentno longer count toward the width budget, so styled input wraps based on what the user sees instead of raw byte length.- Return type:
- click_extra.write_manpages(command, target_dir, prog_name=None, **overrides)[source]¶
Render the command tree and write each man page into
target_dir.Creates
target_dirif missing. Returns the list of written paths.
- click_extra.zero_exit_option(param_decls: Sequence[str] | None = None, default=False, expose_value=False, is_flag=True, help='Always exit with a status code of 0, even when problems are found.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
Subpackages¶
click_extra.configpackageClickExtraConfigConfigOptionConfigOption.file_format_patternsConfigOption.file_pattern_flagsConfigOption.force_posixConfigOption.search_pattern_flagsConfigOption.search_parentsConfigOption.stop_atConfigOption.cascadeConfigOption.extra_excluded_paramsConfigOption.included_paramsConfigOption.strictConfigOption.config_schemaConfigOption.schema_strictConfigOption.fallback_sectionsConfigOption.schema_warn_unknownConfigOption.config_validatorsConfigOption.excluded_paramsConfigOption.file_patternConfigOption.default_pattern()ConfigOption.get_help_extra()ConfigOption.parent_patterns()ConfigOption.search_and_read_file()ConfigOption.parse_conf()ConfigOption.read_and_parse_all_conf()ConfigOption.read_and_parse_conf()ConfigOption.load_ini_config()ConfigOption.load_argfile_config()ConfigOption.load_sqlite_config()ConfigOption.load_plist_config()ConfigOption.merge_default_map()ConfigOption.load_conf()
ExportConfigOptionNoConfigOptionPrebakeConfigSchemaFieldInfoTestSuiteConfigValidateConfigOptionValidationErrorValidationReportconfig_table_to_flags()ensure_config_loaded()field_docstrings()flatten_config_keys()format_from_mime()format_from_path()get_tool_config()make_schema_callable()normalize_config_keys()parse_content()read_file()run_config_validation()schema_field_infos()serialize_content()- Submodules
click_extra.config.builtinmoduleclick_extra.config.flagsmoduleclick_extra.config.formatsmodulePARSER_SUPPORTConfigFormatConfigFormat.TOMLConfigFormat.YAMLConfigFormat.JSONConfigFormat.JSON5ConfigFormat.JSONCConfigFormat.HJSONConfigFormat.INIConfigFormat.XMLConfigFormat.PLISTConfigFormat.SQLITEConfigFormat.ARGFILEConfigFormat.PYPROJECT_TOMLConfigFormat.labelConfigFormat.enabledConfigFormat.patternsConfigFormat.mime_types
SQLITE_CONFIG_TABLEparse_content()SERIALIZABLE_FORMATSserialize_content()format_from_path()format_from_mime()disabled_format_message()read_file()
click_extra.config.optionmoduleget_app_dir()VCS_DIRSCONFIG_OPTION_NAMEDEFAULT_EXCLUDED_PARAMSSentinelNO_CONFIGVCSConfigOptionConfigOption.file_format_patternsConfigOption.file_pattern_flagsConfigOption.force_posixConfigOption.search_pattern_flagsConfigOption.search_parentsConfigOption.stop_atConfigOption.cascadeConfigOption.extra_excluded_paramsConfigOption.included_paramsConfigOption.strictConfigOption.config_schemaConfigOption.schema_strictConfigOption.fallback_sectionsConfigOption.schema_warn_unknownConfigOption.config_validatorsConfigOption.excluded_paramsConfigOption.file_patternConfigOption.default_pattern()ConfigOption.get_help_extra()ConfigOption.parent_patterns()ConfigOption.search_and_read_file()ConfigOption.parse_conf()ConfigOption.read_and_parse_all_conf()ConfigOption.read_and_parse_conf()ConfigOption.load_ini_config()ConfigOption.load_argfile_config()ConfigOption.load_sqlite_config()ConfigOption.load_plist_config()ConfigOption.merge_default_map()ConfigOption.load_conf()
NoConfigOptionValidateConfigOptionensure_config_loaded()ExportConfigOption
click_extra.config.schemamoduleDEFAULT_SUBCOMMANDS_KEYPREPEND_SUBCOMMANDS_KEYEXTENSION_METADATA_KEYCONFIG_PATH_METADATA_KEYNORMALIZE_KEYS_METADATA_KEYValidationErrorConfigValidatornormalize_config_keys()flatten_config_keys()get_tool_config()SchemaFieldInfofield_docstrings()schema_field_infos()make_schema_callable()ValidationReportrun_config_validation()
- click_extra.sphinx package
MYST_NATIVE_ALERTS_VERSIONEXEC_DIRECTIVES_OPT_INSCREENSHOT_DIR_CONFIGSCREENSHOT_PRESET_CONFIGSCREENSHOT_WATERMARK_CONFIGRUN_CAPTURE_CONFIGsetup()- Submodules
- click_extra.sphinx.alerts module
GITHUB_ALERT_PATTERNQUOTE_PREFIX_PATTERNCODE_FENCE_PATTERNINDENTED_CODE_BLOCK_PATTERNAlertFenceStateParserStatecheck_colon_fence()count_quote_depth()process_fence()close_alerts_to_depth()mark_parent_nested()open_alert()process_quoted_line()replace_github_alerts()convert_github_alerts()
- click_extra.sphinx.click module
RST_INDENTPROMPT_SIGILDEFAULT_SCREENSHOT_DIRSCREENSHOT_MARKER_STARTSCREENSHOT_MARKER_ENDMYST_CONTENT_OFFSET_INFLATED_MAXTerminatedEchoingStdinpatch_subprocess()program_from_command_line()ClickRunnerClickDirectiveClickDirective.has_contentClickDirective.required_argumentsClickDirective.optional_argumentsClickDirective.final_argument_whitespaceClickDirective.option_specClickDirective.default_languageClickDirective.show_source_by_defaultClickDirective.show_results_by_defaultClickDirective.show_prompt_by_defaultClickDirective.runner_methodClickDirective.runner_attrClickDirective.runner_factoryClickDirective.runnerClickDirective.languageClickDirective.code_block_options()ClickDirective.show_sourceClickDirective.show_resultsClickDirective.show_promptClickDirective.is_myst_syntaxClickDirective.abs_content_offsetClickDirective.render_code_block()ClickDirective.screenshotClickDirective.screenshot_backgroundClickDirective.screenshot_columnsClickDirective.screenshot_frameClickDirective.write_screenshot()ClickDirective.run()
SourceDirectiveRunDirectiveupdate_screenshot_blocks()TreeDirectiveConfigDirectiveClickDomaincleanup_runner()
- click_extra.sphinx.manpages module
- click_extra.sphinx.matrix module
PYTHON_RELEASE_DATESSUPPORTED_CELLFORBIDDEN_CELLUNDECLARED_CELLDEFAULT_TAG_PATTERNDEFAULT_TAGS_SORTNEWEST_FIRSTOLDEST_FIRSTORDER_CHOICESPythonMatrixGrouppython_versions_released_by()parse_python_spec()python_matrix_groups()python_matrix_table()DependencyMatrixGroupPOETRY_CARET_REPOETRY_TILDE_REPOETRY_WILDCARD_REdependency_matrix_groups()dependency_matrix_table()MatrixDirectivesetup()update_matrix_blocks()
- click_extra.sphinx.myst_docstrings module
- click_extra.sphinx.todos module
Submodules¶
click_extra.blocks module¶
Offline self-updating block toolkit for Markdown sources.
Fence-aware Markdown scanning, the <!-- name ⊠--> / <!-- name-end --> marker
grammar, and the walk-rewrite-write loop behind the click-extra
refresh-directives command.
The toolkit backs the :matrix: directive ({mod}``click_extra.sphinx.matrix``)
and the python:render :mirror: flag, but it depends only on re and
pathlib: nothing here imports Sphinx or docutils. Living in the package
root rather than under
click_extra.sphinx lets a release pipeline or a standalone documentation
script reuse replace_region and update_blocks without pulling in the
sphinx extra.
- click_extra.blocks.OPTION_LINE_RE = re.compile('^[ \\t]*:(?P<key>[\\w+-]+):[ \\t]*(?P<value>.*?)[ \\t]*$')¶
A
:key: valueMyST directive option line (value optional for flags).
- class click_extra.blocks.FenceSpan(start: int, close: int | None)[source]¶
Bases:
NamedTupleA top-level backtick fence in a Markdown source, as line indices.
Create new instance of FenceSpan(start, close)
- click_extra.blocks.fence_spans(lines)[source]¶
Map each top-level backtick fenceâs opening line index to its span.
Fences are consumed as opaque units: a fence line inside an outer fence (a documented example wrapped in a longer
code-blockfence) never starts a span of its own. A close requires a bare run of the same character, at least as long as the opener, at the same indentation. An unterminated fence spans to the end of the file withclose=None.
- click_extra.blocks.marker_res(name)[source]¶
Build the
(open, close)regexes of a<!-- name -->region.The grammar is shared by every self-updating marker region: the opening comment is
<!-- name [args] -->(argsoptional, whitespace separated), the closing comment is<!-- name-end -->. Both capture their leading indentation asindent.
- click_extra.blocks.replace_region(text, name, content, *, pad=True)[source]¶
Return
textwith the body of a<!-- name -->region swapped forcontent.Finds the
<!-- name [args] -->opening and<!-- name-end -->closing markers (the grammar ofmarker_res()) and replaces everything between them withcontent. The markers themselves are preserved, so the region round-trips: a second call with the samecontentis a no-op.When either marker is missing the text is returned unchanged, so the call is safe to fan out over every file of an
update_blocks()rewrite even when only some carry the region. This is the generic counterpart to the fence-driven refreshers ofclick_extra.sphinx.matrixand thepython:render:mirror:flag: use it when the content is produced outside the document (a registry dump, an external generator) rather than by an inline directive.- Parameters:
pad (
bool) â With the defaultTrue,contentis padded by one blank line on each side, the usual layout for a Markdown block. Set it toFalseto keep the blank line after the opening marker (Markdown needs it to start a fresh block) but drop the one before the closing marker, so the region ends flush against it. That flush layout is whatmdformat-footnoterequires: it strips an HTML comment sitting on its own line right after a footnote definition (executablebooks/ mdformat-footnote#11), so a region wrapping footnotes must place its closing marker on the line immediately below the last body line. An emptycontentcollapses to a single blank line between the markers whatever the padding.- Return type:
- click_extra.blocks.iter_markdown_files(paths)[source]¶
Yield the Markdown sources under
paths(files as-is, dirs recursed).
- click_extra.blocks.update_blocks(paths, rewrite, *, check=False)[source]¶
Rewrite self-updating blocks in the Markdown sources under
paths.Walks
paths(files, or directories recursed for*.md), appliesrewrite(text, path)to each, and writes the file back when its content changed. Incheckmode nothing is written; the return value still lists the files that would change, so a caller can exit non-zero to flag stale documentation in CI.
click_extra.cli module¶
Click Extra CLI with pre-baking utilities.
click_extra.cli_wrapper module¶
The click-extra wrap command and the machinery to wrap a foreign Click CLI.
Monkey-patches Clickâs decorator functions before importing (or running) a
target module so its @click.command() / @click.group() produce
colorized, keyword-highlighted, themed variants. Also resolves and invokes the
target, and introspects it for --params, --man and --tree
without firing its callbacks.
Not to be confused with text wrapping: that is click.wrap_text(), exposed
at the package root as click_extra.wrap_text.
- class click_extra.cli_wrapper.WrapperGroup(*args, help_command=True, sort_subcommands=None, subcommand_priorities=None, **kwargs)[source]¶
Bases:
GroupGroup that falls back to the
wrapsubcommand for unknown names.Known subcommands and their aliases are dispatched normally. Anything else is treated as a target script and forwarded to
wrap.Like
Command.__init__, but auto-injects ahelpsubcommand.- Parameters:
help_command (
bool) â whenTrue(the default), ahelpsubcommand is automatically registered. Set toFalseto suppress it, or register your ownhelpsubcommand to override it.sort_subcommands (
bool|None) â how subcommands sharing a priority are broken apart.Truelists them alphabetically,Falsein the order they were registered.None(the default) defers to thesort_subcommandscontext setting, then toTrue. Seemust_sort_subcommands().subcommand_priorities (
Mapping[str,float] |None) â maps a subcommand name to its priority relative toDEFAULT_PRIORITY, lowest listed first. Names left out keep the default priority, so numbering a few subcommands moves only those.
- click_extra.cli_wrapper.patch_click(theme=None, color=True)[source]¶
Replace Clickâs decorator functions with colorized variants.
Must be called before importing the target CLI module so that
@click.command()and@click.group()decorators produce colorized commands.Note
Only the decorator functions are replaced, not the class names (
click.Command,click.Group). Replacing class names would breakisinstanceandissubclasschecks in Click internals (_param_memo) and Cloupâs decorator validators.Note
A decided color (anything but
None) is pinned in two places, because the two kinds of target are colorized by different routes. One built with a plain@click.command()picks up the patched decorator and therefore is a_HelpColorsMixin: the context class installed below carries the decision for it. One carrying an explicitcls=(like FlaskâsFlaskGroup) keeps its own class and a stockclick.Context, and is served by theget_helppatch further down instead. Cover a single route and the flag silently works for half the CLIs in the wild, which is what--color=alwaysdid until it was pinned here too.
- click_extra.cli_wrapper.unpatch_click()[source]¶
Restore Clickâs original decorator functions and methods.
Reverses the changes made by
patch_click(). Useful in tests to avoid leaking global state between test cases.- Return type:
- click_extra.cli_wrapper.resolve_target(script)[source]¶
Resolve a script name to a module path and function name.
Resolution order:
console_scriptsentry points from installed packages.A local project directory: its
console_scriptsentry point is read frompyproject.toml/setup.cfgand its package is added tosys.path..pyfile path.Explicit
module:functionnotation.Bare Python module or package name.
- Return type:
- Returns:
(module_path, function_name)tuple. function_name is empty when the target should be invoked as a module or script file.- Raises:
click.ClickException â If the script cannot be resolved.
Note
Resolving a local project directory has a side effect: the directory holding its top-level package is prepended to
sys.pathso the subsequent import succeeds. The targetâs own dependencies must still be importable in the current environment.
- click_extra.cli_wrapper.invoke_target(script, module_path, function_name, args)[source]¶
Import and call the target CLI.
Reconstructs
sys.argvso Clickâs argument parsing sees the targetâs program name and arguments, and pins__main__.__package__so the program name Click detects is that same script name.Note
A target whose Click command is invoked without an explicit
prog_namefalls back toclick.utils._detect_program_name(), which reads__main__.__package__. That attribute states how click-extra itself was launched: a documentation build runningpython -m sphinxleakedpython -m sphinx.flaskinto a wrapped usage line, andpython -m click_extraleakspython -m click_extra.flaskthe same way. Emptying it for the call pins the detection on its file-execution branch, which answers the basename ofsys.argv[0]: the script name set above.
- click_extra.cli_wrapper.resolve_target_command(script, subcommands=())[source]¶
Import SCRIPT and return its Click command object and a matching context.
Resolves SCRIPT through
resolve_target(), imports the module, then obtains the command object without running the CLI: the entry-point attribute when it is itself a command, otherwise by scanning the moduleâs namespace for Click command instances (preferring groups). Optionalsubcommandsnavigate into nested groups, mirroring the path a user would type.Shared by the
wrapcommandâs introspection modes (--params,--man,--carapace,--tree) so all describe the exact same resolved command.- Raises:
click.ClickException â when no unambiguous Click command can be found, or a requested subcommand does not exist.
- Return type:
- click_extra.cli_wrapper.target_prog_name(script, command)[source]¶
Return the name a user would type to run SCRIPT.
Every rendering of a target is titled with this: a man pageâs
.THline, a Carapace specâsname, a Markdown heading, the root of a--tree. None of them wants the string that was typed to reach the command, which is a filesystem path or a dotted import path as often as it is a command name.Three shapes, in the order they are distinguished:
A path (a separator, or a
.pysuffix): its basename, dropping that suffix.path/to/my_cli.pyis run asmy_cli, not as its own path.A dotted or colon-separated import path: the commandâs own name, which Click took from the function or an explicit
name=. An import path names a module, never a binary.Anything else is a console-script name, already exactly what a user types, and beats the commandâs own name when the two differ (Flaskâs entry point is
flask, its group object is namedcli).
Caution
Case 2 is a best effort. A target reached as
python -m my_package.clihas no single name a user types, so the commandâs own is the closest thing to one. Pass an explicitprog_nameto the underlying renderer when that is not what you want in the output.- Return type:
click_extra.color module¶
Resolve whether terminal output should be colored.
Owns the --color[=WHEN] and --no-color options, the color environment
variables (NO_COLOR, FORCE_COLOR, CLICOLOR, and friends), and the
tri-state WHEN resolution. The actual styling lives elsewhere:
click_extra.styling (the Style primitive), click_extra.theme
(palettes), and click_extra.highlight (help-screen rendering).
- click_extra.color.COLOR_ENVVARS: dict[str, bool] = {'CLICOLOR': True, 'CLICOLORS': True, 'CLICOLORS_FORCE': True, 'CLICOLOR_FORCE': True, 'COLOR': True, 'COLORS': True, 'FORCE_COLOR': True, 'FORCE_COLORS': True, 'LLM': False, 'NOCOLOR': False, 'NOCOLORS': False, 'NO_COLOR': False, 'NO_COLORS': False}¶
List of environment variables recognized as flags to switch color rendering on or off.
The key is the name of the variable and the boolean value the value to pass to
--coloroption flag when encountered.Source:
- click_extra.color.COLOR_DISABLING_TERMS = frozenset({'dumb', 'unknown'})¶
TERMvalues marking a terminal too limited for ANSI niceties.A
dumborunknownterminal advertises neither SGR color nor the cursor-control codes (carriage return, clear-line) an animation relies on, so both Click Extraâs color resolution (resolve_color_env()) and the spinnerâs animation gating (Spinner._resolve_enabled) treat these two values as a hard opt-out. Sharing the set keeps the color and animation axes from drifting apart.An unset
TERMis deliberately excluded: it is common on legitimately color-capable streams (subprocesses, some IDEs) where defaulting to off would be a regression. This matches Rich, which keys its own dumb-terminal detection on the same two values and not on absence.
- click_extra.color.is_a_tty(stream)[source]¶
Whether
streamreports itself as an interactive terminal.Probes
isattydefensively throughgetattr(): not every stream object exposes the method (a bare buffer, an in-memory capture, a test double), and a plainstream.isatty()would raise there instead of answering ânot a terminalâ.- Return type:
- click_extra.color.resolve_color_env()[source]¶
Reconcile the recognized color environment variables into a tri-state.
Inspects every variable listed in
COLOR_ENVVARSand returns:Trueif at least one enabling variable (FORCE_COLOR,CLICOLOR, âŠ) is set. Enabling wins over disabling, so a single one is enough to keep colors.Falseif only disabling variables (NO_COLOR,LLM, âŠ) are set.Nonewhen no recognized variable is present, leaving the caller free to apply its own default (typicallyauto).
A bare variable (no value), or one whose value cannot be parsed as a boolean, counts as activation, in the permissive spirit of the NO_COLOR and FORCE_COLOR conventions.
A
dumborunknownTERM(seeCOLOR_DISABLING_TERMS) casts a disabling vote as well, so a terminal that cannot render ANSI is treated as color-off even when it still reports as a TTY. Because enabling wins, an explicitFORCE_COLORstays authoritative over it.
- click_extra.color.forced_color()[source]¶
Force ANSI color while Click Extra captures CLI text for documentation.
Click Extra renders CLI help and output into docs from both the MkDocs plugin (
click_extra.mkdocs) and the Sphinx directives (click_extra.sphinx.click). During a build that output is a pipe, not a TTY, so the underlying renderers strip their escape codes. Two independent color systems have to be defeated:Clickâs, gated by
should_strip_ansi/ctx.color(whatclick.echoand the Click and Click Extra help formatters consult). Sphinxâs runner additionally flips this one withclick.testing.CliRunner(color=True).Richâs, gated by
rich.console.Console.is_terminal, which ignores the above and readsFORCE_COLOR(https://force-color.org). This is the systemrich-clickuses, andcolor=Truenever reaches it.
FORCE_COLORis the only signal common to both systems (Rich reads it directly; Click Extra recognizes it throughCOLOR_ENVVARS), so it is the lever we set here. We also clear the color-disabling variables Click Extra recognizes (NO_COLOR,LLM, âŠ) so an opt-out in the build environment cannot suppress the rendering, and pinCOLORTERM=truecolorso the branded 24-bit themes render at full depth instead of being quantized to the 256-color palette (seesupports_truecolor()). The previous environment is restored on exit, so the override never leaks beyond a single capture.
- click_extra.color.query_osc_background(timeout=0.2)[source]¶
Ask the terminal for its background color with an xterm OSC 11 query.
Writes
ESC ] 11 ; ? BELto the terminal and reads back itsrgb:RRRR/GGGG/BBBBreply, returning the color as an 8-bit(r, g, b)tuple. ReturnsNonewhenever the query cannot run or the terminal stays silent:when stdin or stdout is not a terminal (piped, redirected, captured);
when no reply arrives within timeout seconds.
Caution
The query reads stdin in cbreak mode. If the user has typed ahead, or another reader competes for stdin, those bytes may be consumed here or interleave with the reply (a leading run is harmless: the reply is located with a
search()). The terminal mode is always restored throughtermios.tcsetattr(). Because of this contention, the query is opt-in: it runs only when a caller explicitly allows it (seeresolve_background()andThemeOptionâsquery_background).
- click_extra.color.resolve_background(allow_query=False)[source]¶
Detect whether the terminal has a dark or light background.
Consults each signal in turn and returns the first that resolves, or
Nonewhen none does (callers then keep their own default). Precedence, highest first:CLITHEMEâ the cli-theme convention. Adarkorlightvalue (optionally suffixed with a:variant) is a deliberate override and wins outright;autoand anything unrecognized fall through.The live OSC 11 query (
query_osc_background()), but only when allow_query is true. It is the most accurate and the only real-time signal, yet it reads stdin, so it stays opt-in.COLORFGBGâ set by a handful of terminals (rxvt, Konsole) and cached by shell-term-background at shell startup. Read last because it is frequently stale: it reflects the value at terminal launch and is not refreshed when the user switches themes.
- Parameters:
allow_query (
bool) â permit the stdin-reading OSC 11 query. Off by default.
See also
âIs this terminal dark or light?â has a small ecosystem of prior art, mixing the same two strategies this function does (a cached environment variable versus a live OSC query):
shell-term-background (POSIX shell) runs the OSC query once at shell startup and caches the answer into
COLORFGBG, with term-background as its Python reader.terminal-light, termbg and terminal-colorsaurus (Rust) query OSC 10/11 live, like
query_osc_background(); the latter two also read the Windows console.
- click_extra.color.COLOR_WHEN = ('auto', 'always', 'never')¶
GNU-canonical tri-state values accepted by
--color=<WHEN>.autodefers to terminal detection,alwaysforces ANSI on,neverstrips it. See GNU coreutils and this discussion.
- click_extra.color.COLOR_WHEN_ALIASES: dict[str, str] = {'force': 'always', 'if-tty': 'auto', 'no': 'never', 'none': 'never', 'tty': 'auto', 'yes': 'always'}¶
GNU coreutils synonyms accepted as hidden aliases for each
COLOR_WHENvalue.GNU
lsacceptsyes/forceforalways,no/noneforneverandtty/if-ttyforauto, alongside the three canonical spellings (seeCOLOR_WHEN). Click Extra mirrors that leniency but keeps the synonyms out of--helpoutput, error messages and shell completion, which only ever advertiseCOLOR_WHEN.
- click_extra.color.publish_invocation_color(ctx)[source]¶
Mirror
ctx.colorinto_invocation_colorfor cross-thread readers.Called by every color callback after it settled its part of the resolution: whichever fires last leaves the final tri-state in the mirror. The first call queues a context-close callback resetting the mirror, so the value never leaks into a later invocation in the same process.
- Return type:
- click_extra.color.invocation_color()[source]¶
The invocationâs resolved color tri-state, reachable from any thread.
Prefers the pinned
ctx.colorof the calling threadâs own Click context, then the process-wide mirror published by the color callbacks (publish_invocation_color()).Nonemeans auto: defer to the output streamâs TTY status, exactly likectx.colorâs own default.This is what makes
--no-colorreach output produced outside the main thread, like the subprocess linesclick_extra.execution.run_cli()streams throughclick_extra.logging.StreamHandler.
- class click_extra.color.ColorWhenChoice(choices, case_sensitive=True)[source]¶
Bases:
Choiceclick.ChoiceoverCOLOR_WHENthat also accepts the hidden GNU synonyms (COLOR_WHEN_ALIASES) and native configuration booleans, folding them to a canonical value before validation.Only the three canonical
COLOR_WHENvalues reach--help, error messages and shell completion, because the publicchoicesstay canonical. Synonyms and booleans are accepted silently and normalized, so downstream code (ColorOption.set_color(),_WHEN_TO_TRISTATE) only ever seesauto,alwaysornever.Matching is case-insensitive and whitespace-tolerant, which also makes the canonical values forgiving, such as
--color=ALWAYS.- convert(value, param, ctx)[source]¶
Fold synonyms and booleans to canonical, then defer to
click.Choice.A native
boolonly reaches this method from a structured configuration file: TOML or JSON booleans, or YAMLâs coercion ofyes/no/on/off/true/false.Truemaps toalwaysandFalsetonever, consistent with a bare--colorand--no-color. The command line always delivers strings, so this never turns--color=trueinto a valid CLI spelling.Caution
A configuration boolean therefore diverges from gitâs color.ui, where
truemeansauto. Click Extra keepstrueequal toalwaysso theyesstring synonym and YAMLâs coercion ofyestoTrueresolve identically across file formats.- Return type:
- class click_extra.color.ColorOption(param_decls=None, is_flag=False, flag_value='always', default='auto', is_eager=True, expose_value=False, help='Colorize the output. A bare --color is the same as --color=always.', **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured
--color[=WHEN]tri-state option.Mirrors the GNU coreutils convention:
WHENis one ofCOLOR_WHEN(auto,alwaysornever), and a bare--color(no value) meansalways. The negative alias--no-coloris carried by the separateNoColorOption, because Click forbids attaching/--no-xsecondary flags to a value option.The resolved tri-state lands on
ctx.color, the Click-standard attribute thatecho()reads through itsresolve_color_default()âshould_strip_ansi()chain:Truekeeps ANSI codes,Falsestrips them,None(auto) defers to the output streamâs TTY status.This option is eager by default, so other eager options (like
--version) are rendered with the resolved color state.Note
--coloris deliberately not wired to anenvvar. The color environment variables (NO_COLOR,FORCE_COLOR, âŠ) are read manually throughresolve_color_env(). Letting Click manage them would dump the wholeCOLOR_ENVVARSset into the--paramsenv-var column, and only bind one variable per option anyway.- add_to_parser(parser, ctx)[source]¶
Register the option, then teach the parser GNU optional-argument rules.
Clickâs optional-value parser binds
--colorto the next token whenever it does not look like an option, somycli --color subcommandwould consumesubcommandas the color value and fail. GNU instead binds an optional argument only when it is attached with=.This wraps the parserâs long-option matcher so a bare
--colorreplays as--color=<flag_value>(always) and leaves the following argument untouched, while--color=<when>keeps working. The wrapper stays inert for every option that does not carry_gnu_optional_value, so it is safe to install on the shared parser.- Return type:
- set_color(ctx, param, value)[source]¶
Resolve
--color=<WHEN>against the environment and pinctx.color.Precedence, highest first:
An explicit
--coloron the command line.The color environment variables, but only when the value comes from the built-in default. A configuration file or
--accessible(both seen here as a non-DEFAULTsource) therefore wins over the environment, matchingAccessibleOption.A color state already pinned by
--no-color, a forced test runner, or an explicitContext(color=...): preserved when this option only resolves toautofrom its default.The
autodefault, leavingctx.coloratNonefor TTY detection.
Whatever branch settles it, the resolution is mirrored process-wide by
publish_invocation_color()so output produced from background threads honors it too.Stays dormant under resilient parsing, like every other eager callback: an introspection context (
make_resilient_context(), behind the man-page, tree and completion-spec exporters) is never closed, so publishing from one would leave the process-wide mirror pinned to that contextâs environment resolution. ANO_COLORbuild environment would then strip the output of every later CLI carrying no color option of its own.- Return type:
- class click_extra.color.NoColorOption(param_decls=None, is_flag=True, default=False, is_eager=True, expose_value=False, help='Disable colorization (alias of --color=never).', **kwargs)[source]¶
Bases:
ExtraOption--no-colorflag that forces--color=never.Click rejects
/--no-xsecondary flags on a value option, so the negative alias of the tri-stateColorOptioncannot live on it and is provided here as a standalone boolean flag. When set, it pinsctx.colortoFalse; when absent it is a no-op, leaving the resolution toColorOption.Shown on its own line directly below
--color(mirroring--no-configbelow--config), since every other negative in the default option set is visible too. Eager by default, likeColorOption, so the color state is settled before other eager options render.- set_no_color(ctx, param, value)[source]¶
Force
ctx.coloroff when a negative alias is passed; no-op otherwise.Dormant under resilient parsing, for the same reason as
ColorOption.set_color(): a never-closed introspection context must not publish the process-wide color mirror.- Return type:
click_extra.command_doc module¶
Extract a Click command into a structured document and render it.
extract_command_doc() walks a command (and, through
iter_command_contexts(), its whole tree) into a CommandDoc: one
extraction carrying the man-pages(7) sections documented in Man-page
(NAME, SYNOPSIS, DESCRIPTION, OPTIONS, COMMANDS, ENVIRONMENT, FILES and EXIT
STATUS). The model then renders to any of the HELP_FORMATS backends:
roff (CommandDoc.to_roff()), Markdown (CommandDoc.to_markdown())
and JSON (CommandDoc.to_dict() / CommandDoc.to_json()), with the
Carapace completion spec delegated to click_extra.carapace.
The roff backend is Click Extraâs answer to the unmaintained click-man package. It improves on it by:
working on a command object via
click.Command.make_context(), so it needs noconsole_scriptsentry point;discovering subcommands dynamically through
click.Group.list_commands()/click.Group.get_command()with a live context;honoring Clickâs
\bno-rewrap marker (rendered as roff.nf/.fi);rendering boolean flags (
--foo/--no-foo) and skipping hidden commands and options;mirroring Cloup option groups as
.SSsubsections of OPTIONS (ungrouped options fall under anOther optionsheading), matching the help screen;emitting ENVIRONMENT (from auto-generated env vars), FILES (from the
--configsearch pattern) and EXIT STATUS sections that click-man never grew.
Font selection follows the man typographic convention encoded by
click_extra.theme.LITERAL_STYLES / REPLACEABLE_STYLES:
literal tokens (command and option names) render bold (\fB), replaceable
tokens (metavars, operands) render italic (\fI).
- click_extra.command_doc.INLINE_LITERAL_RE = re.compile('``([^`]+?)``')¶
Match a reST inline literal (
"âŠ``â``) in a docstring.Click stores docstrings verbatim, so any reST markup the author used to render code-like tokens in HTML docs leaks into
Command.help/Command.short_help. The roff and HTML man-page paths translate these matches into the bold/literal markers their renderers understand; the Sphinx index directive translates them intonodes.literal.
- click_extra.command_doc.iter_inline_literals(text)[source]¶
Walk
textand yield(segment, is_literal)pairs.Split on
INLINE_LITERAL_REso the consumer can apply different rendering to the literal segments (bold for roff, aliteralnode for docutils) without re-parsing the regex.
- click_extra.command_doc.CLICK_EXTRA_URL = 'https://github.com/kdeldycke/click-extra'¶
Click Extraâs home page, stamped into the provenance comment of every generated man page so a reader of the raw roff knows where it came from.
- click_extra.command_doc.MAN_SECTION = '1'¶
Default man page section. Section 1 is for executable programs and shell commands, which is what a Click CLI is.
- click_extra.command_doc.DEFAULT_EXIT_STATUS: tuple[tuple[str, str], ...] = (('0', 'Success.'), ('1', 'A runtime error, or an aborted prompt (Ctrl-C, a declined confirmation).'), ('2', 'A usage error: unknown option, invalid value, missing operand, or an unparsable configuration file.'))¶
Conventional exit codes shared by every Click Extra CLI.
Mirrors the EXIT STATUS table in Man-page. Click returns
2for usage errors (UsageError),1for aborts, and0on success.
- click_extra.command_doc.normalize_examples(examples)[source]¶
Validate and freeze a commandâs
examplesinto(description, command)pairs.Accepts any sequence of two-item sequences, so a list of tuples and a list of lists (what a configuration file or a JSON payload would produce) are both fine.
Noneand an empty sequence both yield an empty tuple.
- class click_extra.command_doc.DocOptionItem(names, metavar, help, required, optional_value=False)[source]¶
Bases:
objectA single OPTIONS entry, extracted from a Click option.
- names: tuple[str, ...]¶
All literal spellings: primary
optsfollowed bysecondary_opts(so--foo/--no-fooboolean flags render both).
- metavar: str | None¶
The rendered metavar, or
Nonewhen the option takes no value (boolean flags and counters).
- optional_value: bool = False¶
Whether the optionâs value is optional (a bare flag is allowed). Rendered as the attached
[=METAVAR]form instead of a space-separated metavar.
- class click_extra.command_doc.DocOptionGroup(options, title=None, help=None)[source]¶
Bases:
objectA titled cluster of OPTIONS entries, mirroring a Cloup option group.
A plain Click command, or a Cloup command with no explicit
@option_group, yields a single group withtitle=None: it renders as a flat OPTIONS list with no.SSsubsection heading, identical to a man page that never grouped its options.- options: tuple[DocOptionItem, ...]¶
The option entries in this group.
- title: str | None = None¶
The subsection heading, rendered as a roff
.SS.Nonefor the implicit single group of an ungrouped command (no heading emitted).
- class click_extra.command_doc.CommandDoc(name, short_help='', section='1', synopsis_pieces=(), description='', operands=(), option_groups=(), subcommands=(), environment=(), files=(), exit_status=(('0', 'Success.'), ('1', 'A runtime error, or an aborted prompt (Ctrl-C, a declined confirmation).'), ('2', 'A usage error: unknown option, invalid value, missing operand, or an unparsable configuration file.')), examples=(), version=None, date='', manual=None, authors=None, copyright=None)[source]¶
Bases:
objectA whole man page in structured form, ready to render to roff.
One
CommandDocmaps to one command (or subcommand). Its fields are the man-pages(7) sections, in the order Man-page documents them. Build it withextract_command_doc()and serialize withto_roff().- synopsis_pieces: tuple[str, ...] = ()¶
Usage metavars after the command name (
[OPTIONS],CITY, âŠ).
- option_groups: tuple[DocOptionGroup, ...] = ()¶
The OPTIONS entries, partitioned into one or more groups. A command without explicit option groups carries a single untitled group.
- subcommands: tuple[tuple[str, str], ...] = ()¶
For groups:
(name, short_help)pairs for the COMMANDS section.
- exit_status: tuple[tuple[str, str], ...] = (('0', 'Success.'), ('1', 'A runtime error, or an aborted prompt (Ctrl-C, a declined confirmation).'), ('2', 'A usage error: unknown option, invalid value, missing operand, or an unparsable configuration file.'))¶
EXIT STATUS entries as
(code, meaning)pairs.
- examples: tuple[tuple[str, str], ...] = ()¶
EXAMPLES entries as
(description, command_line)pairs.Collected from the commandâs own
examplesattribute (seeclick_extra.commands.Command.examples). Empty for a command that declares none, in which case every backend omits the section entirely.
- to_markdown()[source]¶
Render the whole document as Markdown.
Same sections as
to_roff(), in the same order, minus the roff.THheader, whose date, section number and manual name describe a man page rather than the command. The version survives, as a line under the title.- Return type:
- to_dict()[source]¶
Render the whole document as a JSON-serializable mapping.
Subcommands are listed by name and one-line description only, never recursively: a consumer walking a deep tree asks for the child it cares about instead of paying for the whole tree at once.
render_help()exposes the recursive variant separately, for the consumers that do want everything.
- click_extra.command_doc.extract_command_doc(command, ctx, *, version=None, date=None, manual=None, authors=None, copyright=None)[source]¶
Build a
CommandDocfrom a Click command and its context.The context must have been created for
command(for example viaclick.Command.make_context()withresilient_parsing=True), so that auto-generated environment-variable prefixes resolve correctly.- Return type:
- click_extra.command_doc.iter_command_contexts(command, prog_name=None, _parent=None, _path=())[source]¶
Walk a command tree, yielding
(path, command, context)for each visible command.Subcommands are discovered dynamically (
click.Group.list_commands()/get_command()), so dynamically-registered commands are included. Hidden commands are skipped. Each context is built withresilient_parsing=Trueto avoid triggering required-argument errors, prompts, or eager-option side effects.
- click_extra.command_doc.render_manpage(command, prog_name=None, ctx=None, **overrides)[source]¶
Render a single commandâs man page as a roff string.
Reuses
ctxwhen given (like the live invocation context), otherwise builds a throwaway one withresilient_parsing=True. Keyword overrides (version,date,manual,authors,copyright) are passed through toextract_command_doc().- Return type:
- click_extra.command_doc.render_manpages(command, prog_name=None, **overrides)[source]¶
Render the whole command tree, one man page per (sub)command.
Returns an ordered mapping of
{filename: roff}where each filename is the command path joined by hyphens plus the section suffix (likeweather-forecast.1).
- click_extra.command_doc.write_manpages(command, target_dir, prog_name=None, **overrides)[source]¶
Render the command tree and write each man page into
target_dir.Creates
target_dirif missing. Returns the list of written paths.
- click_extra.command_doc.install_manpages(command, prog_name=None, **overrides)[source]¶
Write the command treeâs man pages where
mancan find them.Targets
$XDG_DATA_HOME/man/man1when that variable is set, elseMAN_INSTALL_DIR. Returns the written paths.The environment is read here rather than at import time, so a caller that sets
XDG_DATA_HOMEfor one invocation (a test, a packaging script staging into a build root) is honored. This mirrorsinstall_carapace_spec(), whose spec directory resolves the same way.
- click_extra.command_doc.HELP_FORMATS: dict[str, str] = {'carapace': 'Carapace completion spec (YAML). Doubles as a command-and-flag tree, and is the shape `carapace` itself consumes. Needs the `yaml` extra.', 'json': 'This command as a JSON object: usage, description, arguments, options grouped as the help screen groups them, environment variables, files, exit codes, and its direct subcommands by name.', 'json-full': 'Every command of the tree as JSON, under a `commands` array, each entry in the `json` shape.', 'man': 'This command as a man page: the roff source a packager installs, which `--man` typesets for reading.', 'markdown': 'This command as a Markdown document, one section per topic.', 'markdown-full': 'Every command of the tree as one Markdown document, in tree order.'}¶
The formats
render_help()renders, mapped to their one-line description.Ordered alphabetically, which is also the order
--help-formatadvertises them in. Adding a format is an entry here plus a branch inrender_help(): no new flag, no wider help screen. See Man-page for what each one is good for.Note
The distinction the plain and
-fullvariants draw is progressive disclosure. A plain render describes one command and names its children, so a reader (a tool or an agent, typically) descends one level at a time instead of pulling a whole tree into a context window to answer a question about one leaf. The-fullvariants exist for the opposite job: generating documentation, or diffing a CLIâs whole surface between two releases.
- click_extra.command_doc.INSTALLABLE_FORMATS: frozenset[str] = frozenset({'carapace', 'man'})¶
The formats with a canonical place on disk their consumer reads them from.
A man page under a
mandirectory, a Carapace spec under Carapaceâs. These are the two renderings that are installed rather than read, which is what letsclick-extra wrapoffer them a destination (--output-dir,--install) and refuse one to the others. A JSON or Markdown document has no such place: nothing goes looking for it, so stdout and a shell redirection are the whole story.
- click_extra.command_doc.render_help(command, help_format, prog_name=None, ctx=None, **overrides)[source]¶
Render command in one of the
HELP_FORMATS.Reuses
ctxwhen given (like the live invocation context), otherwise builds a throwaway one withresilient_parsing=True, exactly likerender_manpage(). Keyword overrides are passed through toextract_command_doc(), and ignored by thecarapaceformat, which carries no version or authorship of its own.- Raises:
ValueError â on an unknown format, listing the known ones.
- Return type:
- click_extra.command_doc.MAN_FORMATTERS: tuple[tuple[str, ...], ...] = (('groff', '-man', '-Tutf8', '-rLL={width}n', '-P-c'), ('mandoc', '-Tutf8', '-Owidth={width}'))¶
Commands able to typeset roff into readable terminal text, best first.
Each entry is an argv template read on stdin, with
:width:filled from the terminal.groffis the GNU implementation found nearly everywhere a man page is;mandoccovers the BSDs and Alpine, which ship it instead.Note
-P-chands-cdown togrotty, groffâs terminal driver, pinning the emphasis it produces to the character-backspace pairsOVERSTRIKE_REmatches andread_manpage()strips under--accessible. Left to its own default agrottyrecent enough writes SGR escape sequences instead, which that regular expression cannot see: the manual then reaches a screen reader with its emphasis intact, and loses it altogether once the output is not a terminal and the codes are stripped as color.mandocneeds no counterpart: it overstrikes already.Note
The
manbinary is deliberately not in this list, even though it is the tool being imitated. Reading roff from stdin is where the implementations diverge: GNUmantakes-l -, while the BSD one wants a real file path. Driving the typesetter directly sidesteps a portability problem that buys nothing, since paging is handled here anyway.
- click_extra.command_doc.MAN_INSTALL_DIR: Path = PosixPath('/home/runner/.local/share/man/man1')¶
Where
--installwrites man pages: the userâs own section-1 directory.The default of the XDG base directory spec, which
install_manpages()overrides fromXDG_DATA_HOMEwhen that is set. Some systems do not carry this path in theirMANPATH, in which case the pages land correctly butmanhas to be told where to look.
- click_extra.command_doc.format_manpage(roff, width=None)[source]¶
Typeset roff into readable terminal text, or
Noneif nothing can.Tries each entry of
MAN_FORMATTERSin turn and returns the output of the first that succeeds. ReturnsNonewhen none of them is installed, which the caller is expected to degrade on rather than fail: a CLI that cannot find a typesetter is a CLI running somewhere that never had man pages to begin with (Windows, a slim container), and that is no reason for--manto error.
- click_extra.command_doc.OVERSTRIKE_RE = re.compile('.\\x08')¶
Match the character-backspace pairs a roff typesetter emits for emphasis.
A bold
Nis writtenN\x08Nand an underlined one_\x08N, a convention inherited from line printers that a pager still renders as bold and underline today. Dropping the pairâs first half leaves the plain character.
- click_extra.command_doc.read_manpage(command, ctx=None)[source]¶
Typeset a commandâs manual and send it to the pager.
The reading counterpart of
--help-format man, which emits the roff source a packager installs. Falls back to printing that source, with a warning naming what to install, when no typesetter is available: something on screen beats an error, and the source still carries every word of the manual.Under
--accessiblethe emphasis is stripped and the pager bypassed (echo_via_pager()streams instead). Both matter to the same reader: a pager is a cursor-driven takeover, and overstrike is worse than the ANSI codes accessible mode already removes, since a screen reader voicesN\x08NA\x08AM\x08ME\x08Erather than skipping it.- Return type:
- class click_extra.command_doc.ManOption(param_decls=None, is_flag=True, expose_value=False, is_eager=True, help="Read the command's manual page and exit.", **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured
--manflag that typesets the commandâs manual, pages it, and exits.Eager and value-less, like
ShowParamsOption. Part of the default option set injected bydefault_params(), so every@commandand@groupexposes it. Use@man_optionto add it to a plain Click CLI.Note
The flag is named
--man, not--show-manor--man-page.In the POSIX, GNU and BSD traditions a program does not emit its own man page through a flag: the page is a separate file read with
man <prog>, either hand-written (BSDmdoc) or generated at build time from--helpoutput (GNUhelp2man). Click Extra already covers that build-time path withwrite_manpages(), itshelp2manequivalent.The one ecosystem that exposes a runtime flag is Perlâs
Pod::Usage, whose convention is--helpfor the brief usage and bare--manfor the full manual.--manalso lines up with the neighbouring--helpand--versioninformational flags, which use bare nouns with noshow-prefix.--show-manand--man-pagehave no precedent outside Click Extra.Note
That Perl convention is about reading a manual, and this flag used to print roff source instead, which nobody reads: it was a build artifact wearing a readerâs name. It now typesets the page and sends it to the pager, the way
manitself does, so the flag does what its tradition says.The source did not go away, it moved to where a build step looks for it:
--help-format man, beside every other artifact this module renders. The two are one question apart. Do you want to read the manual, or to ship it?
- class click_extra.command_doc.HelpFormatOption(param_decls=None, expose_value=False, is_eager=True, help='Render the command in the given format and exit.', **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured
--help-formatoption printing the command in one of theHELP_FORMATSand exiting.Eager and value-taking, unlike its
--manneighbour, which is the same renderer reached through a bare flag:--manis exactly--help-format roff, kept because a runtime manual flag has its own tradition (seeManOption).Note
One option carrying a format, rather than one flag per format. A CLIâs option list is the most expensive real estate in its help screen, and every reader pays for it whether or not they will ever export anything: a family of
--help-json,--help-markdownand--help-carapaceflags would widen the label column of every screen, forever, one line per format anyone ever adds. Here a new format costs an entry inHELP_FORMATSand nothing on screen.Note
The rendered output is deliberately colorless whatever
--colorsays. Every format here is meant to be piped into something (a file, a parser, a model), and ANSI escapes in a JSON string or a Markdown fence are noise to all of them.--helpremains the colorized human view.
click_extra.commands module¶
Wraps vanilla Click and Cloup commands with extra features.
Our flavor of commands, groups and context are all subclasses of their vanilla counterparts, but are pre-configured with good and common defaults. You can still use the mixins in here to build up your own custom variants.
- click_extra.commands.DEFAULT_PRIORITY: Final[float] = 100.0¶
Implicit priority of any subcommand or option left unnumbered.
Priorities order the subcommands of a
Groupand the options of aCommand, lowest first. Anything the author did not number sits on this line, so a lone{"prep": 1}promotesprepwithout displacing the rest, and a number above100demotes.Note
Priorities are floats, not integers, so a new entry can be wedged between two existing ones without renumbering:
1.5lands between1and2.That trick is as old as interactive computing. JOSS, which RAND put online in 1963, required every line number to be a pair of integers separated by a period (
1.1,10.12): a page and a line within it, jointly a step. DECâs FOCAL carried the scheme to the PDP-8, with steps running from1.01to31.99. BASIC numbered lines with plain integers, and its10, 20, 30convention is programmers buying back the same insertion room by hand.
- click_extra.commands.EXTRA_OPTION_SETTINGS: tuple[str, ...] = ('show_choices', 'show_envvar')¶
Click Extra context settings forced onto every option when set to non-
None.
- click_extra.commands.default_params(screen=None)[source]¶
Default additional options added to
@commandand@group.- Parameters:
screen (
VersionScreen|None) âa
VersionScreenfor--versionto draw in place of its one-line message. Reach it through theparamshook, binding the screen withfunctools.partialso each decorated command still gets its own fresh option instances:@group(params=partial(default_params, screen=MY_SCREEN)) def cli(): pass
- Return type:
Caution
The order of options has been carefully crafted to handle subtle edge-cases and avoid leaky states in unit tests.
You can still override this hard-coded order for aesthetic reasons and it should be fine. Your end-users are unlikely to be affected by these sneaky bugs, as the CLI context is going to be naturally reset after each invocation (which is not the case in unit tests).
--time/--no-timeHint
--timeis placed at the top of all other eager options so all other optionsâ processing time can be measured.
--config CONFIG_PATHHint
--configis at the top so it can have a direct influence on the default behavior and value of the other options.
--no-config--validate-config CONFIG_PATH--export-config FORMAT--accessibleHint
--accessibleis placed before--colorand--table-formatso it can lower their defaults (viadefault_map) before they are resolved.
--color/--no-color--progress/--no-progress--theme--params--table-format FORMAT--verbosity LEVEL-v,--verbose-q,--quiet--tree--man--help-format FORMAT--version-h,--helpAttention
This is the option produced by the @click.decorators.help_option decorator.
It is not explicitly referenced in the implementation of this function.
Thatâs because itâs going to be added by Click itself, at the end of the list of options. By letting Click handle this, we ensure that the help option will take into account the help_option_names setting.
Note
The list below is the processing order, and it is the only one these edge-cases care about. The help screen reads a separate presentation order, which the
option_prioritiesargument of@commandand@groupreshuffles without touching a single callback. Seeparam_priority(), added for click_extra#544 issue.
- class click_extra.commands.Command(*args, version_fields=None, config_schema=None, config_strict=False, schema_strict=False, fallback_sections=(), config_validators=(), included_params=None, excluded_params=None, extra_option_at_end=True, option_priorities=None, populate_auto_envvars=True, extra_keywords=None, excluded_keywords=None, examples=(), **kwargs)[source]¶
Bases:
_HelpColorsMixin,CommandLike
cloup.command, with sane defaults and extra help screen colorization.List of extra parameters:
- Parameters:
version_fields (
dict[str,Any] |None) â dictionary ofVersionOptiontemplate field overrides forwarded to the version option. Accepts any field fromVersionOption.template_fields(likeprog_name,version,git_branch). Lets you customize--versionoutput from the command decorator without replacing the defaultparamslist.config_strict (
bool) â forwarded to the defaultConfigOptionâsstrictsetting: configuration keys not matching any CLI parameter raise an error instead of being silently ignored. Like the otherconfig_*and*_paramsforwards, it spares you from replacing the whole defaultparamslist to customize the config option.excluded_params (
Sequence[str] |None) â additional parameter IDs to block from configuration files, merged into the defaultConfigOptionâsexcluded_paramsblocklist. Additive, unlike the option-levelexcluded_paramswhich replaces the default blocklist entirely. Items are fully-qualified parameter IDs (likemycli.mail_sources). Mutually exclusive withincluded_params.extra_keywords (
HelpKeywords|None) â aHelpKeywordsinstance whose entries are merged into the auto-collected keyword set. Use this to inject additional strings for help screen highlighting.excluded_keywords (
HelpKeywords|None) â aHelpKeywordsinstance whose entries are removed from the auto-collected keyword set. Use this to suppress highlighting of specific strings.examples (
Sequence[Sequence[str]]) â a sequence of(description, command)string pairs showing the command in use. They are rendered in anExamples:section of the help screen, in the man page, and in every âhelp-format rendering. A malformed pair raisesTypeErrorhere, at command construction, rather than on the first--helpa user runs.extra_option_at_end (
bool) â reorders all parameters attached to the command, by moving all instances ofExtraOptionat the end of the parameter list. The original order of the options is preserved among themselves.option_priorities (
Mapping[str,float] |None) â maps an option to its priority in the help screen, relative toDEFAULT_PRIORITY, lowest shown first. Keys are matched against each parameterâs long and short flags first, then its destination name, so the--config/--no-configpair (which shares theconfigdestination) stays addressable one flag at a time. Presentation only:self.params, and with it the order callbacks are evaluated in, is left alone. Positional arguments are never reordered, their sequence being part of the commandâs grammar.populate_auto_envvars (
bool) â forces all parameters to have their auto-generated environment variables registered. This address the shortcoming ofclickwhich only evaluates them dynamically. By forcing their registration, the auto-generated environment variables gets displayed in the help screen, fixing click#2483 issue. On Windows, environment variable names are case-insensitive, so we normalize them to uppercase.
By default, these Click context settings are applied:
auto_envvar_prefix = self.name(Click feature)Auto-generate environment variables for all options, using the command ID as prefix. The prefix is normalized to be uppercased and all non-alphanumerics replaced by underscores.
help_option_names = ("--help", "-h")(Click feature)Allow help screen to be invoked with either âhelp or -h options.
show_default = True(Click feature)Show all default values in help screen.
Additionally, these Cloup context settings are set:
align_option_groups = False(Cloup feature)show_constraints = True(Cloup feature)show_subcommand_aliases = True(Cloup feature)
Click Extra also adds its own
context_settings:show_choices = None(Click Extra feature)If set to
TrueorFalse, will force that value on all options, so we can globally show or hide choices when prompting a user for input. Only makes sense for options whosepromptproperty is set.Defaults to
None, which will leave all options untouched, and let them decide of their ownshow_choicessetting.show_envvar = None(Click Extra feature)If set to
TrueorFalse, will force that value on all options, so we can globally enable or disable the display of environment variables in help screen.Defaults to
None, which will leave all options untouched, and let them decide of their ownshow_envvarsetting. The rationale being that discoverability of environment variables is enabled by the--paramsoption, which is active by default on extra commands. So there is no need to surcharge the help screen.This addresses the click#2313 issue.
To override these defaults, you can pass your own settings with the
context_settingsparameter:@command( context_settings={ "show_default": False, ... } )
- examples: tuple[tuple[str, str], ...] = ()¶
(description, command)pairs showing the command in use.Normalized from the
examplesconstructor argument bynormalize_examples(). Declared here so the attribute exists on every command, whether or not its author passed any: the renderers reading it (help screen, man page, and everyHELP_FORMATSbackend) then need no guard.
- param_priority(param)[source]¶
Priority of param in the help screen.
Defaults to
DEFAULT_PRIORITY, and is otherwise resolved againstoption_prioritiesby trying each of the parameterâs flags in turn, then its destination name.Important
This orders the help screen alone. The order of
self.paramsdecides when each callback fires:click.core.iter_params_for_processingsorts on(not is_eager, position on the command line), and every eager option the user did not type ties on that second key, leaving declaration order as the tie-break. That is what puts--timeahead of everything it measures and--accessibleahead of the--colordefault it lowers, so the two orders have to be free to disagree.Positional arguments always resolve to the default: their sequence is part of the commandâs grammar, not a matter of presentation.
- Return type:
- main(args=None, prog_name=None, **kwargs)[source]¶
Pre-invocation step that is instantiating the context, then call
invoke()within it.Caution
During context instantiation, each optionâs callbacks are called. These might break the execution flow (like
--helpor--version).Sets the default CLIâs
prog_nameto the commandâs name if not provided, instead of relying on Clickâs auto-detection via the_detect_program_name()method. This is to avoid the CLI being calledpython -m <module_name>, which is not very user-friendly.- Return type:
- make_context(info_name, args, parent=None, **extra)[source]¶
Intercept the call to the original
click.core.Command.make_contextso we can keep a copy of the raw, pre-parsed arguments provided to the CLI.The result are passed to our own
Contextconstructor which is able to initialize the contextâsmetaproperty under our ownclick_extra.context.RAW_ARGSentry. This will be used inShowParamsOption.print_params()to print the table of parameters fed to the CLI.See also
See
click_extra.context.RAW_ARGSfor the full rationale and the upstream-proposal notes (related: click#1279).- Return type:
- format_examples(ctx, formatter)[source]¶
Write an
Examples:section listing the commandâsexamples.Each entry renders its description, then the command line it describes, indented behind a
$prompt. A command declaring none writes nothing at all, so a help screen only grows the section when it has something to put in it.The command lines go out verbatim rather than through
formatter.write_text(): an example exists to be copied, and Clickâs text wrapper would fold a long one onto a second line mid-token. This is the same call the\bno-rewrap marker makes for help prose.Nothing here styles anything. The lines land in the formatterâs buffer, which
getvalue()runs through keyword highlighting on its way out, so the option names, subcommands and CLI names inside an example are painted by the same pass that paints them everywhere else.- Return type:
- format_epilog(ctx, formatter)[source]¶
Insert the examples section ahead of the epilog.
Places it after the options and subcommands, which is where a reader arrives once they know what the command accepts, and keeps the authorâs own epilog as the last word on the screen.
- Return type:
- parse_args(ctx, args)[source]¶
Like parentâs
parse_argsbut with better error messages for single-dash multi-character tokens.Also settles the presentation options before delegating, so
--color,--no-color,--accessibleand--themereach the eager help and version screens regardless of their position on the command line. See_resolve_presentation_eagerly.
- class click_extra.commands.ColorizedCommand(name, context_settings=None, callback=None, params=None, help=None, epilog=None, short_help=None, options_metavar='[OPTIONS]', add_help_option=True, no_args_is_help=False, hidden=False, deprecated=False)[source]¶
Bases:
_HelpColorsMixin,CommandClick Command with help colorization but no extra params.
Mixes in
_HelpColorsMixinfor keyword highlighting and usesContextfor the colorized formatter, without inheriting fromCommand(which would injectdefault_params).Use this as a base for lightweight subcommands (like
help) or for monkey-patching third-party CLIs (viapatch_click()).
- class click_extra.commands.ColorizedGroup(name=None, commands=None, invoke_without_command=False, no_args_is_help=None, subcommand_metavar=None, chain=False, result_callback=None, **kwargs)[source]¶
Bases:
_HelpColorsMixin,GroupClick Group with help colorization but no extra params.
Same as
ColorizedCommandbut for groups.
- class click_extra.commands.HelpCommand(name, context_settings=None, callback=None, params=None, help=None, epilog=None, short_help=None, options_metavar='[OPTIONS]', add_help_option=True, no_args_is_help=False, hidden=False, deprecated=False)[source]¶
Bases:
ColorizedCommandSynthetic subcommand that displays help for the parent group or a subcommand.
Auto-injected into every
Group. Supports nested resolution:mycli help subgroup subcmdshows the help forsubcmdwithinsubgroup.
- class click_extra.commands.Group(*args, help_command=True, sort_subcommands=None, subcommand_priorities=None, **kwargs)[source]¶
Bases:
Command,GroupLike
cloup.Group, with sane defaults and extra help screen colorization.Like
Command.__init__, but auto-injects ahelpsubcommand.- Parameters:
help_command (
bool) â whenTrue(the default), ahelpsubcommand is automatically registered. Set toFalseto suppress it, or register your ownhelpsubcommand to override it.sort_subcommands (
bool|None) â how subcommands sharing a priority are broken apart.Truelists them alphabetically,Falsein the order they were registered.None(the default) defers to thesort_subcommandscontext setting, then toTrue. Seemust_sort_subcommands().subcommand_priorities (
Mapping[str,float] |None) â maps a subcommand name to its priority relative toDEFAULT_PRIORITY, lowest listed first. Names left out keep the default priority, so numbering a few subcommands moves only those.
- command_class¶
Makes commands of a
Groupbe instances ofCommand.That way all subcommands created from a
Groupbenefits from the same defaults and extra help screen colorization.See: https://click.palletsprojects.com/en/stable/api/#click.Group.command_class
alias of
Command
- group_class¶
Let
Groupproduce sub-groups that are also ofGrouptype.See: https://click.palletsprojects.com/en/stable/api/#click.Group.group_class
alias of
type
- must_sort_subcommands(ctx)[source]¶
Resolve whether subcommand listings are alphabetical.
Reads the groupâs own
sort_subcommands, then the context setting of the same name, then falls back toTrue. This is the resolution order Cloup uses foralign_sections, and it is what lets a singlecontext_settings={"sort_subcommands": False}on the root group reach every subgroup below it instead of being repeated on each.- Return type:
- subcommand_priority(name)[source]¶
Priority of the name subcommand.
Defaults to
DEFAULT_PRIORITY.- Return type:
- list_commands(ctx)[source]¶
Subcommand names in presentation order.
Sorted on
subcommand_prioritiesfirst, then broken apart bymust_sort_subcommands(): alphabetically, or by registration order. With no priority declared every subcommand ties, leaving the tie-break as the only ordering, which is Clickâs plain alphabetical listing.In registration order the auto-injected
helpsubcommand is listed last, wherever it happens to have been registered:Group.__init__appends it before any@cli.command()decorator runs, while acommands=[âŠ]constructor argument lands it after, so its natural position says nothing about the authorâs intent. Mirrors whatextra_option_at_enddoes to options.
- list_sections(ctx, include_default_section=True)[source]¶
Like
cloup.Group.list_sections, but ordering the default section.Cloup hard-codes the default section to
Section.sorted(âŠ), which is why overridinglist_commands()alone leaves the help screen alphabetical: the screen is rendered from sections and never calls it. Rebuild that section fromlist_commands()instead, and hand it over already ordered.Note
Sections the author declared themselves are returned untouched. Cloupâs own
Section(is_sorted=âŠ)already governs those, and a user holding aSectioninstance should not have it rewritten underneath them. Priorities andsort_subcommandstherefore address the default section and the flat listings (--tree, man pages, completion specs), not the contents of an explicit section.
- add_command(cmd, name=None, **kwargs)[source]¶
Like
cloup.Group.add_command, but replaces an auto-injectedHelpCommandwhen the user registers their ownhelpsubcommand.- Return type:
- invoke(ctx)[source]¶
Inject
_default_subcommandsand_prepend_subcommandsfrom config.If the user has not provided any subcommands explicitly, and the loaded configuration contains a
_default_subcommandslist for this group, those subcommands are injected intoctx.protected_argsso that Clickâs normalGroup.invoke()dispatches them._prepend_subcommandsalways prepends subcommands to the invocation, regardless of whether CLI subcommands were provided. Only works withchain=Truegroups.- Return type:
- class click_extra.commands.LazySubcommand(import_path, section=None, fallback_to_default_section=True)[source]¶
Bases:
objectDeclaration of a lazily-imported subcommand of a
LazyGroup.Carries the registration settings
cloup.Group.add_command()accepts, which a bare import path cannot express. A subcommand needing none of them is declared as a plain string instead.- section: Section | None = None¶
Help-screen section the subcommand is filed under, once imported.
A section declared here is registered on the group right away, so the help screen orders its sections as they are declared, not as their subcommands happen to be imported. The same
Sectioninstance can be shared with eagerly-registered subcommands.
- fallback_to_default_section: bool = True¶
Whether to file the subcommand under the default section when
sectionisNone.Set to
Falseto leave the subcommand out of every section, which hides it from the help screen while keeping it invocable. Cloup calls this an escape hatch for internal code: do not disable it unless you know what you are doing.
- class click_extra.commands.LazyGroup(*args, lazy_subcommands=None, **kwargs)[source]¶
Bases:
GroupA
Groupthat supports lazy loading of subcommands.Hint
This implementation is based on the snippet from Clickâs documentation: Defining the lazy group.
It has been extended to work with Click Extraâs
config_optionin click_extra#1332 issue.lazy_subcommandsmaps command names to their import paths.Tip
lazy_subcommandsis a map of the form:{"<command-name>": "<module-name>.<command-object-name>"}
For example:
{"mycmd": "my_cli.commands.mycmd"}
A subcommand needing registration settings on top of its import path is declared with a
LazySubcommandinstead of a bare string:{"mycmd": LazySubcommand("my_cli.commands.mycmd", section=my_section)}
Every section declared that way is registered on the group here, so the help screen orders its sections as the author declared them. Waiting for each subcommand to be imported would instead order them by import, which is alphabetical and says nothing about intent.
- lazy_subcommands: dict[str, LazySubcommand]¶
click_extra.decorators module¶
Decorators for group, commands and options.
- class click_extra.decorators.CommandDecorator(*args, **kwargs)[source]¶
Bases:
Protocol[CommandT_co]Static type of the command decorators built by
decorator_factory.Mirrors Clickâs own overloads for
@command/@groupso type checkers infer the produced command class, while also covering the no-parenthesis form enabled byallow_missing_parenthesis.
- class click_extra.decorators.ParameterDecorator(*args, **kwargs)[source]¶
Bases:
ProtocolStatic type of the option and argument decorators built by
decorator_factory.These decorators attach a parameter to the callback and return it unchanged, so the decorated function keeps its own type. The two overloads cover the bare (no-parenthesis) and parenthesized forms.
- click_extra.decorators.allow_missing_parenthesis(dec_factory)[source]¶
Allow to use decorators with or without parenthesis.
As proposed in Cloup issue #127.
- click_extra.decorators.decorator_factory(dec, *new_args, **new_defaults)[source]¶
Clone decorator with a set of new defaults.
- Overloads:
dec (Any), new_args (Any), cls (type[CommandT_co]), new_defaults (Any) â CommandDecorator[CommandT_co]
dec (Any), new_args (Any), cls (type[ParamT] | None), new_defaults (Any) â ParameterDecorator
Used to create our own collection of decorators for our custom options, based on Cloupâs.
The two overloads give static type checkers a precise signature for the decorators this factory produces: command-style decorators (
clsis aclick.Commandsubclass) report the resulting command class, while parameter-style decorators (clsis aclick.Parametersubclass, or absent) return the decorated callback unchanged. Both overloads model the optional-parenthesis behaviour added byallow_missing_parenthesis, which plain inference cannot recover. SeeCommandDecoratorandParameterDecoratorfor the produced shapes.Attention
The
clsargument passed to the factory is used as the reference class from which the produced decoratorâsclsargument must inherit.The idea is to ensure that, for example, the
@commanddecorator re-implemented by Click Extra is always a subclass ofCommand, even when the user overrides theclsargument. That way it can always rely on the additional properties and methods defined in the Click Extra framework, where we have extended Cloup and Click so much that we want to prevent surprising side effects.
- click_extra.decorators.command(*args, **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.group(*args, **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.option(*args, group=None, **attrs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.argument(*args, help=None, **attrs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.help_option(*args, **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.version_option(version=None, *param_decls, cls=<class 'click_extra.version.VersionOption'>, group=None, **kwargs)[source]¶
Attach a
VersionOptionto a command.Drop-in compatible with Clickâs
@version_option: the first positional argument may be an explicit version string. click-extra otherwise auto-detects the version and treats positional arguments as option flags (like every other option decorator), so the two are disambiguated by their leading character: a value starting with-is a flag declaration, anything else is a Click-style version string forwarded into theversiontemplate field.@command @version_option("1.2.3") # Click idiom: pins the displayed version. def my_cmd(): ...
Note
Hand-written instead of produced by
decorator_factory()because Clickâs leadingversionpositional conflicts with theparam_decls-first convention the factory relies on.
- click_extra.decorators.lazy_group(*args, **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.multicall_group(*args, **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.accessible_option(param_decls: Sequence[str] | None = None, is_flag=True, default=False, is_eager=True, expose_value=False, help='Accessibility mode: disable colors and render tables in a borderless, screen-reader-friendly format.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.color_option(param_decls: Sequence[str] | None = None, is_flag=False, flag_value='always', default='auto', is_eager=True, expose_value=False, help='Colorize the output. A bare --color is the same as --color=always.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.columns_option(param_decls: Sequence[str] | None = None, columns: Sequence[ColumnSpec] | None = None, type=None, default: Sequence[str] | None = (), expose_value: bool = False, is_eager: bool = True, help: str = 'Restrict and reorder table columns, SQL SELECT-style. Comma-separated list of column IDs. Default: all columns in canonical order.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.config_option(param_decls: Sequence[str] | None = None, metavar='CONFIG_PATH', type=UNPROCESSED, help='Location of the configuration file. Supports local path with glob patterns or remote URL.', is_eager: bool = True, expose_value: bool = False, file_format_patterns: dict[ConfigFormat, Sequence[str] | str] | Iterable[ConfigFormat] | ConfigFormat | None = None, file_pattern_flags: int = 4104, roaming: bool = True, force_posix: bool = False, search_pattern_flags: int = 285504, search_parents: bool = False, stop_at: Path | str | Literal[Sentinel.VCS] | None = Sentinel.VCS, cascade: bool = False, excluded_params: Iterable[str] | None = None, included_params: Iterable[str] | None = None, strict: bool = False, config_schema: type | Callable[[dict[str, Any]], Any] | None = None, schema_strict: bool = False, fallback_sections: Sequence[str] = (), config_validators: Sequence[ConfigValidator] = (), **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.export_config_option(param_decls: Sequence[str] | None = None, type: click.ParamType | Any = None, metavar: str = 'FORMAT', is_eager: bool = True, expose_value: bool = False, help: str = 'Export the configuration in the selected format to <stdout>, then exit.', **kwargs: Any)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.jobs_option(param_decls: Sequence[str] | None = None, default='auto', expose_value=False, show_default=True, type=<click_extra.execution.JobCount object>, help="Number of parallel jobs. Accepts an integer, 'auto' (the host's logical CPUs minus one) or 'max' (all logical CPUs). 0 runs sequentially.", **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.help_format_option(param_decls: tuple[str, ...] | None = None, expose_value: bool = False, is_eager: bool = True, help: str = 'Render the command in the given format and exit.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.man_option(param_decls: tuple[str, ...] | None = None, is_flag: bool = True, expose_value: bool = False, is_eager: bool = True, help: str = "Read the command's manual page and exit.", **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.no_color_option(param_decls: Sequence[str] | None = None, is_flag=True, default=False, is_eager=True, expose_value=False, help='Disable colorization (alias of --color=never).', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.no_config_option(param_decls: Sequence[str] | None = None, type=UNPROCESSED, help='Ignore all configuration files and only use command line parameters and environment variables.', is_flag=True, flag_value=Sentinel.NO_CONFIG, is_eager=True, expose_value=False, **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.quiet_option(param_decls: Sequence[str] | None = None, **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.show_params_option(param_decls: Sequence[str] | None = None, is_flag=True, expose_value=False, is_eager=True, help='Show all CLI parameters, their provenance, defaults and value, then exit.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.table_format_option(param_decls: Sequence[str] | None = None, type=EnumChoice('aligned', 'asciidoc', 'colon-grid', 'csv', 'csv-excel', 'csv-excel-tab', 'csv-unix', 'double-grid', 'double-outline', 'fancy-grid', 'fancy-outline', 'github', 'grid', 'heavy-grid', 'heavy-outline', 'hjson', 'html', 'jira', 'json', 'json5', 'jsonc', 'latex', 'latex-booktabs', 'latex-longtable', 'latex-raw', 'mediawiki', 'mixed-grid', 'mixed-outline', 'moinmoin', 'orgtbl', 'outline', 'pipe', 'plain', 'presto', 'pretty', 'psql', 'rounded-grid', 'rounded-outline', 'rst', 'simple', 'simple-grid', 'simple-outline', 'textile', 'toml', 'tsv', 'unsafehtml', 'vertical', 'xml', 'yaml', 'youtrack'), default=TableFormat.ROUNDED_OUTLINE, expose_value=False, is_eager=True, help='Rendering style of tables.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.telemetry_option(param_decls: Sequence[str] | None = None, default=False, expose_value=False, envvar=None, show_envvar=True, help='Collect telemetry and usage data.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.theme_option(param_decls: Sequence[str] | None = None, default: str = 'dark', is_eager: bool = True, expose_value: bool = False, query_background: bool = False, help: str = 'Color theme used for help screens.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.timer_option(param_decls: Sequence[str] | None = None, default=False, expose_value=False, is_eager=True, help='Measure and print elapsed execution time.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.tree_option(param_decls: tuple[str, ...] | None = None, is_flag: bool = True, expose_value: bool = False, is_eager: bool = True, help: str = 'Show the tree of nested subcommands and exit.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.validate_config_option(param_decls: Sequence[str] | None = None, type: click.ParamType | Any = <click.types.Path object>, is_eager: bool = True, expose_value: bool = False, help: str = 'Validate the configuration file and exit.', **kwargs: Any)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.verbose_option(param_decls: Sequence[str] | None = None, **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.verbosity_option(param_decls: Sequence[str] | None = None, default_logger: Logger | str = 'root', default: LogLevel = LogLevel.WARNING, metavar='LEVEL', type=EnumChoice('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'), help='Either CRITICAL, ERROR, WARNING, INFO, DEBUG.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.zero_exit_option(param_decls: Sequence[str] | None = None, default=False, expose_value=False, is_flag=True, help='Always exit with a status code of 0, even when problems are found.', **kwargs)¶
Returns a new decorator instantiated with custom defaults.
These defaults values are merged with the userâs own arguments.
A special case is made for the
paramsargument, to allow it to be callable. This limits the issue of the mutable options being shared between commands.This decorator can be used with or without arguments.
- click_extra.decorators.sort_by_option(*header_defs, cls=<class 'click_extra.table.SortByOption'>, group=None, **kwargs)[source]¶
Attach a
SortByOptionto a command.Forwards the positional
header_defs((label, column_id)pairs) straight to the option constructor and registers a regular CloupOption, so the--sort-byoption composes with@option_groupand@constraintlike any other option decorator.Note
Hand-written instead of produced by
decorator_factory()becauseSortByOptionaccepts its column definitions as positional arguments, which conflicts with theparam_decls-first convention the factory relies on.
click_extra.envvar module¶
Type for dict-like environment variables.
- click_extra.envvar.TEnvVarID = str | None¶
Type of environment variable names.
- click_extra.envvar.TNestedEnvVarIDs¶
Type for arbitrary nested environment variable names.
- click_extra.envvar.TEnvVars¶
Type for
dict-like environment variables.
- click_extra.envvar.parse_envvar_flag(value)[source]¶
Read an environment flagâs value as a boolean, permissively.
The single interpretation shared by every flag-like variable Click Extra reads by hand (
NO_COLORand friends,ACCESSIBLE,DO_NOT_TRACK): the value is parsed throughconfigparser.RawConfigParser.BOOLEAN_STATES, and anything unparsable counts as activation, in the permissive spirit of the NO_COLOR and FORCE_COLOR conventions where the variableâs bare presence is the signal.Callers handle presence themselves: pass the value only when the variable is set, an unset variable being no vote at all.
- Return type:
- click_extra.envvar.merge_envvar_ids(*envvar_ids)[source]¶
Merge and deduplicate environment variables.
Multiple parameters are accepted and can be single strings or arbitrary-nested iterables of strings.
Nonevalues are ignored.Variable names are deduplicated while preserving their initial order.
Caution
On Windows, environment variable names are case-insensitive, so we normalize them to uppercase as the standard library does.
Returns a tuple of strings. The result is ready to be used as the
envvarparameter for Clickâs options or arguments.
- click_extra.envvar.clean_envvar_id(envvar_id)[source]¶
Utility to produce a user-friendly environment variable name from a string.
Separates all contiguous alphanumeric string segments, eliminate empty strings, join them with an underscore and uppercase the result.
Attention
We do not rely too much on this utility to try to reproduce the current behavior of Click, which is not consistent regarding case-handling of environment variable.
- Return type:
- click_extra.envvar.param_auto_envvar_id(param, ctx)[source]¶
Compute the auto-generated environment variable of an option or argument.
Returns the auto envvar exactly as computed within Clickâs internals, by
click.core.Parameter.resolve_envvar_value()andclick.core.Option.resolve_envvar_value().
- click_extra.envvar.param_envvar_ids(param, ctx)[source]¶
Returns the deduplicated, ordered list of environment variables for an option or argument, including the auto-generated one.
The auto-generated environment variable is added at the end of the list, so that user-defined envvars takes precedence. This respects the current implementation of
click.core.Option.resolve_envvar_value().Names are normalized to uppercase on Windows by
merge_envvar_ids().
- click_extra.envvar.temporary_env(set_vars=None, unset_vars=())[source]¶
Apply environment variable changes for the blockâs duration, then restore.
set_vars are written into
os.environand unset_vars removed. On exit, every touched variable is restored to its pre-block state: recreated with its former value, or removed when it did not exist before.The process environment is patched directly (not through test-framework fixtures) so the helper serves production code paths and test harnesses alike, with a single restore discipline.
- click_extra.envvar.env_copy(extend=None)[source]¶
Returns a copy of the current environment variables and eventually
extendit.Mimics Pythonâs original implementation by returning
Noneif noextendcontent are provided.A
Nonevalue removes its variable from the copy instead of setting it, which is the only way to hide an inherited variable from a child process: assigning the empty string leaves it set, and a flag read by bare presence (seeparse_envvar_flag()) counts that as activation. Same convention asclick.testing.CliRunner.invoke()âs ownenvargument, and the reasonTEnvVarsvalues are typed optional.Environment variables are expected to be a
dictofstr:str | None.
click_extra.execution module¶
Type for arbitrary nested CLI arguments.
Arguments can be str, pathlib.Path objects or None values.
- click_extra.execution.TNestedArgs¶
Type for arbitrary nested CLI arguments.
Arguments can be
str,pathlib.Pathobjects orNonevalues.alias of
Iterable[str|Path|None|Iterable[TNestedArgs]]
- click_extra.execution.CPU_COUNT = 4¶
Number of logical CPUs available to this process, or
Noneif undetermined.A count of logical processors (hardware threads), resolved by
_logical_cpu_count():os.process_cpu_count()on Python 3.13+, falling back toos.cpu_count()on older runtimes. On a CPU with simultaneous multi-threading (Intel Hyper-Threading, AMD SMT) a 4-physical-core chip reports8. It is therefore not a count of physical cores, and is usually larger than what physical-core tools report, such aspsutil.cpu_count(logical=False)or pytest-xdistâs-n auto(which counts physical cores). Parallelism here is keyed on the logical count on purpose: subprocess- and I/O-bound work overlaps well across hardware threads.
- click_extra.execution.DEFAULT_JOBS = 3¶
Default number of parallel jobs:
CPU_COUNTminus one reserved core.Leaves one logical CPU free for the main process and system tasks, but only on hosts with three logical CPUs or more: on smaller hosts the reservation would collapse the pool to a single (sequential) worker, and threads waiting on subprocesses and I/O cost nothing there, so the whole machine is used instead. Falls back to
1(sequential) when the count cannot be determined.Caution
On a single-CPU host this still resolves to
1and the default silently runs sequentially.JobCount.convert()logs whenever a parallel-intent keyword collapses to a single job this way: as a warning for an explicit request, at info level for the optionâs own default.
- class click_extra.execution.JobCount[source]¶
Bases:
ParamTypeParse a
--jobsvalue: an integer or theauto/maxkeyword.Resolves the symbolic keywords against the hostâs logical CPU count (
CPU_COUNT), counting hardware threads, not physical cores:autoresolves toDEFAULT_JOBS(one fewer than the available logical CPUs, except on hosts with fewer than three, where reserving a core would leave a single worker), the same heuristic used as the optionâs default.maxresolves toCPU_COUNT(every available logical CPU).
Any other token is parsed as an integer and left to
JobsOption.validate_jobs()for clamping and range-checking. Resolving the keywords here keeps the value handed downstream a plainint, so consumers never have to know about the keywords.- choices = ('auto', 'max')¶
Symbolic keywords accepted besides an integer count, in render order.
Exposed as
choicesso the help colorizer highlights them likeclick.Choicevalues: the keyword collector duck-types on this attribute (see thegetattr(param.type, "choices", ...)branch in_HelpColorsMixin._collect_params). It is also the single source of truth reused byget_metavar()andconvert(), so the metavar and the parser never drift apart.
- get_metavar(param, ctx=None)[source]¶
Render
[auto|max|INTEGER](brackets included, asChoicedoes).
- convert(value, param, ctx)[source]¶
Resolve a keyword to a logical-core count, else parse as an integer.
An already-resolved integer is returned untouched, so option defaults and re-validation can flow back through conversion unharmed. When a parallel-intent keyword (
auto/max) resolves to a single job, the collapse is logged: the request reads as âuse several coresâ, but the host has too few logical CPUs, so execution is silently sequential. An explicit request (command line, environment variable, config file) logs a warning; the optionâs own default only logs at info level, else every bare invocation on a 1-CPU host would emit a warning the user never asked for, polluting captured runner streams and the CLI output rendered in Sphinx docs.- Return type:
- shell_complete(ctx, param, incomplete)[source]¶
Suggest the
auto/maxkeywords; an integer count is free-form.Completion proposes only the symbolic keywords, matched case-insensitively to mirror how
convert()lower-cases its input. An integer has no finite set to enumerate, so none is offered, yetconvert()still accepts one.- Return type:
- class click_extra.execution.JobsOption(param_decls=None, default='auto', expose_value=False, show_default=True, type=<click_extra.execution.JobCount object>, help="Number of parallel jobs. Accepts an integer, 'auto' (the host's logical CPUs minus one) or 'max' (all logical CPUs). 0 runs sequentially.", **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured
--jobsoption to control parallel execution.Accepts an integer or one of two keywords resolved by
JobCount:auto(the default: one fewer than the available logical CPU cores, leaving a core free for the main process and system tasks, except on hosts with fewer than three logical CPUs, where reserving one would leave a single worker) andmax(every available logical CPU core). A value of0disables parallelism and runs sequentially.The core count is the number of logical CPUs (hardware threads) available to the process, not physical cores: see
CPU_COUNT. On a host with a single logical CPU,auto/maxresolve to a single job andJobCountlogs that execution will be sequential: as a warning when the keyword was requested explicitly, at info level when it came from the optionâs own default.The resolved value is stored as an
intinctx.meta[click_extra.context.JOBS].Warning
JobsOptiononly resolves and publishes the job count: it does not drive any concurrency by itself. Pass it torun_jobs()(which reads the resolvedctx.meta[click_extra.context.JOBS]count), or read that value yourself and act on it.- validate_jobs(ctx, param, value)[source]¶
Validate the resolved job count and store it in context metadata.
JobCounthas already resolved anyauto/maxkeyword to an integer by the time this runs. A value of0disables parallelism: it is rounded up to1(sequential execution) with a warning. Negative values are likewise clamped to1. A count above the available cores is honored: the pool is aThreadPoolExecutor, and oversubscription is how I/O- and subprocess-bound work overlaps, so the warning only flags the CPU-bound case where extra threads just contend for the GIL. The resolved count is then logged at info level next to the hostâs logical CPU count (CPU_COUNT), so a CLIâs parallelism is visible under--verbosity INFO.- Return type:
- click_extra.execution.resolve_jobs(ctx, count, *, serial_at_debug=False)[source]¶
Resolve how many worker threads to use for a batch of
countitems.Returns the number of items to process in parallel;
1means run sequentially in the calling thread. This is the policy shared byrun_jobs()andrun_lanes(), exposed on its own for callers that must know the resolved count before they fan out (for example to pick a progress-rendering mode). It collapses to sequential when:there is no active CLI context (programmatic or test use),
a single item leaves nothing to parallelize, or
the resolved
JobsOptioncount (ctx.meta[click_extra.context.JOBS]) is1or less.
Otherwise that count wins, capped at
count: there is no point spinning up more workers than there are items.- Parameters:
ctx (
Context|None) â the active Click context, read for the resolved--jobscount (and, withserial_at_debug, the verbosity).Noneforces sequential.count (
int) â how many items are about to be scheduled.serial_at_debug (
bool) â when set, also collapse to sequential atDEBUGverbosity, where coherent per-worker log narration matters more than the speed-up (interleaved threads would scramble it). Off by default.
- Return type:
- click_extra.execution.run_jobs(func, items, *, jobs=None, serial_at_debug=False)[source]¶
Run
funcoveritems, parallelized per the resolved--jobscount.The worker count is taken from
jobswhen given, else resolved from the active commandâsJobsOptionvalue byresolve_jobs(), else1. With a single worker (or at most one item) the items run sequentially and lazily, so a caller can stop early on the first result (for example to abort on the first failure); otherwise they run in a thread pool. Either way results are yielded in submission order, likemap().This is the single-task-per-item special case of
run_lanes()(every item is its own lane). Reach forrun_lanes()when some items must run serially relative to one another while others run concurrently.The pool is thread-based, which suits the I/O- and subprocess-bound work CLI tools usually parallelize (each child releases the GIL). The count is a number of logical CPUs: see
CPU_COUNT.itemsis never materialized: only a bounded window of tasks is queued at a time, so an unbounded or expensive-to-produce stream stays memory-flat and is read no further than the caller consumes.- Parameters:
func (
Callable[[TypeVar(T)],TypeVar(R)]) â Called once per item; its return value is yielded.items (
Iterable[TypeVar(T)]) â The work items. Read lazily, a window at a time.jobs (
int|None) â Override the worker count instead of reading it from the context.1or fewer forces sequential execution.serial_at_debug (
bool) â forwarded toresolve_jobs()whenjobsis not given: collapse to sequential atDEBUGverbosity.
- Return type:
- Returns:
An iterator over
funcâs results, in the order ofitems.
- click_extra.execution.run_lanes(func, lanes, *, jobs=None, serial_at_debug=False)[source]¶
Run
funcover grouped items: serial within a lane, concurrent across.Each lane is an iterable of items.
funcis mapped over every item, but a laneâs own items run serially and in order on a single worker, while distinct lanes run concurrently up to the resolved--jobscount. This is the right primitive when some work must be serialized relative to itself (a shared lock, a rate limit, one mailbox file, one package-manager backend) yet still overlap with unrelated work.run_jobs()is the degenerate case where every lane holds a single item. Concurrency is sized by the number of lanes (one worker per lane), since a lane never splits across workers.Results are yielded in lane-submission order, a laneâs items in order, like
map(). The run stays lazy at any worker count: a lane is materialized only when it is about to be scheduled, and only a bounded window of lanes is in flight, so a caller can break early and the lanes behind it are never read. A lane runs entirely on one worker, so a stateful resource bound to the lane (a per-lane cache, a connection) is touched by only that one thread and needs no lock.- Parameters:
func (
Callable[[TypeVar(T)],TypeVar(R)]) â Called once per item; its return value is yielded.lanes (
Iterable[Iterable[TypeVar(T)]]) â The lanes, each an iterable of items. Read lazily, a window of lanes at a time; a laneâs own items are materialized when it is scheduled.jobs (
int|None) â Override the worker count instead of reading it from the context.1or fewer forces fully sequential execution.serial_at_debug (
bool) â forwarded toresolve_jobs()whenjobsis not given: collapse to sequential atDEBUGverbosity.
- Return type:
- Returns:
An iterator over
funcâs results, lane by lane in submission order.
- class click_extra.execution.TimerOption(param_decls=None, default=False, expose_value=False, is_eager=True, help='Measure and print elapsed execution time.', **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured option that is adding a
--time/--no-timeflag to print elapsed time at the end of CLI execution.The start time is made available in the context in
ctx.meta[click_extra.context.START_TIME].- print_timer()[source]¶
Compute and print elapsed execution time.
Always prints, even when a sibling eager option (
--version,--params,--show-configâŠ) short-circuited the command body viactx.exit(). That makes--timea usable probe for the cost of Click Extraâs own machinery (option parsing, config loading, eager callbacks), not just user command bodies.- Return type:
- init_timer(ctx, param, value)[source]¶
Set up the execution-timer machinery for the current invocation.
Captures
time.perf_counter()as the start time, stores it onctx.metaunderclick_extra.context.START_TIME, and queuesprint_timer()as a context-close callback so the elapsed duration is printed even when a sibling eager option (--version,--paramsâŠ) short-circuits the command body.- Return type:
- class click_extra.execution.ZeroExitOption(param_decls=None, default=False, expose_value=False, is_flag=True, help='Always exit with a status code of 0, even when problems are found.', **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured
-0/--zero-exitoption flag.Follows the convention popularized by linters and static analysers, which exit with a non-zero code whenever they report findings so that automation can gate on it. Setting this flag flips that behavior: the CLI returns
0as long as it ran to completion, reserving non-zero codes for actual execution failures.The resolved value is stored in
ctx.meta[click_extra.context.ZERO_EXIT], aligning with every other Click Extra optionâs per-invocation context-meta storage pattern.Warning
This option is a placeholder: it does not alter the CLIâs exit code by itself. Downstream code must read
ctx.meta[click_extra.context.ZERO_EXIT]and act on it.- set_zero_exit(ctx, param, value)[source]¶
Store the resolved zero-exit flag on the contextâs
metadict.Read via
click_extra.context.get(ctx, click_extra.context.ZERO_EXIT).- Return type:
- click_extra.execution.PROMPT = '$ '¶
Prompt used to simulate the CLI execution.
Hint
Use ASCII characters to avoid issues with Windows terminals.
- click_extra.execution.INDENT = ' '¶
Constants for rendering of CLI execution.
- click_extra.execution.args_cleanup(*args)[source]¶
Flatten recursive iterables, remove all
None, and cast each element to strings.Helps serialize
pathlib.Pathand other objects.It also allows for nested iterables and
Nonevalues as CLI arguments for convenience. We just need to flatten and filters them out.
- click_extra.execution.highlight_bin_name(program, theme=None)[source]¶
Style the binaryâs own name inside
program, leaving its directory plain./opt/homebrew/bin/masrenders with onlymasin the active themeâsinvoked_commandstyle, so the part of the path the eye scans for stands out from the noise of its location. A bare name (no separator) is styled whole. Both POSIX and Windows separators are recognized, whichever comes last.- Parameters:
program (
str) â the command, path and all.theme (
HelpTheme|None) â palette to style with. Defaults to the theme the current invocation runs under, seeformat_cli_prompt().
- Return type:
- Returns:
the styled command.
- click_extra.execution.format_cli_prompt(cmd_args, extra_env=None, theme=None, prompt=None)[source]¶
Render the shell prompt simulating a CLI invocation, for logs and dry-runs.
Prefixes
PROMPTto anyextra_envassignments and the command line. Each token family is styled with the theme slot (get_current_theme()) it holds elsewhere in a CLIâs output, so the line reads like the help screens do:the prompt sigil with
bracket, the structural-token style;each environment assignment as
envvarname, plain=,defaultvalue;the programâs binary name with
invoked_command, its directory plain (seehighlight_bin_name());the
-/--flags withoption; other arguments stay plain.
Useful to print a copy-pasteable command trace in debug logs, dry-runs and test output.
- Parameters:
extra_env (
Mapping[str,str|None] |None) â environment assignments to prefix it with.theme (
HelpTheme|None) â palette to style the line with. Defaults to the theme the current invocation runs under, which is what a CLI printing its own trace wants. A caller drawing the line onto a surface of its own choosing (a light capture, say) passes the one that surface can show.prompt (
str|None) â sigil to draw before the command, when the shell being pictured is not the one running. A capture mimicking a Windows terminal passesPS C:\>;NonekeepsPROMPT, which is this platformâs.
- Return type:
- Returns:
the styled prompt line.
- click_extra.execution.terminate_live_processes()[source]¶
Send
SIGTERMto every subprocess currently running throughrun_cli().Called from the main threadâs
SIGINThandler (seeinstall_interrupt_handler()) so a concurrent fan-out aborts promptly: terminating the children unblocks the worker threads parked inrun_cli(), letting the thread pool drain instead of hanging on a child that ignored the terminalâs process-groupSIGINT.A child spawned with
start_new_sessionnever receives the terminalâsSIGINTat all (it left the foreground process group), so its whole group is signalled here, descendants included.Uses
SIGTERMrather thanSIGKILLso a child still gets to clean up, notably to restore terminal state asudopassword prompt may have altered. The registry is snapshotted under the lock, then signalled outside it, becauserun_cli()may be discarding its own entries from other threads at the same time.- Return type:
- click_extra.execution.install_interrupt_handler(ctx)[source]¶
Make the first Ctrl+C terminate in-flight subprocesses, then abort as usual.
Installs a
SIGINThandler for the duration of the CLI run that callsterminate_live_processes()before re-raisingKeyboardInterrupt(exactly what Pythonâs default handler raises). The abort then proceeds normally, but a concurrent fan-out no longer hangs on surviving children. The previous handler is restored whenctxcloses.Must run in the main thread:
signal.signal()refuses to install a handler from any other, so a non-main-thread caller (embedded use, some tests) is a no-op that keeps the default Ctrl+C behavior.A signal handler is required here rather than a
try/except KeyboardInterruptaround the fan-out: Python delivers Ctrl+C only to the main thread, so worker threads never see the interrupt, and the exception unwinds through the executorâs blockingshutdown(wait=True)teardown before anyexceptin the caller could run. The children must be killed at signal-delivery time, ahead of that teardown.- Return type:
- click_extra.execution.run_cli(args, *, extra_env=None, cwd=None, timeout=None, label=None, merge_streams=False, errors='replace', windows_creation_flags=0, start_new_session=False, command_level=20, output_level=10, log=None)[source]¶
Run a CLI in a subprocess, disclosing the call and streaming its output live.
A
subprocess.run()work-alike for CLI-wrapping tools, with observability built in:the invocation is logged before the spawn, as the copy-pasteable
$ ENV=value command argsline offormat_cli_prompt(), so a user can reproduce by hand what the tool runs on their system;each line of the childâs output is forwarded to the logger as it is produced (ANSI-stripped, tagged with
label), instead of being held back until the child exits, so a long-running command narrates its progress live;the child is registered in the live-process registry for the duration of the call, so
terminate_live_processes()(wired to Ctrl+C byinstall_interrupt_handler()) can abort it.
Contract mirrored from
subprocess.run():returns a
subprocess.CompletedProcesswith the full capturedstdoutandstderrdecoded as UTF-8;raises
subprocess.TimeoutExpired(with the partial capture attached) when the child, or the draining of its output, outlivestimeout. The child is killed first â its whole process tree on Windows (see_kill_windows_process_tree()), its whole POSIX process group when spawned withstart_new_session, the direct child alone otherwise;a
KeyboardInterruptmid-run kills the child (with the same tree, group or direct scope), then propagates.
The child reads from
subprocess.DEVNULLso it can never block onstdin, and never opens a console window on Windows.Note
The pipes are opened in universal-newlines text mode, so a bare
\r(a child redrawing a progress bar in place) terminates a line just like\n: each redraw is streamed as its own log line, and the captured text normalizes both to\n, exactly assubprocess.Popen.communicate()does.- Parameters:
args (
str|Path|None|Iterable[str|Path|None|Iterable[Iterable[str|Path|None|Iterable[TNestedArgs]]]]) â the command line. Nested iterables are flattened,Nonevalues dropped, and every element (Path, versions, âŠ) cast to a string; seeargs_cleanup().extra_env (
Mapping[str,str|None] |None) â environment variables forced over the inherited environment for this call (seeenv_copy()). They are part of the disclosed prompt line, since reproducing the call requires them.cwd (
Path|str|None) â directory to run the child in.Noneinherits the callerâs, which issubprocess.run()âs own default. A relativeargs[0]is resolved by the OS against this directory, not the callerâs, so pass an absolute path (or a name on thePATH) when moving the child elsewhere.timeout (
float|None) â seconds before the child is killed.Nonewaits forever.label (
str|None) â tag identifying this call on each streamed output line, for when several children interleave in one log. Carried as the recordâslabelattribute, whichclick_extra.logging.Formatterrenders glued to the level name and styled like an invoked command (debug:mas: Warning: ...); a foreign formatter can readrecord.labelitself. Applied to the output lines only, never the prompt line.merge_streams (
bool) â route the childâsstderrintostdoutso the OS interleaves both in write order. The resultâsstderris thenNone, like asubprocess.run()call withstderr=STDOUT.errors (
str) â decoding error handler for the childâs output. The default"replace"swaps undecodable bytes forïżœ; pass"backslashreplace"to keep them inspectable as escapes.windows_creation_flags (
int) â extra Windows process-creation flags, OR-ed with the always-onCREATE_NO_WINDOW. No-op off Windows.start_new_session (
bool) â make the child lead its own POSIX session and process group (subprocess.Popenâs parameter of the same name). Every kill path â thetimeoutoverrun, a mid-runKeyboardInterrupt, andterminate_live_processes()â then signals the whole group, so a grandchild spawned by the child (a shim re-executing the real binary, an installer helper) is reaped along with it instead of surviving as an orphan holding the output pipes open. Off by default, and to be left off when a descendant must keep the controlling terminal: a new session detaches from it, so an interactive prompt raised from inside the child (sudoreading/dev/tty) would fail, andsudoâs tty-keyed credential cache would no longer match. No-op on Windows, where the timeout path already kills the full tree. Only the reaping half of this flag has that Windows equivalent, and the other half has none: a POSIX session also detaches the child from the controlling terminal, where a Windows child keeps sharing the parentâs console and can still reach back into it. A subprocess-heavy test suite is where that surfaces âmeta-package-managerâs Windows CI saw a package managerâs own teardown land in the parentpytestprocess as a mid-runKeyboardInterrupt, which a console control event on the shared console explains and which no POSIX runner showed. The lever there iswindows_creation_flags(CREATE_NEW_PROCESS_GROUP), left to the caller because it also changes how a real Ctrl-C reaches the child.command_level (
int) â logging level of the invocation-disclosure line. Defaults tologging.INFO; lower it tologging.DEBUGfor internal probes not worth narrating.output_level (
int) â logging level of the streamed output lines. Defaults tologging.DEBUG.log (
Logger|None) â destination logger. Defaults to the root logger, whose level theVerbosityOptionfamily manages.
- Return type:
click_extra.highlight module¶
Help-screen keyword highlighting and the colorized help formatter.
Hosts the engine that collects highlightable keywords from a Click context
(HelpKeywords, _HelpColorsMixin) and renders them with the
active theme: HelpFormatter styles --help output and
highlight() applies a styling function to arbitrary matches. Split out of
click_extra.color, which now focuses on --color/--no-color
resolution.
- class click_extra.highlight.HelpKeywords(cli_names=<factory>, subcommands=<factory>, command_aliases=<factory>, arguments=<factory>, long_options=<factory>, short_options=<factory>, choices=<factory>, choice_metavars=<factory>, metavars=<factory>, envvars=<factory>, defaults=<factory>)[source]¶
Bases:
objectStructured collection of keywords extracted from a Click context for help screen highlighting.
Each field corresponds to a semantic category with its own styling.
- class click_extra.highlight.HelpFormatter(*args, **kwargs)[source]¶
Bases:
HelpFormatterExtends Cloupâs custom HelpFormatter to highlights options, choices, metavars and default values.
This is being discussed for upstream integration at:
Forces theme to the active one for the current Click context.
Also transform Cloupâs standard
HelpThemeto our ownHelpTheme.Resolves the active theme via
click_extra.theme.get_current_theme(), which reads the per-invocation pick from the Click context (set byThemeOption) and falls back to the module-level default when no context is active.- keywords: HelpKeywords¶
Keywords to highlight, collected from the rendered commandâs context.
Instance state, initialized per formatter:
_HelpColorsMixin.format_helpfills it before rendering, andhighlight_extra_keywords()mutates it (see theexcluded_keywordssubtraction), so a shared class-level default would leak keywords across formatters.
- excluded_keywords: HelpKeywords | None¶
Keywords subtracted from the cross-reference passes, or
None.
- write_usage(prog, args='', prefix=None)[source]¶
ANSI-aware override of
cloup.HelpFormatter.write_usage.On Click
8.3.x,click.formatting.wrap_textmeasures line length with rawlen(), counting every byte of the ANSI escape sequences embedded ininitial_indent(the styledUsage:heading + invoked-command name). With 24-bit RGB themes (like Solarized Dark, Dracula, Nord, Monokai), each styled token carries 17+ extra bytes of escape, which inflates the measured line beyond the width budget and causes premature wraps mid-token:[OPTIONS\n ].Cloup styles
prefixandprogthen delegates to clickâsHelpFormatter.write_usage(), inheriting the bug. This override re-applies the same styling, then bypasseswrap_textwhenever the visible content fits on a single line: the common case for short usage strings where wrapping is unnecessary. Lines that genuinely overflow the visible width fall back to clickâs implementation: the wrap point may still be sub-optimal but the output stays syntactically valid.Note
Click
8.4.0(PR pallets/click#3420) madeclick.formatting.TextWrapperANSI-aware by counting visible width instead of raw bytes, so this override is a no-op fast path on Click>= 8.4.0and only fixes wrapping on the Click8.3.xreleases click-extra still supports.Todo
Drop this override once the minimum supported Click rises to
8.4.0(which includespallets/click#3420). Theterm_len-based visible-width check below becomes redundant once Clickâs own wrapper counts visible width.- Return type:
- highlight_extra_keywords(help_text)[source]¶
Highlight extra keywords in help screens based on the theme.
Uses the
highlight()function for all keyword categories. Each category is processed as a batch of regex patterns with a single styling function, which handles overlapping matches and prevents double-styling.- Return type:
- click_extra.highlight.highlight(content, patterns, styling_func, ignore_case=False)[source]¶
Highlights parts of the
contentthat matchespatterns.Takes care of overlapping parts within the
content, so that the styling function is applied only once to each contiguous range of matching characters.Todo
Support case-foldeing, so we can have the
StraĂestring matching theStrassecontent.This could be tricky as it messes with string length and characters index, which our logic relies on.
Danger
Roundtrip through lower-casing/upper-casing is a can of worms, because some characters change length when their case is changed:
- Return type:
click_extra.humanize module¶
Human-readable rendering of machine values.
Formatters that turn raw numbers into the compact strings shown in terminal
output, tables and reports. The reverse direction, parsing a human-written
value back into a machine type, lives in click_extra.types (see
Duration).
- click_extra.humanize.format_size(size, *, units='iec', precision=1)[source]¶
Render a byte count as a compact, human-readable string.
- Parameters:
size (
float) â The number of bytes. A negative value keeps a leading-.units (
Literal['iec','si','jedec']) â The unit system to render in, one of_UNIT_SYSTEMS:iec(the default) for binary powers with the unambiguousKiB/MiBsymbols,sifor decimal powers withkB/MB, orjedecfor binary powers with the customary but impreciseKB/MB.precision (
int) â Number of fractional digits for every unit above bytes. A byte count is always rendered as a whole number.
- Return type:
- Returns:
The size followed by a space and its unit, like
1.5 KiB. The integer part is grouped with thousands separators.- Raises:
ValueError â If units is not a known unit system.
- click_extra.humanize.format_duration(duration)[source]¶
Render an elapsed duration compactly:
2.3s,1:05, then1:02:03.Below a minute the duration reads as one-decimal seconds (
2.3s). From a minute up it switches to a clock layout, growing an hours field only once it reaches an hour:1:05under an hour,1:02:03at or above.The reverse direction, parsing a human-written duration back into a
timedelta, lives inclick_extra.types(seeDuration).
click_extra.logging module¶
Logging utilities.
Todo
Let the -v/-q counter reach beyond the current LogLevel range, as
sketched by the -vvvv (trace) and -q (silence everything) notes that used
to live on _VerbosityOption:
a
TRACEpseudo-level belowLogLevel.DEBUG(numeric value5, mirroringlogging.DEBUG - 5) so repeated-vcan surface finer-grained tracing pastDEBUG;a
SILENTpseudo-level aboveLogLevel.CRITICAL(any value abovelogging.CRITICAL) so repeated-qcan suppress every record, includingLogLevel.CRITICAL.
Both require extending LogLevel, which ripples into the --verbosity
EnumChoice, the Formatter level-name color
lookup and the level-ordering tests. They are intentionally left out of the
symmetric-counter change that introduced -q, where the counter simply clamps
at DEBUG/CRITICAL.
- class click_extra.logging.LogLevel(*values)[source]¶
Bases:
IntEnumMapping of canonical log level names to their integer level.
Thatâs our own version of logging._nameToLevel, but:
sorted from lowest to highest verbosity,
- excludes the following levels:
NOTSET, which is considered internalWARN, whichis obsoleteFATAL, which shouldnât be used and has been replaced by CRITICAL
- CRITICAL = 50¶
- ERROR = 40¶
- WARNING = 30¶
- INFO = 20¶
- DEBUG = 10¶
- click_extra.logging.DEFAULT_LEVEL: LogLevel = LogLevel.WARNING¶
WARNINGis the default level we expect any loggers to starts their lives at.WARNINGhas been chosen as it is the level at which the default Pythonâs global root logger is set up.This value is also used as the default level for
VerbosityOption.
- class click_extra.logging.StreamHandler(stream=None)[source]¶
Bases:
StreamHandlerA handler to output logs to the console.
Wraps
logging.StreamHandler, but useclick.echo()to support color printing.Only
<stderr>or<stdout>are allowed as output stream.If stream is not specified,
<stderr>is used by defaultInitialize the handler.
If stream is not specified, sys.stderr is used.
- property stream: IO[Any]¶
The stream to which logs are written.
A proxy of the parent
logging.StreamHandlerâs stream attribute.Redefined here to enforce checks on the stream value.
- emit(record)[source]¶
Use
click.echo()to print to the console.Cooperates with any live terminal line currently drawing on the same stream (a
Spinner, or anOperationTrailprogress bar): the record is then printed through itsecho, which erases the in-progress render first, so a log line emitted mid-draw lands on its own line instead of garbling the indicator (and vice versa).The color tri-state is resolved through
invocation_color()rather than left toclick.echo()âs own context lookup: a record emitted from a background thread (a subprocess stream reader, a fan-out worker) has no reachable Click context, and would otherwise ignore--no-colorand keep its ANSI codes on a TTY.- Return type:
- class click_extra.logging.Formatter(fmt=None, datefmt=None, style='%', validate=True, *, defaults=None)[source]¶
Bases:
FormatterClick Extraâs default log formatter.
Initialize the formatter with specified format strings.
Initialize the formatter either with the specified format string, or a default as described above. Allow for specialized date formatting with the optional datefmt argument. If datefmt is omitted, you get an ISO8601-like (or RFC 3339-like) format.
Use a style parameter of â%â, â{â or â$â to specify that you want to use one of %-formatting,
str.format()({}) formatting orstring.Templateformatting in your format string.Changed in version 3.2: Added the
styleparameter.- formatMessage(record)[source]¶
Colorize the recordâs log level name before calling the standard formatter.
Colors are sourced from a
click_extra.theme.HelpTheme, resolved per-invocation viaclick_extra.theme.get_current_theme().A record carrying a
labelattribute (each linerun_cli()streams from a subprocess is tagged with its caller-provided label) renders it glued to the level name, styled like an invoked command:debug:mas: Warning: .... The tag stays out of the message text itself, so a foreign formatter is free to renderrecord.labelits own way.The recordâs
levelnameis restored afterwards: a record may be formatted more than once (several handlers, a captured then re-rendered record), and must not accumulate styling or glued labels.- Return type:
- click_extra.logging.basicConfig(*, filename=None, filemode='a', format='{levelname}: {message}', datefmt=None, style='{', level=None, stream=None, handlers=None, force=False, encoding=None, errors='backslashreplace', stream_handler_class=<class 'click_extra.logging.StreamHandler'>, file_handler_class=<class 'logging.FileHandler'>, formatter_class=<class 'click_extra.logging.Formatter'>)[source]¶
Configure the global
rootlogger.This function is a wrapper around Python standard libraryâs
logging.basicConfig(), but with additional parameters and tweaked defaults.It sets up the global
rootlogger, and optionally adds a file or stream handler to it.Differences in default values:
Argument
basicConfig()defaultlogging.basicConfig()defaultstyle{%format{levelname}: {message}%(levelname)s:%(name)s:%(message)sThis function takes the same parameters as
logging.basicConfig(), but require them to be all passed as explicit keywords arguments.- Parameters:
filename (
str|None) â Specifies that alogging.FileHandlerbe created, using the specified filename, rather than anStreamHandler.filemode (
str) âIf filename is specified, open the file in this
mode.Defaults to
a.Use the specified format string for the handler.
Defaults to
{levelname}: {message}.datefmt (
str|None) â Use the specified date/time format, as accepted bytime.strftime().style (
Literal['%','{','$']) âIf format is specified, use this style for the format string:
%for printf-style,{forstr.format(),$forstring.Template.
Defaults to
{.level (
int|str|None) â Set therootlogger level to the specified level.stream (
IO[Any] |None) â Use the specified stream to initialize theStreamHandler. Note that this argument is incompatible with filename - if both are present, aValueErroris raised.handlers (
Iterable[Handler] |None) â If specified, this should be an iterable of already created handlers to add to therootlogger. Any handlers which donât already have a formatter set will be assigned the default formatter created in this function. Note that this argument is incompatible with filename or stream - if both are present, aValueErroris raised.force (
bool) â If this argument is specified asTrue, any existing handlers attached to therootlogger are removed and closed, before carrying out the configuration as specified by the other arguments.encoding (
str|None) â Name of the encoding used to decode or encode the file. To be specified along with filename, and passed tologging.FileHandlerfor opening the output file.errors (
str|None) â Optional string that specifies how encoding and decoding errors are to be handled by thelogging.FileHandler. Defaults tobackslashreplace. Note that ifNoneis specified, it will be passed as such toopen().
- Return type:
Important
Always keep the signature of this function, the default values of its parameters and its documentation in sync with the one from Pythonâs standard library.
These new arguments are available for better configurability:
- Parameters:
stream_handler_class (
type[Handler]) â Alogging.Handlerclass that will be used inlogging.basicConfig()to create a default stream-based handler. Defaults toStreamHandler.file_handler_class (
type[Handler]) â Alogging.Handlerclass that will be used inlogging.basicConfig()to create a default file-based handler. Defaults tologging.FileHandler.formatter_class (
type[Formatter]) â Alogging.Formatterclass of the formatter that will be used inlogging.basicConfig()to setup the default formatter. Defaults toFormatter.
Note
I donât like the camel-cased name of this function and would have called it
basic_config(), but itâs kept this way for consistency with Pythonâs standard librarylogging.basicConfig().
- click_extra.logging.new_logger(name='root', *, propagate=False, force=True, **kwargs)[source]¶
Setup a logger in the style of Click Extra.
By default, this helper will:
Fetch the loggerregistered under thenameparameter, or creates a new one with that name if it doesnât exist,Set the loggerâs
propagateattribute toFalse,Force removal of any existing handlers and formatters attached to the logger,
Attach a new
StreamHandlerwithFormatter,Return the logger object.
This function is a wrapper around
basicConfig()and takes the same keywords arguments.- Parameters:
name (
str) â ID of the logger to setup. IfNone, Pythonâsrootlogger will be used. If a logger with the provided name is not found in the global registry, a new logger with that name will be created.propagate (
bool) â Sets the loggerâspropagateattribute. Defaults toFalse.force (
bool) â Same as the force parameter fromlogging.basicConfig()andbasicConfig(). Defaults toTrue.kwargs â Any other keyword parameters supported by
logging.basicConfig()andbasicConfig().
- Return type:
- class click_extra.logging.VerbosityOption(param_decls=None, default_logger='root', default=LogLevel.WARNING, metavar='LEVEL', type=EnumChoice('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'), help='Either CRITICAL, ERROR, WARNING, INFO, DEBUG.', **kwargs)[source]¶
Bases:
_VerbosityOption--verbosity LEVELoption to set the log level of_VerbosityOption.Set up a verbosity-altering option.
- Parameters:
default_logger (
Logger|str) â If alogging.Loggerobject is provided, thatâs the instance to which we will set the level to. If the parameter is a string and is found in the global registry, we will use it as the loggerâs ID. Otherwise, we will create a new logger withnew_logger()Default to the globalrootlogger.
- class click_extra.logging.VerboseOption(param_decls=None, **kwargs)[source]¶
Bases:
_CounterOption--verbose/-voption to raise the log level of_VerbosityOptionby one step per repetition.Each
-vraises the verbosity by oneLogLevelstep. The option can be repeated, so-vv(or-v -v) raises it by two steps.The base level the counter starts from is sourced from
VerbosityOption.default. So with--verbosityâs default left atWARNING:-vraises the level toINFO,-vvraises the level toDEBUG,any further repetition is clamped at the loudest level, so
-vvvvvfor example resolves toDEBUG.
-vshares a single signed counter withQuietOptionâs-q, so the two cancel out:-v -qleaves the level unchanged. See_VerbosityOption.resolve_levelfor the full reconciliation rule with--verbosity.Set up a verbosity-altering option.
- Parameters:
default_logger â If a
logging.Loggerobject is provided, thatâs the instance to which we will set the level to. If the parameter is a string and is found in the global registry, we will use it as the loggerâs ID. Otherwise, we will create a new logger withnew_logger()Default to the globalrootlogger.
- class click_extra.logging.QuietOption(param_decls=None, **kwargs)[source]¶
Bases:
_CounterOption--quiet/-qoption to lower the log level of_VerbosityOptionby one step per repetition.The symmetric counterpart of
VerboseOption: where-vraises the verbosity oneLogLevelstep at a time,-qlowers it. Starting fromVerbosityOption.default(WARNINGby default):-qlowers the level toERROR,-qqlowers the level toCRITICAL,any further repetition is clamped at the quietest level, so
-qqqqqfor example resolves toCRITICAL.
-qshares a single signed counter withVerboseOptionâs-v, so the two cancel out:-v -qleaves the level unchanged. See_VerbosityOption.resolve_levelfor the full reconciliation rule with--verbosity.Set up a verbosity-altering option.
- Parameters:
default_logger â If a
logging.Loggerobject is provided, thatâs the instance to which we will set the level to. If the parameter is a string and is found in the global registry, we will use it as the loggerâs ID. Otherwise, we will create a new logger withnew_logger()Default to the globalrootlogger.
click_extra.logo module¶
Terminal rendition of the Click Extra brand mark.
The mark of docs/assets/logo-square.svg is six cubes stacked three-two-one. Here
they are rebuilt as flat shaded solids â one color per face, no outline anywhere â
and painted with half blocks, two sub-pixels to a terminal line.
Flat faces are what let one palette serve a light terminal and a dark one. An
outlined mark carries its shape in the outline, so every stroke has to out-contrast
whatever sits behind it, and the artworkâs own palette spans too wide a range for
that: six of its colors vanish on white, two more on black. A flat mark carries its
shape in the difference between its three planes, which no background can touch,
leaving only the silhouette to keep its distance. That fits comfortably in the middle
of the range, which is where FACE_COLORS sits.
Caution
The markâs structure is carried by color: strip the ANSI codes and it collapses
into one silhouette. VersionScreen therefore only draws
it where color reaches the output, falling back to the plain --version line
everywhere else â which is also the form machine readers parse.
- click_extra.logo.DOCS_URL = 'https://kdeldycke.github.io/click-extra'¶
Canonical documentation host, advertised on the version screen.
- click_extra.logo.TAGLINE = 'Drop-in replacement for Click and Cloup'¶
What the project is, spelled out under the program name.
- click_extra.logo.UNIT = 2¶
Scale of the whole mark, in sub-pixels.
Every dimension is a multiple of it, so the mark is
12 * UNITcolumns wide and5 * UNITlines tall. Two is the largest that still seats the mark beside the version screenâs facts inside eighty columns: 24 columns of mark, three of gutter and fifty of facts comes to 77. Three would need 89, and the screen would decline to draw itself on any standard terminal.
- click_extra.logo.LEVELS: tuple[tuple[int, int], ...] = ((0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (2, 0))¶
Each cubeâs (row, column) up the pyramid, bottom row first.
Also the order
FACE_COLORSis written in, and the order the mark is painted in: a cube resting on two others has to be laid down after them.
- click_extra.logo.BRAND_HUES: tuple[int, ...] = (41, 94, 306, 279, 210, 156)¶
Each cubeâs hue in degrees, in
LEVELSorder.Read off the ribbon that outlines each cubeâs top face in the artwork. The mark has no per-cube hue of its own â cube one alone carries gold, green and olive across its six ribbons â so this is a reading of the artwork rather than a recovery of it. It keeps the terminal mark recognizably the same six colors people already associate with the logo, which an evenly spaced spectrum would not.
- click_extra.logo.SATURATION = 0.62¶
HLS saturation shared by every face. Vivid enough to tell six hues apart.
- click_extra.logo.PLANE_LUMINANCE: dict[str, float] = {'l': 0.13, 'r': 0.22, 't': 0.36}¶
WCAG relative luminance per plane: the lid, then the two walls.
Chosen as a band rather than per color, so every hue is equally far from both backgrounds. The floor of the band is what the mark shows against white and the ceiling what it shows against black, which is why it sits in the middle: the widest band tried reads beautifully on black and falls to 1.74:1 on white.
The 2.25:1 it leaves between a cubeâs lid and its dark wall is well past what an eye needs to see a facet, and it survives every dichromacy, planes differing in luminance alone.
- click_extra.logo.FACE_COLORS: tuple[dict[str, str], ...] = ({'l': '#7F611E', 'r': '#A37B26', 't': '#CB9A30'}, {'l': '#40721B', 'r': '#519122', 't': '#66B52A'}, {'l': '#AD28A1', 'r': '#D344C6', 't': '#E17FD8'}, {'l': '#9730CC', 'r': '#AE5ED9', 't': '#C58CE4'}, {'l': '#2767A8', 'r': '#3985D0', 't': '#70A7DD'}, {'l': '#1B724F', 'r': '#229265', 't': '#2BB87F'})¶
Each cubeâs three face colors, in
LEVELSorder.Derived, not picked: every entry is its cubeâs
BRAND_HUEShue atSATURATION, taken to the luminance its plane declares inPLANE_LUMINANCE. Written out rather than computed at import so the palette stays greppable and a designer can hand-tune one value;test_palette_follows_its_derivationfails if a tuned value drifts off the system.Emitted as 24-bit color. The 256-color cube cannot separate all eighteen, and the usual reason to prefer it does not apply: no touching pair of faces collides there, so a terminal that downsamples still shows six distinct cubes.
- click_extra.logo.geometry()[source]¶
One cubeâs dimensions, in sub-pixels.
A lid four units wide and two tall is 2:1 dimetric, and the smallest such rhombus whose half-height is a whole number â which the row pitch needs. The body matches the lidâs width over two, making every box a true cube.
- click_extra.logo.LOGO_WIDTH = 24¶
Columns the mark occupies.
- click_extra.logo.LOGO_LINES = 10¶
Terminal lines the mark renders to, two sub-pixel rows making one.
- click_extra.logo.faces()[source]¶
Every visible face, bottom row first, as whole-sub-pixel polygons.
2:1 dimetric rather than the artworkâs 30 degrees, and integer vertices rather than a sampled rendering, for the same reason: a 30-degree edge advances 1.732 sub-pixels per row, which no grid can hold, so it comes out as a stair of uneven treads that the eye reads as fraying. Two across for every one down tiles a square grid exactly, and every tread is then the same.
- click_extra.logo.sub_pixels()[source]¶
The mark as a grid of flat colors, hit-tested against the face polygons.
Rasterizing the mark and reading pixels back would hand the antialiaser a say in the palette: every boundary it smooths mints a color belonging to neither face, and a rendition this size comes back carrying over a hundred of them. Testing each sub-pixelâs centre against the polygons keeps it to the eighteen declared, three per cube, which is what makes the edges read as steps rather than smudge.
- click_extra.logo.render_logo()[source]¶
Paint the mark into styled lines, each exactly
LOGO_WIDTHwide.A cell whose two sub-pixels carry different colors paints the top one as foreground over the bottom one as background, which is what fits two independent colors on one line. Runs of cells sharing a color pair are styled together rather than one escape sequence per character, keeping the mark from tripling in size.
Trailing blanks are kept:
VersionScreenpads a ragged logo for us, but a mark that arrives square costs it nothing to measure.
- click_extra.logo.brand_facts()[source]¶
The interpreter and platform every screen reports, plus this projectâs own.
- click_extra.logo.BRAND_SCREEN = VersionScreen(logo=(' \x1b[38;2;43;184;127mââââââ\x1b[0m ', ' \x1b[38;2;27;114;79mâ\x1b[0m\x1b[38;2;43;184;127m\x1b[48;2;27;114;79mââ\x1b[0m\x1b[38;2;43;184;127mââ\x1b[0m\x1b[38;2;43;184;127m\x1b[48;2;34;146;101mââ\x1b[0m\x1b[38;2;34;146;101mâ\x1b[0m ', ' \x1b[38;2;27;114;79mââââ\x1b[0m\x1b[38;2;34;146;101mââââ\x1b[0m ', ' \x1b[38;2;197;140;228mââââ\x1b[0m\x1b[38;2;27;114;79m\x1b[48;2;197;140;228mââ\x1b[0m\x1b[38;2;27;114;79mâ\x1b[0m\x1b[38;2;34;146;101mâ\x1b[0m\x1b[38;2;34;146;101m\x1b[48;2;112;167;221mââ\x1b[0m\x1b[38;2;112;167;221mââââ\x1b[0m ', ' \x1b[38;2;151;48;204mâ\x1b[0m\x1b[38;2;197;140;228m\x1b[48;2;151;48;204mââ\x1b[0m\x1b[38;2;197;140;228mââ\x1b[0m\x1b[38;2;197;140;228m\x1b[48;2;174;94;217mââ\x1b[0m\x1b[38;2;174;94;217mâ\x1b[0m\x1b[38;2;39;103;168mâ\x1b[0m\x1b[38;2;112;167;221m\x1b[48;2;39;103;168mââ\x1b[0m\x1b[38;2;112;167;221mââ\x1b[0m\x1b[38;2;112;167;221m\x1b[48;2;57;133;208mââ\x1b[0m\x1b[38;2;57;133;208mâ\x1b[0m ', ' \x1b[38;2;151;48;204mââââ\x1b[0m\x1b[38;2;174;94;217mââââ\x1b[0m\x1b[38;2;39;103;168mââââ\x1b[0m\x1b[38;2;57;133;208mââââ\x1b[0m ', ' \x1b[38;2;203;154;48mââââ\x1b[0m\x1b[38;2;151;48;204m\x1b[48;2;203;154;48mââ\x1b[0m\x1b[38;2;151;48;204mâ\x1b[0m\x1b[38;2;174;94;217mâ\x1b[0m\x1b[38;2;174;94;217m\x1b[48;2;102;181;42mââ\x1b[0m\x1b[38;2;102;181;42mââ\x1b[0m\x1b[38;2;39;103;168m\x1b[48;2;102;181;42mââ\x1b[0m\x1b[38;2;39;103;168mâ\x1b[0m\x1b[38;2;57;133;208mâ\x1b[0m\x1b[38;2;57;133;208m\x1b[48;2;225;127;216mââ\x1b[0m\x1b[38;2;225;127;216mââââ\x1b[0m ', '\x1b[38;2;127;97;30mâ\x1b[0m\x1b[38;2;203;154;48m\x1b[48;2;127;97;30mââ\x1b[0m\x1b[38;2;203;154;48mââ\x1b[0m\x1b[38;2;203;154;48m\x1b[48;2;163;123;38mââ\x1b[0m\x1b[38;2;163;123;38mâ\x1b[0m\x1b[38;2;64;114;27mâ\x1b[0m\x1b[38;2;102;181;42m\x1b[48;2;64;114;27mââ\x1b[0m\x1b[38;2;102;181;42mââ\x1b[0m\x1b[38;2;102;181;42m\x1b[48;2;81;145;34mââ\x1b[0m\x1b[38;2;81;145;34mâ\x1b[0m\x1b[38;2;173;40;161mâ\x1b[0m\x1b[38;2;225;127;216m\x1b[48;2;173;40;161mââ\x1b[0m\x1b[38;2;225;127;216mââ\x1b[0m\x1b[38;2;225;127;216m\x1b[48;2;211;68;198mââ\x1b[0m\x1b[38;2;211;68;198mâ\x1b[0m', '\x1b[38;2;127;97;30mââââ\x1b[0m\x1b[38;2;163;123;38mââââ\x1b[0m\x1b[38;2;64;114;27mââââ\x1b[0m\x1b[38;2;81;145;34mââââ\x1b[0m\x1b[38;2;173;40;161mââââ\x1b[0m\x1b[38;2;211;68;198mââââ\x1b[0m', ' \x1b[38;2;127;97;30mâââ\x1b[0m\x1b[38;2;163;123;38mâââ\x1b[0m \x1b[38;2;64;114;27mâââ\x1b[0m\x1b[38;2;81;145;34mâââ\x1b[0m \x1b[38;2;173;40;161mâââ\x1b[0m\x1b[38;2;211;68;198mâââ\x1b[0m '), tagline='Drop-in replacement for Click and Cloup', facts=<function brand_facts>, gutter=' ')¶
Click Extraâs own
--versionscreen.Mounted on the
click-extraCLI, and the shape a CLI of your own would copy:from functools import partial from click_extra import group from click_extra.commands import default_params @group(params=partial(default_params, screen=BRAND_SCREEN)) def cli(): pass
The mark is painted once, here, since it never changes.
brand_facts()is passed uncalled so its values are read when--versionis, not when this module is imported â the habit that keeps a costlier fact from being charged to every invocation.
click_extra.multicall module¶
Multicall / argv[0] dispatch: one binary answering to many names.
A multicall binary is a single executable whose behavior is selected by the
name it is invoked with: bzip2, bunzip2 and bzcat are the same file,
vim and view differ by default options, and BusyBox multiplexes hundreds
of applets behind symlinks pointing at one binary. MulticallGroup
brings the pattern to Click Extra: a group that, when invoked under the name
of one of its subcommands, skips the group and behaves exactly like that
subcommand as a standalone binary.
Declare one with multicall_group():
from click_extra import argument, echo, multicall_group, option
@multicall_group()
def kitchen():
'''A multicall kitchen appliance.'''
@kitchen.command()
@option("--temperature", default="180")
@argument("dishes", nargs=-1)
def bake(temperature, dishes):
'''Bake dishes in the oven.'''
@kitchen.command()
@option("--hours", default="2")
@argument("bottles", nargs=-1)
def chill(hours, bottles):
'''Chill bottles in the fridge.'''
Invoked as kitchen, the CLI is a regular group. Invoked through a symlink
named bake (or any other subcommand name), it is the bake command: one
flat argument parse, its own usage line and help screen, and the full set of
Click Extra options merged in:
$ kitchen bake --temperature 200 pie # regular group dispatch
$ ln -s $(which kitchen) bake
$ bake --temperature 200 pie # same thing, no subcommand
A personality maps to a sequence of tokens, not just a subcommand, so a
name can also pre-fill options (bzcat is bzip2 --decompress --stdout):
@multicall_group(personalities={"chill-fast": ("chill", "--hours", "1")})
def kitchen():
...
Note
Behavioral notes for personality mode:
The groupâs own callback does not run: the personality is a standalone command with no parent context.
Configuration and environment variable namespaces follow the personality name:
bakereads its configuration from thebakeapp dir and theBAKE_*environment variables, the way a standalone binary would, and not from the groupâskitchennamespace.The invocation name a command was started under is also exposed on its own, for custom dispatch logic: see
click_extra.context.INVOCATION_NAME.
- click_extra.multicall.WINDOWS_EXE_SUFFIX = '.exe'¶
Suffix of Windows console-script wrappers, stripped from
argv[0].On Windows, entry points are materialized as
.exeshims, so a symlink namedbakelands inargv[0]asbake.exe.
- click_extra.multicall.normalize_personality(tokens)[source]¶
Normalize a personality mapping value into a tuple of CLI tokens.
Accepts a bare subcommand name (
"chill") or a token sequence (("chill", "--hours", "1")). The first token names the subcommand the personality dispatches to; the rest is prepended to the userâs arguments.- Raises:
TypeError â when the value is neither a string nor a sequence.
ValueError â on an empty sequence or a non-string token.
- Return type:
- class click_extra.multicall.PersonalitiesCommand(name, context_settings=None, callback=None, params=None, help=None, epilog=None, short_help=None, options_metavar='[OPTIONS]', add_help_option=True, no_args_is_help=False, hidden=False, deprecated=False)[source]¶
Bases:
ColorizedCommandSynthetic subcommand listing every name a
MulticallGroupanswers to.Auto-injected into every
MulticallGroup, the wayHelpCommandis injected into everyGroup: the group mode needs a place to enumerate the symlink names, and a subcommand costs no new top-level option on the groupâs help screen.
- class click_extra.multicall.MulticallGroup(*args, personalities=None, personalities_command=True, **kwargs)[source]¶
Bases:
GroupA
Groupdispatching on its invocation name, BusyBox-style.When the name the binary was invoked under matches a personality, the group steps aside entirely and runs the matching subcommand as a standalone command: the personality carries the groupâs options merged into the subcommandâs, parses them in one flat pass with no positional ordering constraint, and renders its own usage line and help screen. Any other invocation name falls through to regular group behavior.
The invocation name is, in precedence order:
an explicit
prog_namepassed tomain()(whatclick_extra.testing.CliRunneruses to simulate a symlink),else the unresolved basename of
sys.argv[0].
The basename is used unresolved: resolving through
os.path.realpath()would return the symlinkâs target and destroy the personality. A trailingWINDOWS_EXE_SUFFIXis stripped for Windows console-script shims. Clickâs own_detect_program_name()is deliberately not used: it reads__main__.__package__and answerspython -m âŠin the module case. Seeclick_extra.cli_wrapper.invoke_target()for the full trap. A name matching no personality is not an error: it falls through, which is also what keeps the feature inert under test runners, whereargv[0]is the runnerâs own binary.Like
Group.__init__, but with multicall dispatch.- Parameters:
personalities (
Mapping[str,str|Sequence[str]] |None) â maps an invocation name to the tokens it invokes: a bare subcommand name ("chill") or a token sequence (("chill", "--hours", "1")) whose extra tokens are prepended to the userâs arguments. Left toNone, every non-hidden, non-synthetic subcommand is its own personality.personalities_command (
bool) â whenTrue(the default), apersonalitiessubcommand is auto-registered on the group, listing every invocation name the binary answers to. Register your ownpersonalitiessubcommand to override it.
- resolve_invocation_name(prog_name=None)[source]¶
The name this binary was invoked under.
An explicit prog_name wins: it is what makes the feature testable without symlinks on disk. Otherwise the unresolved basename of
sys.argv[0]is used, with a trailing.exestripped on Windows.
- list_personalities()[source]¶
Every personality name mapped to the tokens it invokes.
The explicit
personalitiesmapping when one was declared, else every non-hidden, non-synthetic subcommand mapped to itself.
- main(args=None, prog_name=None, **kwargs)[source]¶
Dispatch on the invocation name before any argument parsing.
A matching personality runs as a standalone command, the groupâs own options merged into it, its extra tokens prepended to the arguments. Anything else delegates to the regular group
main().- Return type:
- build_personality(name, tokens)[source]¶
Synthesize the standalone command the name personality runs as.
The personality is a fresh instance of the subcommandâs own class, re-instantiated over the groupâs parameters merged with the subcommandâs, not a copy whose
paramsattribute is patched after the fact. Two reasons make the re-instantiation mandatory:Cloup computes its help layout (
arguments,option_groups,ungrouped_options) fromparamsinside__init__, so a patched copy parses every merged option but only renders the subcommandâs own on its help screen.Click Extraâs own
Command.__init__does work that must run over the merged set:extra_option_at_endreordering, option priorities, auto envvar population and help-keyword collection.
Every parameter is deep-copied, because
Command.__init__re-runspopulate_auto_envvarsover the merged set under the personalityâs ownauto_envvar_prefix: sharing instances would rewrite the groupâs and subcommandâsenvvarattributes and leak that back into group mode. This is the same class of leaky statedefault_params()warns about.- Return type:
click_extra.myst_converter module¶
Convert reST docstrings to MyST in Python source files.
Transforms reST markup in docstrings and comments to MyST markdown. The
companion Sphinx extension click_extra.sphinx.myst_docstrings converts
the MyST back to reST at build time, so sphinx.ext.autodoc still works.
Conversions applied (in order):
Cross-references:
:role:`target`->{role}`target`Named links:
`text <url>``_->text <url>`_Inline code:
``code``->`code`#:comment blocks: strip prefix, convert directives, re-wrap.Directives:
.. directive::+ indented body -> `````{directive} ``/ ````` ``
Only docstrings (bare string-expression statements, located with ast)
and comments (located with tokenize) are transformed. String
literals, f-strings, and every other piece of runtime code pass through
byte-for-byte: a regex pattern or an error message that happens to contain
reST markup is not documentation and must not be rewritten.
Safe to re-run: already-converted MyST syntax does not match the reST patterns, so the script is idempotent.
Note
f-string exclusion: Cross-reference and inline-code regexes exclude
targets containing { so that interpolation-style placeholders (like
{self.id} in a documented format template) are untouched.
Note
Nested fences stay as reST: A directive whose body already contains a triple-backtick fence is left in reST. Converting it would nest two same-level fences, which markdown cannot delimit, and the build-time extension passes reST through unchanged anyway.
Note
Nested directives stay as reST: A .. code-block:: inside a
converted backtick-fenced warning directive is emitted as-is. The
hook handles this correctly because it re-indents the body when
converting back to reST.
Note
Link labels lose backticks: `sys.platform <url>`_ is valid MyST
but reST has no nested markup. The hook strips backticks from labels
before emitting the reST link.
- click_extra.myst_converter.detect_source_package(pyproject_path=None)[source]¶
Locate the projectâs single source package from its script entry points.
Reads
[project.scripts]frompyproject.tomland derives the top-level package of each entry point target ("pkg.cli:main"givespkg), so theconvert-to-mystcommand can run bare from a project root.- Parameters:
pyproject_path (
Path|None) â Path of thepyproject.tomlto inspect. Defaults to the one in the current working directory.- Return type:
- Returns:
Path of the single detected package directory.
- Raises:
ValueError â When
pyproject.tomlis missing, declares no script entry point, or several distinct packages are detected.
- click_extra.myst_converter.convert_xrefs(text)[source]¶
Convert reST cross-references to MyST syntax.
- Return type:
- click_extra.myst_converter.convert_links(text)[source]¶
Convert reST named hyperlinks to markdown links.
- Return type:
- click_extra.myst_converter.convert_inline_code(text)[source]¶
Convert reST double-backtick literals to single-backtick.
- Return type:
- click_extra.myst_converter.convert_directives(text)[source]¶
Convert reST directives to MyST backtick fences in a single pass.
Body lines are collected by indentation (deeper than the
..line) and dedented to the fence level. Trailing blank lines between consecutive directives are preserved as a single separator.Nested reST directives (like
.. code-block::inside.. warning::) are emitted as-is in the fence body. The hook re-indents them during the reST round-trip.A directive whose body contains a triple-backtick fence is left in reST entirely: converting it would produce two same-level fences that markdown cannot tell apart, and a longer outer fence is no better since the build-time hook only recognizes triple-backtick fences.
Symmetrically, existing fences are opaque: a reST directive inside a fence body is exactly what a previous conversion of nested directives produces (the inner one stays reST by design), so re-scanning it would break idempotency and nest same-level fences.
- Return type:
- click_extra.myst_converter.convert_comment_blocks(text)[source]¶
Convert
#:Sphinx comment docstrings.Consecutive
#:lines are collected, the prefix is stripped, all conversions are applied to the extracted content, and the prefix is re-added.- Return type:
- click_extra.myst_converter.convert_source(source)[source]¶
Convert reST markup to MyST in a Python moduleâs docstrings and comments.
Docstrings get the full pipeline, in an order that matters: inline constructs (cross-references, links, inline code) run before directives so that directive bodies are already converted when they are dedented into fences. Comments get the inline conversions only, except consecutive full-line
#:comments, whose directives are also converted throughconvert_comment_blocks(). Everything outside docstrings and comments passes through byte-for-byte.- Return type:
click_extra.output module¶
Send command output to a file path or to stdout.
Helpers for the common --output option pattern, where a - value means
âwrite to stdoutâ instead of creating a file literally named -.
- click_extra.output.STDOUT_SENTINEL = '-'¶
Conventional
--outputvalue asking for stdout instead of a file on disk.
- click_extra.output.is_stdout(path)[source]¶
Return
Truewhen path is the stdout sentinel-.Guards against accidentally creating a file literally named
-in the current directory.- Return type:
- click_extra.output.prep_path(path)[source]¶
Open path for writing as UTF-8 text, or return stdout for
-.Always yields a UTF-8 stream, stdout included, sidestepping the
UnicodeEncodeErrora non-ASCII payload triggers on Windows, where the console defaults tocp1252. For a real path, missing parent directories are created first, absorbing themkdir -pa caller would otherwise need.Note
When stdout is an in-memory capture with no backing file descriptor (Clickâs test runner, the Sphinx
{click:run}directive that live-renders CLI output in the docs),fileno()raises and the existing stream is returned as-is. Such streams are already Python text objects, so the Windowscp1252concern does not apply: that only bites a real terminal, which always has a descriptor.
click_extra.parameters module¶
Our own flavor of Option, Argument and parameters.
- class click_extra.parameters.P¶
Type variable bound to
click.Parameter, lettingrequire_sibling_param()return the exact subclass it was asked to find.alias of TypeVar(âPâ, bound=
Parameter)
- click_extra.parameters.PARAM_PATH_SEP = '.'¶
Separator joining the keys of a parameterâs fully-qualified path (
cli.subcommand.param).
- click_extra.parameters.search_params(params, klass, include_subclasses=True, unique=True)[source]¶
Search a particular class of parameter in a list and return them.
- Parameters:
params (
Iterable[Parameter]) â list of parameter instances to search in.klass (
type[Parameter]) â the class of the parameters to look for.include_subclasses (
bool) â ifTrue, includes in the results all parameters subclassing the providedklass. IfFalse, only matches parameters which are strictly instances ofklass. Defaults toTrue.unique (
bool) â ifTrue, raise an error if more than one parameter of the providedklassis found. Defaults toTrue.
- Return type:
- click_extra.parameters.last_param(params, klass)[source]¶
Return the last parameter of exactly
klassin params, orNone.Unlike
search_params(), this matches the exactklass(no subclasses) and tolerates duplicates: when an option is declared more than once (like an explicit@verbosity_optionstacked on a Click Extra command that already ships one), Click keeps the last occurrence, so this mirrors that here instead of erroring out on the ambiguity.
- click_extra.parameters.require_sibling_param(params, requester, klass)[source]¶
Return the sibling klass parameter declared on the same command, or raise.
Some options are inert on their own: they drive machinery owned by a sibling option.
--no-configand--validate-config, for instance, both depend on the--configoption (ConfigOption). This helper centralizes the lookup so every such option raises the sameRuntimeErrorwhen its required sibling is missing, naming the offending flag.- Parameters:
- Return type:
- click_extra.parameters.full_short_help(command)[source]¶
Return the commandâs canonical one-line short help, untruncated.
Clickâs
click.Command.get_short_help_str()truncates to 45 characters by default with a trailing"..."so subcommand listings fit a terminal column. That bound is wrong for generated documentation and completion specs, where the NAME / COMMANDS sections carry the full description and the renderer wraps text on its own.The lookup mirrors Clickâs order: an explicit
short_helpwins, otherwise the first paragraph ofcommand.helpis joined into one line. A truthydeprecatedflag prepends(Deprecated)so the flag stays visible.- Return type:
- click_extra.parameters.resolve_param_help(param, ctx)[source]¶
Return a parameterâs help text, including the dynamically-generated ones.
Reading
param.helpcovers the options that carry a static string, and misses the ones that compute their help from the context: Click Extraâs own-v/-qderive theirs from the resolved base verbosity, and leave the attribute atNone(seeget_help_record()). Falling back to the help record picks those up.The record also carries Clickâs bracket fields (
[default: âŠ],[required],[env var: âŠ]), appended to the prose behind two spaces. They are stripped here: they are not the authorâs documentation, and every backend of this module renders them (or deliberately does not) from structured fields of its own.
- click_extra.parameters.param_spellings(param)[source]¶
All literal spellings of a parameter: primary
optsthensecondary_opts.A boolean flag pair yields both forms (
--foo,--no-foo); a plain option yields just its declared names.
- click_extra.parameters.short_long_opts(opts)[source]¶
Split option spellings into the first short (
-x) and long (--xy) form.Either element is the empty string when that form is absent.
- click_extra.parameters.option_value_kind(param)[source]¶
Classify how an option consumes a value, the basis for rendering its metavar.
"flag": takes no value. A boolean switch (--foo,--foo/--no-foo), a flag with a customflag_value(--no-config), or a counter (-v)."optional": the value may be omitted. Click models this asis_flag=Falsewith aflag_valueset, so a bare--colorstands for the flag value while--color=neverpasses an explicit one."required": consumes a value (--config CONFIG_PATH).
Note
The discriminator is Clickâs
is_flag(pluscount), notis_bool_flag: a flag carrying a customflag_valuesuch asNoConfigOptionreportsis_bool_flag=Falseyet still takes no value.- Return type:
Literal['flag','optional','required']
- click_extra.parameters.resolve_flag_value(param)[source]¶
The value paramâs primary declaration stands for.
Released Click materializes it in
flag_value:Nonefor a plain option or a counter,Truefor a boolean flag, and the declared value otherwise (--colorstanding foralways). Clickâs development branch leaves that attribute as theUNSETsentinel and answers the same question lazily inflag_activation_value, so reading either attribute on its own is right on only one of the two, and storing the sentinel anywhere it will be read back as a value silently turns the flag off.- Return type:
- click_extra.parameters.is_repeatable(param)[source]¶
Whether the parameter may be supplied several times (
multipleorcount).- Return type:
- class click_extra.parameters.Argument(*args, help=None, **attrs)[source]¶
Bases:
_ParameterMixin,ArgumentWrap
cloup.Argument, itself inheriting fromclick.Argument.Inherits first from
_ParameterMixinto allow future overrides of ClickâsParametermethods.
- class click_extra.parameters.Option(*args, group=None, **attrs)[source]¶
Bases:
_ParameterMixin,OptionWrap
cloup.Option, itself inheriting fromclick.Option.Inherits first from
_ParameterMixinto allow future overrides of ClickâsParametermethods.
- class click_extra.parameters.ExtraOption(*args, group=None, **attrs)[source]¶
Bases:
OptionDedicated to option implemented by
click-extraitself.Provides a way to identify Click Extraâs own options with certainty, and restores the pre-Click-8.4.0 contract that a callback (or a typeâs
convert()) can introspect its own parameter source from within itself.Note
This is the one click-extra class that deliberately keeps the
Extraprefix. The8.0.0cleanup dropped it everywhere else (ExtraCommandbecameCommand,ExtraContextbecameContext, and so on), shadowing the matching Cloup or Click class. Here the plainOptionname is already taken by the user-facing enhanced wrapper this class subclasses, so the prefix is not legacy baggage but a real distinction:ExtraOptionmarks click-extraâs own built-in options. That marker is load-bearing, sinceCommandsorts parameters withisinstance(param, ExtraOption)to push the built-in options to the end.Note
Bracket fields (envvar, default, range, required) cannot be pre-styled in
get_help_record()because Clickâs text wrapper splits lines after the record is returned, which would break ANSI codes that span wrapped boundaries. Styling is instead applied post-wrapping inHelpFormatter._style_bracket_fields(), which uses the structured data fromOption.get_help_extra()to identify each field by its label.Note
Built-in option subclasses share a common shape: their
__init__defaultsparam_declsto the optionâs canonical flags and wires an eager callback viakwargs.setdefault("callback", self.<callback>). Every callback name encodes its role with a verb prefix. The common roles are:set_<key>publishes a resolved value toctx.meta(set_color,set_no_color,set_theme,set_telemetry,set_progress,set_accessible,set_zero_exit, the verbosity optionsâset_level);init_<system>additionally installs actxhelper or records a snapshot (init_timer,init_formatter,init_columns,init_sort);validate_<thing>coerces and validates the raw input (validate_jobs,validate_config);print_*renders output and exits (print_man,print_params,print_and_exit).
A few options own a richer operation and name it with its own verb rather than forcing one of the above.
ConfigOptionwiresload_confto read, parse, and merge a configuration file, andNoConfigOptionwirescheck_sibling_config_optionto assert that a sibling--configoption exists.- handle_parse_result(ctx, opts, args)[source]¶
Record the parameter source before delegating to the base implementation.
Warning
Click
8.4.0(PR pallets/click#3404) reorderedParameter.handle_parse_resultsoctx.set_parameter_sourceruns afterprocess_value. Callbacks that introspect their own provenance viactx.get_parameter_source(self.name)therefore readNoneinstead of the actual source.ColorOption,ConfigOption, andShowParamsOptionrely on this introspection (from their eager callback) to decide whether an env var should override the default (--color), whether the--configpath was user-supplied, and what to render in theSourcecolumn of--params.JobsOptionrelies on the same introspection from its typeâs non-eagerconvert()(JobCount), to decide whether anauto/maxcollapsing to a single job logs as a warning (explicit request) or at info level (the optionâs own default).Click
8.4.1restored the pre-8.4.0contract upstream (PR pallets/click#3484), so this override only matters for Click8.4.0itself, which sits inside click-extraâs supported>= 8.3.1range. Pre-recording the source here, for every option regardless of eagerness, keeps that contract on every supported Click.super().handle_parse_resultre-records the same value at the canonical time, so the slot arbitration logic introduced by #3404 is unaffected:slot_emptyis computed fromctx.params, not from_parameter_source.consume_valueruns twice as a side effect: once here and once insuper. Both calls are pure for click-extraâs existing options (no env var side effects, no prompt):consume_valueonly resolves the raw value and its source, it never invokes the parameterâstype.convert(), so this pre-record cannot itself trigger a callbackâs or a typeâs logging or validation twice. Should a future subclass need prompt behavior, this override would need to cache the result instead.The pre-record is skipped when the slot already carries a source from an earlier option sharing the same
name(Clickâs feature-switch pattern), so the arbitration logic insuperstill sees the originalexisting_sourcerather than a stale rewrite from this option.
- class click_extra.parameters.ParamStructure[source]¶
Bases:
objectUtilities to introspect CLI options and commands structure.
Structures are represented by a tree-like
dict.Access to a node is available using a serialized path string composed of the keys to descend to that node, separated by a dot
..- excluded_params: frozenset[str]¶
Fully-qualified IDs of the parameters to block from the structure.
Set by subclasses:
ShowParamsOptionfreezes an empty set, whileConfigOptionresolves a dynamic default (or the user-provided list) within the active context. The two filters are mutually exclusive, a constraint each subclass enforces in its own constructor.
- included_params: frozenset[str] | None¶
Allowlist of parameter IDs, mutually exclusive with
excluded_params.Nonedisables the allowlist. It is resolved intoexcluded_paramsbybuild_param_trees(), once every parameter ID is known.
- static init_tree_dict(*path, leaf=None)[source]¶
Utility method to recursively create a nested dict structure whose keys are provided by
pathlist and at the end is populated by a copy ofleaf.- Return type:
- static get_tree_value(tree_dict, *path)[source]¶
Get in the
tree_dictthe value located at thepath.Raises
KeyErrorif no item is found at the providedpath.- Return type:
- walk_params()[source]¶
Generate an unfiltered list of all CLI parameters.
Everything is included, from top-level groups to subcommands, and from options to arguments.
- Yields a 2-element tuple:
a tuple of keys leading to the parameter;
the parameter object itself.
Thin adapter over
walk_command_params(): it resolves the root CLI from the active context and drops the per-parameter context that the free function also yields.
- TYPE_MAP: ClassVar[dict[type[ParamType], type[str | int | float | bool | list]]] = {<class 'click.types.BoolParamType'>: <class 'bool'>, <class 'click.types.Choice'>: <class 'str'>, <class 'click.types.DateTime'>: <class 'str'>, <class 'click.types.File'>: <class 'str'>, <class 'click.types.FloatParamType'>: <class 'float'>, <class 'click.types.FloatRange'>: <class 'float'>, <class 'click.types.IntParamType'>: <class 'int'>, <class 'click.types.IntRange'>: <class 'int'>, <class 'click.types.Path'>: <class 'str'>, <class 'click.types.StringParamType'>: <class 'str'>, <class 'click.types.Tuple'>: <class 'list'>, <class 'click.types.UUIDParameterType'>: <class 'str'>, <class 'click.types.UnprocessedParamType'>: <class 'str'>}¶
Map Click types to their Python equivalent.
Keys are subclasses of
click.types.ParamType. Values are expected to be simple builtins Python types.This mapping can be seen as a reverse of the
click.types.convert_type()method.
- static map_click_type(click_type)[source]¶
Map a Click parameter type instance to its Python equivalent.
Returns
strfor unrecognised custom types, since command-line parameters are strings by default.See the list of custom types provided by Click.
- static get_param_type(param)[source]¶
Get the Python type of a Click parameter.
Returns
strfor unrecognised custom types, since command-line parameters are strings by default.See the list of custom types provided by Click.
- build_param_trees()[source]¶
Build and return the parameters tree structure.
This removes parameters whose fully-qualified IDs are in the
excluded_paramsblocklist.If
included_paramswas provided, it is resolved intoexcluded_paramshere, where all parameter IDs are available.
- click_extra.parameters.get_param_spec(param, ctx)[source]¶
Extract the option-spec string (like
-v, --verbose) from a parameter.Temporarily unhides hidden options so their help record can be produced.
Note
The
hiddenproperty is only supported byOption, notArgument.Todo
Submit a PR to Click to separate production of param spec and help record. That way we can always produce the param spec even if the parameter is hidden. See: https://github.com/kdeldycke/click-extra/issues/689
- click_extra.parameters.format_param_row(param, ctx, path, is_structured)[source]¶
Compute the structural table cells for a Click parameter.
Returns a
dict[column_id, cell]covering every column that can be derived from the parameter object alone (no runtime invocation state or config-file context). Specifically:id,spec,class,param_type,python_type,hidden,exposed,envvars,default,is_flag,flag_value,is_bool_flag,multiple,nargs,prompt, andconfirmation_prompt.Attributes only defined on
click.Option(hidden,is_flag,flag_value,is_bool_flag,prompt,confirmation_prompt) yieldNoneforclick.Argumentparameters: empty cell in visual formats,nullin structured ones.For structured formats (JSON, YAML, etc.), values are native Python types. For visual formats, values are themed strings matching help-screen styling.
The remaining table columns (
allowed_in_conf,value,source,config_file) require live context and are filled in byrender_params_table().
- click_extra.parameters.make_resilient_context(command, info_name=None, parent=None)[source]¶
Build an introspection context for a command.
Parses no arguments and sets
resilient_parsing=Trueso required-argument errors, prompts and eager-option side effects stay dormant: the canonical way to materialize aclick.Contextpurely to read a commandâs structure (its parameters, env-var prefix and subcommands), shared by the man-page and Carapace exporters.- Return type:
- click_extra.parameters.iter_subcommands(command, ctx, *, skip_hidden=True)[source]¶
Yield a groupâs direct subcommands as
(name, command)pairs.Subcommands are discovered dynamically through
click.Group.list_commands()/get_command(), in listing order, so lazily-registered commands are included. A non-group yields nothing, a name resolving toNoneis skipped, and hidden subcommands are skipped unlessskip_hiddenisFalse(completion specs keep them, flagged hidden; documentation drops them).
- click_extra.parameters.iter_params_for_display(command, ctx)[source]¶
Yield a commandâs parameters in the order its help screen lists them.
A Click Extra command keeps two orders apart:
command.paramsis the processing order, which decides when each callback fires, while the help screen reads the presentation order Cloup caches inarguments,option_groupsandungrouped_options(seeclick_extra.commands.Command.param_priority()). Readingget_params()therefore renders a man page, a Markdown document or a completion spec whose flags no longer match the--helpits reader just saw. This is the accessor every such renderer should go through.Falls back to
get_params()for a command that carries no Cloup option groups, where the two orders are the same list. Any parameter attached after construction, and so absent from the cached groups, is yielded last rather than dropped.
- click_extra.parameters.walk_command_params(cmd, ctx, parent_keys=())[source]¶
Walk the parameter tree of a Click command and all its subcommands.
Yields
(path_keys, param, owning_ctx)for every parameter found on cmd and, recursively, on each subcommand. Each subcommand is walked under its own freshly-built child context, so context-sensitive metadata (notably the auto-generated environment variable, which derives fromContext.auto_envvar_prefix) is computed at the correct nesting level rather than inherited from the root.A subcommand whose name collides with a sibling parameter at the same level is skipped: a single fully-qualified path cannot address both an option and a subcommand at once.
- click_extra.parameters.replay_raw_args(subject_ctx)[source]¶
Re-parse the captured raw arguments to recover per-parameter values.
Click discards the pre-parsed arguments once processing is done, so the value and provenance of each parameter cannot be read back directly. When
RAW_ARGSwas captured on the context (byCommand/Group), replaying it through a fresh parser rebuilds theoptsmapping thatParameter.consume_valueconsults, without re-firing eager callbacks:handle_parse_resultis never called here, only the parser.Returns an empty mapping when no raw arguments were captured, so callers can fall back to parameter defaults.
- click_extra.parameters.param_config_source(root_ctx, keys)[source]¶
Return the configuration file supplying a parameterâs
default_mapvalue.keys is the parameterâs fully-qualified path, root command name first and parameter name last, as yielded by
walk_command_params(). ReturnsNonewhen no configuration file was loaded, when the parameter is absent from every loaded layer, or when the context carries no layereddefault_mapat all.The walk mirrors how Click resolves
default_map, so the attribution matches the value Click actually picks:Root-level parameters are looked up in the root contextâs
~collections.ChainMap, whose first layers are the loaded files in precedence order (seeCONF_SOURCES): the first layer naming the parameter wins.A subcommand section resolves against that same
ChainMap, but Click keeps descending inside the single layer that named the first segment: the file owning a subcommand section owns its whole sub-tree.
Note
Lazy subcommands receive their section from the merged configuration document, injected into the front layer by
_apply_config_to_parent_context(): those values are attributed to the highest-precedence file even when several files contributed to the merge.
- click_extra.parameters.render_params_table(subject_ctx, *, default_columns=None)[source]¶
Introspect
subject_ctx.commandand print its parameter metadata table.Walks the command and any nested subcommands, emitting one row per parameter. The table format and column selection are read from
subject_ctx.meta(seeTABLE_FORMATandCOLUMNS); when neither is set, a sibling--table-format/--columnsoption on the command is consulted, then the default_columns fallback, then the canonical order.When
subject_ctx.metacarries pre-parsedRAW_ARGS, thevalueandsourcecolumns are resolved by replaying those arguments against the command parser; otherwise they fall back to the parameter defaults.This is the shared rendering core behind both
print_params()(introspecting the live CLI) and theclick-extra wrap --paramspath (introspecting a foreign target). The caller is responsible for exiting the context afterwards.Important
Click does not keep the raw, pre-parsed arguments around, so values and their provenance cannot be read back directly. The workaround replays
RAW_ARGS(captured on the context byCommand/Group) through the command parser, callingconsume_value()rather thanhandle_parse_result()so eager callbacks are not re-triggered.- Return type:
- class click_extra.parameters.ShowParamsOption(param_decls=None, is_flag=True, expose_value=False, is_eager=True, help='Show all CLI parameters, their provenance, defaults and value, then exit.', **kwargs)[source]¶
Bases:
ExtraOption,ParamStructureA pre-configured option adding a
--paramsoption.Between configuration files, default values and environment variables, it might be hard to guess under which set of parameters the CLI will be executed. This option print information about the parameters that will be fed to the CLI.
Note
The flag is named
--params, not--show-params. It names the view it prints, matching the neighbouring bare-noun informational flags (--help,--version,--man,--tree), none of which carry ashow-verb prefix. The class and@show_params_optiondecorator keep their historical names: the class is named for what it does (show the parameters), while the flag and the parameterâs ID use the bare noun.- TABLE_HEADERS: ClassVar[tuple[_ColumnSpec, ...]] = (ColumnSpec(id='id', label='ID', description='Fully-qualified parameter path (`cli.subcommand.param_name`) derived from the [`click.Command`](https://click.palletsprojects.com/en/stable/api/#click.Command) tree. Doubles as the key used to address the parameter from a configuration file, which also accepts the kebab-case spelling of the last segment.', max_width=None, optional=False), ColumnSpec(id='spec', label='Spec.', description='Option/argument specification string (like `-v, --verbose`) extracted from [`click.Parameter.get_help_record()`](https://click.palletsprojects.com/en/stable/api/#click.Parameter).', max_width=None, optional=False), ColumnSpec(id='help', label='Help', description="The parameter's own help text, as written by the CLI author. Opt-in: it is the only column carrying free-form prose, so it stays out of the default table and is selected by ID (`--columns id,spec,help`). Structured formats are its main audience: it turns a `--params` dump into a self-describing inventory a tool or an agent can read without also parsing the rendered `--help` screen.", max_width=None, optional=True), ColumnSpec(id='class', label='Class', description="Fully-qualified class of the parameter: a subclass of [`click.Option`](https://click.palletsprojects.com/en/stable/api/#click.Option), [`click.Argument`](https://click.palletsprojects.com/en/stable/api/#click.Argument), [`cloup.Option`](https://cloup.readthedocs.io/en/stable/autoapi/cloup/index.html#cloup.Option), or one of Click Extra's own wrappers ([`click_extra.parameters.Option`](#click_extra.parameters.Option), [`click_extra.parameters.Argument`](#click_extra.parameters.Argument), [`click_extra.parameters.ExtraOption`](#click_extra.parameters.ExtraOption)).", max_width=None, optional=False), ColumnSpec(id='param_type', label='Param type', description='Click value converter class: a subclass of [`click.ParamType`](https://click.palletsprojects.com/en/stable/api/#click.ParamType) like [`click.IntRange`](https://click.palletsprojects.com/en/stable/api/#click.IntRange), [`click.Choice`](https://click.palletsprojects.com/en/stable/api/#click.Choice), or a Click Extra type.', max_width=None, optional=False), ColumnSpec(id='python_type', label='Python type', description='Python built-in type the parsed value resolves to: [`str`](https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str), [`int`](https://docs.python.org/3/library/functions.html#int), [`float`](https://docs.python.org/3/library/functions.html#float), [`bool`](https://docs.python.org/3/library/functions.html#bool), or [`list`](https://docs.python.org/3/library/stdtypes.html#list). Computed by [`ParamStructure.get_param_type()`](#click_extra.parameters.ParamStructure.get_param_type) from the Click `Param type`.', max_width=None, optional=False), ColumnSpec(id='hidden', label='Hidden', description="Reflects [`click.Option`'s `hidden`](https://click.palletsprojects.com/en/stable/api/#click.Option) constructor argument: the option is omitted from `--help` output. Empty for [`click.Argument`](https://click.palletsprojects.com/en/stable/api/#click.Argument), which does not support hiding.", max_width=None, optional=False), ColumnSpec(id='exposed', label='Exposed', description="Reflects [`click.Parameter`'s `expose_value`](https://click.palletsprojects.com/en/stable/api/#click.Parameter) constructor argument: whether the parsed value is forwarded to the command callback. Eager options like `--params` and `--help` typically run a callback and exit, so they are not exposed.", max_width=None, optional=False), ColumnSpec(id='allowed_in_conf', label='Allowed in conf?', description='Click Extra-specific: whether the parameter is reachable from a configuration file. Controlled by [`ParamStructure.excluded_params`](#click_extra.parameters.ParamStructure.excluded_params) and [`included_params`](#click_extra.parameters.ParamStructure.included_params). Empty when the CLI has no [`--config` option](config.md).', max_width=None, optional=False), ColumnSpec(id='envvars', label='Env. vars.', description="Environment variables read for this parameter: the explicit [`click.Parameter`'s `envvar`](https://click.palletsprojects.com/en/stable/api/#click.Parameter) plus the auto-resolved IDs documented in [Environment variables](envvar.md).", max_width=None, optional=False), ColumnSpec(id='default', label='Default', description='Default value returned by [`click.Parameter.get_default()`](https://click.palletsprojects.com/en/stable/api/#click.Parameter.get_default), rendered as its Python `repr()`.', max_width=None, optional=False), ColumnSpec(id='is_flag', label='Is flag', description="Reflects [`click.Option`'s `is_flag`](https://click.palletsprojects.com/en/stable/api/#click.Option): whether the option behaves as a flag (no value taken from the command line). Empty for [`click.Argument`](https://click.palletsprojects.com/en/stable/api/#click.Argument).", max_width=None, optional=False), ColumnSpec(id='flag_value', label='Flag value', description="Reflects [`click.Option`'s `flag_value`](https://click.palletsprojects.com/en/stable/api/#click.Option): the Python value substituted for the option when its flag is used. Defaults to `True` for boolean flags, can be any value for flag-value style options (like `@option('--upper', 'transform', flag_value='upper')`).", max_width=None, optional=False), ColumnSpec(id='is_bool_flag', label='Is bool flag', description='Reflects `click.Option.is_bool_flag` (set internally by Click when `flag_value` is `True` or `False`): the option is a *true* boolean flag, as opposed to a flag-value style option.', max_width=None, optional=False), ColumnSpec(id='multiple', label='Multiple', description="Reflects [`click.Parameter`'s `multiple`](https://click.palletsprojects.com/en/stable/api/#click.Parameter): the parameter can be repeated on the command line, collecting values into a tuple.", max_width=None, optional=False), ColumnSpec(id='nargs', label='Nargs', description="Reflects [`click.Parameter`'s `nargs`](https://click.palletsprojects.com/en/stable/api/#click.Parameter): the number of CLI tokens the parameter consumes. `1` is the default; `-1` denotes a variadic argument.", max_width=None, optional=False), ColumnSpec(id='prompt', label='Prompt', description="Reflects [`click.Option`'s `prompt`](https://click.palletsprojects.com/en/stable/api/#click.Option): the text shown to the user when the option is not provided on the command line. Empty when no prompt is configured.", max_width=None, optional=False), ColumnSpec(id='confirmation_prompt', label='Confirmation prompt', description="Reflects [`click.Option`'s `confirmation_prompt`](https://click.palletsprojects.com/en/stable/api/#click.Option): whether the user is asked to enter the value twice for confirmation.", max_width=None, optional=False), ColumnSpec(id='value', label='Value', description='Current value of the parameter at invocation time, computed by [`click.Parameter.consume_value()`](https://click.palletsprojects.com/en/stable/api/#click.Parameter) from the merged sources (CLI, environment, config file, default).', max_width=None, optional=False), ColumnSpec(id='source', label='Source', description='Provenance of the resolved value: a [`click.core.ParameterSource`](https://click.palletsprojects.com/en/stable/api/#click.core.ParameterSource) enum member such as `COMMANDLINE`, `ENVIRONMENT`, `DEFAULT_MAP`, or `DEFAULT`.', max_width=None, optional=False), ColumnSpec(id='config_file', label='Config file', description='The configuration file the effective value was loaded from, when `Source` reports `DEFAULT_MAP`. With [`cascade=True`](config.md#cascading-configuration-files) several files are layered and this column names the one that won the parameter; with a single loaded file, every config-sourced parameter names that file. Empty for every other source and when no configuration file was loaded. Opt-in, like `help`: paths are wide and stay redundant with `Source` until several files take part.', max_width=None, optional=True))¶
Rich column registry for the
--paramstable.Each entry is a
click_extra.table.ColumnSpeccarrying the columnâs stableid(used by--columnsand as structured-format key), its displaylabel, and a MyST/Markdowndescriptionconsumed by the documentationâs auto-generated Available columns section. Iteration yields columns in canonical display order.
- classmethod column_labels()[source]¶
Return just the display labels of
TABLE_HEADERS(in order).
- classmethod column_ids()[source]¶
Return just the stable IDs of
TABLE_HEADERS(in order).
- classmethod default_columns()[source]¶
Return the columns rendered when
--columnsasks for no projection.Every column but the
optionalones, which stay addressable by ID and out of the way until named.- Return type:
tuple[_ColumnSpec, âŠ]
- classmethod default_column_ids()[source]¶
Return the stable IDs of
default_columns()(in order).
- classmethod default_column_labels()[source]¶
Return the display labels of
default_columns()(in order).
- classmethod find_column(column_id)[source]¶
Return the
ColumnSpecmatchingcolumn_id.Raises
KeyErrorif no column has this ID; callers should convert the error into aclick.UsageErrorwhen surfaced to a user.
- classmethod render_doc_table()[source]¶
Render
TABLE_HEADERSas a Markdown table for documentation.Used by the
show_params_columns_tableMyST substitution indocs/conf.pyto feed the Available columns section ofdocs/parameters.md: editing a description here automatically rebuilds the docs table on the nextsphinx-build.- Return type:
- excluded_params¶
Deactivates the blocking of any parameter.
- included_params¶
No allowlist filter; show all parameters.
- print_params(ctx, param, value)[source]¶
Introspect the current CLI and print its parameter metadata table.
Thin wrapper over
render_params_table(), the shared rendering core also drivingclick-extra wrap --paramsfor foreign CLIs. The live invocation context carries everything the core needs: the capturedRAW_ARGS(attached byCommand/Group) for value and source resolution, plus any sibling--table-format/--columnsoptions.- Return type:
click_extra.prebake module¶
Bake build-time metadata into Python source files before compilation.
Compiled binaries (Nuitka, PyInstaller) and git-less runtimes (Docker
images, archive checkouts) cannot resolve version or Git metadata at runtime
the way click_extra.version.VersionOption does. The values must
instead be written into the source before the build, by rewriting the
relevant dunder assignments (__version__, __git_short_hash__, âŠ) in
place with ast.
This mirrors shadow-rs, which
injects build-time constants (BRANCH, SHORT_COMMIT, COMMIT_HASH,
COMMIT_DATE, TAG, âŠ) into Rust binaries at compile time.
Todo
Add the following build-time template fields, mirroring the constants shadow-rs injects:
{build_time}: when the distribution was built (shadow-rs exposes it asBUILD_TIME, with RFC 2822 and RFC 3339 variantsBUILD_TIME_2822/BUILD_TIME_3339).{build_os}/{build_target}/{build_target_arch}: the OS, target triple and architecture the build ran on. These describe the build host, unlike{env_info}which reports the runtime Python, OS and architecture, so both are worth keeping for cross-built binaries.
- click_extra.prebake.prebake_version(file_path, local_version)[source]¶
Pre-bake a
__version__string with a PEP 440 local version identifier.Reads file_path, finds the
__version__assignment viaast, and, if the version contains.devand does not already contain+, appends+<local_version>.This is the compile-time complement to the runtime
click_extra.version.VersionOption.versionproperty: Nuitka/PyInstaller binaries cannot rungitat runtime, so the hash must be baked into__version__in the source file before compilation.Returns the new version string on success, or
Noneif no change was made (release version, already pre-baked, or no__version__found).
- click_extra.prebake.prebake_dunder(file_path, name, value)[source]¶
Replace an empty dunder variableâs value in a Python source file.
Reads file_path, finds a top-level
name = ""assignment viaast, and, if the current value is an empty string, replaces it with value.Placeholders must use empty strings (
__field__ = "", notNone). The AST matcher only recognizes string literals, and the empty string acts as a falsy sentinel that stays type-consistent with baked values (alwaysstr).This is the generic counterpart to
prebake_version(): whereprebake_versionappends a PEP 440 local identifier to__version__, this function does a full replacement of any dunder variable that starts empty. Typical use case: injecting a release commit SHA into__git_tag_sha__ = ""at build time.Returns the new value on success, or
Noneif no change was made (variable not found, or already has a non-empty value).
- click_extra.prebake.discover_package_init_files()[source]¶
Discover
__init__.pyfiles from[project.scripts].Reads the
pyproject.tomlin the current working directory, extracts[project.scripts]entry points, and returns the unique__init__.pypaths for each top-level package.Only returns paths that exist on disk. Returns an empty list if
pyproject.tomlis missing or has no[project.scripts].
click_extra.pygments module¶
Pygments lexers, filters, and formatters for ANSI escape sequences.
Parses ANSI SGR escape sequences (ECMA-48 / ISO 6429) from terminal output and renders them as colored HTML with CSS classes. Supports the standard 8/16 named colors, the 256-color indexed palette, and 24-bit RGB.
SGR text attributes: bold, faint, italic, underline, blink, reverse video, strikethrough, and overline.
OSC 8 hyperlinks are rendered as HTML <a> tags. Other OSC sequences are silently
stripped.
Note
24-bit RGB colors (SGR 38;2;r;g;b and 48;2;r;g;b) are preserved by default
and rendered by AnsiHtmlFormatter as inline style="color: #rrggbb" /
style="background-color: #rrggbb" spans (CSS classes cannot enumerate 16.7M
colors). Other token components (bold, named colors, palette indices) keep their
CSS-class rendering. Pass true_color=False to AnsiColorLexer, AnsiFilter,
or any session lexer (via get_lexer_by_name(..., true_color=False)) to opt into
quantization to the nearest entry in the 256-color palette instead.
- click_extra.pygments.Ansi = ('Ansi',)¶
Unified token namespace for ANSI styling.
Compound tokens from the lexer (like
Token.Ansi.Bold.Red) and individual style components (likeToken.Ansi.Red) share this single namespace. The formatter decomposes compound tokens into individual CSS classes at render time.
- click_extra.pygments.DEFAULT_TOKEN_TYPE = ('Generic', 'Output')¶
Default Pygments token type to render with ANSI support.
Defaults to
Generic.Outputtokens, as this is the token type used by all REPL-like and terminal session lexers.
- class click_extra.pygments.AnsiColorLexer(*args, **kwargs)[source]¶
Bases:
LexerLexer for text containing ANSI escape sequences.
Parses Select Graphic Rendition (SGR) codes and emits compound
Token.Ansi.*tokens representing the active styling state. OSC 8 hyperlinks emitToken.AnsiLinkStart/Token.AnsiLinkEndstructural tokens. All other escape sequences are silently stripped.Supported SGR codes:
Text attributes: bold (1), faint (2), italic (3), underline (4), blink (5), reverse video (7), strikethrough (9), overline (53), and their resets.
Named colors: standard (30-37, 40-47) and bright (90-97, 100-107).
256-color indexed palette (38;5;n, 48;5;n).
24-bit RGB (38;2;r;g;b, 48;2;r;g;b), quantized to the nearest 256-color entry.
Supported OSC sequences:
OSC 8 hyperlinks: rendered as
<a>tags byAnsiHtmlFormatter. Only URLs with safe schemes (http, https, mailto, ftp, ftps) are emitted; others are stripped.
Initialize the lexer.
- Parameters:
true_color â Default
True. 24-bit RGB sequences are preserved asToken.Ansi.FG_{rrggbb}/Token.Ansi.BG_{rrggbb}tokens, whichAnsiHtmlFormatterrenders as inlinestyle="color: #rrggbb"/style="background-color: #rrggbb"attributes (CSS classes cannot enumerate 16.7M colors). PassFalseto quantize 24-bit RGB to the nearest entry in the 256-color palette and emitToken.Ansi.C{n}/Token.Ansi.BGC{n}tokens that map to CSS classes via the style dict.
- name = 'ANSI Color'¶
Full name of the lexer, in human-readable form
- aliases = ('ansi-color', 'ansi', 'ansi-terminal')¶
A list of short, unique identifiers that can be used to look up the lexer from a list, e.g., using
get_lexer_by_name().
- class click_extra.pygments.AnsiFilter(**options)[source]¶
Bases:
FilterCustom filter transforming a particular kind of token (
Generic.Outputby default) into ANSI tokens.Initialize an
AnsiColorLexerand configure thetoken_typeto be colorized.- Parameters:
true_color â Forwarded to the inner
AnsiColorLexerto control whether 24-bit RGB sequences are preserved asFG_/BG_hex tokens for inline-style rendering (defaultTrue) or quantized to the 256-color palette. SeeAnsiColorLexerfor details.
Note
Only one
token_typeis supported. All Pygments session lexers (ShellSessionBaseLexerand the manually-maintained list incollect_session_lexers) emit terminal output exclusively asGeneric.Output. No upstream issue or PR proposes splitting output into additional token types (likeGeneric.Errorfor stderr). If that changes, this filter would need to accept a set of token types instead of a single one. See pygments#1148 and pygments#2499 for the closest related discussions.
- click_extra.pygments.collect_session_lexers()[source]¶
Retrieve all lexers producing shell-like sessions in Pygments.
This function contains a manually-maintained list of lexers, to which we dynamically add lexers inheriting from
ShellSessionBaseLexer.Hint
To help maintain this list, there is a test that will fail if a new REPL/terminal-like lexer is added to Pygments but not referenced here.
- click_extra.pygments.LEXER_MAP: dict[type[Lexer], type[Lexer]] = {<class 'pygments.lexers.algebra.GAPConsoleLexer'>: <class 'pygments.lexer.AnsiGAPConsoleLexer'>, <class 'pygments.lexers.dylan.DylanConsoleLexer'>: <class 'pygments.lexer.AnsiDylanConsoleLexer'>, <class 'pygments.lexers.erlang.ElixirConsoleLexer'>: <class 'pygments.lexer.AnsiElixirConsoleLexer'>, <class 'pygments.lexers.erlang.ErlangShellLexer'>: <class 'pygments.lexer.AnsiErlangShellLexer'>, <class 'pygments.lexers.julia.JuliaConsoleLexer'>: <class 'pygments.lexer.AnsiJuliaConsoleLexer'>, <class 'pygments.lexers.matlab.MatlabSessionLexer'>: <class 'pygments.lexer.AnsiMatlabSessionLexer'>, <class 'pygments.lexers.php.PsyshConsoleLexer'>: <class 'pygments.lexer.AnsiPsyshConsoleLexer'>, <class 'pygments.lexers.python.PythonConsoleLexer'>: <class 'pygments.lexer.AnsiPythonConsoleLexer'>, <class 'pygments.lexers.r.RConsoleLexer'>: <class 'pygments.lexer.AnsiRConsoleLexer'>, <class 'pygments.lexers.ruby.RubyConsoleLexer'>: <class 'pygments.lexer.AnsiRubyConsoleLexer'>, <class 'pygments.lexers.shell.BashSessionLexer'>: <class 'pygments.lexer.AnsiBashSessionLexer'>, <class 'pygments.lexers.shell.MSDOSSessionLexer'>: <class 'pygments.lexer.AnsiMSDOSSessionLexer'>, <class 'pygments.lexers.shell.PowerShellSessionLexer'>: <class 'pygments.lexer.AnsiPowerShellSessionLexer'>, <class 'pygments.lexers.shell.TcshSessionLexer'>: <class 'pygments.lexer.AnsiTcshSessionLexer'>, <class 'pygments.lexers.special.OutputLexer'>: <class 'pygments.lexer.AnsiOutputLexer'>, <class 'pygments.lexers.sql.PostgresConsoleLexer'>: <class 'pygments.lexer.AnsiPostgresConsoleLexer'>, <class 'pygments.lexers.sql.SqliteConsoleLexer'>: <class 'pygments.lexer.AnsiSqliteConsoleLexer'>}¶
Map original session lexers to their ANSI-capable variants.
- click_extra.pygments.EXTRA_ANSI_CSS: dict[str, str] = {'Blink': 'animation: ansi-blink 1s step-end infinite', 'Bold': 'font-weight: bold', 'Faint': 'opacity: 0.5', 'Italic': 'font-style: italic', 'Overline': 'text-decoration: overline', 'Reverse': 'filter: invert(1)', 'Strikethrough': 'text-decoration: line-through', 'Underline': 'text-decoration: underline'}¶
All SGR text attribute CSS declarations.
Maps
Token.Ansicomponent names to CSS declarations. These are kept out of the Pygments style dict (_ANSI_STYLES) to prevent Furoâs dark-mode CSS generator from injectingcolor: #D0D0D0fallbacks that conflict with foreground color tokens.Used by
AnsiHtmlFormatter.get_token_style_defsto inject CSS rules that both standalonepygmentizeand Furoâs dark-mode CSS generator pick up.
- class click_extra.pygments.AnsiHtmlFormatter(**kwargs)[source]¶
Bases:
HtmlFormatterHTML formatter with ANSI color and hyperlink support.
Extends Pygmentsâ
HtmlFormatterto handle compoundToken.Ansi.*tokens by decomposing them into individual CSS classes, augments the base style with ANSI color definitions for the 256-color indexed palette, and renders OSC 8 hyperlinks as HTML<a>tags.Intercept the
styleargument to augment it with ANSI color support.Creates a new style instance that inherits from the one provided by the user, but updates its
stylesattribute with ANSI token definitions from_ANSI_STYLES.- name = 'ANSI HTML'¶
Full name for the formatter, in human-readable form.
- aliases: ClassVar[list[str]] = ['ansi-html']¶
A list of short, unique identifiers that can be used to lookup the formatter from a list, e.g. using
get_formatter_by_name().
- format_unencoded(tokensource, outfile)[source]¶
Render tokens to HTML, converting OSC 8 link and 24-bit RGB markers to tags.
Replaces
Token.AnsiLinkStart/Token.AnsiLinkEndwith Unicode Private Use Area markers, stripsFG_/BG_24-bit RGB components from compound tokens and replaces them with PUA markers carrying the hex value, delegates to Pygmentsâ HTML rendering, then post-processes the output to swap markers for<a>and inline-styled<span>tags.- Return type:
- get_token_style_defs(arg=None)[source]¶
Extend Pygmentsâ token CSS with rules for SGR attributes it cannot express.
Overriding
get_token_style_defs(rather thanget_style_defs) ensures that Furoâs dark-mode CSS generator, which calls this method directly, also picks up the extra rules built by_extra_ansi_css_lines.
- get_ansi_style_defs(arg=None)[source]¶
Return only this formatterâs ANSI CSS, dropping Pygmentsâ base syntax-token rules.
The MkDocs plugin layers these over a themeâs own syntax highlighting, so it must not pull in the standard token rules (those would override the theme). Keeps the
-Ansi-*token rules plus everything_extra_ansi_css_linesadds. Owning this selection here, next to the rules it returns, keeps the MkDocs plugin from hard-coding this formatterâs class names and CSS internals.- Return type:
click_extra.pytest module¶
Pytest fixtures and marks to help testing Click CLIs.
- click_extra.pytest.runner()[source]¶
Runner fixture for
click_extra.testing.CliRunner.Pins
HOME(and its platform-specific equivalents) to a subdirectory of the runnerâs isolated filesystem so configuration-file discovery is deterministic and independent of the ambient environment. Without this, the handful of tests asserting on the config-search debug output depend on the callerâsHOME: hermetic builders setHOME=/homeless-shelter, which would otherwise leak into those assertions.The environment is patched directly (via
temporary_env()) rather than through themonkeypatchfixture on purpose: depending onmonkeypatchhere would tear it down afterisolated_filesystemremoved the working directory it tries to restore, breaking unrelated tests thatchdirwithin the runner.Warning
The pinning is scoped to each test requesting this fixture, but a cache filled from inside one is not: a module-global populated lazily during a test records what a home-less environment answered, and keeps serving that for the rest of the workerâs session. A binary resolved through a
$HOME-dependent shim is the usual victim, answering an error rather than a version, after which every later test on that worker sees the tool as missing. Seed such a cache from a session-scoped fixture, which runs before the first test and outside this isolation.
- click_extra.pytest.invoke(runner)[source]¶
Invoke fixture shorthand for
click_extra.testing.CliRunner.invoke().
- click_extra.pytest.isolated_app_dir(monkeypatch, tmp_path)[source]¶
Repoint configuration-file discovery at a fresh, empty directory.
The default
--configsearch pattern derives fromclick.get_app_dir(), which resolves to the host configuration folder (~/Library/Application Support/<app>on macOS,~/.config/<app>on Unix,%APPDATA%\<app>on Windows). Any configuration file living there bleeds into every in-process CLI invocation, making a test suite pass or fail depending on the developerâs personal configuration.This fixture repoints
get_app_dir(bothclickâs and the reference bound into click-extraâs config machinery) at a per-test temporary directory, whatever application name is requested. It returns that directory, so a test can also plant a configuration file in it to exercise the default discovery against a controlled file.An explicit
--config <path>bypasses the default search pattern and is left unaffected.Note
The
runner()fixture pinsHOMEand its platform equivalents inside an isolated filesystem, which also redirects the discovery paths built from the home directory â but only for tests requesting that fixture. This one interceptsget_app_dirdirectly, covering any in-process invocation, without touchingHOME(a suite may need the real one elsewhere) and without leaking into subprocesses.To make a whole suite hermetic, alias it to an
autousefixture in yourconftest.py:import pytest @pytest.fixture(autouse=True) def isolate_user_config(isolated_app_dir): return isolated_app_dir
- click_extra.pytest.command_decorators(no_commands=False, no_groups=False, no_click=False, no_cloup=False, no_extra=False, with_parenthesis=True, with_types=False)[source]¶
Returns collection of Pytest parameters to test all command-like decorators.
- Return type:
- Returns:
Pytest parameters covering each command-like decorator variant:
click.commandclick.command()cloup.commandcloup.command()click_extra.commandclick_extra.command()click.groupclick.group()cloup.groupcloup.group()click_extra.groupclick_extra.group()
- click_extra.pytest.option_decorators(no_options=False, no_arguments=False, no_click=False, no_cloup=False, no_extra=False, with_parenthesis=True, with_types=False)[source]¶
Returns collection of Pytest parameters to test all parameter-like decorators.
- Return type:
- Returns:
Pytest parameters covering each parameter-like decorator variant:
click.optionclick.option()cloup.optioncloup.option()click_extra.optionclick_extra.option()click.argumentclick.argument()cloup.argumentcloup.argument()click_extra.argumentclick_extra.argument()
click_extra.rst_to_myst module¶
Convert sphinx-apidoc RST output to MyST markdown.
Note
The converter handles only the narrow RST subset that sphinx-apidoc
generates: section headings (title + underline), automodule directives
with indented options, and structural headers like Submodules.
Autodoc directives cannot be used as native MyST directives because they
perform internal rST nested parsing that requires an rST parser context
only {eval-rst} provides. See MyST-Parser #587.
- click_extra.rst_to_myst.convert_apidoc_rst_to_myst(content)[source]¶
Convert
sphinx-apidocRST to MyST markdown with{eval-rst}blocks.
- click_extra.rst_to_myst.convert_rst_files_in_directory(directory)[source]¶
Convert
sphinx-apidocRST files to MyST markdown in the given directory.For each
.rstfile containing.. automodule::directives:If a
.mdfile with the same stem exists, delete the.rst(the existing markdown takes precedence).Otherwise, convert the RST content to MyST and write a
.mdfile, then delete the.rst.
click_extra.screenshot module¶
Width a capture is taken and rendered at, see AUTO_COLUMNS.
- click_extra.screenshot.TColumns: TypeAlias = int | typing.Literal['auto']¶
Width a capture is taken and rendered at, see
AUTO_COLUMNS.
- class click_extra.screenshot.CaptureFormat(*values)[source]¶
Bases:
EnumDocument formats a capture can be rendered to.
The value doubles as the file extension
format_from_path()matches on.- HTML = 'html'¶
Selectable, searchable text in a self-contained
<pre>.Built on
ansi_to_html(), so it needs no extra.
- SVG = 'svg'¶
A picture of a terminal window, for a surface that strips inline HTML.
Laid out on a character grid by
render_svg().
- class click_extra.screenshot.CaptureBackground(*values)[source]¶
Bases:
EnumTerminal chrome a capture is drawn on.
A capture freezes the colors of the run it pictures, so the chrome has to answer to the palette that run was colored for. Neither direction survives the other: a screen colored for a dark terminal is unreadable on white, and click-extraâs own
lightandmanpagethemes wash out on the dark chrome a renderer defaults to.The value doubles as the
--backgroundchoice the CLI offers.- DARK = 'dark'¶
What a terminal, and this packageâs default theme, usually look like.
- LIGHT = 'light'¶
For a CLI rendered with a light-background theme.
- click_extra.screenshot.DEFAULT_PRESET = ('No terminal at all', ((), ''), 0, '$', "'Fira Code', 'Cascadia Code', Menlo, Consolas, monospace", ('#292929', '#c5c8c6', ('#2e3436', '#cc0000', '#4e9a06', '#c4a000', '#3465a4', '#75507b', '#06989a', '#d3d7cf', '#555753', '#ef2929', '#8ae234', '#fce94f', '#729fcf', '#ad7fa8', '#34e2e2', '#eeeeec'), '#292929'), ('#ffffff', '#000000', ('#2e3436', '#cc0000', '#4e9a06', '#c4a000', '#3465a4', '#75507b', '#06989a', '#d3d7cf', '#555753', '#ef2929', '#8ae234', '#fce94f', '#729fcf', '#ad7fa8', '#34e2e2', '#eeeeec'), '#ffffff'))¶
Terminal a capture with no
--presetis drawn as.plainmimics no desktop, which is what a capture wearing no decoration should resolve its colors against. Naming it here is what keeps the two formats looking like the same terminal, and keeps one catalog answering for every palette a capture can use: without it the default colors would be a second set of literals free to drift from the one the presets publish.
- click_extra.screenshot.CAPTURE_PALETTES: dict[CaptureBackground, TerminalPalette] = {CaptureBackground.DARK: ('#292929', '#c5c8c6', ('#2e3436', '#cc0000', '#4e9a06', '#c4a000', '#3465a4', '#75507b', '#06989a', '#d3d7cf', '#555753', '#ef2929', '#8ae234', '#fce94f', '#729fcf', '#ad7fa8', '#34e2e2', '#eeeeec'), '#292929'), CaptureBackground.LIGHT: ('#ffffff', '#000000', ('#2e3436', '#cc0000', '#4e9a06', '#c4a000', '#3465a4', '#75507b', '#06989a', '#d3d7cf', '#555753', '#ef2929', '#8ae234', '#fce94f', '#729fcf', '#ad7fa8', '#34e2e2', '#eeeeec'), '#ffffff')}¶
Colors each chrome resolves a captureâs ANSI codes against.
A palette carries the 16 ANSI colors alongside the background and foreground, which is the other half of the job: a CLI naming
blueleaves the shade to whoever draws it, and the one that reads on white is not the one that reads on#292929.
- click_extra.screenshot.CAPTURE_BACKGROUND = '#292929'¶
Background a dark capture is drawn on.
Stating it is not optional: a help screen colored for a dark terminal is unreadable on a page that defaults to white.
- click_extra.screenshot.CAPTURE_FOREGROUND = '#c5c8c6'¶
Color of the text a dark capture leaves unstyled. See
CAPTURE_BACKGROUND.
- click_extra.screenshot.LIGHT_CAPTURE_BACKGROUND = '#ffffff'¶
Background a light capture is drawn on.
See
CAPTURE_BACKGROUND: an SVG and an HTML capture of the same run have to look like the same terminal.
- click_extra.screenshot.LIGHT_CAPTURE_FOREGROUND = '#000000'¶
Color of the text a light capture leaves unstyled.
- click_extra.screenshot.PROMPT_THEMES: dict[CaptureBackground, HelpTheme | None] = {CaptureBackground.DARK: None, CaptureBackground.LIGHT: HelpTheme(invoked_command=Style(fg='black', bold), command_help=<function identity>, heading=Style(fg='magenta', underline), constraint=Style(fg='magenta'), section_help=<function identity>, col1=<function identity>, col2=<function identity>, alias=Style(fg='blue', bold), alias_secondary=Style(fg='blue', bold, dim), epilog=<function identity>, critical=Style(fg='red', bold), error=Style(fg='red'), warning=Style(fg='magenta'), info=<function identity>, debug=Style(fg='blue', dim), option=Style(fg='blue', bold), subcommand=Style(fg='blue', bold), choice=Style(fg='magenta', bold), metavar=Style(fg='blue', dim, italic), bracket=Style(dim), envvar=Style(fg='magenta', dim), default=Style(fg='green', dim, italic), range_label=Style(fg='blue', dim), required=Style(fg='red', dim), argument=Style(fg='blue', italic), deprecated=Style(fg='red'), search=Style(fg='green'), success=Style(fg='green'), cross_ref_highlight=True, subheading=Style(fg='blue', dim))}¶
Theme the prompt line is drawn with, per chrome.
The captured output arrives already colored by the CLI that produced it, under whatever theme that run was told to use. The prompt is the one line this process draws itself, so it is the one that would otherwise land on white chrome in the dark defaultâs near-white
invoked_commandstyle, invisible.Nonekeeps whatever theme the invocation already runs under. So does a missing entry: the mapping is read throughdict.get(), andBUILTIN_THEMESis empty when a trimmed install dropsthemes.toml.
- click_extra.screenshot.NO_PAINT = 'none'¶
Border or shadow value asking for none to be drawn.
SVGâs own keyword for an absent paint, so it reaches the
strokeattribute unchanged, and CSSâs for an absent shadow.
- click_extra.screenshot.OPAQUE = 1.0¶
Opacity of a window showing nothing of what sits behind it.
Anything under it is what a terminal calls transparency: the backdrop, or the page embedding the capture, comes through the windowâs body while its text, frame and title bar stay as they are.
0.0leaves the text alone on the page.
- click_extra.screenshot.CAPTURE_BORDERS: dict[CaptureBackground, str] = {CaptureBackground.DARK: 'rgba(255,255,255,0.35)', CaptureBackground.LIGHT: 'rgba(0,0,0,0.25)'}¶
Color the window frame is drawn in, per chrome.
The dark entry is a translucent white that reads against
#292929and against nothing else: a light capture framed with it is a white window on a white page, the shape of the terminal only guessable from its text. Each chrome names a frame its own background can show.
- click_extra.screenshot.CAPTURE_SHADOWS: dict[CaptureBackground, str] = {CaptureBackground.DARK: 'rgba(0,0,0,0.5)', CaptureBackground.LIGHT: 'rgba(0,0,0,0.25)'}¶
Color the windowâs drop shadow floods with, per chrome.
Where the frame states the windowâs edge, the shadow lifts it off whatever page embeds the capture, which is the other half of not dissolving into it. A reader whose renderer drops the filter still gets the frame.
- click_extra.screenshot.WATERMARK_INK = 'rgba(128,128,128,0.85)'¶
Color the credit line is drawn in.
The one paint in a capture that answers to neither chrome, because it is the one thing drawn outside the window: the margin is transparent, so the mark sits on whatever page embeds the image, which the capture never gets to see. A white mark suits the dark chrome it was picked for and disappears on a README; a neutral gray reads on both, and dims into a backdrop when one is painted.
- click_extra.screenshot.DEFAULT_BORDER_WIDTH = 1¶
Thickness, in pixels, of the frame drawn around the window.
- click_extra.screenshot.TITLEBAR_HEIGHT = 40¶
Height, in pixels, of the strip a title and its buttons sit in.
The padding a renderer leaves above the text, which is what a windowâs chrome occupies. Restated here because a capture wearing neither decoration nor caption drops the strip, and one drawn as a real terminal paints it.
- click_extra.screenshot.DEFAULT_RADIUS = 8¶
How round the windowâs corners are, in pixels.
The radius a renderer draws on its own, which is what a terminal on a desktop looks like. Zero squares them, for a capture meant to read as a plain block.
- click_extra.screenshot.SHADOW_BLUR = 6¶
Standard deviation, in pixels, of the drop shadowâs blur.
- click_extra.screenshot.SHADOW_OFFSET = 3¶
Downward offset, in pixels, of the drop shadow.
- click_extra.screenshot.CSS_SIDE_ANGLES = {'to bottom': 180.0, 'to bottom left': 225.0, 'to bottom right': 135.0, 'to left': 270.0, 'to left bottom': 225.0, 'to left top': 315.0, 'to right': 90.0, 'to right bottom': 135.0, 'to right top': 45.0, 'to top': 0.0, 'to top left': 315.0, 'to top right': 45.0}¶
Angle each CSS side keyword names, in degrees clockwise from
to top.to bottomis what a gradient opening with no direction at all means, which is why it doubles as the default. Seegradient_svg().
- click_extra.screenshot.DEFAULT_MARGIN = 48¶
Transparent pixels left around the window, on all four sides.
Room for the shadow to fall into, first of all: a filter draws outside the shape it is applied to, and anything past the imageâs own box is cut. It is also what a backdrop has to show through, and what keeps the window from touching the text of the page embedding it.
- click_extra.screenshot.DEFAULT_PADDING = 8¶
Pixels added inside the window, around the captured text.
On top of the few a renderer adds on its own (8, and 40 above for the title bar), which leaves a help screenâs first column tight against the frame.
- click_extra.screenshot.TITLE_SIZE = 18¶
Height, in pixels, of the caption drawn in a windowâs title bar.
- click_extra.screenshot.WATERMARK_SIZE = 13¶
Height, in pixels, of the credit lineâs glyphs.
Below the terminalâs own text, since a mark competing with the screen it credits is a mark in the way.
- click_extra.screenshot.WATERMARK_INSET = 12¶
Pixels between the credit line and the imageâs bottom-right corner.
It is drawn in the margin, the one band of a capture that carries nothing else. A capture shot with
margin=0has no such band, and the line lands on the windowâs own corner instead of beside it.
- click_extra.screenshot.DEFAULT_WATERMARK = 'generated with click-extra 9.0.0'¶
Credit line every capture carries unless another one, or none, is asked for.
A capture travels: it lands on a slide, in a README, on a social card, far from the page that explains where it came from. The mark is what still says so, and names the release that drew it, so a reader can tell an image shot two years ago from one shot today.
Note
This is a default, not a fixture.
--watermark ""draws none, and any other text replaces it: a project crediting itself rather than its tooling is the expected case, not an exception.
- click_extra.screenshot.CAPTURE_TERMINAL_HINTS: dict[CaptureBackground, dict[str, str]] = {CaptureBackground.DARK: {'CLITHEME': 'dark', 'COLORFGBG': '15;0'}, CaptureBackground.LIGHT: {'CLITHEME': 'light', 'COLORFGBG': '0;15'}}¶
Environment a terminal of each chrome would carry, handed to the command.
A capture is a terminal simulated for a command that cannot see one: its width is pinned and its colors forced, because a pipe would have it wrap to a guess and print none. Its background is the third thing a terminal states and a pipe does not, through the two variables
resolve_background()reads: the cli-themeCLITHEME, andCOLORFGBGcarryingforeground;backgroundpalette indices.So a CLI asking for âtheme auto renders for the chrome its picture is drawn on, instead of falling back to dark inside a light window. A CLI that never asks is unaffected: the variables only answer a question it does not put.
- click_extra.screenshot.CAPTURE_FONT_STACK = "'Fira Code', 'Cascadia Code', Menlo, Consolas, monospace"¶
Monospaced fonts a capture asks for, best first.
Nothing is embedded and nothing is fetched, so both formats set the text in the first family the reader already has, and a capture renders the same offline, on a page forbidding third-party requests, and in a viewer that speaks no CSS
@font-face.Family names are single-quoted on purpose: this lands in a double-quoted
styleattribute, which a double quote here would terminate early.
- click_extra.screenshot.CELL_HEIGHT = 20.0¶
Height of one glyph cell, in pixels, which is also the textâs font size.
- click_extra.screenshot.FONT_ASPECT_RATIO = 0.61¶
Width-to-height ratio of the font a capture is laid out for.
Fira Codeâs, the first family
CAPTURE_FONT_STACKasks for. Every monospaced fallback behind it is close enough that the grid holds, andtextLengthpins each run to its columns for the ones that are not.
- click_extra.screenshot.CELL_WIDTH = 12.2¶
Width of one glyph cell, in pixels. One character of a monospaced terminal.
- click_extra.screenshot.LINE_HEIGHT = 24.4¶
Vertical distance between two consecutive text baselines, in pixels.
- click_extra.screenshot.CELL_BLEED = 0.25¶
Pixels a cellâs background is grown by, past the line it belongs to.
Two rectangles meeting on an exact boundary leave a hairline of page showing through when a renderer rounds their edges to different pixels. Overlapping them slightly is what closes that seam, and is invisible because the color painted twice is the same color.
- click_extra.screenshot.CELL_TOP_INSET = 1.5¶
Pixels between a lineâs top edge and the cell backgrounds drawn on it.
A glyph does not fill its line box: the leading sits above the tallest letter. Starting the paint just under that keeps a highlighted run reading as one block of color rather than as a band taller than the text it marks.
- click_extra.screenshot.TILE_RUN = 8¶
Cells of tiling characters drawn before their offset is restated.
Small enough that a font whose tiles are a fraction of a pixel off the grid cannot drift a visible amount before the next offset resets it, and large enough that a tableâs rule stays a handful of elements rather than one per cell. See
tile_runs().
- click_extra.screenshot.DIM_RATIO = 0.4¶
How far a
dimrunâs ink is mixed toward the background, seeblend().
- click_extra.screenshot.RTL_BIDI_CLASSES = frozenset({'AL', 'AN', 'R'})¶
Unicode bidirectional classes written right to left.
Right-to-left letters, Arabic letters and Arabic-Indic numbers, as
unicodedata.bidirectional()names them. Seeis_bidirectional().
- click_extra.screenshot.WINDOW_PADDING = 8¶
Pixels every window keeps between its frame and its text, on three sides.
The fourth is the top, where
TITLEBAR_HEIGHTanswers instead. This is the windowâs own breathing room, before thepaddinga capture may ask for on top.
- click_extra.screenshot.WINDOW_INSET = 1¶
Pixels between the imageâs edge and the windowâs frame.
A stroke straddles the shape it outlines, so a frame drawn flush with the viewBox loses its outer half to the crop. Inset by more than that half and the whole line shows.
- click_extra.screenshot.AUTO_COLUMNS: Literal['auto'] = 'auto'¶
Width asking for the one the captured text itself decides.
Neither end of the pipeline is pinned: the command wraps to whatever terminal it finds (Clickâs own 80 when that is a pipe, or a documentation build), and the image is laid out at the longest line that came back, see
fit_columns(). Nothing the command printed folds inside the picture then, which is what a line the command does not wrap on its own needs: a prompt, a wide table, a machine-readable dump.The cost is that the picture stops being a fixed-width terminal, so a capture meant to sit beside others at the same width should name that width instead.
- click_extra.screenshot.DEFAULT_COLUMNS = 80¶
Terminal width a capture is taken at, in characters.
Both ends of the pipeline have to agree on it: the command wraps its output to this width, and the renderer lays the image out at the same one. Let them disagree and the rendered lines overrun the image. 80 is the width Click itself falls back to off a terminal, which makes it the value a capture lands on by accident anyway.
- click_extra.screenshot.MIN_COLUMNS = 20¶
Narrowest width a capture is rendered at.
A floor on
AUTO_COLUMNSas much as on an explicit width: a command printing nothing but blank lines would otherwise ask for an image no glyph fits in.
- click_extra.screenshot.LINE_NUMBER_SEPARATOR = ' â '¶
Rule drawn between a lineâs number and the line itself.
A vertical bar rather than a bare space, so the gutter reads as a column of its own even where the output is itself indented.
- click_extra.screenshot.DEFAULT_TRUNCATION = '[...]'¶
Marker standing in for the lines
trim_lines()cut away.
- click_extra.screenshot.PADDING = ' \xa0'¶
Characters separating one column of a capture from the next.
render_svg()emits every space as a non-breaking one, so the padding survives an XML round-trip and no renderer collapses a run of them.
- click_extra.screenshot.number_lines(text, start=1)[source]¶
Prefix each line of
textwith its number, in a dim gutter.The numbers are drawn into the terminal text rather than into a column of the image, which is the same trade Pygments makes with its inline line numbers: every renderer places them for free, and every reader copying the capture copies them too.
Right-aligned on the widest number, so the gutter is one column whatever the outputâs length, and separated by
LINE_NUMBER_SEPARATOR.
- click_extra.screenshot.preset_palette(preset, background)[source]¶
The colors a preset shows on the given chrome.
- Return type:
- click_extra.screenshot.resolve_palette(preset, background)[source]¶
The colors a capture resolves its ANSI codes against.
The presetâs palette on the given chrome, or the default terminalâs (
CAPTURE_PALETTES) when no preset dresses the capture. The one resolution rule shared byrender()andrender_html(), so the two formats cannot disagree on what a chrome looks like.- Return type:
- click_extra.screenshot.is_bidirectional(text)[source]¶
Whether
textcarries a character written right to left.Arabic, Hebrew and their neighbours are reordered by whoever draws them, and the cursive ones are shaped: a letterâs form depends on what it joins. A terminal grid describes neither, which is why
render_svg()stops pinning such a run to an exact width.
- click_extra.screenshot.cell_width(text)[source]¶
Columns
textoccupies on a terminalâs character grid.Not its length: a CJK ideograph is drawn two cells wide, a combining mark none at all.
wcwidth.wcswidth()answers for both, and returns-1for a string carrying a control character, where the count of characters is the closest thing to an answer left.
- click_extra.screenshot.fit_columns(text)[source]¶
Width, in characters, of the longest line in
text.ANSI escapes are stripped first: they style the glyphs around them and occupy no cell of their own. Measured in terminal cells, so a line of CJK asks for the two columns per glyph it is drawn with. Floored at
MIN_COLUMNS.
- click_extra.screenshot.capture_output(args, *, columns=80, background=CaptureBackground.DARK, merge_stderr=False, timeout=None)[source]¶
Run a command and capture its output, ANSI escape sequences and all.
A command whose output is a pipe rather than a terminal strips its own colors, and wraps to whatever width it can guess. Both are pinned here:
forced_color()sets theFORCE_COLORlever every mainstream color system obeys and clears any opt-out the environment carries, whileCOLUMNSfixes the width the command wraps to.Only
stdoutis captured by default. That is what keeps a capture free of the progress lines and build chatter a wrapper likeuvwrites tostderr, with no shell redirection to remember.- Parameters:
args (
str|Path|None|Iterable[str|Path|None|Iterable[Iterable[str|Path|None|Iterable[TNestedArgs]]]]) â the command line, in the nested formrun_cli()accepts.columns (
int|Literal['auto']) â terminal width, in characters, the command wraps its output to.AUTO_COLUMNSpins nothing and lets the command find its own.background (
CaptureBackground) â chrome the capture is headed for, stated to the command the way a terminal would, seeCAPTURE_TERMINAL_HINTS.merge_stderr (
bool) â foldstderrinto the captured output, for a command printing its help there.timeout (
float|None) â seconds before the command is killed.Nonewaits forever.
- Return type:
- Returns:
the completed process, whose
stdoutholds the captured text.
- click_extra.screenshot.trim_lines(text, *, head=None, tail=None, truncation='[...]')[source]¶
Keep only the first
headand lasttaillines oftext.Whatever is dropped is replaced by a single
truncationline, so the image admits that it was cut rather than pretending to be the whole output. Text short enough to survive both bounds comes back untouched, with no marker.- Parameters:
- Return type:
- Returns:
the trimmed text.
- click_extra.screenshot.palette_color(color, palette)[source]¶
Resolve any color a
Stylecarries to a hex string.The 16 named and indexed ANSI slots are not colors, they are names: a terminal decides what its
redlooks like, and a capture has no terminal, so they answer topalette. Every other form a style can carry (a 24-bit triplet, a 256-cube index, a hex string) already states its own color and passes through.- Parameters:
palette (
TerminalPalette) â the terminal colors to resolve names against.
- Return type:
- Returns:
the color, as
#rrggbb.- Raises:
ValueError â when the value names no color.
- click_extra.screenshot.blend(color, into, ratio)[source]¶
Mix
colortowardinto, the way a terminal fades dim text.SVG has no dim, and thinning the glyphs with
opacitywould let whatever sits behind the capture show through them. Mixing the two colors up front keeps the text opaque and lands the same shade.
- click_extra.screenshot.grid(text, columns)[source]¶
Lay ANSI text out on a terminalâs character grid.
The one place a capture stops being a stream and becomes a picture. Each styled run of
split_ansi()is split at newlines into rows, then placed on the column it starts at, measured in cells rather than characters so a wide glyph takes the two it is drawn with.A line reaching past
columnssoft-wraps onto the next row, the way it would on a terminal that narrow, rather than being cropped: a command is free to print a line it never wraps itself (a long URL, a wide table, a machine-readable dump), and a picture that silently swallowed the overflow would be lying about what ran. A glyph straddling the edge moves down whole.Returning the column with each run is what lets
render_svg()place a run without measuring anything back out of its own output.
- click_extra.screenshot.gradient_svg(value, unique_id, width, height)[source]¶
Translate a CSS gradient into the paint server SVG draws it with.
An SVG
filltakes a paint: a color, or a reference to a gradient declared as an element of its own. The syntax a pageâs CSS carries,linear-gradient(135deg, #ff9a9e, #fad0c4), means nothing to it, and a capture handed one would come out unpainted. So the CSS is read here and re-emitted as the element SVG does understand, which is what lets the same--backdropvalue serve both formats.Understood:
linear-gradientopening with an optional angle (135deg) or side keyword (to bottom right, seeCSS_SIDE_ANGLES), andradial-gradient, both followed by two or more color stops, each pinnable at a percentage. Anything else returnsNoneand is left alone, being a plain color as far as this is concerned.The gradient is placed in user space, which is what makes it exact rather than approximated: the CSS line runs through the imageâs center at the given angle, and is as long as the box measures along it (
|W·sinΞ| + |H·cosΞ|), while a radial one reaches the farthest corner.- Parameters:
- Return type:
- Returns:
the
<defs>markup and thefillvalue referencing it, orNonewhen the value is not a gradient this understands.
- click_extra.screenshot.titlebar_strip(left, top, width, *, paint, radius)[source]¶
Paint the strip a terminal seats its title and buttons in.
A capture leaves that strip the color of the terminal itself, where a real window carries a chrome of its own: the strip is what a readerâs eye reads as the top of a window rather than as the first line of output.
Drawn as a path rather than a rectangle because only its top corners follow the windowâs own rounding; the bottom two meet the text and stay square.
- Parameters:
- Return type:
- Returns:
the SVG markup.
- click_extra.screenshot.watermark_svg(text, *, width, height, paint, font_stack="'Fira Code', 'Cascadia Code', Menlo, Consolas, monospace")[source]¶
Draw the credit line in the imageâs bottom-right corner.
Placed in the margin rather than over the terminal, which is what keeps it from covering a line of output: a capture is a picture of text, and a mark crossing that text costs the reader the thing being shown.
Carries a
watermarkclass, so a reader taking a capture apart can tell the one run the renderer never captured from the ones it did.- Parameters:
- Return type:
- Returns:
the SVG markup, empty when there is nothing to draw.
- click_extra.screenshot.window_buttons(buttons, *, width, color, font_stack="'Fira Code', 'Cascadia Code', Menlo, Consolas, monospace")[source]¶
Draw a title barâs decorations, as the terminal being mimicked draws them.
Two conventions, and a window carries one or the other: macOS fills round buttons on the left, Windows and GNOME set glyphs against the right edge. Both are placed in the windowâs own coordinates, so they follow it wherever the frame moves it.
- Parameters:
buttons (
WindowButtons) â which decorations to draw.width (
float) â width of the window they are drawn in, in pixels.color (
str) â paint for the glyphs. Circles carry their own.font_stack (
str) â fonts the glyphs are set in, the windowâs own.
- Return type:
- Returns:
the SVG markup, empty when the window wears none.
- click_extra.screenshot.column_segments(text, column)[source]¶
Cut a run of text into the columns it actually occupies.
A run carries its own padding: a help screenâs âcount INTEGER Number of greetings. is one styled run holding two columns and the gutter between them. Drawn as a single element, the second column only lands where it belongs if the renderer honors
textLengthand resolves the font, because the gutterâs width is being paid for in glyphs.librsvgdoes neither, and the columns collapse onto each other.Cutting the run at its gutters and giving each piece its own offset asks nothing of the renderer but to draw glyphs at coordinates.
- click_extra.screenshot.tile_runs(text, column)[source]¶
Break a columnâs text into the pieces drawn as one element each.
Ordinary text is one piece: the renderer lays it out and
textLengthholds the result to the width it occupies.Text carrying a tile (
_TILING_RE) is cut into groups of at mostTILE_RUNcells, each landing on a stated offset. A<text>element is the smallest thing some renderers position at all:librsvg(and through itrsvg-convertand ImageMagick) honors the firstxof an element and then lays every following glyph out at the fontâs own advance, ignoring bothtextLengthand any furtherx. A rule of 75 tiles drawn a tenth of a pixel narrow therefore ends a whole cell short of theâbelow it, and the tableâs corners miss. Restating the offset every few cells bounds that error to well under a pixel, whatever the font, and costs a tile nothing since none of them ligate.
- click_extra.screenshot.glyph_offsets(text, column)[source]¶
Place a piece of text on the grid, as the attributes SVG reads.
A right-to-left piece is pinned by its offset alone: it is reordered and shaped by whoever draws it, and holding it to a width fights that.
- click_extra.screenshot.style_rules(style, palette)[source]¶
Compile a style to the CSS an SVG text run is drawn with.
- Parameters:
style (
Style) â the runâs style, assplit_ansi()yields it.palette (
TerminalPalette) â the terminal colors to resolve names against.
- Return type:
- Returns:
the CSS declarations, semicolon-separated.
- click_extra.screenshot.run_paint(style, palette)[source]¶
The color painted behind a run, or
Nonewhere it shows the terminalâs own.- Parameters:
style (
Style) â the runâs style.palette (
TerminalPalette) â the terminal colors to resolve names against.
- Return type:
- Returns:
the background color, as
#rrggbb, orNoneto paint nothing.
- click_extra.screenshot.render_svg(text, *, columns, title='', unique_id=None, palette=('#292929', '#c5c8c6', ('#2e3436', '#cc0000', '#4e9a06', '#c4a000', '#3465a4', '#75507b', '#06989a', '#d3d7cf', '#555753', '#ef2929', '#8ae234', '#fce94f', '#729fcf', '#ad7fa8', '#34e2e2', '#eeeeec'), '#292929'), font_stack="'Fira Code', 'Cascadia Code', Menlo, Consolas, monospace", border='none', border_width=1, radius=8, backdrop='none', shadow='none', margin=0, padding=0, buttons=(('#ff5f57', '#febc2e', '#28c840'), ''), buttons_color=None, titlebar='none', collapse_titlebar=False, opacity=1.0, watermark='', watermark_color='rgba(128,128,128,0.85)')[source]¶
Draw captured terminal text as a picture of a terminal window.
A terminal is a fixed grid of identically-sized cells, which is what makes this arithmetic rather than typesetting:
grid()says which cell each run of same-styled characters starts on, and every coordinate below is that column timesCELL_WIDTH.Two primitives draw everything. A
<rect>fills the cells behind a run that carries a background, and a<text>draws its glyphs, pinned to its columns withtextLengthso the layout survives a reader who does not have the font.Note
A runâs padding is left out of its
<text>and paid for in thexoffset instead. Written the other way, a column only lands where it belongs if the glyphs are exactly the width assumed here, which asks the renderer to both honortextLengthand resolve the font. A web browser does both.librsvg(and through itrsvg-convertand ImageMagick) ignorestextLength, and a file manager, a git client or a thumbnailer commonly falls back to a proportional font. Starting each run on its own column asks neither.- Parameters:
text (
str) â captured output, ANSI escape sequences included.columns (
int) â width of the terminal, in characters.title (
str) â caption drawn in the windowâs title bar. Empty draws none.unique_id (
str|None) â prefix namespacing this documentâs CSS classes and element IDs, seerender(). Derived from the content when not given.palette (
TerminalPalette) â terminal colors the captureâs ANSI codes resolve against.font_stack (
str) â fonts the text is set in, best first.border (
str) â paint for the windowâs frame.NO_PAINTdraws none.border_width (
int) â thickness of that frame, in pixels.radius (
int) â how round the windowâs corners are, in pixels.backdrop (
str) â paint filling the whole image, margin included, or a CSS gradient, seegradient_svg().NO_PAINTleaves it transparent.shadow (
str) â color the windowâs drop shadow floods with.margin (
int) â transparent pixels left around the window, on all four sides.padding (
int) â pixels added inside the window, around the text.buttons (
WindowButtons) â decorations drawn in the title bar.buttons_color (
str|None) â paint for the glyph decorations. Circles carry their own colors.Nonetakes the paletteâs foreground.titlebar (
str) â paint for the strip the title and buttons sit in.NO_PAINTleaves it the terminalâs own color.collapse_titlebar (
bool) â drop that strip, closing the window over the first line of text. For a capture wearing neither decoration nor caption.opacity (
float) â how solid the windowâs body is, fromOPAQUEdown to0.0. Only the body thins out: the frame, the title bar and the text keep their own paint.watermark (
str) â credit line drawn in the imageâs bottom-right corner.watermark_color (
str) â color that line is drawn in, alpha included.
- Return type:
- Returns:
the SVG source.
- click_extra.screenshot.render_html(text, *, title='', full=True, background=CaptureBackground.DARK, preset=None, border='none', border_width=1, radius=8, backdrop='none', shadow='none', margin=0, padding=0, buttons=None, buttons_color='#c5c8c6', font_stack="'Fira Code', 'Cascadia Code', Menlo, Consolas, monospace", titlebar='none', collapse_titlebar=False, opacity=1.0, watermark='', watermark_color='rgba(128,128,128,0.85)')[source]¶
Render captured terminal text to HTML.
The
<pre>carries its own inline styling, so a fragment pasted into an existing page needs no stylesheet and cannot be restyled out of legibility by the host. Nothing else is needed either: a<pre>preserves the captureâs own spacing, which is what spares HTML the column arithmeticrender_svg()performs for a picture.Caution
The text is escaped before its ANSI is translated, the order
click_extra.tableuses for itshtmlformat. Skip it and any<a CLI prints opens a tag: click-extraâs own--export-confighelp says it writesto <stdout>.Note
An OSC 8 hyperlink loses its URL and keeps its visible text: the escape is dropped rather than turned into an
<a>.- Parameters:
text (
str) â captured output, ANSI escape sequences included.title (
str) â<title>of the document. Ignored for a fragment.full (
bool) â wrap the<pre>in a standalone document.Falsereturns the<pre>alone, to paste into a page that has its own.background (
CaptureBackground) â chrome to draw on, seeCaptureBackground.border (
str) â color of the blockâs frame, seerender_svg().border_width (
int) â thickness of that frame, in pixels.radius (
int) â how round the blockâs corners are, in pixels.backdrop (
str) â paint filling the page behind the block.shadow (
str) â color of the blockâs drop shadow, seerender_svg().margin (
int) â pixels left around the block, on all four sides.padding (
int) â pixels added inside the block, on top of its own.buttons (
WindowButtons|None) â ignored. HTML reflows with the page embedding it, so it carries the text and its colors, not a window drawn around them.buttons_color (
str) â ignored, seebuttons.titlebar (
str) â ignored, seebuttons.collapse_titlebar (
bool) â ignored, seebuttons.opacity (
float) â how solid the blockâs background is, fromOPAQUEdown to0.0, where the page shows straight through the text.watermark (
str) â credit line drawn under the block, against its right edge, where an SVG draws it in the margin. Empty draws none.watermark_color (
str) â color that line is drawn in, alpha included.
- Return type:
- Returns:
the rendered markup.
- click_extra.screenshot.render(text, *, format=CaptureFormat.SVG, columns=80, title='', unique_id=None, full=True, background=CaptureBackground.DARK, preset=None, border=None, border_width=1, radius=None, backdrop='none', shadow=None, margin=48, padding=8, opacity=1.0, watermark='generated with click-extra 9.0.0', watermark_color=None)[source]¶
Render captured terminal text to the document
formatnames.- Parameters:
text (
str) â captured output, ANSI escape sequences included.format (
CaptureFormat) â which document to produce.columns (
int|Literal['auto']) â terminal width, in characters, an SVG is laid out at, orAUTO_COLUMNSfor the width its own longest line asks for. HTML reflows, so it ignores this.title (
str) â caption drawn in an SVGâs window chrome, or an HTML documentâs<title>.unique_id (
str|None) â SVG only. Prefix namespacing the sourceâs CSS classes and element IDs. Pinning it to something stable (the output fileâs name, say) keeps a regenerated capture diffing line by line, instead of renaming every class as soon as a single character of output changes. Characters a CSS class name cannot carry are folded to a dash.full (
bool) â HTML only. Seerender_html().background (
CaptureBackground) â chrome to draw on, seeCaptureBackground.border (
str|None) â color of the windowâs frame.Nonetakes the one the chrome can show, seeCAPTURE_BORDERS;NO_PAINTdraws none.border_width (
int) â thickness of that frame, in pixels.radius (
int|None) â how round the windowâs corners are, in pixels. Zero squares them.backdrop (
str) â paint filling the image behind the window, margin included.NO_PAINTleaves it transparent.shadow (
str|None) â color of the windowâs drop shadow.Nonetakes the chromeâs own, seeCAPTURE_SHADOWS;NO_PAINTdraws none.margin (
int) â transparent pixels left around the window, on all four sides.padding (
int) â pixels added inside the window, around the text.opacity (
float) â how solid the windowâs body is, fromOPAQUEdown to0.0. Below it, whatever the capture is laid over shows through.watermark (
str) â credit line drawn in the imageâs bottom-right corner, seeDEFAULT_WATERMARK. An empty string draws none.watermark_color (
str|None) â color that line is drawn in.NonetakesWATERMARK_INK, which reads on a page of either color.
- Return type:
- Returns:
the rendered document.
- Raises:
ImportError â rendering SVG without the
screenshotextra installed.
- click_extra.screenshot.capture(args, *, format=CaptureFormat.SVG, columns=80, prompt=None, head=None, tail=None, truncation='[...]', merge_stderr=False, timeout=None, line_numbers=False, title='', unique_id=None, full=True, background=CaptureBackground.DARK, preset=None, border=None, border_width=1, radius=None, backdrop='none', shadow=None, margin=48, padding=8, opacity=1.0, watermark='generated with click-extra 9.0.0', watermark_color=None)[source]¶
Run a command and render its output as a document.
Chains
capture_output(),trim_lines()andrender(). The invocation is drawn above the output as a shell prompt, styled by the active theme throughformat_cli_prompt(), so the capture shows what to type to reproduce it.- Parameters:
args (
str|Path|None|Iterable[str|Path|None|Iterable[Iterable[str|Path|None|Iterable[TNestedArgs]]]]) â the command line to run.format (
CaptureFormat) â which document to produce.columns (
int|Literal['auto']) â terminal width, in characters, orAUTO_COLUMNSto pin none and lay the image out at what the command printed.prompt (
str|None) â command line to display, when it differs from the one run.uv run --frozen -- my-clireproduces a capture from a checkout, butmy-cliis what a reader types. An empty string draws no prompt at all.head (
int|None) â number of leading output lines to keep.tail (
int|None) â number of trailing output lines to keep.truncation (
str) â line standing in for the lines cut byheadortail.merge_stderr (
bool) â foldstderrinto the captured output.timeout (
float|None) â seconds before the command is killed.line_numbers (
bool) â draw each lineâs number in a gutter, seenumber_lines(). The prompt counts as the first of them, being the invocation everything under it came from.background (
CaptureBackground) â seerender().
- Return type:
- Returns:
the rendered document, and the commandâs exit code.
- click_extra.screenshot.format_from_path(path)[source]¶
Pick the capture format a file name asks for.
- Parameters:
path (
Path) â where the capture is to be written.- Return type:
- Returns:
the
CaptureFormatits extension names.- Raises:
ValueError â when the extension names no format.
click_extra.screenshot_presets module¶
The bundled catalog of terminal presets a capture can be drawn as.
A capture is a picture of a terminal, and terminals do not look alike. A preset carries the four things that make one recognizable, so a reader placing the image knows which desktop it came from:
the window decorations, three round buttons on the left for macOS, three glyphs on the right for Windows, a single one for GNOME;
the palette its colors resolve against, which is what turns a bright blue into Campbellâs
#3B78FFor Tangoâs#729FCF;the font the terminal ships with;
the prompt its shell draws,
$againstPS C:\>.
None of it is applied unless asked for: a capture with no preset keeps the rendererâs own neutral window, which is what every image in this projectâs documentation is drawn as.
Caution
A palette here is a published default, transcribed from the scheme each terminal ships (Campbell and One Half Light for Windows Terminal, Basic and Pro for Appleâs Terminal, Tango for GNOME), and cross-checked against iTerm2-Color-Schemes. It is what the terminal looks like out of the box, not what any given reader has configured theirs to.
- class click_extra.screenshot_presets.TerminalPalette(background: str, foreground: str, ansi: tuple[str, ...], titlebar: str)[source]¶
Bases:
NamedTupleThe colors a terminal resolves a captureâs ANSI codes against.
The 16
ansientries are the standard palette in the canonical order: black, red, green, yellow, blue, magenta, cyan, white, then the same eight in their bright variants.Create new instance of TerminalPalette(background, foreground, ansi, titlebar)
- class click_extra.screenshot_presets.WindowButtons(circles: tuple[str, ...] = (), glyphs: str = '')[source]¶
Bases:
NamedTupleThe decorations a terminal draws in its title bar.
Two shapes cover the desktops: macOS draws filled circles on the left, Windows and GNOME draw glyphs on the right.
Nonein either field leaves that half undrawn, which is what a bare window asks for.Create new instance of WindowButtons(circles, glyphs)
- click_extra.screenshot_presets.MACOS_BUTTONS: Final = (('#ff5f57', '#febc2e', '#28c840'), '')¶
Close, minimize and zoom, the three round buttons of an Aqua title bar.
- click_extra.screenshot_presets.WINDOWS_BUTTONS: Final = ((), 'ïŒâĄâ')¶
Minimize, maximize and close, the three glyphs of a Windows title bar.
- click_extra.screenshot_presets.GNOME_BUTTONS: Final = ((), 'â')¶
The single close button a GNOME window carries by default.
- click_extra.screenshot_presets.APPLE_ANSI: Final = ('#000000', '#c23621', '#25bc24', '#adad27', '#492ee1', '#d338d3', '#33bbc8', '#cbcccd', '#818383', '#fc391f', '#31e722', '#eaec23', '#5833ff', '#f935f8', '#14f0f0', '#e9ebeb')¶
Palette shared by Apple Terminalâs
BasicandProschemes.
- click_extra.screenshot_presets.CAMPBELL_ANSI: Final = ('#0c0c0c', '#c50f1f', '#13a10e', '#c19c00', '#0037da', '#881798', '#3a96dd', '#cccccc', '#767676', '#e74856', '#16c60c', '#f9f1a5', '#3b78ff', '#b4009e', '#61d6d6', '#f2f2f2')¶
Palette of
Campbell, the scheme Windows Terminal opens with.
- click_extra.screenshot_presets.ONE_HALF_LIGHT_ANSI: Final = ('#383a42', '#e45649', '#50a14f', '#c18301', '#0184bc', '#a626a4', '#0997b3', '#fafafa', '#4f525d', '#df6c75', '#98c379', '#e4c07a', '#61afef', '#c577dd', '#56b5c1', '#ffffff')¶
Palette of
One Half Light, the light scheme Windows Terminal ships.
- click_extra.screenshot_presets.TANGO_ANSI: Final = ('#2e3436', '#cc0000', '#4e9a06', '#c4a000', '#3465a4', '#75507b', '#06989a', '#d3d7cf', '#555753', '#ef2929', '#8ae234', '#fce94f', '#729fcf', '#ad7fa8', '#34e2e2', '#eeeeec')¶
Palette of Tango, which GNOME Terminal ships in a dark and a light dress.
- class click_extra.screenshot_presets.TerminalPreset(label: str, buttons: WindowButtons, radius: int, prompt: str, font_stack: str, dark: TerminalPalette, light: TerminalPalette)[source]¶
Bases:
NamedTupleA terminal a capture can be drawn as.
Pass one to
click-extra screenshot --preset, or to aclick:runblock as:screenshot-preset:. Anything stated alongside it wins: a preset picks the defaults, it does not lock them.Create new instance of TerminalPreset(label, buttons, radius, prompt, font_stack, dark, light)
- buttons: WindowButtons¶
Decorations drawn in the title bar, see
WindowButtons.
- font_stack: str¶
Fonts the capture asks for, the terminalâs own first.
Nothing is embedded, so a reader without the family falls back down the list. Which is why each ends with the same generic
monospacea browser always resolves.
- dark: TerminalPalette¶
Colors the terminal shows on its dark scheme.
- light: TerminalPalette¶
Colors it shows on its light one.
- click_extra.screenshot_presets.PRESETS: Final[dict[str, TerminalPreset]] = {'linux': ('GNOME Terminal', ((), 'â'), 6, '$', "'Ubuntu Mono', 'DejaVu Sans Mono', monospace", ('#2e3436', '#d3d7cf', ('#2e3436', '#cc0000', '#4e9a06', '#c4a000', '#3465a4', '#75507b', '#06989a', '#d3d7cf', '#555753', '#ef2929', '#8ae234', '#fce94f', '#729fcf', '#ad7fa8', '#34e2e2', '#eeeeec'), '#303030'), ('#ffffff', '#2e3436', ('#2e3436', '#cc0000', '#4e9a06', '#c4a000', '#3465a4', '#75507b', '#06989a', '#d3d7cf', '#555753', '#ef2929', '#8ae234', '#fce94f', '#729fcf', '#ad7fa8', '#34e2e2', '#eeeeec'), '#ebebeb')), 'macos': ('Apple Terminal', (('#ff5f57', '#febc2e', '#28c840'), ''), 10, '$', "'SF Mono', Menlo, Monaco, monospace", ('#000000', '#f2f2f2', ('#000000', '#c23621', '#25bc24', '#adad27', '#492ee1', '#d338d3', '#33bbc8', '#cbcccd', '#818383', '#fc391f', '#31e722', '#eaec23', '#5833ff', '#f935f8', '#14f0f0', '#e9ebeb'), '#3a3a3a'), ('#ffffff', '#000000', ('#000000', '#c23621', '#25bc24', '#adad27', '#492ee1', '#d338d3', '#33bbc8', '#cbcccd', '#818383', '#fc391f', '#31e722', '#eaec23', '#5833ff', '#f935f8', '#14f0f0', '#e9ebeb'), '#e9e9e9')), 'plain': ('No terminal at all', ((), ''), 0, '$', "'Fira Code', 'Cascadia Code', Menlo, Consolas, monospace", ('#292929', '#c5c8c6', ('#2e3436', '#cc0000', '#4e9a06', '#c4a000', '#3465a4', '#75507b', '#06989a', '#d3d7cf', '#555753', '#ef2929', '#8ae234', '#fce94f', '#729fcf', '#ad7fa8', '#34e2e2', '#eeeeec'), '#292929'), ('#ffffff', '#000000', ('#2e3436', '#cc0000', '#4e9a06', '#c4a000', '#3465a4', '#75507b', '#06989a', '#d3d7cf', '#555753', '#ef2929', '#8ae234', '#fce94f', '#729fcf', '#ad7fa8', '#34e2e2', '#eeeeec'), '#ffffff')), 'windows': ('Windows Terminal', ((), 'ïŒâĄâ'), 0, 'PS C:\\>', "'Cascadia Code', 'Cascadia Mono', Consolas, monospace", ('#0c0c0c', '#cccccc', ('#0c0c0c', '#c50f1f', '#13a10e', '#c19c00', '#0037da', '#881798', '#3a96dd', '#cccccc', '#767676', '#e74856', '#16c60c', '#f9f1a5', '#3b78ff', '#b4009e', '#61d6d6', '#f2f2f2'), '#202020'), ('#fafafa', '#383a42', ('#383a42', '#e45649', '#50a14f', '#c18301', '#0184bc', '#a626a4', '#0997b3', '#fafafa', '#4f525d', '#df6c75', '#98c379', '#e4c07a', '#61afef', '#c577dd', '#56b5c1', '#ffffff'), '#f3f3f3'))}¶
Every terminal a capture can be drawn as, alphabetically.
plainis the odd one out: it mimics no desktop, dropping the buttons and the rounded corners for a capture that has to read as a block of output rather than as a window, on a slide or in a paper.
click_extra.spinner module¶
An indeterminate terminal spinner for long-running, blocking work.
Click ships click.progressbar(), but it is determinate: it needs a known
length or an iterable to advance through. Some work has no measurable progress:
a blocking subprocess, a network round-trip, a query whose duration is unknown.
For those, the only honest feedback is âsomething is happeningâ.
Spinner fills that gap. It animates a small frame sequence on a daemon
thread, so the caller can stay blocked in a single call (communicate(),
urlopen(), âŠ) while the spinner keeps turning:
from time import sleep
from click_extra import Spinner
with Spinner("Brewing tea"):
sleep(5) # A blocking call with no measurable progress.
Caution
The spinner draws with carriage returns and ANSI control codes, so it is a
no-op whenever its output stream is not a TTY (a pipe, a file, a captured
test buffer, a CI log), unless enabled is forced. This keeps redirected
output and machine-readable formats clean.
Note
On Windows, Spinner.start() enables the consoleâs virtual-terminal
processing so the ANSI control codes animate in place rather than print
literally (â â[0m ⊠â[K). Modern terminals (Windows Terminal, recent
conhost) already have it on; this just covers older consoles.
- click_extra.spinner.active_spinner(stream=None)[source]¶
Return the innermost
Spinnercurrently animating, orNone.A spinner-typed view of
_active_line(), skipping any progress-bar indicator that may own the line instead. Withstreamgiven, only a spinner drawing on that very stream matches.
- class click_extra.spinner.Spinner(label='', *, frames=None, spinner=None, reverse=False, interval=None, delay=0.0, style=None, timer=False, stream=None, enabled=None, hide_cursor=True, beep=False)[source]¶
Bases:
objectA thread-animated, indeterminate progress spinner usable as a context manager.
The animation runs on a background daemon thread, leaving the calling thread free to block on the actual work. Entering the context (or calling
start()) begins the animation; leaving it (or callingstop()) halts the thread and erases the spinner line so it never lingers above the next output.Note
A single
Spinnerinstance drives one animation at a time. mpm and similar tools run their subprocesses sequentially, so one shared instance whoselabelis reassigned between steps is enough; for concurrent work, use one instance per thread.Configure (but do not start) the spinner.
- Parameters:
label (
str|Callable[...,Any]) â text shown after the spinner glyph. As a special case, a bare@Spinnerdecorator passes the wrapped function here instead; it is detected and the label defaults to empty.frames (
Sequence[str] |None) â the animation frames, cycled in order. Defaults toSPINNER_FRAMES, or thespinnerpresetâs frames when given.spinner (
SpinnerPreset|None) â aSpinnerPresetfrom theSPINNERScatalog (spinner=SPINNERS["moon"]), supplying both frames and a tuned interval. An explicitframesorintervalstill overrides it.reverse (
bool) â cycle the frames backwards, spinning the animation the other way. Set it when the rotation runs counter to what you expect; it composes with any customframes.interval (
float|None) â seconds between two frames. Defaults to0.1, or thespinnerpresetâs interval when given.delay (
float) â seconds to wait before drawing the first frame. A non-zero delay keeps the spinner silent for calls that finish quickly, so it only surfaces once an operation is genuinely slow.style (
Style|None) â aStyleapplied to the spinner glyph, label and timer (Style(fg="cyan", bold=True)). Color is decoupled from animation:--no-color/NO_COLORstrip it while the spinner keeps spinning (seeProgressOption).timer (
bool|Callable[[float],str]) â append the elapsed wall-clock time to the spinner, and to any finalok()/fail()line.Trueusesformat_duration()for the default compact format (2.3s,1:05, then1:02:03). Pass a callable(seconds: float) -> strto format the duration yourself, liketimer=lambda s: f"{s / 60:.0f}m"for whole minutes.stream (
IO[str] |None) â where to draw; defaults tosys.stderrso the spinner never mixes intostdoutdata.enabled (
bool|None) â force the spinner on or off.None(the default) auto-detects, animating only whenstreamis a TTY.hide_cursor (
bool) â hide the text cursor while spinning and restore it on stop.beep (
bool) â ring the terminal bell once when the spinner stops. It fires only when the spinner was active, so a disabled or redirected spinner stays silent.
- Raises:
ValueError â if
stylecarries a color or attribute that cannot be rendered.
- label: str¶
Text drawn after the spinner glyph.
Reassign it at any time while the spinner runs to reflect the current step; the animation thread reads it afresh on every frame.
- property elapsed_time: float¶
Seconds elapsed since
start(), frozen oncestop()is called.Returns
0.0before the spinner has started.
- property shown: bool¶
Whether the spinner has drawn at least one frame to its stream.
Trueonly once an animation frame was actually rendered. It staysFalsefor a disabled spinner (off a TTY, on aTERM=dumbterminal, or withenabled=False) and for a call that finishes withindelay, before the first frame. Reset bystart().Use it to gate output that should mirror the spinnerâs visibility.
ok()andfail()write their line unconditionally, so an outcome is still recorded in a pipe or log; guard them withshownwhen you only want the finisher on screen after a spinner the user actually saw:with Spinner("Baking bread") as spinner: bake() if spinner.shown: spinner.ok()
- start()[source]¶
Begin animating on a background thread, unless the spinner is disabled.
A disabled spinner (non-TTY stream, or
enabled=False) returns at once without spawning a thread or emitting anything (but still records the start time, so a laterok()/fail()can report a duration).- Return type:
- stop()[source]¶
Halt the animation and erase the spinner line.
Idempotent and safe to call when the spinner never started. Restores the cursor and clears the line only if the animation actually drew to the terminal.
- Return type:
- echo(message='')[source]¶
Print
messageon its own line above the running spinner.Clickâs
click.progressbar()and a bareprintboth fight the animation: a frame drawn between the cursor returns and the text mangles the line.echo()takes the same draw lock as the animation thread, erases the in-progress frame, writesmessagefollowed by a newline, and lets the next tick redraw the spinner underneath. It is safe to call from another thread while the spinner runs.Output goes to the spinnerâs own
stream(stderrby default), so results written tostdoutnever need it. When the spinner is not animating (disabled, or a non-TTY stream), it degrades to a plain write ofmessagewith no control codes.- Return type:
- ok(symbol=None, *, style=None)[source]¶
Stop the spinner and leave a persistent success line on screen.
Where
stop()erases the spinner,ok()replaces the final frame withsymbolfollowed by the current label (and the elapsed time whentimeris set), then keeps that line.symboldefaults to the themed success glyphOK_GLYPH(â), painted with the active themeâssuccessslot unlessstyleoverrides it. Color is stripped under--no-color/NO_COLOR; the glyph stays.- Return type:
- click_extra.spinner.trail_glyph(ok)[source]¶
Return the themed
âorâglyph for a trail line or finisher.The success glyph
OK_GLYPHpainted with the active themeâssuccessslot, or the failure glyphKO_GLYPHpainted with itserrorslot.- Return type:
- click_extra.spinner.trail_line(ok, message)[source]¶
Format one
â/âtrail line: a status glyph followed bymessage.- Return type:
- class click_extra.spinner.OperationTrail(*, label='', unit='', total=0, jobs=1, spinner=None, progress_bar=False, timer=None, clock='elapsed', enabled=None, echo_sequential=True, delay=0.0, stream=None)[source]¶
Bases:
objectA
â/âprogress trail and finisher for a batch of operations.Where
Spinnernarrates one long-running call,OperationTrailreports a batch of them: each completed operation leaves a persistenttrail_line()on screen, a runningdone/totaltally keeps the batchâs pulse visible, andfinish()closes with a persistent summary line. The natural reporting companion of the concurrency primitivesrun_jobs()andrun_lanes(), rendered one of three ways:sequential (
jobs <= 1): echo each outcome as it lands, with no aggregate indicator (each operation is free to keep its own per-callSpinner).finish()appends the elapsed time.concurrent (
jobs > 1): drive one aggregateSpinner(per-call spinners would collide on the shared stream), buffering outcomes until it first draws, then streaming the rest live above it. Pick the animation from theSPINNERScatalog withspinner=.progress bar (
progress_bar=True): drive one aggregate determinate bar carrying the{done}/:total:` tally, with outcomes streaming above it. Serves sequential and concurrent batches alike, and needs a known `total.
All render only on an interactive stream unless
enabledforces the matter, so pipes, CI logs and captured test buffers stay clean. The runningâtally is kept as outcomes land (ok_count), so a caller computes no counts of its own.Thread-safe:
mark()may be called from worker threads. Use it as a context manager whenever it may run concurrently, to bound the aggregate spinnerâs life; a purely sequential caller may construct it bare.from click_extra.execution import run_jobs from click_extra.spinner import OperationTrail with OperationTrail(label="Fetching", unit="feeds", total=len(feeds), jobs=jobs) as trail: def fetch(feed): trail.mark(*pull(feed)) # pull() returns (ok, message). list(run_jobs(fetch, feeds, jobs=jobs)) trail.finish( trail.ok_count == len(feeds), f"Fetched {trail.ok_count}/{len(feeds)} feeds", )
Configure (but do not start) the trail.
- Parameters:
label (
str) â present-tense verb for the running aggregate indicator ("Fetching"), composed into its{label} {done}/{total} {unit}tally.unit (
str) â the noun counted in the tally ("files","feeds").total (
int) â how many outcomes are expected, for thedone/totalcount.jobs (
int) â the batchâs worker count;> 1selects the concurrent rendering (one aggregate spinner),<= 1the sequential one (plain echoed lines).spinner (
SpinnerPreset|None) â aSpinnerPresetfrom theSPINNERScatalog (spinner=SPINNERS["moon"]) for the concurrent aggregate spinner. Ignored by the sequential and progress-bar renderings, and mutually exclusive withprogress_bar.progress_bar (
bool) â render the aggregate indicator as a determinateclick.progressbar()instead of a spinner, for a sequential or concurrent batch alike. Requires a positivetotal(a bar needs a length) and is mutually exclusive withspinner.timer (
bool|Callable[[float],str] |None) â append each operationâs and the batchâs elapsed time to the trail lines and the finisher.None(the default) follows the CLIâs--time/--no-timeflag;Trueforces timing on withformat_duration()âs compact clock, a callable(seconds: float) -> strforces it on with a custom format, andFalseforces it off. Per-operation times come from asecondsargument tomark(), filled in automatically by anoperation()handle.clock (
Literal['elapsed','eta']) â whether a running aggregate indicator shows elapsed time ("elapsed", the default: a stopwatch counting up, visible from the start) or remaining time ("eta": an estimate from the batchâs rate, appearing only once an outcome lets it be computed). Both the progress bar and the concurrent spinner honor"eta"(the spinner reuses Clickâs progress-bar estimate, since the trail knows itstotal). Per-operation and finisher times are always elapsed.enabled (
bool|None) â force the trail on or off.None(the default) auto-detects: the sequential echo renders only on an interactive stream, and the aggregate indicator applies its own TTY gate.echo_sequential (
bool) â whether a sequential batch echoes its outcome lines and finisher at all. Turn it off when the batch has another output that is the real product (a result table) and the trail would be noise; an aggregate indicator is unaffected.delay (
float) â seconds before the aggregate indicator first draws: a fast batch then completes without ever flashing one.stream (
IO[str] |None) â where to render; defaults tosys.stderrso the trail never mixes intostdoutdata.
- Raises:
ValueError â if
progress_baris set without a positivetotal, or together withspinner, or ifclockis neither"elapsed"nor"eta".
- mark(ok, message, seconds=None)[source]¶
Record one
â/âoutcome: tally it and render its trail line.- Parameters:
seconds (
float|None) â the operationâs own elapsed time. Whentimeris on it is formatted and appended tomessageas(2.3s). Anoperation()handle fills this in from when it was created; pass it yourself when you already hold a duration.- Return type:
- finish(ok, summary)[source]¶
Render the persistent
â/â{summary}finisher.With an aggregate indicator, it becomes the indicatorâs kept line (a spinnerâs
Spinner.ok()/Spinner.fail()line, or the barâs replacement line); sequential without one, a plain echoed line. The batchâs elapsed time since construction is appended whentimeris on (the default).- Return type:
- operation()[source]¶
Start a timed operation, returning a handle to record its outcome.
The handle captures the current time; call
_Operation.mark()when the work finishes to record itsâ/âoutcome with the elapsed time appended (whentimeris on). This is how a batch reports per-operation timings under concurrency, where the trail itself never sees when an operation began:def fetch(feed): op = trail.operation() ok, message = pull(feed) op.mark(ok, message)
- Return type:
_Operation
- class click_extra.spinner.ProgressOption(param_decls=None, is_flag=True, default=True, is_eager=True, expose_value=False, help='Show progress indicators during long operations. Disabled for non-interactive output (pipes, dumb terminals, CI) and by --accessible.', **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured
--progress/--no-progressflag gating spinner display.Resolves to a single boolean published at
ctx.meta[click_extra.context.PROGRESS], which a CLI reads to decide whether to start aSpinner. The default isTrue;--accessiblelowers it toFalse(viadefault_map) so a screen reader is never handed a spinning glyph.Note
Spinner display is intentionally decoupled from color, even though both emit ANSI. A spinner is an interactivity concern, not a color one: it is built from cursor-control codes (hide-cursor, carriage return, clear-line), which the NO_COLOR standard explicitly does not govern â it âonly signals the userâs intention regarding adding ANSI color to text outputâ. So
--no-color/NO_COLORstrip the spinnerâs colors but never hide it.This matches how the wider ecosystem treats the two axes as orthogonal: cargo, npm, pip, Rich, indicatif and ora all gate progress on the terminal (and a dedicated
--progress/--quietknob), whileNO_COLORonly affects color. Rich usesTERM=dumbâ notNO_COLORâ as the signal to drop cursor-moving features like progress bars.The spinner is therefore silenced by two things only, neither of them color:
non-interactive output â a pipe, file, CI log, or
TERM=dumbterminal that cannot move the cursor (seeSpinner._resolve_enabled);explicit intent â
--no-progressor--accessible.
This option is eager. It no longer reads
ctx.color, so its position relative toColorOptionis not load-bearing.- set_progress(ctx, param, value)[source]¶
Publish whether progress spinners may be shown.
Stores the resolved
--progressflag atPROGRESS. Deliberately independent of color: see theProgressOptionnote for why a spinner is gated on interactivity (TTY /TERM=dumb) and--accessible, never on--no-color/NO_COLOR.- Return type:
- click_extra.spinner.progressbar(iterable=None, length=None, label=None, hidden=None, show_eta=None, **kwargs)[source]¶
Drop-in for
click.progressbar()honoring--progressand--time.Clickâs own progress bar is determinate, the counterpart to the indeterminate
Spinner. This thin wrapper gates its visibility on the samePROGRESSflag the spinner uses, so a single--no-progress(or--accessible, which lowers theprogressdefault) silences both, and gates its estimated-time display on--time.- Parameters:
hidden (
bool|None) â tri-state. Left at its defaultNone, the bar follows the resolved--progressflag: hidden when the user (or--accessible) turned progress off, shown otherwise. An explicitTrueorFalseforces the bar regardless, mirroring how an explicitcolor=argument overridesctx.coloronclick.echo(). With no active context (the bar used outside a Click command) it defaults to shown.show_eta (
bool|None) â tri-state, likehidden. Left at its defaultNone, the estimated-time-remaining display follows the--time/--no-timeflag: shown under--time, hidden otherwise (its default, or outside a command). An explicitTrueorFalseforces it, keeping a bare barâs timing in step with anOperationTrailâstimer. Clickâs own default isTrue.
- Return type:
ProgressBar[TypeVar(V)]
Note
The
--progressflag gates visibility and--timethe ETA. Color is already handled upstream: Click renders the bar throughclick.echo(), whosecolor=Noneresolves againstctx.color, so--no-color/NO_COLORstrip the barâs ANSI without any work from this wrapper.
click_extra.spinner_presets module¶
The bundled catalog of terminal spinner presets.
Ported from cli-spinners, with frame intervals converted from milliseconds to seconds.
- click_extra.spinner_presets.ASCII_SPINNER_FRAMES: Final = ('-', '\\', '|', '/')¶
Plain ASCII animation frames, for terminals or fonts lacking Unicode glyphs.
- click_extra.spinner_presets.SPINNER_FRAMES: Final = ('â ', 'â ', 'â č', 'â ž', 'â Œ', 'â Ž', 'â Š', 'â §', 'â ', 'â ')¶
Default animation frames: the ubiquitous Braille-dots spinner.
Ten frames give a smooth rotation in any UTF-8 terminal. Fall back to
ASCII_SPINNER_FRAMESwhere Braille glyphs are unavailable.
- class click_extra.spinner_presets.SpinnerPreset(frames: tuple[str, ...], interval: float)[source]¶
Bases:
NamedTupleA named spinner animation: its frames and the interval they look best at.
The
SPINNERScatalog is ported from cli-spinners, with intervals converted from milliseconds to seconds. Pass one toSpinnervia itsspinnerargument.Create new instance of SpinnerPreset(frames, interval)
- click_extra.spinner_presets.SPINNERS: Final = {'aesthetic': (('â°â±â±â±â±â±â±', 'â°â°â±â±â±â±â±', 'â°â°â°â±â±â±â±', 'â°â°â°â°â±â±â±', 'â°â°â°â°â°â±â±', 'â°â°â°â°â°â°â±', 'â°â°â°â°â°â°â°', 'â°â±â±â±â±â±â±'), 0.08), 'arc': (('â', 'â ', 'â', 'â', 'âĄ', 'â'), 0.1), 'arrow': (('â', 'â', 'â', 'â', 'â', 'â', 'â', 'â'), 0.1), 'arrow2': (('âŹïž ', 'âïž ', 'âĄïž ', 'âïž ', 'âŹïž ', 'âïž ', 'âŹ ïž ', 'âïž '), 0.08), 'arrow3': (('âčâčâčâčâč', 'âžâčâčâčâč', 'âčâžâčâčâč', 'âčâčâžâčâč', 'âčâčâčâžâč', 'âčâčâčâčâž'), 0.12), 'balloon': ((' ', '.', 'o', 'O', '@', '*', ' '), 0.14), 'balloon2': (('.', 'o', 'O', '°', 'O', 'o', '.'), 0.12), 'betaWave': (('ÏÎČÎČÎČÎČÎČÎČ', 'ÎČÏÎČÎČÎČÎČÎČ', 'ÎČÎČÏÎČÎČÎČÎČ', 'ÎČÎČÎČÏÎČÎČÎČ', 'ÎČÎČÎČÎČÏÎČÎČ', 'ÎČÎČÎČÎČÎČÏÎČ', 'ÎČÎČÎČÎČÎČÎČÏ'), 0.08), 'binary': (('010010', '001100', '100101', '111010', '111101', '010111', '101011', '111000', '110011', '110101'), 0.08), 'bluePulse': (('đč ', 'đ· ', 'đ” ', 'đ” ', 'đ· '), 0.1), 'bounce': (('â ', 'â ', 'â ', 'â '), 0.12), 'bouncingBall': (('( â )', '( â )', '( â )', '( â )', '( â)', '( â )', '( â )', '( â )', '( â )', '(â )'), 0.08), 'bouncingBar': (('[ ]', '[= ]', '[== ]', '[=== ]', '[====]', '[ ===]', '[ ==]', '[ =]', '[ ]', '[ =]', '[ ==]', '[ ===]', '[====]', '[=== ]', '[== ]', '[= ]'), 0.08), 'boxBounce': (('â', 'â', 'â', 'â'), 0.12), 'boxBounce2': (('â', 'â', 'â', 'â'), 0.1), 'christmas': (('đČ', 'đ'), 0.4), 'circle': (('âĄ', 'â', 'â '), 0.12), 'circleHalves': (('â', 'â', 'â', 'â'), 0.05), 'circleQuarters': (('âŽ', 'â·', 'â¶', 'â”'), 0.12), 'clock': (('đ ', 'đ ', 'đ ', 'đ ', 'đ ', 'đ ', 'đ ', 'đ ', 'đ ', 'đ ', 'đ ', 'đ '), 0.1), 'dots': (('â ', 'â ', 'â č', 'â ž', 'â Œ', 'â Ž', 'â Š', 'â §', 'â ', 'â '), 0.08), 'dots10': (('âą', 'âą', 'âą', 'âĄ', 'âĄ', 'âĄ', '⥠'), 0.08), 'dots11': (('â ', 'â ', 'â ', 'âĄ', 'âą', 'â ', 'â ', 'â '), 0.1), 'dots12': (('âąâ ', 'âĄâ ', 'â â ', 'âąâ ', 'âĄâ ', 'â â ', 'âąâ ', 'âĄâ ', 'â â ', 'âąâ ', 'âĄâ ', 'â â ', 'âąâ ', 'âĄâ ', 'â â ', 'â â ', 'â â ', 'â â ', 'â â ', 'â â ©', 'â âą', 'â âĄ', 'âąâ ©', 'âĄâą', 'â âĄ', 'âąâ ©', 'âĄâą', 'â âĄ', 'âąâ š', 'âĄâą', 'â âĄ', 'âąâ ', 'âĄâą', 'â âĄ', 'âąâ ', 'âĄâ ', 'â â ', 'â â ', 'â â ', 'â â ', 'â â ', 'â â ©', 'â âą', 'â âĄ', 'â â ©', 'â âą', 'â âĄ', 'â â ©', 'â âą', 'â âĄ', 'â â š', 'â âą', 'â âĄ', 'â â ', 'â âą', 'â âĄ'), 0.08), 'dots13': (('âŁŒ', 'âŁč', 'âą»', 'â ż', 'âĄ', 'âŁ', '⣧', '⣶'), 0.08), 'dots14': (('â â ', 'â â ', 'â â č', 'â âąž', 'â ⣰', 'âąâŁ ', 'âŁâŁ', 'âŁâĄ', 'âŁâ ', 'âĄâ ', 'â â ', 'â â '), 0.08), 'dots2': (('âŁŸ', 'âŁœ', '⣻', 'âąż', '⥿', 'âŁ', '⣯', '⣷'), 0.08), 'dots3': (('â ', 'â ', 'â ', 'â ', 'â ', 'â Š', 'â Ž', 'â Č', 'â ł', 'â '), 0.08), 'dots4': (('â ', 'â ', 'â ', 'â ', 'â ', 'â ž', 'â °', 'â ', 'â °', 'â ž', 'â ', 'â ', 'â ', 'â '), 0.08), 'dots5': (('â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â Č', 'â Ž', 'â Š', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â '), 0.08), 'dots6': (('â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â Č', 'â Ž', 'â €', 'â ', 'â ', 'â €', 'â Ž', 'â Č', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â '), 0.08), 'dots7': (('â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â Š', 'â €', 'â ', 'â ', 'â €', 'â Š', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â '), 0.08), 'dots8': (('â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â Č', 'â Ž', 'â €', 'â ', 'â ', 'â €', 'â ', 'â ', 'â €', 'â Š', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â '), 0.08), 'dots8Bit': (('â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'âĄ', 'âĄ', 'âĄ', 'âĄ', 'âĄ', '⥠', 'âĄ', 'âĄ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'âĄ', 'âĄ', 'âĄ', 'âĄ', 'âĄ', 'âĄ', 'âĄ', 'âĄ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'âĄ', 'âĄ', 'âĄ', 'âĄ', 'âĄ', 'âĄ', 'âĄ', 'âĄ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'â ', 'âĄ', 'âĄ', 'âĄ', 'âĄ', 'âĄ', 'âĄ', 'âĄ', 'âĄ', 'â ', 'â Ą', 'â ą', 'â Ł', 'â €', 'â „', 'â Š', 'â §', '⥠', '⥥', '⥹', '⥣', '⥀', '⥄', '⥊', '⥧', 'â š', 'â ©', 'â Ș', 'â «', 'â Ź', 'â ', 'â ź', 'â Ż', '⥚', '⥩', 'âĄȘ', '⥫', '⥏', 'âĄ', '⥟', '⥯', 'â °', 'â ±', 'â Č', 'â ł', 'â Ž', 'â ”', 'â ¶', 'â ·', '⥰', '⥱', 'âĄČ', '⥳', '⥎', '⥔', '⥶', '⥷', 'â ž', 'â č', 'â ș', 'â »', 'â Œ', 'â œ', 'â Ÿ', 'â ż', '⥞', 'âĄč', 'âĄș', '⥻', 'âĄŒ', 'âĄœ', 'âĄŸ', '⥿', 'âą', 'âą', 'âą', 'âą', 'âą', 'âą ', 'âą', 'âą', 'âŁ', 'âŁ', 'âŁ', 'âŁ', 'âŁ', '⣠', 'âŁ', 'âŁ', 'âą', 'âą', 'âą', 'âą', 'âą', 'âą', 'âą', 'âą', 'âŁ', 'âŁ', 'âŁ', 'âŁ', 'âŁ', 'âŁ', 'âŁ', 'âŁ', 'âą', 'âą', 'âą', 'âą', 'âą', 'âą', 'âą', 'âą', 'âŁ', 'âŁ', 'âŁ', 'âŁ', 'âŁ', 'âŁ', 'âŁ', 'âŁ', 'âą', 'âą', 'âą', 'âą', 'âą', 'âą', 'âą', 'âą', 'âŁ', 'âŁ', 'âŁ', 'âŁ', 'âŁ', 'âŁ', 'âŁ', 'âŁ', 'âą ', '⹥', 'âąą', '⹣', '⹀', 'âą„', '⹊', 'âą§', '⣠', '⣥', '⣹', '⣣', '⣀', '⣄', '⣊', '⣧', 'âąš', 'âą©', 'âąȘ', 'âą«', '⹏', 'âą', 'âąź', '⹯', '⣚', '⣩', 'âŁȘ', '⣫', '⣏', 'âŁ', '⣟', '⣯', 'âą°', 'âą±', 'âąČ', 'âął', '⹎', 'âą”', 'âą¶', 'âą·', '⣰', '⣱', 'âŁČ', '⣳', '⣎', '⣔', '⣶', '⣷', 'âąž', 'âąč', 'âąș', 'âą»', 'âąŒ', 'âąœ', 'âąŸ', 'âąż', '⣞', 'âŁč', 'âŁș', '⣻', 'âŁŒ', 'âŁœ', 'âŁŸ', '⣿'), 0.08), 'dots9': (('âąč', 'âąș', 'âąŒ', '⣞', 'âŁ', '⥧', 'âĄ', 'âĄ'), 0.08), 'dotsCircle': (('âą ', 'â â ', 'â â ', 'â â ±', ' ⥱', 'âąâĄ°', 'âąâĄ ', 'âąâĄ'), 0.08), 'dqpb': (('d', 'q', 'p', 'b'), 0.1), 'dwarfFortress': ((' ââââââÂŁÂŁÂŁ ', 'âșââââââÂŁÂŁÂŁ ', 'âșââââââÂŁÂŁÂŁ ', 'âșââââââÂŁÂŁÂŁ ', 'âșââââââÂŁÂŁÂŁ ', 'âșââââââÂŁÂŁÂŁ ', 'âșââââââÂŁÂŁÂŁ ', 'âșââââââÂŁÂŁÂŁ ', 'âșââââââÂŁÂŁÂŁ ', 'âș âââââÂŁÂŁÂŁ ', ' âșâââââÂŁÂŁÂŁ ', ' âșâââââÂŁÂŁÂŁ ', ' âșâââââÂŁÂŁÂŁ ', ' âșâââââÂŁÂŁÂŁ ', ' âșâââââÂŁÂŁÂŁ ', ' âșâââââÂŁÂŁÂŁ ', ' âșâââââÂŁÂŁÂŁ ', ' âșâââââÂŁÂŁÂŁ ', ' âș ââââÂŁÂŁÂŁ ', ' âșââââÂŁÂŁÂŁ ', ' âșââââÂŁÂŁÂŁ ', ' âșââââÂŁÂŁÂŁ ', ' âșââââÂŁÂŁÂŁ ', ' âșââââÂŁÂŁÂŁ ', ' âșââââÂŁÂŁÂŁ ', ' âșââââÂŁÂŁÂŁ ', ' âșââââÂŁÂŁÂŁ ', ' âș âââÂŁÂŁÂŁ ', ' âșâââÂŁÂŁÂŁ ', ' âșâââÂŁÂŁÂŁ ', ' âșâââÂŁÂŁÂŁ ', ' âșâââÂŁÂŁÂŁ ', ' âșâââÂŁÂŁÂŁ ', ' âșâââÂŁÂŁÂŁ ', ' âșâââÂŁÂŁÂŁ ', ' âșâââÂŁÂŁÂŁ ', ' âș ââÂŁÂŁÂŁ ', ' âșââÂŁÂŁÂŁ ', ' âșââÂŁÂŁÂŁ ', ' âșââÂŁÂŁÂŁ ', ' âșââÂŁÂŁÂŁ ', ' âșââÂŁÂŁÂŁ ', ' âșââÂŁÂŁÂŁ ', ' âșââÂŁÂŁÂŁ ', ' âșââÂŁÂŁÂŁ ', ' âș âÂŁÂŁÂŁ ', ' âșâÂŁÂŁÂŁ ', ' âșâÂŁÂŁÂŁ ', ' âșâÂŁÂŁÂŁ ', ' âșâÂŁÂŁÂŁ ', ' âșâÂŁÂŁÂŁ ', ' âșâÂŁÂŁÂŁ ', ' âșâÂŁÂŁÂŁ ', ' âșâÂŁÂŁÂŁ ', ' âș ÂŁÂŁÂŁ ', ' âșÂŁÂŁÂŁ ', ' âșÂŁÂŁÂŁ ', ' âșâÂŁÂŁ ', ' âșâÂŁÂŁ ', ' âșâÂŁÂŁ ', ' âșâÂŁÂŁ ', ' âșâÂŁÂŁ ', ' âșâÂŁÂŁ ', ' âș ÂŁÂŁ ', ' âșÂŁÂŁ ', ' âșÂŁÂŁ ', ' âșâÂŁ ', ' âșâÂŁ ', ' âșâÂŁ ', ' âșâÂŁ ', ' âșâÂŁ ', ' âșâÂŁ ', ' âș ÂŁ ', ' âșÂŁ ', ' âșÂŁ ', ' âșâ ', ' âșâ ', ' âșâ ', ' âșâ ', ' âșâ ', ' âșâ ', ' âș ', ' âș &', ' âș âŒ&', ' âș ⌠&', ' âș⌠&', ' âș⌠& ', ' ⌠& ', ' âș & ', ' ⌠& ', ' âș & ', ' ⌠& ', ' âș & ', '⌠& ', ' & ', ' & ', ' & â ', ' & â ', ' & â ', ' & ÂŁ ', ' & âÂŁ ', ' & âÂŁ ', ' & âÂŁ ', ' & ÂŁÂŁ ', ' & âÂŁÂŁ ', ' & âÂŁÂŁ ', '& âÂŁÂŁ ', '& ÂŁÂŁÂŁ ', ' âÂŁÂŁÂŁ ', ' âÂŁÂŁÂŁ ', ' âÂŁÂŁÂŁ ', ' âÂŁÂŁÂŁ ', ' ââÂŁÂŁÂŁ ', ' ââÂŁÂŁÂŁ ', ' ââÂŁÂŁÂŁ ', ' ââÂŁÂŁÂŁ ', ' âââÂŁÂŁÂŁ ', ' âââÂŁÂŁÂŁ ', ' âââÂŁÂŁÂŁ ', ' âââÂŁÂŁÂŁ ', ' ââââÂŁÂŁÂŁ ', ' ââââÂŁÂŁÂŁ ', ' ââââÂŁÂŁÂŁ ', ' ââââÂŁÂŁÂŁ ', ' âââââÂŁÂŁÂŁ ', ' âââââÂŁÂŁÂŁ ', ' âââââÂŁÂŁÂŁ ', ' âââââÂŁÂŁÂŁ ', ' ââââââÂŁÂŁÂŁ ', ' ââââââÂŁÂŁÂŁ ', ' ââââââÂŁÂŁÂŁ ', ' ââââââÂŁÂŁÂŁ ', ' ââââââÂŁÂŁÂŁ '), 0.08), 'earth': (('đ ', 'đ ', 'đ '), 0.18), 'fingerDance': (('đ€ ', 'đ€ ', 'đ ', 'â ', 'đ€ ', 'đ '), 0.16), 'fish': (('~~~~~~~~~~~~~~~~~~~~', '> ~~~~~~~~~~~~~~~~~~', 'Âș> ~~~~~~~~~~~~~~~~~', '(Âș> ~~~~~~~~~~~~~~~~', '((Âș> ~~~~~~~~~~~~~~~', '<((Âș> ~~~~~~~~~~~~~~', '><((Âș> ~~~~~~~~~~~~~', ' ><((Âș> ~~~~~~~~~~~~', '~ ><((Âș> ~~~~~~~~~~~', '~~ <>((Âș> ~~~~~~~~~~', '~~~ ><((Âș> ~~~~~~~~~', '~~~~ <>((Âș> ~~~~~~~~', '~~~~~ ><((Âș> ~~~~~~~', '~~~~~~ <>((Âș> ~~~~~~', '~~~~~~~ ><((Âș> ~~~~~', '~~~~~~~~ <>((Âș> ~~~~', '~~~~~~~~~ ><((Âș> ~~~', '~~~~~~~~~~ <>((Âș> ~~', '~~~~~~~~~~~ ><((Âș> ~', '~~~~~~~~~~~~ <>((Âș> ', '~~~~~~~~~~~~~ ><((Âș>', '~~~~~~~~~~~~~~ <>((Âș', '~~~~~~~~~~~~~~~ ><((', '~~~~~~~~~~~~~~~~ <>(', '~~~~~~~~~~~~~~~~~ ><', '~~~~~~~~~~~~~~~~~~ <', '~~~~~~~~~~~~~~~~~~~~'), 0.08), 'fistBump': (('đ€\u3000\u3000\u3000\u3000đ€ ', 'đ€\u3000\u3000\u3000\u3000đ€ ', 'đ€\u3000\u3000\u3000\u3000đ€ ', '\u3000đ€\u3000\u3000đ€\u3000 ', '\u3000\u3000đ€đ€\u3000\u3000 ', '\u3000đ€âšđ€\u3000\u3000 ', 'đ€\u3000âš\u3000đ€\u3000 '), 0.08), 'flip': (('_', '_', '_', '-', '`', '`', "'", 'ÂŽ', '-', '_', '_', '_'), 0.07), 'grenade': (('Ű ', 'âČ ', ' ÂŽ ', ' ⟠', ' âž', ' âž', ' |', ' â', ' â', ' à·Ž ', ' â', ' ', ' ', ' '), 0.08), 'growHorizontal': (('â', 'â', 'â', 'â', 'â', 'â', 'â', 'â', 'â', 'â', 'â', 'â'), 0.12), 'growVertical': (('â', 'â', 'â', 'â ', 'â', 'â', 'â', 'â ', 'â', 'â'), 0.12), 'hamburger': (('â±', 'âČ', 'âŽ'), 0.1), 'hearts': (('đ ', 'đ ', 'đ ', 'đ ', 'đ '), 0.1), 'layer': (('-', '=', 'âĄ'), 0.15), 'line': (('-', '\\', '|', '/'), 0.13), 'line2': (('â ', '-', 'â', 'â', 'â', '-'), 0.1), 'material': (('ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ', 'ââââââââââââââââââââ'), 0.017), 'mindblown': (('đ ', 'đ ', 'đź ', 'đź ', 'đŠ ', 'đŠ ', 'đ§ ', 'đ§ ', 'đ€Ż ', 'đ„ ', 'âš ', '\u3000 ', '\u3000 ', '\u3000 '), 0.16), 'monkey': (('đ ', 'đ ', 'đ ', 'đ '), 0.3), 'moon': (('đ ', 'đ ', 'đ ', 'đ ', 'đ ', 'đ ', 'đ ', 'đ '), 0.08), 'noise': (('â', 'â', 'â'), 0.1), 'orangeBluePulse': (('đž ', 'đ¶ ', 'đ ', 'đ ', 'đ¶ ', 'đč ', 'đ· ', 'đ” ', 'đ” ', 'đ· '), 0.1), 'orangePulse': (('đž ', 'đ¶ ', 'đ ', 'đ ', 'đ¶ '), 0.1), 'pipe': (('â€', 'â', 'âŽ', 'â', 'â', 'â', 'âŹ', 'â'), 0.1), 'point': (('âââ', 'âââ', 'âââ', 'âââ', 'âââ'), 0.125), 'pong': (('ââ â', 'ââ â', 'â â â', 'â â â', 'â ⥠â', 'â â â', 'â â â', 'â â â', 'â â â', 'â â â', 'â ⥠â', 'â â â', 'â â â', 'â â â', 'â â â', 'â â â', 'â âĄâ', 'â â â', 'â â â', 'â â â', 'â â â', 'â â â', 'â ⥠â', 'â â â', 'â â â', 'â â â', 'â â â', 'â â â', 'â ⥠â', 'ââ â'), 0.08), 'rollingLine': (('/ ', ' - ', ' \\ ', ' |', ' |', ' \\ ', ' - ', '/ '), 0.08), 'runner': (('đ¶ ', 'đ '), 0.14), 'sand': (('â ', 'â ', 'â ', 'âĄ', 'âĄ', 'âĄ', '⥠', 'âŁ', 'âŁ', 'âŁ', 'âŁ', 'âŁ', 'âŁ', '⣀', '⣄', '⣊', '⣟', '⣶', '⣷', '⣿', '⥿', 'â ż', 'âą', 'â ', 'âĄ', 'â ', 'â «', 'âą', 'â ', 'â ', 'âĄ', 'â ', 'â ', 'â Ą', 'âą'), 0.08), 'shark': (('â|\\____________â', 'â_|\\___________â', 'â__|\\__________â', 'â___|\\_________â', 'â____|\\________â', 'â_____|\\_______â', 'â______|\\______â', 'â_______|\\_____â', 'â________|\\____â', 'â_________|\\___â', 'â__________|\\__â', 'â___________|\\_â', 'â____________|\\â', 'â____________/|â', 'â___________/|_â', 'â__________/|__â', 'â_________/|___â', 'â________/|____â', 'â_______/|_____â', 'â______/|______â', 'â_____/|_______â', 'â____/|________â', 'â___/|_________â', 'â__/|__________â', 'â_/|___________â', 'â/|____________â'), 0.12), 'simpleDots': (('. ', '.. ', '...', ' '), 0.4), 'simpleDotsScrolling': (('. ', '.. ', '...', ' ..', ' .', ' '), 0.2), 'smiley': (('đ ', 'đ '), 0.2), 'soccerHeader': ((' đ§âœïž đ§ ', 'đ§ âœïž đ§ ', 'đ§ âœïž đ§ ', 'đ§ âœïž đ§ ', 'đ§ âœïž đ§ ', 'đ§ âœïž đ§ ', 'đ§ âœïžđ§ ', 'đ§ âœïž đ§ ', 'đ§ âœïž đ§ ', 'đ§ âœïž đ§ ', 'đ§ âœïž đ§ ', 'đ§ âœïž đ§ '), 0.08), 'speaker': (('đ ', 'đ ', 'đ ', 'đ '), 0.16), 'squareCorners': (('â°', 'âł', 'âČ', 'â±'), 0.18), 'squish': (('â«', 'âȘ'), 0.1), 'star': (('â¶', 'âž', 'âč', 'âș', 'âč', 'â·'), 0.07), 'star2': (('+', 'x', '*'), 0.08), 'timeTravel': (('đ ', 'đ ', 'đ ', 'đ ', 'đ ', 'đ ', 'đ ', 'đ ', 'đ ', 'đ ', 'đ ', 'đ '), 0.1), 'toggle': (('â¶', 'â·'), 0.25), 'toggle10': (('ă', 'ă', 'ă'), 0.1), 'toggle11': (('â§', 'â§'), 0.05), 'toggle12': (('â', 'â'), 0.12), 'toggle13': (('=', '*', '-'), 0.08), 'toggle2': (('â«', 'âȘ'), 0.08), 'toggle3': (('âĄ', 'â '), 0.12), 'toggle4': (('â ', 'âĄ', 'âȘ', 'â«'), 0.1), 'toggle5': (('âź', 'âŻ'), 0.1), 'toggle6': (('á', 'á'), 0.3), 'toggle7': (('⊟', '⊿'), 0.08), 'toggle8': (('â', 'â'), 0.1), 'toggle9': (('â', 'â'), 0.1), 'triangle': (('âą', 'âŁ', 'â€', 'â„'), 0.05), 'weather': (('âïž ', 'âïž ', 'âïž ', 'đ€ ', 'â ïž ', 'đ„ ', 'âïž ', 'đ§ ', 'đš ', 'đ§ ', 'đš ', 'đ§ ', 'đš ', 'â ', 'đš ', 'đ§ ', 'đš ', 'âïž ', 'đ„ ', 'â ïž ', 'đ€ ', 'âïž ', 'âïž '), 0.1)}¶
Named spinner animations ported from cli-spinners, keyed by name.
Each value is a
SpinnerPresetbundling frames and a tuned interval. Select one withSpinnerâsspinnerargument:from click_extra import Spinner, SPINNERS with Spinner("Brewing tea", spinner=SPINNERS["moon"]): ...
Unlike the upstream
\b-based renderers,Spinnerredraws the whole line, so the multi-character animations (bouncingBar,pong,shark, âŠ) render correctly here.
click_extra.table module¶
Width limits of a table: one entry per column, or a scalar for all of them.
- click_extra.table.ColumnWidth = int | typing.Literal['auto'] | None¶
Width limit of a single column: a character count,
auto, or no limit.
- click_extra.table.MaxColumnWidths = collections.abc.Sequence[int | typing.Literal['auto'] | None] | int | typing.Literal['auto'] | None¶
Width limits of a table: one entry per column, or a scalar for all of them.
- class click_extra.table.TableFormat(*values)[source]¶
Bases:
EnumEnumeration of supported table formats.
Hard-coded to be in alphabetical order. Content of this enum is checked in unit tests.
Warning
The
youtrackformat is missing in action from any official JetBrains documentation. It will be removed in python-tabulate v0.11.- ALIGNED = 'aligned'¶
- ASCIIDOC = 'asciidoc'¶
- COLON_GRID = 'colon-grid'¶
- CSV = 'csv'¶
- CSV_EXCEL = 'csv-excel'¶
- CSV_EXCEL_TAB = 'csv-excel-tab'¶
- CSV_UNIX = 'csv-unix'¶
- DOUBLE_GRID = 'double-grid'¶
- DOUBLE_OUTLINE = 'double-outline'¶
- FANCY_GRID = 'fancy-grid'¶
- FANCY_OUTLINE = 'fancy-outline'¶
- GITHUB = 'github'¶
- GRID = 'grid'¶
- HEAVY_GRID = 'heavy-grid'¶
- HEAVY_OUTLINE = 'heavy-outline'¶
- HJSON = 'hjson'¶
- HTML = 'html'¶
- JIRA = 'jira'¶
- JSON = 'json'¶
- JSON5 = 'json5'¶
- JSONC = 'jsonc'¶
- LATEX = 'latex'¶
- LATEX_BOOKTABS = 'latex-booktabs'¶
- LATEX_LONGTABLE = 'latex-longtable'¶
- LATEX_RAW = 'latex-raw'¶
- MEDIAWIKI = 'mediawiki'¶
- MIXED_GRID = 'mixed-grid'¶
- MIXED_OUTLINE = 'mixed-outline'¶
- MOINMOIN = 'moinmoin'¶
- ORGTBL = 'orgtbl'¶
- OUTLINE = 'outline'¶
- PIPE = 'pipe'¶
- PLAIN = 'plain'¶
- PRESTO = 'presto'¶
- PRETTY = 'pretty'¶
- PSQL = 'psql'¶
- ROUNDED_GRID = 'rounded-grid'¶
- ROUNDED_OUTLINE = 'rounded-outline'¶
- RST = 'rst'¶
- SIMPLE = 'simple'¶
- SIMPLE_GRID = 'simple-grid'¶
- SIMPLE_OUTLINE = 'simple-outline'¶
- TEXTILE = 'textile'¶
- TOML = 'toml'¶
- TSV = 'tsv'¶
- UNSAFEHTML = 'unsafehtml'¶
- VERTICAL = 'vertical'¶
- XML = 'xml'¶
- YAML = 'yaml'¶
- YOUTRACK = 'youtrack'¶
- property is_markup: bool¶
Whether this format is a markup rendering.
ANSI codes never reach a markup rendering raw: they are either translated to the formatâs native styling (see
supports_styling) or stripped from cell values. Forcing--coloron the command line preserves them as-is in the markup formats without styling support.
- property supports_styling: bool¶
Whether ANSI codes are translated to this formatâs native styling.
See
STYLED_FORMATSfor the registry, and the rationale behind each excluded markup format.
- property is_wrappable: bool¶
Whether this format renders a cell wrapped onto several lines.
See
WRAPPABLE_FORMATSfor the registry, and the rationale behind each excluded format.
- click_extra.table.MARKUP_FORMATS = frozenset({TableFormat.ASCIIDOC, TableFormat.CSV, TableFormat.CSV_EXCEL, TableFormat.CSV_EXCEL_TAB, TableFormat.CSV_UNIX, TableFormat.GITHUB, TableFormat.HJSON, TableFormat.HTML, TableFormat.JIRA, TableFormat.JSON, TableFormat.JSON5, TableFormat.JSONC, TableFormat.LATEX, TableFormat.LATEX_BOOKTABS, TableFormat.LATEX_LONGTABLE, TableFormat.LATEX_RAW, TableFormat.MEDIAWIKI, TableFormat.MOINMOIN, TableFormat.ORGTBL, TableFormat.PIPE, TableFormat.RST, TableFormat.TEXTILE, TableFormat.TOML, TableFormat.TSV, TableFormat.UNSAFEHTML, TableFormat.XML, TableFormat.YAML, TableFormat.YOUTRACK})¶
Subset of table formats that are considered as markup rendering.
- click_extra.table.STYLED_FORMATS: dict[TableFormat, Callable[[str], str]] = {TableFormat.HTML: <function ansi_to_html>, TableFormat.JIRA: <function ansi_to_jira>, TableFormat.LATEX: <function ansi_to_latex>, TableFormat.LATEX_BOOKTABS: <function ansi_to_latex>, TableFormat.LATEX_LONGTABLE: <function ansi_to_latex>, TableFormat.LATEX_RAW: <function ansi_to_latex>, TableFormat.MEDIAWIKI: <function ansi_to_html>, TableFormat.TEXTILE: <function ansi_to_textile>, TableFormat.UNSAFEHTML: <function ansi_to_html>}¶
Markup formats able to express styles natively, mapped to their ANSI translator.
print_table()runs the rendered output of these formats through their translator, converting the ANSI codes carried by cells and headers into the formatâs own styling markup: inline-CSS HTML<span>s for the HTML pair and MediaWiki (which accepts embedded HTML), Textile%{...}spans, Jira{color:...}macros, and xcolor-based LaTeX macros.Note
Translation happens on the rendered output, not on cell values, on purpose. tabulate escapes cell content for some formats (
htmlescapes HTML entities, non-rawlatexvariants escape TeX specials) while ANSI sequences pass through unscathed, so pre-render translation would get its markup mangled by those escaping rules. Post-render injection also keeps column-width computation on the ANSI text, which tabulate measures correctly.Important
Every markup format absent from this registry keeps the historical behavior: ANSI codes are stripped from cells before rendering. The verdict, format by format:
asciidoc: no portable inline styling. Colors require stylesheet-defined roles or+++passthrough blocks tied to the HTML backend, both lossy and non-standard.csv,csv-excel,csv-excel-tab,csv-unix,tsv: data interchange formats, with no concept of styling.github,pipe: GitHub sanitizes inlinestyleattributes from rendered Markdown, so translated HTML spans would not display any color there. Raw ANSI can still be forced with--colorfor terminal Markdown viewers which support escape sequences.hjson,json,json5,jsonc,toml,xml,yaml: structured serialization formats meant for programmatic consumption. Styling is presentation, not data.moinmoin: MoinMoin wiki markup has no standard inline color syntax, and embedded HTML is disabled by default.orgtbl: Org-mode has emphasis markers but no inline color markup.rst: reStructuredText needs custom roles backed by a stylesheet for inline color; there is no standard inline syntax.youtrack: undocumented by JetBrains and scheduled for removal in python-tabulate 0.11.
- click_extra.table.DEFAULT_FORMAT = TableFormat.ROUNDED_OUTLINE¶
Default table format, if none is specified.
- click_extra.table.RECORD_KEY = 'record'¶
Key used for each record in structured formats that require named containers (TOML
[[record]], XML<record>).
- click_extra.table.XML_ROOT_KEY = 'records'¶
Root element name for XML table output.
- click_extra.table.SERIALIZATION_FORMATS = frozenset({TableFormat.HJSON, TableFormat.JSON, TableFormat.JSON5, TableFormat.JSONC, TableFormat.TOML, TableFormat.XML, TableFormat.YAML})¶
Structured serialization formats whose renderers escape raw ESC bytes, making post-render
strip_ansi()ineffective.
- click_extra.table.AUTO_WIDTH: Final = 'auto'¶
Sentinel asking for a column width derived from the space left on the terminal.
Annotated
Finalso it narrows toLiteral["auto"]instead ofstr, which is what lets it stand in for the raw string anywhere aColumnWidthis expected.
- click_extra.table.MIN_COLUMN_WIDTH = 8¶
Floor applied to an
AUTO_WIDTHcolumn, so a crowded table still renders a usable column instead of collapsing it to nothing.
- click_extra.table.WRAPPABLE_FORMATS = frozenset({TableFormat.COLON_GRID, TableFormat.DOUBLE_GRID, TableFormat.DOUBLE_OUTLINE, TableFormat.FANCY_GRID, TableFormat.FANCY_OUTLINE, TableFormat.GRID, TableFormat.HEAVY_GRID, TableFormat.HEAVY_OUTLINE, TableFormat.MIXED_GRID, TableFormat.MIXED_OUTLINE, TableFormat.OUTLINE, TableFormat.PLAIN, TableFormat.PRESTO, TableFormat.PRETTY, TableFormat.PSQL, TableFormat.ROUNDED_GRID, TableFormat.ROUNDED_OUTLINE, TableFormat.RST, TableFormat.SIMPLE, TableFormat.SIMPLE_GRID, TableFormat.SIMPLE_OUTLINE, TableFormat.VERTICAL})¶
Formats laying a wrapped cell over several lines while keeping it one cell.
Column widths are a presentation hint: they are honored by the formats listed here and silently dropped by every other one, the same way styling degrades per format in
STYLED_FORMATS. Dropping is the point, as a width forced onto a format below would corrupt its output.Important
Every format absent from this registry renders
max_column_widthsunusable, for one of four reasons:aligned: this moduleâs own zero-padding format. tabulate does not indent its continuation lines, so a wrapped cell escapes its column.github,jira,orgtbl,pipe: continuation lines are emitted as additional table rows. They look right in a terminal, but a Markdown, Jira or Org renderer reads them as extra records.asciidoc,html,latex,latex-booktabs,latex-longtable,latex-raw,mediawiki,moinmoin,textile,unsafehtml,youtrack: the line break lands raw inside the cell markup, where the target renderer either collapses it back to a space or breaks the row. These formats delegate wrapping to whatever displays them.csv,csv-excel,csv-excel-tab,csv-unix,tsv, and theSERIALIZATION_FORMATS: data interchange, where a line break inside a field changes the record rather than its presentation.
- click_extra.table.EMOJI_PRESENTATION_SELECTOR = 'ïž'¶
Unicode VARIATION SELECTOR-16, asking for the emoji form of what precedes it.
- click_extra.table.NARROW_EMOJI_PRESENTATION_TERMINALS = frozenset({'Apple_Terminal'})¶
$TERM_PROGRAMvalues of terminals ignoring an emoji-presentation request.UTS #51 makes an emoji-presentation sequence (a character followed by
EMOJI_PRESENTATION_SELECTOR) two columns wide. That is whatwcwidthmeasures, and what a terminal implementing Unicode 9 widths advances the cursor by. A terminal named here advances by the base characterâs own width instead, soâïž(U+2049 U+FE0F) takes one column and its glyph is painted over the next one.Measuring such a cell as two columns there pads its row one column short, and every rule right of that cell lands early: the table looks broken on exactly the rows carrying an emoji. A character wide in its own right (
â, U+2705) carries no selector and is never in question.Detection reads
$TERM_PROGRAM, which a multiplexer overwrites with its own name, and rightly so: undertmuxorscreenit is the multiplexer that lays the cells out.
- click_extra.table.EMOJI_PRESENTATION_RE = re.compile('.ïž')¶
Matches one emoji-presentation sequence: a character and the selector.
- click_extra.table.render_table(table_data, headers=None, table_format=None, sort_key=None, max_column_widths=None, **kwargs)[source]¶
Render a table and return it as a string.
headersentries carrying a column ID (ColumnSpecinstances or(label, column_id)pairs) plug the table into the active--sort-byselection: when no explicitsort_keyis given, rows sort by the selected columns this table carries, and keep their original order when it carries none. Seecolumn_sort_key()for the exact semantics.- Parameters:
sort_key (
Callable[[Sequence[str|None]],Any] |None) â Optional callable passed tosorted()as thekeyargument. When provided, rows are sorted before rendering.max_column_widths (
Sequence[int|Literal['auto'] |None] |int|Literal['auto'] |None) â Width limits, as one entry per column or a single value for all of them. Each entry is a character count,"auto"to absorb the width left on the terminal, orNonefor no limit. Defaults to themax_widthdeclared byColumnSpecheaders. Silently dropped by formats outsideWRAPPABLE_FORMATS.
- Return type:
- click_extra.table.print_table(table_data, headers=None, table_format=None, sort_key=None, max_column_widths=None, **kwargs)[source]¶
Render a table and print it to the console.
headersentries carrying a column ID (ColumnSpecinstances or(label, column_id)pairs) plug the table into the active--sort-byselection: when no explicitsort_keyis given, rows sort by the selected columns this table carries, and keep their original order when it carries none. Seecolumn_sort_key()for the exact semantics.ANSI codes carried by cell values and headers depend on the format:
Markup formats with native styling support (see
STYLED_FORMATS) get them translated to the formatâs own styling markup, unless color output is disabled (--no-color,NO_COLOR, âŠ).Other markup formats get them stripped from cell values before rendering, unless
--coloris explicitly forced on the command line.Plain-text formats keep them raw, and defer to
echo()âs sensitivity to the global colorization settings.
- Parameters:
sort_key (
Callable[[Sequence[str|None]],Any] |None) â Optional callable passed tosorted()as thekeyargument. When provided, rows are sorted before rendering.max_column_widths (
Sequence[int|Literal['auto'] |None] |int|Literal['auto'] |None) â Width limits, as one entry per column or a single value for all of them. Each entry is a character count,"auto"to absorb the width left on the terminal, orNonefor no limit. Defaults to themax_widthdeclared byColumnSpecheaders. Silently dropped by formats outsideWRAPPABLE_FORMATS.
- Return type:
- click_extra.table.serialize_data(data, table_format, *, default=None, root_element='records', **kwargs)[source]¶
Serialize arbitrary Python data to a structured format.
Unlike
render_table()which expects tabular rows and headers, this function accepts any JSON-compatible data structure (dicts, lists, nested combinations) and serializes it to the requested format.Only formats in
SERIALIZATION_FORMATSare supported.- Parameters:
data (
Any) â Arbitrary data to serialize (dicts, lists, scalars).table_format (
TableFormat) â Target serialization format.default (
Callable|None) â Fallback serializer for types not natively supported. Defaults tostr, soPathand similar types are stringified automatically. Set to a custom callable for different behavior.root_element (
str) â Root element name for XML output.kwargs â Extra keyword arguments forwarded to the underlying serializer (like
sort_keysorindentfor JSON).
- Raises:
ValueError â If the format is not a serialization format.
- Return type:
- click_extra.table.print_data(data, table_format, *, default=None, root_element='records', package='click-extra', **kwargs)[source]¶
Serialize arbitrary Python data and print it to the console.
Wraps
serialize_data()with user-friendly error handling for missing optional dependencies.- Parameters:
data (
Any) â Arbitrary data to serialize.table_format (
TableFormat) â Target serialization format.default (
Callable|None) â Fallback serializer for custom types. Defaults tostr.root_element (
str) â Root element name for XML output.package (
str) â Package name for install instructions in error messages.kwargs â Extra keyword arguments forwarded to the underlying serializer.
- Return type:
- class click_extra.table.TableFormatOption(param_decls=None, type=EnumChoice('aligned', 'asciidoc', 'colon-grid', 'csv', 'csv-excel', 'csv-excel-tab', 'csv-unix', 'double-grid', 'double-outline', 'fancy-grid', 'fancy-outline', 'github', 'grid', 'heavy-grid', 'heavy-outline', 'hjson', 'html', 'jira', 'json', 'json5', 'jsonc', 'latex', 'latex-booktabs', 'latex-longtable', 'latex-raw', 'mediawiki', 'mixed-grid', 'mixed-outline', 'moinmoin', 'orgtbl', 'outline', 'pipe', 'plain', 'presto', 'pretty', 'psql', 'rounded-grid', 'rounded-outline', 'rst', 'simple', 'simple-grid', 'simple-outline', 'textile', 'toml', 'tsv', 'unsafehtml', 'vertical', 'xml', 'yaml', 'youtrack'), default=TableFormat.ROUNDED_OUTLINE, expose_value=False, is_eager=True, help='Rendering style of tables.', **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured option that is adding a
--table-formatflag to select the rendering style of a table.The selected table format ID is made available in the context in
ctx.meta[click_extra.context.TABLE_FORMAT], where therender_table()andprint_table()context methods pick it up as their default format.ctx.metais shared along the context chain, so declaring this option on a group makes the selected format reach every subcommand:ctx.render_table(table_data, headers, **kwargs): renders and returns the table as a string,ctx.print_table(table_data, headers, **kwargs): renders and prints the table to the console.
Where:
table_datais a 2-dimensional iterable of iterables for rows and cells values,headersis a list of string to be used as column headers,**kwargsare any extra keyword arguments supported by the underlying table formatting function.
- init_formatter(ctx, param, table_format)[source]¶
Save the resolved
table_formatin the contextâs sharedmeta.The
render_table()andprint_table()context methods read it back at call time.- Return type:
- click_extra.table.column_sort_key(header_defs, sort_columns=None, cell_key=None)[source]¶
Build a row sort key from the
sort_columnsa table actually carries.header_defsdescribes the rendered columns:ColumnSpecinstances or(label, column_id)tuples, withcolumn_id=Nonefor columns that cannot be sorted on. The requestedsort_columnsthe table carries drive the comparison first, de-duplicated and in request order; the remaining columns follow in their natural left-to-right order for tie-breaking.Returns
Nonewhen the table carries none of the requested columns, signalling that rows should keep their original order. This is what lets one--sort-byselection apply across subcommands rendering heterogeneous tables: each table sorts by the requested fields it knows, and a table knowing none of them is left untouched.
- class click_extra.table.ColumnSpec(id, label, description='', max_width=None, optional=False)[source]¶
Bases:
objectRich description of a single column in a rendered table.
Three fields, all required-by-convention even though
descriptiondefaults to empty so quick prototypes do not have to write a sentence for every column:id: stable, snake_case identifier used by--columnsto address the column, to key structured-format serializations, and to thread state throughclick_extra.context.COLUMNS.label: the human-readable header shown at the top of the rendered table.description: a MyST/Markdown blurb describing what the column represents. Used to auto-generate the column reference in the documentation.
A fourth,
max_width, is purely optional presentation.Note
Frozen + slots: instances are immutable and lightweight. Tuples of
ColumnSpecare intended to be defined as module-level constants (likeclick_extra.parameters.ShowParamsOption.TABLE_HEADERS).- description: str¶
MyST/Markdown description of what the column carries.
Used to auto-generate the Available columns section in the docs via the
show_params_columns_tableMyST substitution. Plain text without inline markup is fine: links and emphasis are optional sugar.
- max_width: int | Literal['auto'] | None¶
Width limit of this column, as a character count or
AUTO_WIDTH.Cells longer than the limit wrap onto several lines, in the formats able to render that (see
WRAPPABLE_FORMATS).None, the default, lets the column take whatever width its widest cell needs.Declaring the width here rather than passing a positional list to
render_table()keeps it attached to its column, so it survives a--columnsprojection that drops or reorders columns.
- optional: bool¶
Whether the column is left out of the table until
--columnsasks for it.A column carrying long free-form prose costs every other column its width once it joins the default projection, which is a poor trade for a reader who did not ask for it. Marking it optional keeps it out of the unprojected table while leaving it addressable by ID, so a consumer that wants it (a structured-format export feeding a machine, typically) selects it explicitly.
- click_extra.table.render_columns_markdown_table(columns)[source]¶
Render an iterable of
ColumnSpecas a 2-column Markdown table.Output shape:
| Column | Description | | :--- | :--- | | ``Label`` | description | ...
Suitable for inlining into MyST documents via
myst_substitutionsso the Available columns reference can be auto-generated from a single source of truth.- Return type:
- click_extra.table.select_columns(columns, selected_ids)[source]¶
Filter and reorder
columnsaccording toselected_ids.Returns
columnsunchanged whenselected_idsis falsy (no projection). Otherwise yields the matchingColumnSpecin the orderselected_idsspecifies, SQL-SELECT-style. RaisesKeyErrorfor unknown IDs so the caller can convert it into aclick.UsageError.- Return type:
- click_extra.table.select_row(row, selected_ids, canonical_ids)[source]¶
Build a positional row by reading cells from
rowin the selection order.Falls back to
canonical_idswhenselected_idsis empty / unset, so the row preserves its canonical column order in the absence of any user selection.- Return type:
- class click_extra.table.ColumnsType(accepted_ids=())[source]¶
Bases:
MultiChoiceColumn-flavored alias of
click_extra.types.MultiChoice.Pins the comma separator and case-sensitive matching (column IDs are snake_case identifiers, not free-form strings), and renames the metavar fallback to
COLUMNSinstead of the genericMULTI. Theaccepted_idsconstructor keyword is a column-flavored alias ofMultiChoice.choices.Initialize the type.
- Parameters:
choices â the accepted values. When non-empty,
convert()rejects unknown tokens withfail. When empty, the type behaves as a pure separator-aware parser and leaves validation to the consumer.separator â the token boundary. Use any single character; this also drives the metavar rendering (
[a<sep>b<sep>c]).case_sensitive â when
False, tokens matchchoicescase-insensitively and the returned tuple holds the canonical (original-case) values fromchoices.
- class click_extra.table.ColumnsOption(param_decls=None, columns=None, type=None, default=(), expose_value=False, is_eager=True, help='Restrict and reorder table columns, SQL SELECT-style. Comma-separated list of column IDs. Default: all columns in canonical order.', **kwargs)[source]¶
Bases:
ExtraOptionA
--columnsoption that lets users restrict and reorder table columns.Accepts a comma-separated list of column IDs, SQL-
SELECT-style:$ my-cli --columns id,spec,value --params
The selection is stored in
ctx.meta[click_extra.context.COLUMNS]and consumed by table-rendering callbacks (likeclick_extra.parameters.ShowParamsOption) to project rows + headers before rendering.Pass
columns=at construction time with the column registry the option should advertise: the help text then lists the accepted IDs and the default selection, and the callback validates the user input against that registry so unknown IDs fail fast with aclick.UsageError. Withoutcolumns=, the option stays generic: it parses any IDs and leaves validation to the downstream consumer.Empty / unset means render every column in canonical order: the default behavior, indistinguishable from not passing
--columnsat all.- columns: tuple[ColumnSpec, ...]¶
Column registry this option advertises and validates against (may be empty).
- class click_extra.table.SortByOption(*header_defs, param_decls=None, columns=None, default=None, expose_value=False, cell_key=None, help='Sort table by this column. Repeat to set priority.', **kwargs)[source]¶
Bases:
ExtraOptionA
--sort-byoption whose choices are derived from column definitions.Stores the selected column IDs in
ctx.meta[click_extra.context.SORT_BY]and publishes the derived row sort key inctx.meta[click_extra.context.TABLE_SORT_KEY], whichctx.print_tablepicks up so that table output is automatically sorted, without changing its(table_data, headers)call contract. The option acceptsmultiple=True, so users can repeat--sort-byto define a multi-column sort priority.Column definitions may be
ColumnSpecinstances or raw(label, column_id)tuples, passed positionally or via thecolumns=keyword. Passing aColumnSpecregistry viacolumns=lets the same tuple drive bothColumnsOption(--columns) and--sort-by, so the two options stay in sync from a single source of truth.COLUMNS = ( ColumnSpec("package_id", "Package ID"), ColumnSpec("package_name", "Name"), ColumnSpec("manager_id", "Manager"), ) @command @table_format_option @columns_option(columns=COLUMNS) @sort_by_option(columns=COLUMNS) @pass_context def my_cmd(ctx): ctx.print_table(rows, [col.label for col in COLUMNS])
Definitions may instead be bare column ID strings, declaring a field vocabulary untied to any single table layout. This fits a
--sort-bydeclared once on a group whose subcommands render heterogeneous tables: no sort key is published since no layout is known up front. The selection is resolved per table byprint_table(), from the column IDs its headers carry â each table sorts by the selected fields it knows (remaining columns breaking ties left to right) and keeps its original row order when it knows none.@group @sort_by_option("package_id", "package_name", "manager_id") def my_cli(): pass @my_cli.command def installed(): print_table(rows, [("Package ID", "package_id"), ("Manager", "manager_id")]) @my_cli.command def managers(): print_table(rows, [("Manager", "manager_id"), ("Path", None)])
- field_vocabulary¶
Whether definitions are bare column IDs, untied to any table layout.
In this mode
init_sort()only publishes the selection on the context: the sort is resolved per table atprint_table()time.
- init_sort(ctx, param, sort_columns)[source]¶
Publish the row sort key on the contextâs shared
meta.Builds the sort key from this optionâs column definitions and the selected
sort_columns, then stores it underctx.meta[click_extra.context.TABLE_SORT_KEY], wherectx.print_tablepicks it up. The call contract is the same sorted or not:ctx.print_table(table_data, headers).In field-vocabulary mode no table layout is known at declaration time, so no key is published: only the selection lands on the context (
ctx.metais shared with every subcommand), resolved per table byprint_table()from the column IDs its headers carry.- Return type:
click_extra.telemetry module¶
Telemetry utilities.
- class click_extra.telemetry.TelemetryOption(param_decls=None, default=False, expose_value=False, envvar=None, show_envvar=True, help='Collect telemetry and usage data.', **kwargs)[source]¶
Bases:
ExtraOptionA pre-configured
--telemetry/--no-telemetryoption flag.Respects the proposed DO_NOT_TRACK environment variable as a unified standard to opt-out of telemetry for TUI/console apps: a truthy
DO_NOT_TRACKforces telemetry off, overriding the user-defined environment variables, the auto-generated values, and configuration files. Only an explicit--telemetryon the command line outranks it.The resolved value is stored in
ctx.meta[click_extra.context.TELEMETRY], aligning with every other Click Extra optionâs per-invocation context-meta storage pattern.See also
- set_telemetry(ctx, param, value)[source]¶
Reconcile the flag with
DO_NOT_TRACKand store the result onctx.meta.An explicit
--telemetry/--no-telemetryon the command line wins. Otherwise a truthyDO_NOT_TRACK(bare presence, or any value not parseable as false, in the permissive spirit of the color environment variables) forces telemetry off. Read viaclick_extra.context.get(ctx, click_extra.context.TELEMETRY).Note
DO_NOT_TRACKis read here rather than wired through the optionâsenvvar: Clickâs environment plumbing feeds the raw value straight to the boolean flag, soDO_NOT_TRACK=1would enable telemetry, inverting the convention. Reading it manually keeps the opt-out meaning, mirroring howColorOptionreadsNO_COLORand friends.- Return type:
click_extra.test_suite module¶
Declarative, black-box CLI test suites.
A test suite is a list of CLITestCase invocations: each runs a target
command (a name, a command line, or a path to a binary) once with extra
parameters, then checks its exit code and stdout/stderr against literal,
substring, or regex expectations. Cases carry their own platform skip/only
rules, so one suite runs across operating systems unchanged.
Suites are written in any list-capable configuration format and loaded with
load_test_suite() (which picks the format from the file extension) or
parse_test_suite() (which parses a serialized string). TOML and JSON are
built in; YAML and the other SUITE_FORMATS need their matching
click-extra[âŠ] extra. run_test_suite() drives a list of cases against
a target, parallelized per the resolved --jobs count (see
click_extra.execution.run_jobs()) and reporting live progress through a
click_extra.spinner.Spinner.
This is the black-box, subprocess-level complement to
click_extra.testing.CliRunner, which drives a CLI in-process.
Todo
Tokenize a Windows command line with quoting/escaping support, like shlex
does on POSIX. The str.split() fallback _split_args uses there only splits
on whitespace, so a quoted argument such as --name "two words" is wrongly
broken into three tokens. Use
w32lex, the Windows counterpart to
shlex.
- click_extra.test_suite.SUITE_FORMATS: tuple[ConfigFormat, ...] = (ConfigFormat.TOML, ConfigFormat.JSON, ConfigFormat.YAML, ConfigFormat.JSON5, ConfigFormat.JSONC, ConfigFormat.HJSON)¶
Configuration formats a test suite can be serialized in, built-in ones first.
These are the formats able to represent a top-level list of case mappings, matched against a fileâs extension by
load_test_suite(). TOML and JSON parse with no extra dependency; the others each need their matchingclick-extra[âŠ]extra. TOML has no bare top-level array, so a TOML suite lists its cases under a[[cases]]array of tables (seeparse_test_suite()); the others use a bare list. INI (no nesting) and XML (no natural list representation) are excluded.Per-format availability is resolved by
ConfigFormat, so a format whose parser is not installed raises anImportErrorpointing at its extra at parse time.
- exception click_extra.test_suite.SkippedTest[source]¶
Bases:
ExceptionRaised when a test case should be skipped.
- class click_extra.test_suite.CLITestCase(cli_parameters=<factory>, env=<factory>, unset_env=<factory>, skip_platforms=<factory>, only_platforms=<factory>, timeout=None, exit_code=None, strip_ansi=False, output_contains=<factory>, stdout_contains=<factory>, stderr_contains=<factory>, output_regex_matches=<factory>, stdout_regex_matches=<factory>, stderr_regex_matches=<factory>, output_regex_fullmatch=None, stdout_regex_fullmatch=None, stderr_regex_fullmatch=None, execution_trace=None)[source]¶
Bases:
objectA single CLI test case: how to invoke the command and what to expect.
Each case runs the command-under-test once with
cli_parametersappended, then checks the captured result against the expectation directives below. A case with no expectation only asserts the command ran (plusexit_code, if set).- cli_parameters: tuple[str, ...] | str¶
Arguments and options appended to the command-under-test.
A plain string is split into arguments (on spaces on Windows, with
shlexelsewhere); a list or tuple is used as-is.
- env: dict[str, str]¶
Environment variables set on the command, over the inherited environment.
The second input surface of a CLI, and the only way to reach a variable-only feature from a suite: an option can be typed as a
cli_parametersflag, a variable cannot. Values must be strings, so a number or a boolean is quoted ("1", not1): an environment holds strings only, and coercing would have to pick betweenTrueandtrueon the authorâs behalf.Applied to that one child process, never to the suite runnerâs own environment, so cases stay independent under
--jobs. Seeunset_envto take a variable away instead.
- unset_env: tuple[str, ...] | str¶
Environment variables removed from the inherited environment.
The half
envcannot express. Assigning the empty string leaves a variable set, and a flag read by bare presence (NO_COLORand its family) counts that as activation, so hiding one from the command means removing it. This is what keeps a case from answering to whatever the shell running the suite happens to export.A separate directive rather than a
nullvalue inenvbecause TOML has no null literal, and a suite is as likely to be written in TOML as in YAML. Removing a variable that is not set is a no-op.
- skip_platforms: Trait | Group | str | None | Iterable[Trait | Group | str | None | Iterable[_TNestedReferences]]¶
Platforms (or platform-group IDs) on which to skip this case.
Accepts
extra_platformsidentifiers such aslinux,macos,windows, in any case, mixed freely with group IDs.
- only_platforms: Trait | Group | str | None | Iterable[Trait | Group | str | None | Iterable[_TNestedReferences]]¶
Restrict this case to these platforms; skip it everywhere else.
The mirror image of
skip_platforms, using the same identifiers.
- timeout: float | str | None = None¶
Seconds before the command is killed and the case fails as a timeout.
Falls back to the commandâs
--timeoutdefault, then to no limit.
- output_contains: tuple[str, ...] | str¶
Substrings that must all be present in the combined output.
The combined output interleaves stdout and stderr in the order the command wrote them, matching what a user sees in a terminal. The
output_*directives are mutually exclusive with thestdout_*/stderr_*ones: a single subprocess run captures either the merged stream or the separate ones, not both.
- output_regex_matches: tuple[Pattern | str, ...] | str¶
Regexes that must each match somewhere in the combined output (searched,
re.DOTALL). Seeoutput_containsfor the merged-stream semantics.
- stdout_regex_matches: tuple[Pattern | str, ...] | str¶
Regexes that must each match somewhere in stdout (searched,
re.DOTALL).
- stderr_regex_matches: tuple[Pattern | str, ...] | str¶
Regexes that must each match somewhere in stderr (searched,
re.DOTALL).
- output_regex_fullmatch: Pattern | str | None = None¶
Regex that must fully match the combined output, line by line. See
output_containsfor the merged-stream semantics.
- stdout_regex_fullmatch: Pattern | str | None = None¶
Regex that must fully match stdout, line by line.
- stderr_regex_fullmatch: Pattern | str | None = None¶
Regex that must fully match stderr, line by line.
- execution_trace: str | None = None¶
Rendering of the command execution and its output.
Populated after the case runs, for inspection on failure; not a directive you set in a test suite.
- property has_merged_output_directives: bool¶
Whether any
output_*directive (merged stream) is set.
- property has_separate_stream_directives: bool¶
Whether any
stdout_*orstderr_*directive (separate streams) is set.
- run_cli_test(command, additional_skip_platforms, default_timeout, work_directory=None)[source]¶
Run a CLI command and check its output against the test case.
The provided
commandcan be either:a path to a binary or script to execute;
a command name to be searched in the
PATH,a command line with arguments to be parsed and executed by the shell.
The caseâs
envandunset_envdirectives are layered over the inherited environment for this child process only.work_directoryis the directory the command runs in, defaulting to the one the runner itself is in.commandis resolved to an absolute path before it takes effect, so moving the target elsewhere never changes which binary is executed, only what a relative path inside the command resolves against.- Return type:
- click_extra.test_suite.cases_from_data(data)[source]¶
Build
CLITestCaseinstances from already-parsed suite data.The in-memory counterpart to
parse_test_suite()(which parses a string) andload_test_suite()(which reads a file): feed it a suite that is already a Python object, such as the nativecasesmappings declared in a[tool.<cli>.test-suite]config section.A suite is a list of case mappings, each keyed by
CLITestCasedirective names. Formats with no bare top-level array (TOML) carry that list under a top-levelcaseskey, so a mapping is unwrapped here.- Raises:
ValueError â the suite is empty, a mapping suite omits
cases, or a case uses unknown directives.TypeError â the suite is not a list, or a case is not a mapping.
- Return type:
- click_extra.test_suite.parse_test_suite(suite_string, fmt=ConfigFormat.YAML)[source]¶
Parse a serialized test suite string into
CLITestCaseinstances.fmtselects the serialization format, one ofSUITE_FORMATS; it defaults to YAML for string sources with no extension to key on, such as an environment variable.load_test_suite()is the file-based counterpart.- Raises:
ValueError â the suite is empty,
fmtcannot express a suite, a mapping suite omitscases, or a case uses unknown directives.TypeError â the suite is not a list, or a case is not a mapping.
ImportError â the formatâs optional parser is not installed.
- Return type:
- click_extra.test_suite.load_test_suite(path)[source]¶
Read a test suite file and parse it by the format of its extension.
The format is resolved from
pathâs name over the list-capableSUITE_FORMATS(sosuite.tomlparses as TOML,suite.yamlas YAML). Reading and format detection are delegated toclick_extra.config.formats.read_file().- Raises:
ValueError â the file extension matches no suite format.
ImportError â the matched formatâs optional parser is not installed.
- Return type:
- click_extra.test_suite.run_test_suite(command, cases, *, jobs=1, select_test=None, skip_platform=None, timeout=None, work_directory=None, exit_on_error=False, show_trace_on_error=True, stats=True, show_progress=True)[source]¶
Run a list of test cases against a target command and tally the results.
Cases are parallelized per
jobs(seeclick_extra.execution.run_jobs()): at one worker they run sequentially and lazily, soexit_on_errorcan stop before the rest start; otherwise they run in a thread pool and every case runs to completion. Either way outcomes are tallied in submission order. On an interactive terminal aclick_extra.spinner.Spinnerreports progress unlessshow_progressis false.- Parameters:
command (
Path|str) â The target to test: a command name, a command line, or a path to a binary or script.cases (
Sequence[CLITestCase]) â The test cases to run.jobs (
int) â Number of parallel workers;1runs sequentially.select_test (
Sequence[int] |None) â 1-based case numbers to run; others are skipped.skip_platform (
Trait|Group|str|None|Iterable[Trait|Group|str|None|Iterable[Trait|Group|str|None|Iterable[Trait|Group|str|None|Iterable[_TNestedReferences]]]]) â Extra platforms (or group IDs) to skip every case on.timeout (
float|None) â Default per-case timeout in seconds when a case sets none.work_directory (
Path|str|None) â Directory every case runs its command in, defaulting to the runnerâs own. It moves the target, never the runner: the suite file is read before any case starts, andcommandis resolved to an absolute path first, so neither is looked up relative to it.exit_on_error (
bool) â Stop at the first failure (sequential runs only).show_trace_on_error (
bool) â Echo the execution trace of each failed case.stats (
bool) â Echo a one-line worker summary up front and a result tally.show_progress (
bool) â Allow the progress spinner on an interactive terminal.
- Return type:
- Returns:
A
collections.Counterwithtotal,skipped, andfailedkeys. A non-zerofailedcount signals the caller to exit with an error.
click_extra.testing module¶
CLI testing and simulation of their execution.
- click_extra.testing.OUTPUT_LABEL = '<output>'¶
Label for the merged stream, where stdout and stderr are interleaved.
- click_extra.testing.STDOUT_LABEL = '<stdout>'¶
Label for the standard output stream.
- click_extra.testing.STDERR_LABEL = '<stderr>'¶
Label for the standard error stream.
- click_extra.testing.EXIT_CODE_LABEL = '<exit_code>'¶
Label for the process exit code.
- click_extra.testing.STREAM_FIELDS = {'output_': ('<output>', 'output'), 'stderr_': ('<stderr>', 'stderr'), 'stdout_': ('<stdout>', 'stdout')}¶
Maps a test-case field prefix to its stream label and
StreamViewattribute.output_*directives target the merged stream;stdout_*andstderr_*target the separate streams. Bothrender_cli_run()andclick_extra.test_suite.CLITestCase.run_cli_test()read this single table so the rendered trace and the assertion loop agree on labels and stream selection.
- class click_extra.testing.StreamView(stdout='', stderr='', output='', exit_code=None)[source]¶
Bases:
objectNormalized view of a CLI runâs captured streams and exit code.
Both runners produce one of these so the renderer and the assertion loop read a single shape, regardless of whether the run was driven in-process (Clickâs
click.testing.Result) or as a black-box subprocess (subprocess.CompletedProcess).A run captures either the merged stream (
output) or the separatestdoutandstderrstreams, never both: the unused fields stay empty.- output: str = ''¶
Captured merged stream (stdout and stderr interleaved), or empty when the separate streams were captured.
- classmethod from_result(result)[source]¶
Build a view from an in-process
click.testing.Result.Click always exposes
stdout,stderrand the interleavedoutputtogether, so all three are carried over verbatim.- Return type:
- classmethod from_completed_process(result)[source]¶
Build a view from a black-box
subprocess.CompletedProcess.A subprocess run with stderr merged into stdout (
stderr=STDOUT) reportsresult.stderrasNone: that case is rendered as the interleavedoutputstream. Otherwise the two streams are kept separate.- Return type:
- click_extra.testing.render_cli_run(args, result, env=None)[source]¶
Generates the full simulation of CLI execution, including output.
Mostly used to print debug traces to user or in test results.
- Return type:
- click_extra.testing.INVOKE_ARGS = {'args', 'catch_exceptions', 'cli', 'color', 'env', 'input', 'self'}¶
Parameter IDs of
click.testing.CliRunner.invoke().We need to collect them to help us identify which extra parameters passed to
invoke()collides with its original signature.Warning
This has been reported upstream to Click project but has been rejected and not considered an issue worth fixing.
- class click_extra.testing.Result(runner, stdout_bytes, stderr_bytes, output_bytes, return_value, exit_code, exception, exc_info=None)[source]¶
Bases:
ResultA
Resultsubclass with automatic traceback formatting.Enhances
__repr__so that pytest assertion failures show the full traceback instead of just the exception type.
- class click_extra.testing.CliRunner(charset='utf-8', env=None, echo_stdin=False, catch_exceptions=True, capture='sys')[source]¶
Bases:
CliRunnerAugment
click.testing.CliRunnerwith extra features and bug fixes.- invoke(cli, *args, input=None, env=None, catch_exceptions=True, color=None, **extra)[source]¶
Same as
click.testing.CliRunner.invoke()with extra features.The first positional parameter is the CLI to invoke. The remaining positional parameters of the function are the CLI arguments. All other parameters are required to be named.
The CLI arguments can be nested iterables of arbitrary depth. This is useful for argument composition of test cases with @pytest.mark.parametrize.
Allow forcing of the
colorproperty at the class-level viaforce_colorattribute.Adds a special case in the form of
color="forced"parameter, which allows colored output to be kept, while forcing the initialization ofContext.color = True. This is not allowed in current implementation ofclick.testing.CliRunner.invoke()because of colliding parameters.Strips all ANSI codes from results if
colorwas explicitly set toFalse.Always prints a simulation of the CLI execution as the user would see it in its terminal. Including colors.
Pretty-prints a formatted exception traceback if the command fails.
- Parameters:
cli (
Command) â CLI to invoke.args (
str|Path|None|Iterable[str|Path|None|Iterable[Iterable[str|Path|None|Iterable[TNestedArgs]]]]) â can be nested iterables composed ofstr,pathlib.Pathobjects andNonevalues. The nested structure will be flattened andNonevalues will be filtered out. Then all elements will be cast tostr. Seeargs_cleanup()for details.input (
str|bytes|IO|None) â same asclick.testing.CliRunner.invoke().env (
Mapping[str,str|None] |None) â same asclick.testing.CliRunner.invoke().catch_exceptions (
bool) â same asclick.testing.CliRunner.invoke().color (
bool|Literal['forced'] |None) â If a boolean, the parameter will be passed as-is toclick.testing.CliRunner.isolation(). If"forced", the parameter will be passed asTruetoclick.testing.CliRunner.isolation()and an extracolor=Trueparameter will be passed to the invoked CLI.extra (
Any) â same asclick.testing.CliRunner.invoke(), but colliding parameters are allowed and properly passed on to the invoked CLI.
- Return type:
- click_extra.testing.unescape_regex(text)[source]¶
De-obfuscate a regex for better readability.
This is like the reverse of
re.escape().- Return type:
- exception click_extra.testing.RegexLineMismatch(regex_line, content_line, line_number)[source]¶
Bases:
AssertionErrorRaised when a regex line does not match the corresponding content line.
- click_extra.testing.REGEX_NEWLINE = '\\n'¶
Newline token used to split a multi-line regex pattern for line-by-line matching.
- click_extra.testing.regex_fullmatch_line_by_line(regex, content)[source]¶
Check that the
contentmatches the givenregex.If the
regexdoes not fully match thecontent, raise anAssertionError, with a message showing the first mismatching line.This is useful when comparing large walls of text, such as CLI output.
- Return type:
click_extra.theme_docs module¶
Render a theme palette as an inline-styled HTML fragment for documentation.
palette_html() is called from docs/theme.md to render every
built-in themeâs palette at Sphinx build time.
inject_slot_example_docstring() is registered as a Sphinx
autodoc-process-docstring hook from docs/conf.py to inject a colored
example into each HelpTheme slotâs autodoc block. This is build-time
documentation code, kept out of the runtime theme module.
- click_extra.theme_docs.inject_slot_example_docstring(app, what, name, obj, options, lines)[source]¶
Sphinx
autodoc-process-docstringhook injecting per-slot colored examples.For every
HelpThemeslot that has an entry in_PALETTE_EXAMPLES, append anansi-colorcode block to the slotâs autodoc lines. The example is rendered through_render_slot_ansi, which callsBUILTIN_THEMES["dark"].<slot>(text)to obtain the actual ANSI escapes click-extra would emit at runtime.Wire this up from a Sphinx
conf.pywith:from click_extra.theme_docs import inject_slot_example_docstring def setup(app): app.connect("autodoc-process-docstring", inject_slot_example_docstring)
The hook intentionally targets only
click_extra.theme.HelpTheme.<slot>names so it wonât accidentally rewrite unrelated docstrings; downstream projects can register the hook in their ownconf.pyif they consume HelpTheme docstrings.- Return type:
- click_extra.theme_docs.palette_html(theme)[source]¶
Render a themeâs palette as an inline-styled HTML
<dl>fragment.The output is a two-column definition list (slot name â styled swatch plus attribute decorations) safe to inject into MyST or reST host documents via the
python:renderSphinx directive (or anyraw:: htmlblock). Used bydocs/theme.mdto render every built-in themeâs palette at Sphinx build time without hand-maintaining swatch tables. Downstream projects with their own custom themes can call the same helper to get matching swatch listings in their own docs:```{python:render} from click_extra.theme_docs import palette_html from my_app.themes import MY_THEME print(palette_html(MY_THEME)) ```Slots that hold
identity(no styling applied), the booleancross_ref_highlighttoggle, the internal_style_kwargscache, and a handful of inherited cloup slots that built-ins never style are skipped: every emitted row corresponds to a real palette choice in the theme.- Return type:
click_extra.types module¶
Custom click.ParamType subclasses for multi-pick, Enum choices and
durations, plus the standalone duration parsers that back Duration.
- class click_extra.types.MultiChoice(choices=(), separator=',', case_sensitive=True)[source]¶
Bases:
ParamTypeComma-separated multi-pick from a fixed set of values.
The pick-many counterpart to
click.Choice. Accepts a single token containing several values joined by a configurableseparator(defaults to,), parses it into atuple[str, ...]and validates each value againstchoiceswhen that set is non-empty.The rendered metavar is
[a,b,c](separator-joined, parallel toChoiceâs[a|b|c]):click_extra.highlight._HelpColorsMixinauto-detects the separator and highlights each individual value the same way it does forChoice.Note
Click does not ship a built-in equivalent. The closest idiomatic approach is
click.Choice([...]) + multiple=True, which requires the flag to be repeated (--tag a --tag b --tag c) rather than comma-separated. The lack of a single-token, separator-based variant upstream has been raised in:pallets/click#2771 (open): request for
nargs=-1with a non-whitespace separator, covering exactly this use case.pallets/click#2537 (closed as not planned): earlier request for space-separated multi values via
nargs=-1on options.
Maintainers have leaned on the orthogonality argument:
multiple=Truealready exists, separator conventions vary across communities (,vs.:vs.;), and escaping breaks down when a value contains the chosen separator.MultiChoiceships the convention anyway because SQL-styleSELECT a, b, csyntax reads more naturally for the tabular use casesclick-extrasupports (click_extra.table.ColumnsOptionis the headline consumer).Initialize the type.
- Parameters:
choices (
Sequence[str]) â the accepted values. When non-empty,convert()rejects unknown tokens withfail. When empty, the type behaves as a pure separator-aware parser and leaves validation to the consumer.separator (
str) â the token boundary. Use any single character; this also drives the metavar rendering ([a<sep>b<sep>c]).case_sensitive (
bool) â whenFalse, tokens matchchoicescase-insensitively and the returned tuple holds the canonical (original-case) values fromchoices.
- get_metavar(param, ctx=None)[source]¶
Render
[a<sep>b<sep>c]whenchoicesis set,Noneotherwise.Nonefalls back to Clickâs default rendering (the uppercasedname, likeMULTI).
- class click_extra.types.ChoiceSource(*values)[source]¶
Bases:
EnumSource of choices for
EnumChoice.- KEY = 'key'¶
- NAME = 'name'¶
- VALUE = 'value'¶
- STR = 'str'¶
- class click_extra.types.EnumChoice(choices, case_sensitive=False, choice_source=ChoiceSource.STR, show_aliases=False, transform=None)[source]¶
Bases:
ChoiceChoice type for
Enum.Allows to select which part of the members to use as choice strings, by setting the
choice_sourceparameter to one of:ChoiceSource.KEYorChoiceSource.NAMEto use the key (thenameproperty),ChoiceSource.VALUEto use thevalue,ChoiceSource.STRto use thestr()string representation, orA custom callable that takes an
Enummember and returns a string.
Defaults to
ChoiceSource.STR, which only requires you to define the__str__()method on yourEnumto produce beautiful choice strings.The
transformparameter takes a callable reshaping the string produced by the source. It composes with every source, and is the only way to spell choices in a CLI-friendly case whileshow_aliasesis on: aliases are reachable throughChoiceSource.KEY,ChoiceSource.NAMEandChoiceSource.VALUEalone, which are stuck on raw Python identifiers.Same as
click.Choice, but takes anEnumaschoices.Also defaults to case-insensitive matching.
- choices: tuple[str, ...]¶
The strings available as choice.
Hint
Contrary to the parent
Choiceclass, we store choices directly as strings, not theEnummembers themselves. That way there is no surprises when displaying them to the user.This trick bypass
Enum-specific code path in the Click library. Because, after all, a terminal environment only deals with strings: arguments, parameters, parsing, help messages, environment variables, etc.
- get_choice_string(member)[source]¶
Derive the choice string from the given
Enumâsmember.The string produced by the choice source is passed through
transform.- Return type:
- normalize_choice(choice, ctx)[source]¶
Expand the parentâs
normalize_choice()to acceptEnummembers as input.An
Enummember is mapped to its choice string first; any other value is passed to the parent untouched.- Return type:
- shell_complete(ctx, param, incomplete)[source]¶
Return completion items with choices normalized via
normalize_choice().Overrides the parent to ensure
normalize_choice()is always called on each candidate, fixing Click 8.4.0 whereshell_complete()returned raw (unnormalized) choice strings forChoiceSource.KEY.Note
On Click 8.4.1+ this override is a no-op: the parent already calls
normalize_choice(), and re-normalizing is idempotent (casefold(casefold(s)) == casefold(s)).- Return type:
- click_extra.types.parse_duration(value, *, now=None)[source]¶
Parse a friendly, ISO 8601 or RFC 3339 duration into a
timedelta.The soft, library-friendly counterpart of the
Durationparameter type: it accepts the same three input shapes but returnsNoneinstead of raising when value matches none of them, so it suits classifying values read from files or other machine sources. UnlikeDuration, it does not collapse a zero duration toNone:parse_duration("0")istimedelta(0), letting callers tell a zero duration from an unparsable value.Noneis returned only for an empty value, a future timestamp, or a value matching no known form.- Parameters:
- Return type:
- Returns:
The parsed
timedelta(possibly zero), orNone.
- click_extra.types.parse_friendly_duration(value)[source]¶
Parse only a friendly duration (
7 days,12h, a bare number of days).Returns the parsed
timedelta(possibly zero, so"0 days"istimedelta(0)), orNonefor anything that is not a friendly duration: ISO 8601 forms, calendar units (months, years), and empty or unrecognized values. Seeparse_duration()for the format-detecting umbrella.
- click_extra.types.parse_iso8601_duration(value)[source]¶
Parse only an ISO 8601 duration (
P7D,PT12H,P1WT6H).Returns the parsed
timedelta(possibly zero, so"PT0S"istimedelta(0)), orNonefor anything that is not an ISO 8601 duration: friendly forms, calendar (year or month) components, and empty or unrecognized values. Seeparse_duration()for the format-detecting umbrella.
- class click_extra.types.Duration[source]¶
Bases:
ParamTypeParse a duration or an age into a
datetime.timedelta.Accepts three input shapes:
Friendly duration:
7 days,1 week,12h,30m,45s, or a bare number of days like7. Case-insensitive.ISO 8601 duration:
P7D,PT12H,P1WT6H. Case-insensitive.RFC 3339 absolute timestamp:
2024-05-01T00:00:00Zor with an offset like+02:00. Converted at parse time to its age,now - timestamp.
Some inputs parse to
Noneinstead of atimedelta: a zero duration, an empty string, and a timestamp in the future. Cutoff options (cooldowns, timeouts, retention windows, cache TTLs) readNoneas âno cutoffâ, so a0on the command line disables the gate and overrides a value set in a configuration file.To parse outside a Click parameter (classifying a value read from a file, say), reach for the soft
parse_duration()family, which returnsNoneinstead of raising on an unrecognized value.Note
Durations resolve to a fixed number of seconds, assuming a day is 24 hours. The local time zone, DST transitions, and calendar boundaries are ignored. Calendar units (months, years) are rejected for the same reason: 28-31 days and 365-366 days make them unsuitable for a precise cutoff. Use
daysorweeksinstead.
click_extra.version module¶
Label-to-value rows of a version screen, in the order they are drawn.
- click_extra.version.RESET = '\x1b[0m'¶
The sequence closing every style, for padding that must inherit none of one.
- click_extra.version.theme_slot(slot)[source]¶
A style reading its palette slot off the active theme, on every call.
The version templateâs fields used to hold a style captured from the
darkpalette at import, on the reasoning that a default binds once anyway. That froze the message to one palette:--theme lightrecolored every help screen and left--versionpainting the program name bright white, which on a light terminal is white on white. Deferring the lookup to call time is what makes the message follow--theme,CLICK_EXTRA_THEMEand the background-sniffingautoalike, and what drops its color entirely under the monochromemanpagepalette.get_current_theme()already answers with the colorless theme outside an invocation, and with a full palette inside one, so no slot can come back missing.
- click_extra.version.unstyled(text)[source]¶
Identity style, for a segment left with no color of its own.
- Return type:
- click_extra.version.Facts¶
Label-to-value rows of a version screen, in the order they are drawn.
- click_extra.version.GIT_FIELDS: dict[str, tuple[str, ...]] = {'git_branch': ('rev-parse', '--abbrev-ref', 'HEAD'), 'git_date': ('show', '-s', '--format=%ci', 'HEAD'), 'git_long_hash': ('rev-parse', 'HEAD'), 'git_short_hash': ('rev-parse', '--short', 'HEAD'), 'git_tag': ('describe', '--tags', '--exact-match', 'HEAD')}¶
Git fields whose live value is the stripped output of one static
gitsubcommand, mapped to that subcommandâs args.git_tag_sha,git_distanceandgit_dirtyare excluded: their resolution is not a single staticgitinvocation whose stripped output is the value.git_tag_shadereferences the tag (git rev-list -1 <tag>),git_distanceparsesgit describeandgit_dirtymaps the porcelain status to a label. Seeresolve_git_tag_sha(),resolve_git_distance()andresolve_git_dirty().For the resolver of every pre-bakeable git field (these five plus the three computed ones), keyed uniformly by field ID, see
GIT_RESOLVERS.
- click_extra.version.run_git(*args, cwd=None, allow_empty=False)[source]¶
Run a
gitcommand and return its stripped output, orNone.cwd defaults to the current working directory when not provided.
By default an empty output is collapsed to
None(treated like a failure). Set allow_empty to keep an empty string instead, which some commands use meaningfully:git status --porcelainprints nothing for a clean work tree, and that is distinct from the command failing.
- click_extra.version.resolve_git_dirty(cwd=None)[source]¶
Report the work-tree state as
"dirty","clean"orNone.Returns
"dirty"whengit status --porcelainreports uncommitted changes,"clean"when it reports none, andNonewhen the state cannot be determined (not a Git repository, orgitis unavailable).The empty output of a clean work tree is meaningful here, so the command is run with
allow_emptyto tell it apart from a failure.
- click_extra.version.resolve_git_distance(cwd=None)[source]¶
Count commits since the most recent tag, as a string, or
None.Parses
git describe --tags --long, whose output has the form<tag>-<distance>-g<short_hash>. ReturnsNonewhen no tag is reachable, the directory is not a Git repository, orgitis unavailable.
- click_extra.version.resolve_git_tag_sha(cwd=None)[source]¶
Resolve the commit SHA the tag at
HEADpoints at, orNone.Runs
git describe --tags --exact-match HEADto find the tag, thengit rev-list -1 <tag>to dereference it to a commit SHA. ReturnsNonewhenHEADis not at a tagged commit, the directory is not a Git repository, orgitis unavailable.
- click_extra.version.GIT_RESOLVERS: dict[str, Callable[[Path | None], str | None]] = {'git_branch': <function _direct_git_resolver.<locals>.resolver>, 'git_date': <function _direct_git_resolver.<locals>.resolver>, 'git_dirty': <function resolve_git_dirty>, 'git_distance': <function resolve_git_distance>, 'git_long_hash': <function _direct_git_resolver.<locals>.resolver>, 'git_short_hash': <function _direct_git_resolver.<locals>.resolver>, 'git_tag': <function _direct_git_resolver.<locals>.resolver>, 'git_tag_sha': <function resolve_git_tag_sha>}¶
Canonical live resolver for every pre-bakeable
git_*field.Maps each field ID to a callable that takes an optional working directory and returns the fieldâs value by shelling out to
git(orNonewhen it cannot be resolved). This is the single source of truth for how each git field is computed live, shared by two consumers:VersionOptionâs runtime accessors, which wrap each resolver with the pre-baked-dunder and.git_archival.jsonfallbacks.the
click-extra prebake allcommand, which calls every resolver to bake values into source files at build time.
Keeping it here means adding a new git field is a one-line edit in this module, with no matching change needed in the CLI.
- click_extra.version.find_archival_file(start)[source]¶
Walk up from start to find a
.git_archival.jsonfile.Returns the first match in start or any of its parents, or
None.
- click_extra.version.read_archival(path)[source]¶
Parse a
.git_archival.jsonfile into a string mapping.Returns an empty mapping when the file is missing, unreadable, or not a valid JSON object.
- click_extra.version.archival_field(data, field_id)[source]¶
Resolve a
git_*field from parsed.git_archival.jsondata.data follows the setuptools-scm archival schema:
node(full hash),node-date,describe-nameandref-names. The same file is read by setuptools-scm and Dunamai, so a single committed.git_archival.jsonserves all three.Returns
Nonewhen the field is absent, empty, or still holds an unsubstituted$Format:âŠ$placeholder. That last case is what a plain checkout contains:git archiveperforms the substitution, so values are real only inside an exported archive (including GitHubâs source tarballs).There is no entry for
git_dirty: an archive has no work tree, so its state is unknowable.
- click_extra.version.resolve_distribution(names)[source]¶
Return the first installed distribution among names, or
None.Probes each candidate name in order with
importlib.metadata.distribution()and returns the first that resolves to an installed distribution. Used to pick a distribution from a set of plausible spellings (for example the program name with-` / `_variants) before reading its metadata.
- click_extra.version.meta_value(meta, *keys)[source]¶
Return the first non-empty value among core-metadata keys.
Accessed through
in+[](rather than.get()) to dodge the deprecated implicit-Nonereturn on missing keys.
- click_extra.version.resolve_author(meta)[source]¶
Return the author(s) from metaâs core metadata, or
None.Prefers the
Authorfield, then theMaintainerfield, then the display name parsed out of theAuthor-email/Maintainer-emailfields (Name <email>). ReturnsNonewhen meta isNoneor no author can be determined.
- click_extra.version.resolve_license(meta)[source]¶
Return the license from metaâs core metadata, or
None.Prefers the SPDX
License-Expressionfield (core metadata 2.4+). Falls back to the human-readable name of the firstLicense ::trove classifier, then to the free-formLicensefield (which may hold the full license text). ReturnsNonewhen meta isNoneor no license can be determined.
- click_extra.version.platform_label()[source]¶
Current platform and CPU architecture, as displayed to the user.
- Return type:
- click_extra.version.env_summary()[source]¶
One-line interpreter and platform summary.
The same two facts
default_facts()puts on the version screen, joined for a CLI that would rather spend one line of its plain--versionon them than draw a screen at all:@version_option(fields={"env_info": env_summary()}).- Return type:
- click_extra.version.dependency_versions()[source]¶
The Click and Cloup releases this install is sitting on.
Worth a row on a screen whose main job is to be pasted into a bug report: Click Extra subclasses both, so which of the three is at fault is the first question any such report raises. Not a default fact, since a CLI built on Click Extra may reasonably consider that its own business rather than its userâs.
Read from the installed distributions rather than the packagesâ own
__version__, which Click deprecated in8.4.0and removes in9.1.- Return type:
- click_extra.version.default_facts()[source]¶
The facts every version screen carries, as an ordered label-to-value map.
A mapping rather than a sequence of pairs so a CLI can adjust one row without restating the rest,
dictpreserving insertion order and replacement keeping a key where it already sat:default_facts() | {"Platform": my_own_label} # replaces, in place default_facts() | {"Docs": DOCS_URL} # appends, at the end
- click_extra.version.visible_width(text)[source]¶
Columns text occupies once its escape sequences are discounted.
Caution
Counts characters, not display cells, so a logo drawn with double-width characters (CJK, emoji) measures short and its screen lays out ragged. Every character a terminal renders one cell wide is fine, which covers ASCII, the block and box-drawing ranges, and braille.
- Return type:
- class click_extra.version.VersionScreen(logo, tagline='', facts=<function default_facts>, gutter=' ')[source]¶
Bases:
objectA logo, and the facts to seat beside it, as
--versionshould draw them.Owns the layout only. The artwork arrives already rendered â a string, or the lines of one â so a CLI is free to draw its mark however it likes, in ASCII line art, half-blocks or anything else, without this class knowing. Hand one to
VersionOptionthrough itsscreenargument, or to a whole CLI throughdefault_params(screen=âŠ).- facts()¶
Label-to-value rows under the tagline, or a callable producing them.
A callable defers the work to render time, which matters when a value costs something to compute: a CLI counting plugins should not pay for that on every invocation just to have the number ready in case
--versionis asked for.
- property lines: tuple[str, ...]¶
The markâs lines, every one padded out to
width.Padding here rather than asking for it is what lets a caller hand over whatever its renderer produced. Trailing blanks are invisible on a line by itself and ragged the moment anything is placed beside it, and a caller cannot repair that afterwards:
str.ljustcounts the escape sequences it cannot see, so on a styled line it silently does nothing.
- rows(prog_name, version, styles)[source]¶
The column of facts, as (plain, styled) pairs.
Both forms are built together because the styled one cannot be measured: its escape sequences take columns that never reach the screen, and the plain twin is what
render()sizes the layout against.The program name and version take the same styles the plain message gives them, so the two renderings of
--versioncannot drift apart on color.
- render(prog_name, version, styles)[source]¶
Compose the mark and the facts into the screen, or decline to.
The facts are centred against the markâs height, and either column may be the taller of the two: a line missing from one side simply renders blank.
Returns
Nonewhen the terminal is too narrow to seat the two columns side by side, leaving the caller to fall back rather than emit a wrapped mess. The threshold is measured off the facts actually built, since their widest row grows with whatever a CLI chose to report. A non-interactive stream reportsshutilâs 80-column default, wide enough that a redirected-but-forced-color run still gets the screen it asked for.
- click_extra.version.colors_reach_output()[source]¶
Will ANSI codes survive all the way to the userâs terminal?
Resolves Click Extraâs color tri-state, deferring to the output streamâs TTY status on its
autodefault, exactly asclick.echodoes when it decides whether to strip the codes itself.- Return type:
- class click_extra.version.VersionOption(param_decls=None, message=None, fields=None, styles=None, message_style=None, screen=None, is_flag=True, expose_value=False, is_eager=True, help='Show the version and exit.', **kwargs)[source]¶
Bases:
ExtraOptionGather CLI metadata and prints a colored version string.
Note
This started as a copy of the standard @click.version_option() decorator, but is no longer a drop-in replacement. Hence the
Extraprefix.This address the following Click issues:
click#2324, to allow its use with the declarative
params=argument.click#2331, by distinguishing the module from the package.
click#1756, by allowing path and Python version.
Preconfigured as a
--versionoption flag.- Parameters:
message (
str|None) â the message template to print, in format string syntax. Defaults to{prog_name}, version {version}.fields (
Mapping[str,Any] |None) â mapping of template field name to a forced value, overriding the value auto-computed for that field. Keys must be members oftemplate_fields(for example{"version": "1.2.3"}).styles (
Mapping[str,Callable[[str],str] |None] |None) â mapping of template field name to itsStyle, merged overdefault_styles. PassNoneas a value to clear a fieldâs default style. Keys must be members oftemplate_fields.message_style (
Callable[[str],str] |None) â fallback style for the message literals and for any field that has no style of its own.screen (
VersionScreen|None) â aVersionScreento draw instead of the one-line message, whenever the terminal can take it. Left unset,--versionbehaves exactly as it always has.
- template_fields: tuple[str, ...] = ('module', 'module_name', 'module_file', 'module_version', 'package_name', 'package_version', 'author', 'license', 'exec_name', 'version', 'git_repo_path', 'git_branch', 'git_long_hash', 'git_short_hash', 'git_date', 'git_tag', 'git_tag_sha', 'git_distance', 'git_dirty', 'prog_name', 'env_info')¶
List of field IDs recognized by the message template.
- default_styles: ClassVar[dict[str, IStyle]] = {'env_info': Style(fg='bright_black'), 'exec_name': <function theme_slot.<locals>.apply>, 'git_branch': Style(fg='cyan'), 'git_date': Style(fg='bright_black'), 'git_dirty': Style(fg='red'), 'git_distance': <function theme_slot.<locals>.apply>, 'git_long_hash': Style(fg='yellow'), 'git_repo_path': Style(fg='bright_black'), 'git_short_hash': Style(fg='yellow'), 'git_tag': Style(fg='cyan'), 'git_tag_sha': Style(fg='yellow'), 'module_name': <function theme_slot.<locals>.apply>, 'module_version': <function theme_slot.<locals>.apply>, 'package_name': <function theme_slot.<locals>.apply>, 'package_version': <function theme_slot.<locals>.apply>, 'prog_name': <function theme_slot.<locals>.apply>, 'version': <function theme_slot.<locals>.apply>}¶
Default style for each template field.
Fields absent from this mapping render with no style of their own and fall back to
message_style(or no color when that is unset). User-providedstylesare merged over these defaults.The name and version fields defer to the active palette through
theme_slot()rather than naming a color. Both slots render exactly what the literals they replaced did under thedarkdefault âinvoked_commandis bright white bold,successis green â so nothing moves for a CLI that never touches--theme, while one that does finally gets a version message to match.
- message: str = '{prog_name}, version {version}'¶
Default message template used to render the version string.
- static cli_frame()[source]¶
Returns the frame in which the CLI is implemented.
Inspects the execution stack frames to find the package in which the userâs CLI is implemented.
Returns the frame itself.
- Return type:
- property module: ModuleType[source]¶
Returns the module in which the CLI resides.
- property module_version: str | None[source]¶
Returns the string found in the local
__version__variable.Hint
__version__is an old pattern from early Python packaging. It is not a standard variable and is not defined in the packaging PEPs.You should prefer using the
package_versionproperty below instead, which uses the standard libraryimportlib.metadataAPI.Weâre still supporting it for backward compatibility with existing codebases, as Click removed it in version 8.2.0.
- property package_version: str | None[source]¶
Returns the package version if installed.
Resolved from the distribution name (see
_distribution_name) viaimportlib.metadata.version(). ReturnsNoneif the package is not installed or cannot be resolved.
- property author: str | None[source]¶
Returns the package author(s) from its core metadata.
Delegates to
resolve_author(): prefers theAuthorfield, then theMaintainerfield, then the display name parsed out of theAuthor-email/Maintainer-emailfields (Name <email>). ReturnsNoneif no author can be determined.
- property license: str | None[source]¶
Returns the package license from its core metadata.
Delegates to
resolve_license(): prefers the SPDXLicense-Expressionfield, falls back to the human-readable name of the firstLicense ::trove classifier, then to the free-formLicensefield. ReturnsNoneif no license can be determined.
- property exec_name: str[source]¶
User-friendly name of the executed CLI.
Returns the module name. But if the later is
__main__, returns the package name.If not packaged, the CLI is assumed to be a simple standalone script, and the returned name is the scriptâs file name (including its extension).
- property version: str | None[source]¶
Return the version of the CLI.
Returns the module version if a
__version__variable is set alongside the CLI in its module.Else returns the package version if the CLI is implemented in a package, using importlib.metadata.version().
For development versions (containing
.dev), automatically appends the Git short hash as a PEP 440 local version identifier, producing versions like1.2.3.dev0+abc1234. This helps identify the exact commit a dev build was produced from. If Git is unavailable, the plain dev version is returned.Versions that already contain a
+(a pre-baked local version identifier, typically set at build time by CI pipelines) are returned as-is to avoid producing invalid double-suffixed versions like1.2.3.dev0+abc1234+xyz5678.
- property git_branch: str | None[source]¶
Returns the current Git branch name.
Checks for a pre-baked
__git_branch__dunder first, thengit rev-parse --abbrev-ref HEAD, then.git_archival.json.
- property git_long_hash: str | None[source]¶
Returns the full Git commit hash.
Checks for a pre-baked
__git_long_hash__dunder first, thengit rev-parse HEAD, then.git_archival.json.
- property git_short_hash: str | None[source]¶
Returns the short Git commit hash.
Checks for a pre-baked
__git_short_hash__dunder first, thengit rev-parse --short HEAD, then.git_archival.json(where it is derived from the first 7 characters of the full hash).Hint
The short hash is usually the first 7 characters of the full hash, but this is not guaranteed to be the case.
But it is at least guaranteed to be unique within the repository, and a minimum of 4 characters.
- property git_date: str | None[source]¶
Returns the commit date in ISO format:
YYYY-MM-DD HH:MM:SS +ZZZZ.Checks for a pre-baked
__git_date__dunder first, thengit show -s --format=%ci HEAD, then.git_archival.json(whosenode-dateis strict ISO 8601, like2021-01-01T12:00:00+00:00).
- property git_tag: str | None[source]¶
Returns the Git tag pointing at HEAD, if any.
Checks for a pre-baked
__git_tag__dunder first, thengit describe --tags --exact-match HEAD, then.git_archival.json.Returns
Noneif HEAD is not at a tagged commit.
- property git_tag_sha: str | None[source]¶
Returns the commit SHA that the current tag points at.
Checks for a pre-baked
__git_tag_sha__dunder first, thengit rev-list -1on the tag returned bygit_tag, then.git_archival.json. ReturnsNoneif HEAD is not at a tag.
- property git_distance: str | None[source]¶
Number of commits since the most recent tag, or
None.Checks for a pre-baked
__git_distance__dunder first, then parsesgit describe --tags --long, then falls back to.git_archival.json.Nonewhen no tag is reachable or Git is unavailable.
- property git_dirty: str | None[source]¶
Work-tree state:
"dirty","clean"orNone.Checks for a pre-baked
__git_dirty__dunder first, then runsgit status --porcelain.Nonewhen not in a Git repository or Git is unavailable. There is no.git_archival.jsonfallback: an archive has no work tree, so its state is unknowable.
- property prog_name: str | None¶
Return the name of the CLI, from Clickâs point of view.
Get the info_name of the root command.
Note
Unlike its siblings, this field is resolved on every access instead of being cached on the instance: it is the one template field whose value legitimately varies between invocations of the same option instance sharing a process.
multicalldispatch relies on that, running one CLI under many names in sequence, and aprog_namepassed tomain()varies it without any multicall at all. A cached value would pin the first name seen forever.
- property env_info: dict[str, Any][source]¶
Various environment info.
Returns the data produced by boltons.ecoutils.get_profile().
- field_style(field_id=None)[source]¶
Style painting the field_id segment of a rendered message.
A field carrying no style of its own falls back to
message_style, and one left unset by the caller too renders bare. Call with nofield_idfor the style of the templateâs literal segments, which ismessage_stylealone.
- colored_template(template=None)[source]¶
Insert ANSI styles to a message template.
Accepts a custom
templateas parameter, otherwise uses the default message defined on the Option instance.This step is necessary because we need to linearize the template to apply the ANSI codes on the string segments. This is a consequence of the nature of ANSI, directives which cannot be encapsulated within another (unlike markup tags like HTML).
- Return type:
- render_message(template=None)[source]¶
Render the version string from the provided template.
Accepts a custom
templateas parameter, otherwise uses the defaultself.colored_template()produced by the instance.A CLI carrying a
VersionScreengets that drawn instead, whenever three conditions hold. Failing any one of them falls back to the plain template unchanged, which is a deliberate guarantee rather than a default: that form is the one every machine reader parses.Color reaches the output. Not because a mark needs it â a good one survives having its escapes stripped â but because it is the one lever a caller already has. A redirected
--version, or one run under--no-coloror NO_COLOR, is asking for something parseable.The terminal is wide enough to seat the facts beside the mark without wrapping them.
Accessible mode is off. A mark read out character by character is noise to a screen reader, so
--accessiblekeeps the plain message.
- Return type:
- print_debug_message()[source]¶
Render in debug logs all template fields in color.
A field resolving to a nested structure is dumped as indented JSON under its own label, instead of the single-line
repra template would produce for it. Only:env_info:is built that way today, and it alone accounts for two thirds of this listing: a thousand characters on one line is what a bug report carries otherwise. Upstream reads its profile the same way, through boltons.ecoutils.get_profile_json(indent=True).- Return type: