Decorators

Click Extra’s decorators (@command, @group, @option, @argument, @version_option, the full @*_option family) are produced by a single factory that wraps cloup’s originals with three extra behaviors:

  1. Subclass-enforced cls=: every @command / @group always yields a Command / Group (or a user-supplied subclass thereof), so click-extra’s machinery (config loading, theme registry, --show-params introspection) can’t be silently bypassed by passing a vanilla click.Command class.

  2. Default-parameter injection: default_params() (the global option set: --time, --config, --color, --theme, …) is passed as a callable, so each command gets its own freshly-instantiated option list rather than sharing the same mutable instances.

  3. Optional-parenthesis decoration: @command and @command() are both legal call forms, matching the convention requested in Cloup #127.

If you only ever use the decorators click-extra ships out of the box, you don’t need to read further. This page is for downstream code that wants to wire its own @my_option decorator into the same factory.

decorator_factory(dec, *new_args, **new_defaults)

Clone a base decorator with a new set of default arguments, while validating that any user-supplied cls= is a subclass of the factory’s cls=. The result is itself a decorator that accepts the same arguments as dec and forwards them with the new defaults merged in.

The signature reads like this in click-extra’s own decorator file:

# click_extra/decorators.py
from .commands import Command, Group, default_params

command = decorator_factory(
    dec=cloup.command,
    cls=Command,
    params=default_params,
)
group = decorator_factory(
    dec=cloup.group,
    cls=Group,
    params=default_params,
)
        flowchart TD
    call(["@command / @option(...)<br/>possibly with cls=Custom"]) --> paren{"called with<br/>or without parens?"}
    paren -->|"@command"| norm["allow_missing_parenthesis<br/>normalizes both call forms"]
    paren -->|"@command()"| norm
    norm --> has{"user passed cls= ?"}
    has -->|no| build["use the factory's default cls<br/>(Command / Group / ...)"]
    has -->|yes| sub{"cls subclasses<br/>the factory's cls?"}
    sub -->|yes| build
    sub -->|no| err["raise TypeError<br/>with the full MRO listing"]
    build --> out["decorator with merged defaults<br/>and a fresh params() list"]
    

After that wiring, @command always produces a Command, and @command(cls=MyCommand) is accepted only if MyCommand is a subclass of Command. Anything else raises a TypeError with a full MRO listing of the offending class, so the caller sees why their override was rejected:

MyCommand
TypeError("The 'cls' argument must be a subclass of Command, got: click.core.Command, builtins.object")

Callable params=

When the factory is given params= as a callable (like default_params), it’s invoked once per decorated command so each command receives a fresh list of option instances. Without this indirection, two commands declared in the same module would share the same TimerOption instance, the same ConfigOption instance, and so on, which sounds harmless but produces subtle bugs (a callback registered by one command runs again when the second command exits, the parameter source map carries stale entries, …). Pass any zero-argument callable that returns a list of click.Parameter instances.

allow_missing_parenthesis(dec_factory)

A small wrapper that lets a decorator-factory be called either with parentheses (the standard @dec() form) or without (@dec). decorator_factory applies it automatically to every decorator it produces.

default
default
hi

The standard decorator suite

Every default option ships with a matching decorator built via decorator_factory:

Decorator

Wraps

command

cloup.command(cls=Command, params=default_params)

group

cloup.group(cls=Group, params=default_params)

lazy_group

group(cls=LazyGroup)

option

cloup.option(cls=Option)

argument

cloup.argument(cls=Argument)

help_option

click.decorators.help_option(*DEFAULT_HELP_NAMES)

version_option

option(cls=VersionOption)

color_option

option(cls=ColorOption)

config_option

option(cls=ConfigOption)

no_config_option

option(cls=NoConfigOption)

validate_config_option

option(cls=ValidateConfigOption)

export_config_option

option(cls=ExportConfigOption)

jobs_option

option(cls=JobsOption)

show_params_option

option(cls=ShowParamsOption)

table_format_option

option(cls=TableFormatOption)

telemetry_option

option(cls=TelemetryOption)

theme_option

option(cls=ThemeOption)

timer_option

option(cls=TimerOption)

verbose_option

option(cls=VerboseOption)

verbosity_option

option(cls=VerbosityOption)

Every entry in this list is an allow_missing_parenthesis-wrapped factory, so @theme_option and @theme_option() are both legal, and @theme_option(default="light") overrides the default while keeping the click-extra subclass guarantee.

Each factory-built decorator also exposes the constructor signature of its option class, so editors, help() and the API reference below show the real parameters instead of an opaque (*args, **kwargs).

Rolling your own

To plug a custom ExtraOption subclass into the same machinery, instantiate decorator_factory(dec=option, cls=MyOption):

--retries: type=CounterOption, default=0
--workers: type=CounterOption, default=0

This pattern is how click-extra builds every *_option decorator listed above, and how downstream projects can extend the suite without re-implementing the subclass-validation / fresh-params machinery.

click_extra.decorators API

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/@group so type checkers infer the produced command class, while also covering the no-parenthesis form enabled by allow_missing_parenthesis.

class click_extra.decorators.ParameterDecorator(*args, **kwargs)[source]

Bases: Protocol

Static 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]
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

Clone decorator with a set of new defaults.

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 (cls is a click.Command subclass) report the resulting command class, while parameter-style decorators (cls is a click.Parameter subclass, or absent) return the decorated callback unchanged. Both overloads model the optional-parenthesis behaviour added by allow_missing_parenthesis, which plain inference cannot recover. See CommandDecorator and ParameterDecorator for the produced shapes.

Attention

The cls argument passed to the factory is used as the reference class from which the produced decorator’s cls argument must inherit.

The idea is to ensure that, for example, the @command decorator re-implemented by Click Extra is always a subclass of Command, even when the user overrides the cls argument. 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 params argument, 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 params argument, 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 params argument, 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 params argument, 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 params argument, 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 VersionOption to 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 the version template 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 leading version positional conflicts with the param_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 params argument, 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 plain, 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 params argument, 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 params argument, 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 params argument, 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, 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 params argument, 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 params argument, 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' (one fewer than the host's logical CPUs) 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 params argument, 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 = "Show the command's man page (roff) 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 params argument, 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 params argument, 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 params argument, 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, count: bool = True, **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 params argument, 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 params argument, 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 params argument, 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 params argument, 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 params argument, 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 params argument, 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 params argument, 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 params argument, 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, count: bool = True, **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 params argument, 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 params argument, 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 params argument, 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 SortByOption to a command.

Forwards the positional header_defs ((label, column_id) pairs) straight to the option constructor and registers a regular Cloup Option, so the --sort-by option composes with @option_group and @constraint like any other option decorator.

Note

Hand-written instead of produced by decorator_factory() because SortByOption accepts its column definitions as positional arguments, which conflicts with the param_decls-first convention the factory relies on.