logging_strict.util.click_lazy_group.__all__: tuple[str, ...] = ("LazyGroup",)

Module object exports

Nested pattern

LazyGroup (top)
└── lg –> cli (group)

└── thecmd (command)

$> cli lg thecmd

  • cli – For illustration, (pretend) entrypoint name, not the click.group name.

  • lg – The point/goal is to import less code.

    lazy_subcommands={"lg": "mypkg.mysubpackage.lg"}

    Mimics pyproject.toml [project.scripts] structure. Python users should already be familiar with LazyGroup.lazy_subcommands usage.

    Your click entrypoint module will likely contain multiple subcommands. This is how to choose one click subcommand without importing modules of other subcommands. The dict LazyGroup.lazy_subcommands controls the routing.

    lg is an example key to, retrieve the value (from LazyGroup.lazy_subcommands), the module import dotted path. That module and respective click subcommand is imported.

  • thecmd – your click subcommand from decorator @cli.command(name="thecmd")

    or if name not provided, the click subcommand function name, e.g. run_thecmd.

Nested example in:

  • tests/test_click_lazy_group.py::TestLazyCall:test_nested_pattern

  • tests/cli/lg.py

    Module contains a click.group and one or more group.command.

Flat pattern

LazyGroup (top)

├── build –> build_cmd (command) ├── test –> test_cmd (command) └── check –> check_cmd (command)

$> cli build --sdist

One extra hop in nested. Returns whatever object the dotted path points to. Click handles both.

Flat example

Entrypoint module

import click
from logging_strict.util.click_lazy_group import LazyGroup

@click.group(
    cls=LazyGroup,
    lazy_subcommands={
        "build": "wreck.commands.build:build_cmd",
        "test":  "wreck.commands.test:test_cmd",
        "check": "wreck.commands.check:check_cmd",
    },
    context_settings={"help_option_names": ["-h", "--help"]},
)
def cli():
    # entrypoint func name, which is usually main, not cli.
    pass

Flat example in:

  • tests/test_click_lazy_group.py::TestLazyCall:test_flat_pattern

  • tests/cli/cmds_build.py

    Module contains one group.command.

Example command module

@click.command(name="build")
@click.option("--sdist", is_flag=True, help="Build an sdist")
@click.option("--wheel", is_flag=True, help="Build a wheel")
@click.option("--outdir", type=click.Path(), default="dist", show_default=True)
def build_cmd(sdist: bool, wheel: bool, outdir: str) -> None: ...

See also

Unmaintained package click-lazy. But without redundant cached_property layer.

class logging_strict.util.click_lazy_group.LazyGroup(*args, lazy_subcommands=None, **kwargs)

click subcommands live in their own module. Only the subcommand being used will be imported.

Variables:

lazy_subcommands (dict[str, str] | None) – command name and respective import dotted path

get_command(ctx, cmd_name)

Extends click get_command

Return type:

click.Command | None

list_commands(ctx)

registered but not imported commands

Return type:

list[str]