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
« 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 `memory get` subcommand for the Bijux CLI.
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.
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}`
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"""
22from __future__ import annotations
24from collections.abc import Mapping
25import platform
27import typer
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)
45def _build_payload(include_runtime: bool, key: str, value: str) -> Mapping[str, object]:
46 """Builds the payload for a single memory key-value response.
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.
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
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.
74 This command validates the key's format and then fetches the corresponding
75 value from the memory service.
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.
86 Returns:
87 None:
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"
95 fmt_lower = validate_common_flags(fmt, command, quiet)
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 )
111 memory_svc = resolve_memory_service(command, fmt_lower, quiet, verbose, debug)
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 )
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 )