Coverage for  / home / runner / work / bijux-cli / bijux-cli / src / bijux_cli / cli / commands / config / get.py: 100%

34 statements  

« 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 

3 

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

5 

6This module contains the logic for retrieving the value of a specific key 

7from the active configuration store. It provides a structured, machine-readable 

8response containing the value or an error if the key is not found. 

9 

10Output Contract: 

11 * Success: `{"value": str}` 

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

13 

14Exit Codes: 

15 * `0`: Success. 

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

17 * `2`: The specified key was not found in the configuration. 

18""" 

19 

20from __future__ import annotations 

21 

22import platform 

23 

24import typer 

25 

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.errors import ConfigError 

46from bijux_cli.core.exit_policy import ExitIntentError 

47from bijux_cli.core.precedence import current_execution_policy, resolve_exit_intent 

48from bijux_cli.services.config.contracts import ConfigProtocol 

49 

50 

51def get_config( 

52 ctx: typer.Context, 

53 key: str = typer.Argument(..., help="Configuration key to look up"), 

54 quiet: bool = typer.Option(False, *OPT_QUIET, help=HELP_QUIET), 

55 fmt: str = typer.Option("json", *OPT_FORMAT, help=HELP_FORMAT), 

56 pretty: bool = typer.Option(True, OPT_PRETTY, help=HELP_NO_PRETTY), 

57 log_level: str = typer.Option("info", *OPT_LOG_LEVEL, help=HELP_LOG_LEVEL), 

58) -> None: 

59 """Retrieves the value for a given configuration key. 

60 

61 This function fetches the value for the specified key from the configuration 

62 service and uses the `new_run_command` helper to emit it in a structured 

63 payload. It handles errors, such as the key not being found. 

64 

65 Args: 

66 ctx (typer.Context): The Typer context for the CLI. 

67 key (str): The configuration key whose value should be retrieved. 

68 quiet (bool): If True, suppresses all output except for errors. 

69 fmt (str): The output format, "json" or "yaml". 

70 pretty (bool): If True, pretty-prints the output. log_level (str): Logging level for diagnostics. 

71 

72 Returns: 

73 None: 

74 

75 Raises: 

76 SystemExit: Always exits with a contract-compliant status code and 

77 payload, indicating success or detailing the error. 

78 """ 

79 command = "config get" 

80 effective = current_execution_policy() 

81 fmt_lower = validate_common_flags( 

82 fmt, 

83 command, 

84 effective.quiet, 

85 include_runtime=effective.include_runtime, 

86 log_level=effective.log_level, 

87 ) 

88 quiet = effective.quiet 

89 include_runtime = effective.include_runtime 

90 pretty = effective.pretty 

91 

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

93 

94 try: 

95 value = config_svc.get(key) 

96 except ConfigError as exc: 

97 if str(exc).startswith("Config key not found"): 

98 intent = resolve_exit_intent( 

99 message=f"Config key not found: {key}", 

100 code=2, 

101 failure="not_found", 

102 command=command, 

103 fmt=fmt_lower, 

104 quiet=quiet, 

105 include_runtime=include_runtime, 

106 error_type=ErrorType.USER_INPUT, 

107 log_level=effective.log_level, 

108 extra={"key": key}, 

109 ) 

110 raise ExitIntentError(intent) from exc 

111 intent = resolve_exit_intent( 

112 message=f"Failed to get config: {exc}", 

113 code=1, 

114 failure="get_failed", 

115 command=command, 

116 fmt=fmt_lower, 

117 quiet=quiet, 

118 include_runtime=include_runtime, 

119 error_type=ErrorType.INTERNAL, 

120 log_level=effective.log_level, 

121 ) 

122 raise ExitIntentError(intent) from exc 

123 

124 def payload_builder(include_runtime: bool) -> dict[str, object]: 

125 """Builds a payload containing the retrieved configuration value. 

126 

127 Args: 

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

129 

130 Returns: 

131 dict[str, object]: A dictionary containing the key's value and 

132 optional runtime metadata. 

133 """ 

134 payload: dict[str, object] = {"value": value} 

135 if include_runtime: 

136 payload.update( 

137 { 

138 "python": ascii_safe(platform.python_version(), "python_version"), 

139 "platform": ascii_safe(platform.platform(), "platform"), 

140 } 

141 ) 

142 return payload 

143 

144 new_run_command( 

145 command_name=command, 

146 payload_builder=payload_builder, 

147 quiet=quiet, 

148 fmt=fmt_lower, 

149 pretty=pretty, 

150 log_level=log_level, 

151 )