bijux-cli 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bijux_cli/__init__.py +39 -0
- bijux_cli/__main__.py +417 -0
- bijux_cli/__version__.py +42 -0
- bijux_cli/api.py +326 -0
- bijux_cli/cli.py +68 -0
- bijux_cli/commands/__init__.py +170 -0
- bijux_cli/commands/audit.py +293 -0
- bijux_cli/commands/config/__init__.py +85 -0
- bijux_cli/commands/config/clear.py +124 -0
- bijux_cli/commands/config/export.py +148 -0
- bijux_cli/commands/config/get.py +141 -0
- bijux_cli/commands/config/list_cmd.py +127 -0
- bijux_cli/commands/config/load.py +128 -0
- bijux_cli/commands/config/py.typed +0 -0
- bijux_cli/commands/config/reload.py +125 -0
- bijux_cli/commands/config/service.py +107 -0
- bijux_cli/commands/config/set.py +260 -0
- bijux_cli/commands/config/unset.py +140 -0
- bijux_cli/commands/dev/__init__.py +46 -0
- bijux_cli/commands/dev/di.py +285 -0
- bijux_cli/commands/dev/list_plugins.py +66 -0
- bijux_cli/commands/dev/py.typed +0 -0
- bijux_cli/commands/dev/service.py +120 -0
- bijux_cli/commands/docs.py +329 -0
- bijux_cli/commands/doctor.py +181 -0
- bijux_cli/commands/help.py +436 -0
- bijux_cli/commands/history/__init__.py +43 -0
- bijux_cli/commands/history/clear.py +160 -0
- bijux_cli/commands/history/py.typed +0 -0
- bijux_cli/commands/history/service.py +362 -0
- bijux_cli/commands/memory/__init__.py +59 -0
- bijux_cli/commands/memory/clear.py +114 -0
- bijux_cli/commands/memory/delete.py +144 -0
- bijux_cli/commands/memory/get.py +146 -0
- bijux_cli/commands/memory/list.py +115 -0
- bijux_cli/commands/memory/py.typed +0 -0
- bijux_cli/commands/memory/service.py +242 -0
- bijux_cli/commands/memory/set.py +136 -0
- bijux_cli/commands/memory/utils.py +54 -0
- bijux_cli/commands/plugins/__init__.py +59 -0
- bijux_cli/commands/plugins/check.py +240 -0
- bijux_cli/commands/plugins/info.py +143 -0
- bijux_cli/commands/plugins/install.py +327 -0
- bijux_cli/commands/plugins/list.py +73 -0
- bijux_cli/commands/plugins/py.typed +0 -0
- bijux_cli/commands/plugins/scaffold.py +287 -0
- bijux_cli/commands/plugins/uninstall.py +206 -0
- bijux_cli/commands/plugins/utils.py +158 -0
- bijux_cli/commands/py.typed +0 -0
- bijux_cli/commands/repl.py +709 -0
- bijux_cli/commands/sleep.py +169 -0
- bijux_cli/commands/status.py +289 -0
- bijux_cli/commands/utilities.py +637 -0
- bijux_cli/commands/version.py +152 -0
- bijux_cli/contracts/__init__.py +48 -0
- bijux_cli/contracts/audit.py +66 -0
- bijux_cli/contracts/config.py +127 -0
- bijux_cli/contracts/context.py +93 -0
- bijux_cli/contracts/docs.py +65 -0
- bijux_cli/contracts/doctor.py +32 -0
- bijux_cli/contracts/emitter.py +58 -0
- bijux_cli/contracts/history.py +101 -0
- bijux_cli/contracts/memory.py +76 -0
- bijux_cli/contracts/observability.py +94 -0
- bijux_cli/contracts/process.py +48 -0
- bijux_cli/contracts/py.typed +0 -0
- bijux_cli/contracts/registry.py +115 -0
- bijux_cli/contracts/retry.py +53 -0
- bijux_cli/contracts/serializer.py +100 -0
- bijux_cli/contracts/telemetry.py +46 -0
- bijux_cli/core/__init__.py +44 -0
- bijux_cli/core/constants.py +21 -0
- bijux_cli/core/context.py +218 -0
- bijux_cli/core/di.py +695 -0
- bijux_cli/core/engine.py +199 -0
- bijux_cli/core/enums.py +52 -0
- bijux_cli/core/exceptions.py +184 -0
- bijux_cli/core/paths.py +21 -0
- bijux_cli/core/py.typed +0 -0
- bijux_cli/httpapi.py +552 -0
- bijux_cli/infra/__init__.py +43 -0
- bijux_cli/infra/emitter.py +140 -0
- bijux_cli/infra/observability.py +148 -0
- bijux_cli/infra/process.py +177 -0
- bijux_cli/infra/py.typed +0 -0
- bijux_cli/infra/retry.py +300 -0
- bijux_cli/infra/serializer.py +573 -0
- bijux_cli/infra/telemetry.py +159 -0
- bijux_cli/py.typed +0 -0
- bijux_cli/services/__init__.py +233 -0
- bijux_cli/services/audit.py +268 -0
- bijux_cli/services/config.py +677 -0
- bijux_cli/services/docs.py +170 -0
- bijux_cli/services/doctor.py +34 -0
- bijux_cli/services/history.py +527 -0
- bijux_cli/services/memory.py +129 -0
- bijux_cli/services/plugins/__init__.py +346 -0
- bijux_cli/services/plugins/entrypoints.py +151 -0
- bijux_cli/services/plugins/groups.py +177 -0
- bijux_cli/services/plugins/hooks.py +113 -0
- bijux_cli/services/plugins/py.typed +0 -0
- bijux_cli/services/plugins/registry.py +284 -0
- bijux_cli/services/py.typed +0 -0
- bijux_cli/services/utils.py +68 -0
- bijux_cli-0.1.0.dist-info/METADATA +297 -0
- bijux_cli-0.1.0.dist-info/RECORD +108 -0
- bijux_cli-0.1.0.dist-info/WHEEL +4 -0
- bijux_cli-0.1.0.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright © 2025 Bijan Mousavi
|
|
3
|
+
|
|
4
|
+
"""Implements the `config get` subcommand for the Bijux CLI.
|
|
5
|
+
|
|
6
|
+
This module contains the logic for retrieving the value of a specific key
|
|
7
|
+
from the active configuration store. It provides a structured, machine-readable
|
|
8
|
+
response containing the value or an error if the key is not found.
|
|
9
|
+
|
|
10
|
+
Output Contract:
|
|
11
|
+
* Success: `{"value": str}`
|
|
12
|
+
* Verbose: Adds `{"python": str, "platform": str}` to the payload.
|
|
13
|
+
* Error: `{"error": str, "code": int}`
|
|
14
|
+
|
|
15
|
+
Exit Codes:
|
|
16
|
+
* `0`: Success.
|
|
17
|
+
* `1`: An unexpected error occurred while accessing the configuration.
|
|
18
|
+
* `2`: The specified key was not found in the configuration.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import platform
|
|
24
|
+
|
|
25
|
+
import typer
|
|
26
|
+
|
|
27
|
+
from bijux_cli.commands.utilities import (
|
|
28
|
+
ascii_safe,
|
|
29
|
+
emit_error_and_exit,
|
|
30
|
+
new_run_command,
|
|
31
|
+
parse_global_flags,
|
|
32
|
+
)
|
|
33
|
+
from bijux_cli.contracts import ConfigProtocol
|
|
34
|
+
from bijux_cli.core.constants import (
|
|
35
|
+
HELP_DEBUG,
|
|
36
|
+
HELP_FORMAT,
|
|
37
|
+
HELP_NO_PRETTY,
|
|
38
|
+
HELP_QUIET,
|
|
39
|
+
HELP_VERBOSE,
|
|
40
|
+
)
|
|
41
|
+
from bijux_cli.core.di import DIContainer
|
|
42
|
+
from bijux_cli.core.exceptions import CommandError
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def get_config(
|
|
46
|
+
ctx: typer.Context,
|
|
47
|
+
key: str = typer.Argument(..., help="Configuration key to look up"),
|
|
48
|
+
quiet: bool = typer.Option(False, "-q", "--quiet", help=HELP_QUIET),
|
|
49
|
+
verbose: bool = typer.Option(False, "-v", "--verbose", help=HELP_VERBOSE),
|
|
50
|
+
fmt: str = typer.Option("json", "-f", "--format", help=HELP_FORMAT),
|
|
51
|
+
pretty: bool = typer.Option(True, "--pretty/--no-pretty", help=HELP_NO_PRETTY),
|
|
52
|
+
debug: bool = typer.Option(False, "-d", "--debug", help=HELP_DEBUG),
|
|
53
|
+
) -> None:
|
|
54
|
+
"""Retrieves the value for a given configuration key.
|
|
55
|
+
|
|
56
|
+
This function fetches the value for the specified key from the configuration
|
|
57
|
+
service and uses the `new_run_command` helper to emit it in a structured
|
|
58
|
+
payload. It handles errors, such as the key not being found.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
ctx (typer.Context): The Typer context for the CLI.
|
|
62
|
+
key (str): The configuration key whose value should be retrieved.
|
|
63
|
+
quiet (bool): If True, suppresses all output except for errors.
|
|
64
|
+
verbose (bool): If True, includes Python/platform details in the output.
|
|
65
|
+
fmt (str): The output format, "json" or "yaml".
|
|
66
|
+
pretty (bool): If True, pretty-prints the output.
|
|
67
|
+
debug (bool): If True, enables debug diagnostics.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
None:
|
|
71
|
+
|
|
72
|
+
Raises:
|
|
73
|
+
SystemExit: Always exits with a contract-compliant status code and
|
|
74
|
+
payload, indicating success or detailing the error.
|
|
75
|
+
"""
|
|
76
|
+
flags = parse_global_flags()
|
|
77
|
+
|
|
78
|
+
quiet = flags["quiet"]
|
|
79
|
+
verbose = flags["verbose"]
|
|
80
|
+
fmt = flags["format"]
|
|
81
|
+
pretty = flags["pretty"]
|
|
82
|
+
debug = flags["debug"]
|
|
83
|
+
|
|
84
|
+
include_runtime = verbose
|
|
85
|
+
fmt_lower = fmt.lower()
|
|
86
|
+
|
|
87
|
+
command = "config get"
|
|
88
|
+
|
|
89
|
+
config_svc = DIContainer.current().resolve(ConfigProtocol)
|
|
90
|
+
|
|
91
|
+
try:
|
|
92
|
+
value = config_svc.get(key)
|
|
93
|
+
except CommandError as exc:
|
|
94
|
+
if str(exc).startswith("Config key not found"):
|
|
95
|
+
emit_error_and_exit(
|
|
96
|
+
f"Config key not found: {key}",
|
|
97
|
+
code=2,
|
|
98
|
+
failure="not_found",
|
|
99
|
+
command=command,
|
|
100
|
+
fmt=fmt_lower,
|
|
101
|
+
quiet=quiet,
|
|
102
|
+
include_runtime=include_runtime,
|
|
103
|
+
debug=debug,
|
|
104
|
+
extra={"key": key},
|
|
105
|
+
)
|
|
106
|
+
emit_error_and_exit(
|
|
107
|
+
f"Failed to get config: {exc}",
|
|
108
|
+
code=1,
|
|
109
|
+
failure="get_failed",
|
|
110
|
+
command=command,
|
|
111
|
+
fmt=fmt_lower,
|
|
112
|
+
quiet=quiet,
|
|
113
|
+
include_runtime=include_runtime,
|
|
114
|
+
debug=debug,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
def payload_builder(include_runtime: bool) -> dict[str, object]:
|
|
118
|
+
"""Builds a payload containing the retrieved configuration value.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
include_runtime (bool): If True, includes Python and platform info.
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
dict[str, object]: A dictionary containing the key's value and
|
|
125
|
+
optional runtime metadata.
|
|
126
|
+
"""
|
|
127
|
+
payload: dict[str, object] = {"value": value}
|
|
128
|
+
if include_runtime:
|
|
129
|
+
payload["python"] = ascii_safe(platform.python_version(), "python_version")
|
|
130
|
+
payload["platform"] = ascii_safe(platform.platform(), "platform")
|
|
131
|
+
return payload
|
|
132
|
+
|
|
133
|
+
new_run_command(
|
|
134
|
+
command_name=command,
|
|
135
|
+
payload_builder=payload_builder,
|
|
136
|
+
quiet=quiet,
|
|
137
|
+
verbose=verbose,
|
|
138
|
+
fmt=fmt_lower,
|
|
139
|
+
pretty=pretty,
|
|
140
|
+
debug=debug,
|
|
141
|
+
)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright © 2025 Bijan Mousavi
|
|
3
|
+
|
|
4
|
+
"""Implements the `config list` subcommand for the Bijux CLI.
|
|
5
|
+
|
|
6
|
+
This module contains the logic for listing all keys currently defined in the
|
|
7
|
+
active configuration store. It retrieves the keys and presents them in a
|
|
8
|
+
structured, machine-readable list format.
|
|
9
|
+
|
|
10
|
+
Output Contract:
|
|
11
|
+
* Success: `{"items": [{"key": str}, ...]}`
|
|
12
|
+
* Verbose: Adds `{"python": str, "platform": str}` to the payload.
|
|
13
|
+
* Error: `{"error": str, "code": int}`
|
|
14
|
+
|
|
15
|
+
Exit Codes:
|
|
16
|
+
* `0`: Success.
|
|
17
|
+
* `1`: An unexpected error occurred while accessing the configuration.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
from collections.abc import Mapping
|
|
23
|
+
import platform
|
|
24
|
+
|
|
25
|
+
import typer
|
|
26
|
+
|
|
27
|
+
from bijux_cli.commands.utilities import (
|
|
28
|
+
ascii_safe,
|
|
29
|
+
emit_error_and_exit,
|
|
30
|
+
new_run_command,
|
|
31
|
+
parse_global_flags,
|
|
32
|
+
)
|
|
33
|
+
from bijux_cli.contracts import ConfigProtocol
|
|
34
|
+
from bijux_cli.core.constants import (
|
|
35
|
+
HELP_DEBUG,
|
|
36
|
+
HELP_FORMAT,
|
|
37
|
+
HELP_NO_PRETTY,
|
|
38
|
+
HELP_QUIET,
|
|
39
|
+
HELP_VERBOSE,
|
|
40
|
+
)
|
|
41
|
+
from bijux_cli.core.di import DIContainer
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def 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
|
+
)
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright © 2025 Bijan Mousavi
|
|
3
|
+
|
|
4
|
+
"""Implements the `config load` subcommand for the Bijux CLI.
|
|
5
|
+
|
|
6
|
+
This module contains the logic for replacing the application's entire
|
|
7
|
+
configuration with the contents of a specified file. It discards any
|
|
8
|
+
in-memory settings and loads the new configuration, emitting a structured
|
|
9
|
+
confirmation upon success.
|
|
10
|
+
|
|
11
|
+
Output Contract:
|
|
12
|
+
* Success: `{"status": "loaded", "file": str}`
|
|
13
|
+
* Verbose: Adds `{"python": str, "platform": str}` to the payload.
|
|
14
|
+
* Error: `{"error": str, "code": int}`
|
|
15
|
+
|
|
16
|
+
Exit Codes:
|
|
17
|
+
* `0`: Success.
|
|
18
|
+
* `2`: The specified file could not be found, read, or parsed.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import platform
|
|
24
|
+
|
|
25
|
+
import typer
|
|
26
|
+
|
|
27
|
+
from bijux_cli.commands.utilities import (
|
|
28
|
+
ascii_safe,
|
|
29
|
+
emit_error_and_exit,
|
|
30
|
+
new_run_command,
|
|
31
|
+
parse_global_flags,
|
|
32
|
+
)
|
|
33
|
+
from bijux_cli.contracts import ConfigProtocol
|
|
34
|
+
from bijux_cli.core.constants import (
|
|
35
|
+
HELP_DEBUG,
|
|
36
|
+
HELP_FORMAT,
|
|
37
|
+
HELP_NO_PRETTY,
|
|
38
|
+
HELP_QUIET,
|
|
39
|
+
HELP_VERBOSE,
|
|
40
|
+
)
|
|
41
|
+
from bijux_cli.core.di import DIContainer
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def load_config(
|
|
45
|
+
ctx: typer.Context,
|
|
46
|
+
path: str = typer.Argument(..., help="Path to load from"),
|
|
47
|
+
quiet: bool = typer.Option(False, "-q", "--quiet", help=HELP_QUIET),
|
|
48
|
+
verbose: bool = typer.Option(False, "-v", "--verbose", help=HELP_VERBOSE),
|
|
49
|
+
fmt: str = typer.Option("json", "-f", "--format", help=HELP_FORMAT),
|
|
50
|
+
pretty: bool = typer.Option(True, "--pretty/--no-pretty", help=HELP_NO_PRETTY),
|
|
51
|
+
debug: bool = typer.Option(False, "-d", "--debug", help=HELP_DEBUG),
|
|
52
|
+
) -> None:
|
|
53
|
+
"""Loads configuration from a specified file.
|
|
54
|
+
|
|
55
|
+
This function replaces the current in-memory configuration with the
|
|
56
|
+
contents of the file at the given path. It provides a structured payload
|
|
57
|
+
to confirm the operation was successful.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
ctx (typer.Context): The Typer context for the CLI.
|
|
61
|
+
path (str): The path to the configuration file to load.
|
|
62
|
+
quiet (bool): If True, suppresses all output except for errors.
|
|
63
|
+
verbose (bool): If True, includes Python/platform details in the output.
|
|
64
|
+
fmt (str): The output format, "json" or "yaml".
|
|
65
|
+
pretty (bool): If True, pretty-prints the output.
|
|
66
|
+
debug (bool): If True, enables debug diagnostics.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
None:
|
|
70
|
+
|
|
71
|
+
Raises:
|
|
72
|
+
SystemExit: Always exits with a contract-compliant status code and
|
|
73
|
+
payload, indicating success or detailing the error.
|
|
74
|
+
"""
|
|
75
|
+
flags = parse_global_flags()
|
|
76
|
+
|
|
77
|
+
quiet = flags["quiet"]
|
|
78
|
+
verbose = flags["verbose"]
|
|
79
|
+
fmt = flags["format"]
|
|
80
|
+
pretty = flags["pretty"]
|
|
81
|
+
debug = flags["debug"]
|
|
82
|
+
|
|
83
|
+
include_runtime = verbose
|
|
84
|
+
fmt_lower = fmt.lower()
|
|
85
|
+
|
|
86
|
+
command = "config load"
|
|
87
|
+
|
|
88
|
+
config_svc = DIContainer.current().resolve(ConfigProtocol)
|
|
89
|
+
|
|
90
|
+
try:
|
|
91
|
+
config_svc.load(path)
|
|
92
|
+
except Exception as exc:
|
|
93
|
+
emit_error_and_exit(
|
|
94
|
+
f"Failed to load config: {exc}",
|
|
95
|
+
code=2,
|
|
96
|
+
failure="load_failed",
|
|
97
|
+
command=command,
|
|
98
|
+
fmt=fmt_lower,
|
|
99
|
+
quiet=quiet,
|
|
100
|
+
include_runtime=include_runtime,
|
|
101
|
+
debug=debug,
|
|
102
|
+
extra={"path": path},
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
def payload_builder(include_runtime: bool) -> dict[str, object]:
|
|
106
|
+
"""Builds the payload confirming a successful configuration load.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
include_runtime (bool): If True, includes Python and platform info.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
dict[str, object]: The structured payload.
|
|
113
|
+
"""
|
|
114
|
+
payload: dict[str, object] = {"status": "loaded", "file": path}
|
|
115
|
+
if include_runtime:
|
|
116
|
+
payload["python"] = ascii_safe(platform.python_version(), "python_version")
|
|
117
|
+
payload["platform"] = ascii_safe(platform.platform(), "platform")
|
|
118
|
+
return payload
|
|
119
|
+
|
|
120
|
+
new_run_command(
|
|
121
|
+
command_name=command,
|
|
122
|
+
payload_builder=payload_builder,
|
|
123
|
+
quiet=quiet,
|
|
124
|
+
verbose=verbose,
|
|
125
|
+
fmt=fmt_lower,
|
|
126
|
+
pretty=pretty,
|
|
127
|
+
debug=debug,
|
|
128
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright © 2025 Bijan Mousavi
|
|
3
|
+
|
|
4
|
+
"""Implements the `config reload` subcommand for the Bijux CLI.
|
|
5
|
+
|
|
6
|
+
This module contains the logic for manually reloading the application's
|
|
7
|
+
configuration from its source file on disk. It discards any in-memory
|
|
8
|
+
settings and replaces them with the content of the configuration file,
|
|
9
|
+
emitting a structured confirmation upon success.
|
|
10
|
+
|
|
11
|
+
Output Contract:
|
|
12
|
+
* Success: `{"status": "reloaded"}`
|
|
13
|
+
* Verbose: Adds `{"python": str, "platform": str}` to the payload.
|
|
14
|
+
* Error: `{"error": str, "code": int}`
|
|
15
|
+
|
|
16
|
+
Exit Codes:
|
|
17
|
+
* `0`: Success.
|
|
18
|
+
* `2`: The configuration file could not be read or parsed.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import platform
|
|
24
|
+
|
|
25
|
+
import typer
|
|
26
|
+
|
|
27
|
+
from bijux_cli.commands.utilities import (
|
|
28
|
+
ascii_safe,
|
|
29
|
+
emit_error_and_exit,
|
|
30
|
+
new_run_command,
|
|
31
|
+
parse_global_flags,
|
|
32
|
+
)
|
|
33
|
+
from bijux_cli.contracts import ConfigProtocol
|
|
34
|
+
from bijux_cli.core.constants import (
|
|
35
|
+
HELP_DEBUG,
|
|
36
|
+
HELP_FORMAT,
|
|
37
|
+
HELP_NO_PRETTY,
|
|
38
|
+
HELP_QUIET,
|
|
39
|
+
HELP_VERBOSE,
|
|
40
|
+
)
|
|
41
|
+
from bijux_cli.core.di import DIContainer
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def reload_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
|
+
"""Reloads the configuration from disk and emits a structured result.
|
|
53
|
+
|
|
54
|
+
This function forces a refresh of the application's configuration from its
|
|
55
|
+
persistent storage file. It is useful when the configuration has been
|
|
56
|
+
modified externally. A success or error payload is always emitted.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
ctx (typer.Context): The Typer context for the CLI.
|
|
60
|
+
quiet (bool): If True, suppresses all output except for errors.
|
|
61
|
+
verbose (bool): If True, includes Python/platform details in the output.
|
|
62
|
+
fmt (str): The output format, "json" or "yaml".
|
|
63
|
+
pretty (bool): If True, pretty-prints the output.
|
|
64
|
+
debug (bool): If True, enables debug diagnostics.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
None:
|
|
68
|
+
|
|
69
|
+
Raises:
|
|
70
|
+
SystemExit: Always exits with a contract-compliant status code and
|
|
71
|
+
payload, indicating success or detailing the error.
|
|
72
|
+
"""
|
|
73
|
+
flags = parse_global_flags()
|
|
74
|
+
|
|
75
|
+
quiet = flags["quiet"]
|
|
76
|
+
verbose = flags["verbose"]
|
|
77
|
+
fmt = flags["format"]
|
|
78
|
+
pretty = flags["pretty"]
|
|
79
|
+
debug = flags["debug"]
|
|
80
|
+
|
|
81
|
+
include_runtime = verbose
|
|
82
|
+
fmt_lower = fmt.lower()
|
|
83
|
+
|
|
84
|
+
command = "config reload"
|
|
85
|
+
|
|
86
|
+
config_svc = DIContainer.current().resolve(ConfigProtocol)
|
|
87
|
+
|
|
88
|
+
try:
|
|
89
|
+
config_svc.reload()
|
|
90
|
+
except Exception as exc:
|
|
91
|
+
emit_error_and_exit(
|
|
92
|
+
f"Failed to reload config: {exc}",
|
|
93
|
+
code=2,
|
|
94
|
+
failure="reload_failed",
|
|
95
|
+
command=command,
|
|
96
|
+
fmt=fmt_lower,
|
|
97
|
+
quiet=quiet,
|
|
98
|
+
include_runtime=include_runtime,
|
|
99
|
+
debug=debug,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
def payload_builder(include_runtime: bool) -> dict[str, object]:
|
|
103
|
+
"""Builds the payload confirming a successful configuration reload.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
include_runtime (bool): If True, includes Python and platform info.
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
dict[str, object]: The structured payload.
|
|
110
|
+
"""
|
|
111
|
+
payload: dict[str, object] = {"status": "reloaded"}
|
|
112
|
+
if include_runtime:
|
|
113
|
+
payload["python"] = ascii_safe(platform.python_version(), "python_version")
|
|
114
|
+
payload["platform"] = ascii_safe(platform.platform(), "platform")
|
|
115
|
+
return payload
|
|
116
|
+
|
|
117
|
+
new_run_command(
|
|
118
|
+
command_name=command,
|
|
119
|
+
payload_builder=payload_builder,
|
|
120
|
+
quiet=quiet,
|
|
121
|
+
verbose=verbose,
|
|
122
|
+
fmt=fmt_lower,
|
|
123
|
+
pretty=pretty,
|
|
124
|
+
debug=debug,
|
|
125
|
+
)
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright © 2025 Bijan Mousavi
|
|
3
|
+
|
|
4
|
+
"""Implements the root callback for the `bijux config` command group.
|
|
5
|
+
|
|
6
|
+
This module defines the default action for the `bijux config` command. When
|
|
7
|
+
invoked without a subcommand (like `get`, `set`, or `unset`), it lists all
|
|
8
|
+
key-value pairs currently stored in the active configuration, presenting them
|
|
9
|
+
in a structured, machine-readable format.
|
|
10
|
+
|
|
11
|
+
Output Contract:
|
|
12
|
+
* Success: `{"KEY_1": "VALUE_1", "KEY_2": "VALUE_2", ...}`
|
|
13
|
+
* Verbose: Adds `{"python": str, "platform": str}` to the payload.
|
|
14
|
+
* Error: `{"error": str, "code": int}`
|
|
15
|
+
|
|
16
|
+
Exit Codes:
|
|
17
|
+
* `0`: Success.
|
|
18
|
+
* `1`: An unexpected error occurred while accessing the configuration.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import platform
|
|
24
|
+
|
|
25
|
+
import typer
|
|
26
|
+
|
|
27
|
+
from bijux_cli.commands.utilities import ascii_safe, new_run_command, parse_global_flags
|
|
28
|
+
from bijux_cli.contracts import ConfigProtocol
|
|
29
|
+
from bijux_cli.core.constants import (
|
|
30
|
+
HELP_DEBUG,
|
|
31
|
+
HELP_FORMAT,
|
|
32
|
+
HELP_NO_PRETTY,
|
|
33
|
+
HELP_QUIET,
|
|
34
|
+
HELP_VERBOSE,
|
|
35
|
+
)
|
|
36
|
+
from bijux_cli.core.di import DIContainer
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def config(
|
|
40
|
+
ctx: typer.Context,
|
|
41
|
+
quiet: bool = typer.Option(False, "-q", "--quiet", help=HELP_QUIET),
|
|
42
|
+
verbose: bool = typer.Option(False, "-v", "--verbose", help=HELP_VERBOSE),
|
|
43
|
+
fmt: str = typer.Option("json", "-f", "--format", help=HELP_FORMAT),
|
|
44
|
+
pretty: bool = typer.Option(True, "--pretty/--no-pretty", help=HELP_NO_PRETTY),
|
|
45
|
+
debug: bool = typer.Option(False, "-d", "--debug", help=HELP_DEBUG),
|
|
46
|
+
) -> None:
|
|
47
|
+
"""Defines the entrypoint for the `bijux config` command group.
|
|
48
|
+
|
|
49
|
+
This function serves as the default action when `bijux config` is run
|
|
50
|
+
without a subcommand. It retrieves and displays all key-value pairs from
|
|
51
|
+
the current configuration. If a subcommand (`get`, `set`, etc.) is
|
|
52
|
+
invoked, this function yields control to it.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
ctx (typer.Context): The Typer context for the CLI.
|
|
56
|
+
quiet (bool): If True, suppresses all output except for errors.
|
|
57
|
+
verbose (bool): If True, includes Python/platform details in the output.
|
|
58
|
+
fmt (str): The output format, "json" or "yaml".
|
|
59
|
+
pretty (bool): If True, pretty-prints the output.
|
|
60
|
+
debug (bool): If True, enables debug diagnostics.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
None:
|
|
64
|
+
"""
|
|
65
|
+
if ctx.invoked_subcommand:
|
|
66
|
+
return
|
|
67
|
+
|
|
68
|
+
flags = parse_global_flags()
|
|
69
|
+
|
|
70
|
+
quiet = flags["quiet"]
|
|
71
|
+
verbose = flags["verbose"]
|
|
72
|
+
fmt = flags["format"]
|
|
73
|
+
pretty = flags["pretty"]
|
|
74
|
+
debug = flags["debug"]
|
|
75
|
+
|
|
76
|
+
fmt_lower = fmt.lower()
|
|
77
|
+
|
|
78
|
+
command = "config"
|
|
79
|
+
|
|
80
|
+
config_svc = DIContainer.current().resolve(ConfigProtocol)
|
|
81
|
+
|
|
82
|
+
def payload_builder(include_runtime: bool) -> dict[str, object]:
|
|
83
|
+
"""Builds the payload containing all configuration values.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
include_runtime (bool): If True, includes Python and platform info.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
dict[str, object]: A dictionary of all configuration key-value
|
|
90
|
+
pairs and optional runtime metadata.
|
|
91
|
+
"""
|
|
92
|
+
data = config_svc.all()
|
|
93
|
+
payload: dict[str, object] = dict(data)
|
|
94
|
+
if include_runtime:
|
|
95
|
+
payload["python"] = ascii_safe(platform.python_version(), "python_version")
|
|
96
|
+
payload["platform"] = ascii_safe(platform.platform(), "platform")
|
|
97
|
+
return payload
|
|
98
|
+
|
|
99
|
+
new_run_command(
|
|
100
|
+
command_name=command,
|
|
101
|
+
payload_builder=payload_builder,
|
|
102
|
+
quiet=quiet,
|
|
103
|
+
verbose=verbose,
|
|
104
|
+
fmt=fmt_lower,
|
|
105
|
+
pretty=pretty,
|
|
106
|
+
debug=debug,
|
|
107
|
+
)
|