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

26 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 `memory get` subcommand for the Bijux CLI. 

5 

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

7from the transient, in-memory data store. It provides a structured, 

8machine-readable response containing the value or an error if the key is 

9not found. 

10 

11Output Contract: 

12 * Success: `{"status": "ok", "key": str, "value": str}` 

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

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

15 

16Exit Codes: 

17 * `0`: Success. 

18 * `1`: The key was not found, or another unexpected error occurred. 

19 * `2`: The provided key was invalid. 

20""" 

21 

22from __future__ import annotations 

23 

24from collections.abc import Mapping 

25import platform 

26 

27import typer 

28 

29from bijux_cli.commands.memory.utils import resolve_memory_service 

30from bijux_cli.commands.utilities import ( 

31 ascii_safe, 

32 emit_error_and_exit, 

33 new_run_command, 

34 validate_common_flags, 

35) 

36from bijux_cli.core.constants import ( 

37 HELP_DEBUG, 

38 HELP_FORMAT, 

39 HELP_NO_PRETTY, 

40 HELP_QUIET, 

41 HELP_VERBOSE, 

42) 

43 

44 

45def _build_payload(include_runtime: bool, key: str, value: str) -> Mapping[str, object]: 

46 """Builds the payload for a single memory key-value response. 

47 

48 Args: 

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

50 key (str): The memory key that was retrieved. 

51 value (str): The value associated with the key. 

52 

53 Returns: 

54 Mapping[str, object]: A dictionary containing the status, key, value, 

55 and optional runtime metadata. 

56 """ 

57 payload: dict[str, object] = {"status": "ok", "key": key, "value": value} 

58 if include_runtime: 

59 payload["python"] = ascii_safe(platform.python_version(), "python_version") 

60 payload["platform"] = ascii_safe(platform.platform(), "platform") 

61 return payload 

62 

63 

64def get_memory( 

65 key: str = typer.Argument(..., help="Key to retrieve"), 

66 quiet: bool = typer.Option(False, "-q", "--quiet", help=HELP_QUIET), 

67 verbose: bool = typer.Option(False, "-v", "--verbose", help=HELP_VERBOSE), 

68 fmt: str = typer.Option("json", "-f", "--format", help=HELP_FORMAT), 

69 pretty: bool = typer.Option(True, "--pretty/--no-pretty", help=HELP_NO_PRETTY), 

70 debug: bool = typer.Option(False, "-d", "--debug", help=HELP_DEBUG), 

71) -> None: 

72 """Retrieves a value by key from the transient in-memory store. 

73 

74 This command validates the key's format and then fetches the corresponding 

75 value from the memory service. 

76 

77 Args: 

78 key (str): The memory key to look up. Must be between 1 and 4096 

79 printable, non-whitespace characters. 

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

81 verbose (bool): If True, includes Python/platform details in the output. 

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

83 pretty (bool): If True, pretty-prints the output. 

84 debug (bool): If True, enables debug diagnostics. 

85 

86 Returns: 

87 None: 

88 

89 Raises: 

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

91 payload, indicating success or detailing an error. 

92 """ 

93 command = "memory get" 

94 

95 fmt_lower = validate_common_flags(fmt, command, quiet) 

96 

97 if not ( 

98 1 <= len(key) <= 4096 and all(c.isprintable() and not c.isspace() for c in key) 

99 ): 

100 emit_error_and_exit( 

101 "Invalid key: must be 1-4096 printable non-space characters", 

102 code=2, 

103 failure="invalid_key", 

104 command=command, 

105 fmt=fmt_lower, 

106 quiet=quiet, 

107 include_runtime=verbose, 

108 debug=debug, 

109 ) 

110 

111 memory_svc = resolve_memory_service(command, fmt_lower, quiet, verbose, debug) 

112 

113 try: 

114 value = memory_svc.get(key) 

115 except KeyError: 

116 emit_error_and_exit( 

117 f"Key not found: {key}", 

118 code=1, 

119 failure="not_found", 

120 command=command, 

121 fmt=fmt_lower, 

122 quiet=quiet, 

123 include_runtime=verbose, 

124 debug=debug, 

125 ) 

126 except Exception as exc: 

127 emit_error_and_exit( 

128 f"Failed to get memory: {exc}", 

129 code=1, 

130 failure="get_failed", 

131 command=command, 

132 fmt=fmt_lower, 

133 quiet=quiet, 

134 include_runtime=verbose, 

135 debug=debug, 

136 ) 

137 

138 new_run_command( 

139 command_name=command, 

140 payload_builder=lambda include: _build_payload(include, key, value), 

141 quiet=quiet, 

142 verbose=verbose, 

143 fmt=fmt_lower, 

144 pretty=pretty, 

145 debug=debug, 

146 )