Coverage for /home/runner/work/bijux-cli/bijux-cli/src/bijux_cli/commands/config/list_cmd.py: 100%
30 statements
« prev ^ index » next coverage.py v7.10.4, created at 2025-08-19 23:36 +0000
« prev ^ index » next coverage.py v7.10.4, created at 2025-08-19 23:36 +0000
1# SPDX-License-Identifier: MIT
2# Copyright © 2025 Bijan Mousavi
4"""Implements the `config list` subcommand for the Bijux CLI.
6This module contains the logic for listing all keys currently defined in the
7active configuration store. It retrieves the keys and presents them in a
8structured, machine-readable list format.
10Output Contract:
11 * Success: `{"items": [{"key": str}, ...]}`
12 * Verbose: Adds `{"python": str, "platform": str}` to the payload.
13 * Error: `{"error": str, "code": int}`
15Exit Codes:
16 * `0`: Success.
17 * `1`: An unexpected error occurred while accessing the configuration.
18"""
20from __future__ import annotations
22from collections.abc import Mapping
23import platform
25import typer
27from bijux_cli.commands.utilities import (
28 ascii_safe,
29 emit_error_and_exit,
30 new_run_command,
31 parse_global_flags,
32)
33from bijux_cli.contracts import ConfigProtocol
34from bijux_cli.core.constants import (
35 HELP_DEBUG,
36 HELP_FORMAT,
37 HELP_NO_PRETTY,
38 HELP_QUIET,
39 HELP_VERBOSE,
40)
41from bijux_cli.core.di import DIContainer
44def list_config(
45 ctx: typer.Context,
46 quiet: bool = typer.Option(False, "-q", "--quiet", help=HELP_QUIET),
47 verbose: bool = typer.Option(False, "-v", "--verbose", help=HELP_VERBOSE),
48 fmt: str = typer.Option("json", "-f", "--format", help=HELP_FORMAT),
49 pretty: bool = typer.Option(True, "--pretty/--no-pretty", help=HELP_NO_PRETTY),
50 debug: bool = typer.Option(False, "-d", "--debug", help=HELP_DEBUG),
51) -> None:
52 """Lists all configuration keys from the active configuration store.
54 This function retrieves all defined keys, sorts them, and then uses the
55 `new_run_command` helper to emit them in a structured payload.
57 Args:
58 ctx (typer.Context): The Typer context for the CLI.
59 quiet (bool): If True, suppresses all output except for errors.
60 verbose (bool): If True, includes Python/platform details in the output.
61 fmt (str): The output format, "json" or "yaml".
62 pretty (bool): If True, pretty-prints the output.
63 debug (bool): If True, enables debug diagnostics.
65 Returns:
66 None:
68 Raises:
69 SystemExit: Always exits with a contract-compliant status code and
70 payload, indicating success or detailing the error.
71 """
72 flags = parse_global_flags()
74 quiet = flags["quiet"]
75 verbose = flags["verbose"]
76 fmt = flags["format"]
77 pretty = flags["pretty"]
78 debug = flags["debug"]
80 include_runtime = verbose
81 fmt_lower = fmt.lower()
83 command = "config list"
85 config_svc = DIContainer.current().resolve(ConfigProtocol)
87 try:
88 keys = config_svc.list_keys()
89 except Exception as exc:
90 emit_error_and_exit(
91 f"Failed to list config: {exc}",
92 code=1,
93 failure="list_failed",
94 command=command,
95 fmt=fmt_lower,
96 quiet=quiet,
97 include_runtime=include_runtime,
98 debug=debug,
99 )
101 def payload_builder(include_runtime: bool) -> Mapping[str, object]:
102 """Builds a payload containing the list of configuration keys.
104 Args:
105 include_runtime (bool): If True, includes Python and platform info.
107 Returns:
108 Mapping[str, object]: A dictionary containing a sorted list of
109 keys under an "items" field, plus optional runtime metadata.
110 """
111 payload: dict[str, object] = {
112 "items": [{"key": k} for k in sorted(keys, key=str.lower)]
113 }
114 if include_runtime:
115 payload["python"] = ascii_safe(platform.python_version(), "python_version")
116 payload["platform"] = ascii_safe(platform.platform(), "platform")
117 return payload
119 new_run_command(
120 command_name=command,
121 payload_builder=payload_builder,
122 quiet=quiet,
123 verbose=verbose,
124 fmt=fmt_lower,
125 pretty=pretty,
126 debug=debug,
127 )