Execution

Click Extra bundles a few pre-configured options that control how a CLI runs: how long it takes (--time), how many parallel jobs it may use (--jobs), and what exit code it returns (-0/--zero-exit). Each publishes its resolved value on ctx.meta for downstream code to consume.

Timer

Click Extra can measure the execution time of a CLI via a dedicated --time/--no-time option.

Here how to use the standalone decorator:

from time import sleep
from click import command, echo, pass_context
from click_extra import timer_option

@command
@timer_option
def timer():
    sleep(0.2)
    echo("Hello world!")
$ timer --help
Usage: timer [OPTIONS]

Options:
  --time / --no-time  Measure and print elapsed execution time.
  --help              Show this message and exit.
$ timer --time
Hello world!
Execution time: 0.200 seconds.

You can get the timestamp of the CLI start from the context:

from click import command, echo, pass_context
from click_extra import timer_option

@command
@timer_option
@pass_context
def timer_command(ctx):
    start_time = ctx.meta["click_extra.start_time"]
    echo(f"Start timestamp: {start_time}")
$ timer --time
Start timestamp: 113.249066019
Execution time: 0.000 seconds.

Parallel jobs

A pre-configured --jobs option to control parallel execution. Defaults to one fewer than available CPU cores, leaving one core free for the main process and system tasks.

The option itself does not drive any concurrency: it only captures the user’s intent.

from click import command, echo, pass_context
from click_extra import jobs_option

@command
@jobs_option
@pass_context
def build(ctx):
    """Build the project."""
    jobs = ctx.meta["click_extra.jobs"]
    echo(f"Building with {jobs} parallel jobs.")
$ build --help
Usage: build [OPTIONS]

  Build the project.

Options:
  --jobs INTEGER  Number of parallel jobs. Defaults to one less than available
                  CPUs.  [default: 1]
  --help          Show this message and exit.
$ build --jobs 4
warning: Requested 4 jobs exceeds available CPU cores (1).
Building with 4 parallel jobs.

Warning

When the requested value is below 1, it is clamped to 1 and a warning is logged. When it exceeds available CPU cores, a warning is logged but the value is honored.

Tip

The resolved (clamped, validated) job count is published on ctx.meta as JOBS for downstream code to consume. See the available keys table to read it from your own callbacks.

Zero exit code

A pre-configured -0/--zero-exit option flag, following the convention popularized by linters and static analysers: they exit with a non-zero code whenever they report findings, so automation can gate on it. Setting this flag flips that behavior, so the CLI returns 0 as long as it ran to completion, reserving non-zero codes for actual execution failures.

The option itself does not alter the exit code: it only captures the user’s intent.

from click import command, echo, pass_context
from click_extra import zero_exit_option

@command
@zero_exit_option
@pass_context
def inspect(ctx):
    """Inspect a basket of fruits."""
    bruised = 2
    echo(f"Found {bruised} bruised fruits.")
    if bruised and not ctx.meta["click_extra.zero_exit"]:
        ctx.exit(1)
$ inspect --help
Usage: inspect [OPTIONS]

  Inspect a basket of fruits.

Options:
  -0, --zero-exit  Always exit with a status code of 0, even when problems are
                   found.
  --help           Show this message and exit.

By default the command reports a non-zero exit code when it finds problems:

$ inspect
Found 2 bruised fruits.

With --zero-exit (or its -0 shorthand) the command still reports its findings but always exits with 0:

$ inspect --zero-exit
Found 2 bruised fruits.

Tip

The resolved flag is published on ctx.meta as ZERO_EXIT for downstream code to consume. See the available keys table to read it from your own callbacks.

click_extra.execution API

        classDiagram
  ExtraOption <|-- JobsOption
  ExtraOption <|-- TimerOption
  ExtraOption <|-- ZeroExitOption
    

Options controlling how a CLI runs: timing, parallelism and exit code.

These options share the same shape: each is a pre-configured ExtraOption that publishes its resolved value on ctx.meta for downstream code to consume. Only TimerOption acts on its own (printing the elapsed time); JobsOption and ZeroExitOption are contracts the framework records but does not enforce.

click_extra.execution.CPU_COUNT = 1

Number of available CPU cores, or None if undetermined.

click_extra.execution.DEFAULT_JOBS = 1

Default number of parallel jobs: one fewer than available cores.

Falls back to 1 on single-core machines or when the core count cannot be determined.

class click_extra.execution.JobsOption(param_decls=None, default=1, expose_value=False, show_default=True, type=<class 'int'>, help='Number of parallel jobs. Defaults to one less than available CPUs.', **kwargs)[source]

Bases: ExtraOption

A pre-configured --jobs option to control parallel execution.

Defaults to one fewer than the number of available CPU cores, leaving one core free for the main process and system tasks.

The resolved value is stored in ctx.meta[click_extra.context.JOBS].

Warning

This option is a placeholder for future parallel execution utilities. It does not drive any concurrency by itself: downstream code must read ctx.meta[click_extra.context.JOBS] and act on it.

validate_jobs(ctx, param, value)[source]

Validate job count and store the effective value in context metadata.

Clamps values below 1 to 1 and warns when the requested count exceeds available CPU cores.

Return type:

None

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: ExtraOption

A pre-configured option that is adding a --time/--no-time flag 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, --show-params, --show-config…) short-circuited the command body via ctx.exit(). That makes --time a usable probe for the cost of Click Extra’s own machinery (option parsing, config loading, eager callbacks), not just user command bodies.

Return type:

None

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 on ctx.meta under click_extra.context.START_TIME, and queues print_timer() as a context-close callback so the elapsed duration is printed even when a sibling eager option (--version, --show-params…) short-circuits the command body.

Renamed from register_timer_on_close to align with the init_<system> convention shared with init_formatter and init_sort.

Return type:

None

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: ExtraOption

A pre-configured -0/--zero-exit option 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 0 as 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 meta dict.

Read via click_extra.context.get(ctx, click_extra.context.ZERO_EXIT).

Return type:

None