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

1# SPDX-License-Identifier: MIT 

2# Copyright © 2025 Bijan Mousavi 

3 

4"""Implements the `config list` subcommand for the Bijux CLI. 

5 

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. 

9 

10Output Contract: 

11 * Success: `{"items": [{"key": str}, ...]}` 

12 * Verbose: Adds `{"python": str, "platform": str}` to the payload. 

13 * Error: `{"error": str, "code": int}` 

14 

15Exit Codes: 

16 * `0`: Success. 

17 * `1`: An unexpected error occurred while accessing the configuration. 

18""" 

19 

20from __future__ import annotations 

21 

22from collections.abc import Mapping 

23import platform 

24 

25import typer 

26 

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 

42 

43 

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. 

53 

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. 

56 

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. 

64 

65 Returns: 

66 None: 

67 

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() 

73 

74 quiet = flags["quiet"] 

75 verbose = flags["verbose"] 

76 fmt = flags["format"] 

77 pretty = flags["pretty"] 

78 debug = flags["debug"] 

79 

80 include_runtime = verbose 

81 fmt_lower = fmt.lower() 

82 

83 command = "config list" 

84 

85 config_svc = DIContainer.current().resolve(ConfigProtocol) 

86 

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 ) 

100 

101 def payload_builder(include_runtime: bool) -> Mapping[str, object]: 

102 """Builds a payload containing the list of configuration keys. 

103 

104 Args: 

105 include_runtime (bool): If True, includes Python and platform info. 

106 

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 

118 

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 )