Skip to content

Utils

provide.foundation.cli.utils

Common CLI utilities for output, logging, and testing.

Classes

CliTestRunner

CliTestRunner()

Test runner for CLI commands using Click's testing facilities.

Source code in provide/foundation/cli/utils.py
def __init__(self) -> None:
    self.runner = CliRunner()
Functions
invoke
invoke(
    cli: Command | Group,
    args: list[str] | None = None,
    input: str | None = None,
    env: dict[str, str] | None = None,
    catch_exceptions: bool = True,
    **kwargs: Any
) -> Result

Invoke a CLI command for testing.

Source code in provide/foundation/cli/utils.py
def invoke(
    self,
    cli: click_types.Command | click_types.Group,
    args: list[str] | None = None,
    input: str | None = None,
    env: dict[str, str] | None = None,
    catch_exceptions: bool = True,
    **kwargs: Any,
) -> Result:
    """Invoke a CLI command for testing."""
    return self.runner.invoke(
        cli,
        args=args,
        input=input,
        env=env,
        catch_exceptions=catch_exceptions,
        **kwargs,
    )
isolated_filesystem
isolated_filesystem() -> object

Context manager for isolated filesystem.

Source code in provide/foundation/cli/utils.py
def isolated_filesystem(self) -> object:
    """Context manager for isolated filesystem."""
    return self.runner.isolated_filesystem()

Functions

assert_cli_error

assert_cli_error(
    result: Result,
    expected_error: str | None = None,
    exit_code: int | None = None,
) -> None

Assert that a CLI command failed.

Source code in provide/foundation/cli/utils.py
def assert_cli_error(
    result: Result,
    expected_error: str | None = None,
    exit_code: int | None = None,
) -> None:
    """Assert that a CLI command failed."""
    if result.exit_code == 0:
        raise AssertionError(f"Command succeeded unexpectedly\nOutput: {result.output}")

    if exit_code is not None and result.exit_code != exit_code:
        raise AssertionError(f"Wrong exit code.\nExpected: {exit_code}\nActual: {result.exit_code}")

    if expected_error and expected_error not in result.output:
        raise AssertionError(f"Expected error not found.\nExpected: {expected_error}\nActual: {result.output}")

assert_cli_success

assert_cli_success(
    result: Result, expected_output: str | None = None
) -> None

Assert that a CLI command succeeded.

Source code in provide/foundation/cli/utils.py
def assert_cli_success(result: Result, expected_output: str | None = None) -> None:
    """Assert that a CLI command succeeded."""
    if result.exit_code != 0:
        raise AssertionError(
            f"Command failed with exit code {result.exit_code}\n"
            f"Output: {result.output}\n"
            f"Exception: {result.exception}",
        )

    if expected_output and expected_output not in result.output:
        raise AssertionError(
            f"Expected output not found.\nExpected: {expected_output}\nActual: {result.output}",
        )

create_cli_context

create_cli_context(**kwargs: Any) -> CLIContext

Create a CLIContext for CLI usage.

Loads from environment, then overlays any provided kwargs.

Parameters:

Name Type Description Default
**kwargs Any

Override values for the context

{}

Returns:

Type Description
CLIContext

Configured CLIContext instance

Source code in provide/foundation/cli/utils.py
def create_cli_context(**kwargs: Any) -> CLIContext:
    """Create a CLIContext for CLI usage.

    Loads from environment, then overlays any provided kwargs.

    Args:
        **kwargs: Override values for the context

    Returns:
        Configured CLIContext instance

    """
    ctx = CLIContext.from_env()
    for key, value in kwargs.items():
        if value is not None and hasattr(ctx, key):
            setattr(ctx, key, value)
    return ctx

echo_error

echo_error(message: str, json_output: bool = False) -> None

Output an error message.

Parameters:

Name Type Description Default
message str

Error message to output

required
json_output bool

Whether to output as JSON

False
Source code in provide/foundation/cli/utils.py
def echo_error(message: str, json_output: bool = False) -> None:
    """Output an error message.

    Args:
        message: Error message to output
        json_output: Whether to output as JSON

    """
    if json_output:
        perr(message, json_key="error")
    else:
        perr(f"✗ {message}", color="red")

echo_info

echo_info(message: str, json_output: bool = False) -> None

Output an informational message.

Parameters:

Name Type Description Default
message str

Info message to output

required
json_output bool

Whether to output as JSON

False
Source code in provide/foundation/cli/utils.py
def echo_info(message: str, json_output: bool = False) -> None:
    """Output an informational message.

    Args:
        message: Info message to output
        json_output: Whether to output as JSON

    """
    if json_output:
        pout(message, json_key="info")
    else:
        pout(f"i {message}")

echo_json

echo_json(data: Any, err: bool = False) -> None

Output data as JSON.

Parameters:

Name Type Description Default
data Any

Data to output as JSON

required
err bool

Whether to output to stderr

False
Source code in provide/foundation/cli/utils.py
def echo_json(data: Any, err: bool = False) -> None:
    """Output data as JSON.

    Args:
        data: Data to output as JSON
        err: Whether to output to stderr

    """
    if err:
        perr(data)
    else:
        pout(data)

echo_success

echo_success(
    message: str, json_output: bool = False
) -> None

Output a success message.

Parameters:

Name Type Description Default
message str

Success message to output

required
json_output bool

Whether to output as JSON

False
Source code in provide/foundation/cli/utils.py
def echo_success(message: str, json_output: bool = False) -> None:
    """Output a success message.

    Args:
        message: Success message to output
        json_output: Whether to output as JSON

    """
    if json_output:
        pout(message, json_key="success")
    else:
        pout(f"✓ {message}", color="green")

echo_warning

echo_warning(
    message: str, json_output: bool = False
) -> None

Output a warning message.

Parameters:

Name Type Description Default
message str

Warning message to output

required
json_output bool

Whether to output as JSON

False
Source code in provide/foundation/cli/utils.py
def echo_warning(message: str, json_output: bool = False) -> None:
    """Output a warning message.

    Args:
        message: Warning message to output
        json_output: Whether to output as JSON

    """
    if json_output:
        perr(message, json_key="warning")
    else:
        perr(f"⚠ {message}", color="yellow")

setup_cli_logging

setup_cli_logging(
    ctx: CLIContext, reinit_logging: bool = True
) -> None

Setup logging for CLI applications using a CLIContext object.

This function is the designated way to configure logging within a CLI application built with foundation. It uses the provided context object to construct a full TelemetryConfig and initializes the system.

Parameters:

Name Type Description Default
ctx CLIContext

The foundation CLIContext, populated by CLI decorators.

required
reinit_logging bool

Whether to force re-initialization of logging (default: True). Set to False when embedding Foundation in a host application to avoid clobbering the host's logging configuration.

True
Source code in provide/foundation/cli/utils.py
def setup_cli_logging(
    ctx: CLIContext,
    reinit_logging: bool = True,
) -> None:
    """Setup logging for CLI applications using a CLIContext object.

    This function is the designated way to configure logging within a CLI
    application built with foundation. It uses the provided context object
    to construct a full TelemetryConfig and initializes the system.

    Args:
        ctx: The foundation CLIContext, populated by CLI decorators.
        reinit_logging: Whether to force re-initialization of logging (default: True).
            Set to False when embedding Foundation in a host application to avoid
            clobbering the host's logging configuration.

    """
    console_formatter = "json" if ctx.json_output else ctx.log_format

    logging_config = LoggingConfig(
        default_level=ctx.log_level,  # type: ignore[arg-type]
        console_formatter=console_formatter,  # type: ignore[arg-type]
        omit_timestamp=False,
        logger_name_emoji_prefix_enabled=not ctx.no_emoji,
        das_emoji_prefix_enabled=not ctx.no_emoji,
        log_file=ctx.log_file,
    )

    telemetry_config = TelemetryConfig(
        service_name=ctx.profile,
        logging=logging_config,
    )

    hub = get_hub()
    hub.initialize_foundation(config=telemetry_config, force=reinit_logging)