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

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

5 

6This module contains the logic for storing a key-value pair in a transient, 

7in-memory data store. The data persists only for the lifetime of the 

8application's parent process. A structured confirmation is emitted upon success. 

9 

10Output Contract: 

11 * Success: `{"status": "updated", "key": str, "value": str}` 

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

13 

14Exit Codes: 

15 * `0`: Success. 

16 * `1`: An unexpected error occurred (e.g., service unavailable, set failed). 

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

18""" 

19 

20from __future__ import annotations 

21 

22import platform 

23 

24import typer 

25 

26from bijux_cli.cli.commands.memory.resolve import resolve_memory_service 

27from bijux_cli.cli.core.command import ( 

28 ascii_safe, 

29 new_run_command, 

30 raise_exit_intent, 

31 validate_common_flags, 

32) 

33from bijux_cli.cli.core.constants import ( 

34 OPT_FORMAT, 

35 OPT_LOG_LEVEL, 

36 OPT_PRETTY, 

37 OPT_QUIET, 

38) 

39from bijux_cli.cli.core.help_text import ( 

40 HELP_FORMAT, 

41 HELP_LOG_LEVEL, 

42 HELP_NO_PRETTY, 

43 HELP_QUIET, 

44) 

45from bijux_cli.core.enums import ErrorType 

46from bijux_cli.core.precedence import current_execution_policy 

47 

48 

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

50 """Constructs the payload confirming a key-value pair was set. 

51 

52 Args: 

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

54 key (str): The key that was updated. 

55 value (str): The new value assigned to the key. 

56 

57 Returns: 

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

59 and optional runtime metadata. 

60 """ 

61 payload: dict[str, object] = {"status": "updated", "key": key, "value": value} 

62 if include_runtime: 

63 return { 

64 "status": payload["status"], 

65 "key": key, 

66 "value": value, 

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

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

69 } 

70 return payload 

71 

72 

73def set_memory( 

74 key: str = typer.Argument(..., help="Key to set"), 

75 value: str = typer.Argument(..., help="Value to set"), 

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

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

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

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

80) -> None: 

81 """Sets a key-value pair in the transient in-memory store. 

82 

83 This command validates the key's format and then stores the key-value 

84 pair using the memory service. 

85 

86 Args: 

87 key (str): The memory key to set. Must be between 1 and 4096 printable, 

88 non-whitespace characters. 

89 value (str): The value to associate with the key. 

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

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

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

93 

94 Returns: 

95 None: 

96 

97 Raises: 

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

99 payload, indicating success or detailing an error. 

100 """ 

101 command = "memory set" 

102 policy = current_execution_policy() 

103 quiet = policy.quiet 

104 include_runtime = policy.include_runtime 

105 pretty = policy.pretty 

106 log_level_value = policy.log_level 

107 fmt_lower = validate_common_flags( 

108 fmt, 

109 command, 

110 quiet, 

111 include_runtime=include_runtime, 

112 log_level=log_level_value, 

113 ) 

114 

115 if not ( 

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

117 ): 

118 raise_exit_intent( 

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

120 code=2, 

121 failure="invalid_key", 

122 error_type=ErrorType.USER_INPUT, 

123 command=command, 

124 fmt=fmt_lower, 

125 quiet=quiet, 

126 include_runtime=include_runtime, 

127 log_level=log_level_value, 

128 ) 

129 

130 memory_svc = resolve_memory_service( 

131 command, fmt_lower, quiet, include_runtime, log_level_value 

132 ) 

133 

134 try: 

135 memory_svc.set(key, value) 

136 except Exception as exc: 

137 raise_exit_intent( 

138 f"Failed to set memory: {exc}", 

139 code=1, 

140 failure="set_failed", 

141 error_type=ErrorType.INTERNAL, 

142 command=command, 

143 fmt=fmt_lower, 

144 quiet=quiet, 

145 include_runtime=include_runtime, 

146 log_level=log_level_value, 

147 ) 

148 

149 new_run_command( 

150 command_name=command, 

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

152 quiet=quiet, 

153 fmt=fmt_lower, 

154 pretty=pretty, 

155 log_level=log_level, 

156 )