Coverage for / home / runner / work / bijux-cli / bijux-cli / src / bijux_cli / cli / commands / config / load.py: 100%
30 statements
« prev ^ index » next coverage.py v7.13.2, created at 2026-01-26 17:59 +0000
« prev ^ index » next coverage.py v7.13.2, created at 2026-01-26 17:59 +0000
1# SPDX-License-Identifier: Apache-2.0
2# Copyright © 2025 Bijan Mousavi
4"""Implements the `config load` subcommand for the Bijux CLI.
6This module contains the logic for replacing the application's entire
7configuration with the contents of a specified file. It discards any
8in-memory settings and loads the new configuration, emitting a structured
9confirmation upon success.
11Output Contract:
12 * Success: `{"status": "loaded", "file": str}`
13 * Error: `{"error": str, "code": int}`
15Exit Codes:
16 * `0`: Success.
17 * `2`: The specified file could not be found, read, or parsed.
18"""
20from __future__ import annotations
22import platform
24import typer
26from bijux_cli.cli.core.command import (
27 ascii_safe,
28 new_run_command,
29 validate_common_flags,
30)
31from bijux_cli.cli.core.constants import (
32 OPT_FORMAT,
33 OPT_LOG_LEVEL,
34 OPT_PRETTY,
35 OPT_QUIET,
36)
37from bijux_cli.cli.core.help_text import (
38 HELP_FORMAT,
39 HELP_LOG_LEVEL,
40 HELP_NO_PRETTY,
41 HELP_QUIET,
42)
43from bijux_cli.core.di import DIContainer
44from bijux_cli.core.enums import ErrorType
45from bijux_cli.core.exit_policy import ExitIntentError
46from bijux_cli.core.precedence import current_execution_policy, resolve_exit_intent
47from bijux_cli.services.config.contracts import ConfigProtocol
50def load_config(
51 ctx: typer.Context,
52 path: str = typer.Argument(..., help="Path to load from"),
53 quiet: bool = typer.Option(False, *OPT_QUIET, help=HELP_QUIET),
54 fmt: str = typer.Option("json", *OPT_FORMAT, help=HELP_FORMAT),
55 pretty: bool = typer.Option(True, OPT_PRETTY, help=HELP_NO_PRETTY),
56 log_level: str = typer.Option("info", *OPT_LOG_LEVEL, help=HELP_LOG_LEVEL),
57) -> None:
58 """Loads configuration from a specified file.
60 This function replaces the current in-memory configuration with the
61 contents of the file at the given path. It provides a structured payload
62 to confirm the operation was successful.
64 Args:
65 ctx (typer.Context): The Typer context for the CLI.
66 path (str): The path to the configuration file to load.
67 quiet (bool): If True, suppresses all output except for errors.
68 fmt (str): The output format, "json" or "yaml".
69 pretty (bool): If True, pretty-prints the output. log_level (str): Logging level for diagnostics.
71 Returns:
72 None:
74 Raises:
75 SystemExit: Always exits with a contract-compliant status code and
76 payload, indicating success or detailing the error.
77 """
78 command = "config load"
79 effective = current_execution_policy()
80 fmt_lower = validate_common_flags(
81 fmt,
82 command,
83 effective.quiet,
84 include_runtime=effective.include_runtime,
85 log_level=effective.log_level,
86 )
87 quiet = effective.quiet
88 include_runtime = effective.include_runtime
89 pretty = effective.pretty
91 config_svc = DIContainer.current().resolve(ConfigProtocol)
93 try:
94 config_svc.load(path)
95 except Exception as exc:
96 intent = resolve_exit_intent(
97 message=f"Failed to load config: {exc}",
98 code=2,
99 failure="load_failed",
100 command=command,
101 fmt=fmt_lower,
102 quiet=quiet,
103 include_runtime=include_runtime,
104 error_type=ErrorType.USER_INPUT,
105 log_level=effective.log_level,
106 extra={"path": path},
107 )
108 raise ExitIntentError(intent) from exc
110 def payload_builder(include_runtime: bool) -> dict[str, object]:
111 """Builds the payload confirming a successful configuration load.
113 Args:
114 include_runtime (bool): If True, includes Python and platform info.
116 Returns:
117 dict[str, object]: The structured payload.
118 """
119 payload: dict[str, object] = {"status": "loaded", "file": path}
120 if include_runtime:
121 payload.update(
122 {
123 "python": ascii_safe(platform.python_version(), "python_version"),
124 "platform": ascii_safe(platform.platform(), "platform"),
125 }
126 )
127 return payload
129 new_run_command(
130 command_name=command,
131 payload_builder=payload_builder,
132 quiet=quiet,
133 fmt=fmt_lower,
134 pretty=pretty,
135 log_level=log_level,
136 )