Skip to content

Main

main

Creates CLI commands and sub-commands using Typer package.

This module can be invoked from shell by executing pca command. This is enabled in the following lines in pyproject.toml:

[project.scripts]
pca = "python_cli_app_template.cli.main:app"

Read detailed help about commands and parameters by executing pca --help

GLOBAL_LOG_LEVEL = logging.INFO module-attribute

app = typer.Typer(help=f'Python CLI experimental. Version: {__version__}') module-attribute

get_current_log_level(module: str | None) -> str

Source code in src/python_cli_app_template/cli/main.py
def get_current_log_level(module: str | None) -> str:
    if module:
        return logging.getLevelName(logging.getLogger(module).getEffectiveLevel())
    else:
        return logging.getLevelName(logging.root.getEffectiveLevel())

main(ctx: typer.Context, config_file: Annotated[list[str] | None, typer.Option(help='Specify config file.')] = None, verbose: Annotated[bool | None, typer.Option(help='Verbose mode.', callback=verbose_callback, is_eager=True)] = None, version: Annotated[bool | None, typer.Option(--version, help='Print version and exit.', callback=version_callback, is_eager=True)] = None)

Python CLI Application template: boilerplate project for modern CLI utility

Source code in src/python_cli_app_template/cli/main.py
@app.callback()
def main(
    ctx: typer.Context,
    config_file: Annotated[list[str] | None, typer.Option(help='Specify config file.')] = None,
    verbose: Annotated[
        bool | None, typer.Option(help='Verbose mode.', callback=verbose_callback, is_eager=True)
    ] = None,
    version: Annotated[
        bool | None,
        typer.Option('--version', help='Print version and exit.', callback=version_callback, is_eager=True),
    ] = None,
):
    """Python CLI Application template: boilerplate project for modern CLI utility"""
    logging.root.debug(f'Current {__name__} log level: {get_current_log_level(__name__)}')

    # TODO Remove parameters processed by the callbacks
    logging.root.debug(f'Global arguments: config-file={config_file}, verbose={verbose}, version={version}')

    logging.root.debug(f'Config file: {config_file}')
    for config_file_item in config_file or []:
        logging.root.debug(f'Loading config item: {config_file_item}')
        load_config_file(config_file_item)

verbose_callback(value: bool) -> None

Source code in src/python_cli_app_template/cli/main.py
def verbose_callback(value: bool) -> None:  # noqa: FBT001
    if value is None:
        return
    if value:
        logging.root.setLevel(logging.DEBUG)
        logging.getLogger(__name__).debug('Setting log level to DEBUG')
    else:
        logging.root.setLevel(logging.WARNING)

version_callback(value: bool)

Print version and exit.

Source code in src/python_cli_app_template/cli/main.py
def version_callback(value: bool):  # noqa: FBT001
    """Print version and exit."""
    if value:
        typer.echo(f'Python CLI app template: {__version__}')
        logging.getLogger(__name__).debug('Exiting as --version is expected to do nothing but print version')
        raise typer.Exit()