cmdbox-cli 1.0.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.
Files changed (112) hide show
  1. cmdbox/__init__.py +0 -0
  2. cmdbox/cli/__init__.py +0 -0
  3. cmdbox/cli/app.py +125 -0
  4. cmdbox/cli/commands/__init__.py +0 -0
  5. cmdbox/cli/commands/alias_fallback.py +102 -0
  6. cmdbox/cli/commands/command_crud.py +429 -0
  7. cmdbox/cli/commands/command_run.py +255 -0
  8. cmdbox/cli/commands/history.py +109 -0
  9. cmdbox/cli/commands/init.py +54 -0
  10. cmdbox/cli/commands/settings.py +62 -0
  11. cmdbox/cli/commands/tag_crud.py +277 -0
  12. cmdbox/cli/commands/variable_crud.py +349 -0
  13. cmdbox/cli/common/__init__.py +0 -0
  14. cmdbox/cli/common/errors.py +58 -0
  15. cmdbox/cli/common/update_fields.py +88 -0
  16. cmdbox/cli/completions/__init__.py +0 -0
  17. cmdbox/cli/completions/commands.py +26 -0
  18. cmdbox/cli/completions/fields.py +31 -0
  19. cmdbox/cli/completions/tags.py +24 -0
  20. cmdbox/cli/completions/variables.py +26 -0
  21. cmdbox/cli/handlers/__init__.py +0 -0
  22. cmdbox/cli/handlers/command_handlers.py +357 -0
  23. cmdbox/cli/handlers/common_handlers.py +15 -0
  24. cmdbox/cli/handlers/history_handlers.py +94 -0
  25. cmdbox/cli/handlers/init_handler.py +127 -0
  26. cmdbox/cli/handlers/run_handler.py +178 -0
  27. cmdbox/cli/handlers/settings_handler.py +59 -0
  28. cmdbox/cli/handlers/tag_handlers.py +220 -0
  29. cmdbox/cli/handlers/variable_handlers.py +272 -0
  30. cmdbox/cli/prompts/__init__.py +0 -0
  31. cmdbox/cli/prompts/completers.py +161 -0
  32. cmdbox/cli/prompts/prompts.py +108 -0
  33. cmdbox/cli/prompts/validators.py +46 -0
  34. cmdbox/cli/ui/__init__.py +0 -0
  35. cmdbox/cli/ui/console.py +31 -0
  36. cmdbox/cli/ui/editor.py +141 -0
  37. cmdbox/cli/ui/presenters/__init__.py +0 -0
  38. cmdbox/cli/ui/presenters/app_presenter.py +8 -0
  39. cmdbox/cli/ui/presenters/command_presenter.py +168 -0
  40. cmdbox/cli/ui/presenters/history_presenter.py +83 -0
  41. cmdbox/cli/ui/presenters/init_instructions.py +52 -0
  42. cmdbox/cli/ui/presenters/init_presenter.py +57 -0
  43. cmdbox/cli/ui/presenters/result_presenter.py +144 -0
  44. cmdbox/cli/ui/presenters/settings_presenter.py +130 -0
  45. cmdbox/cli/ui/presenters/tag_presenter.py +97 -0
  46. cmdbox/cli/ui/presenters/variable_presenter.py +103 -0
  47. cmdbox/cli/ui/primitives.py +410 -0
  48. cmdbox/cli/ui/theme.py +43 -0
  49. cmdbox/cli/ui/theme_builder.py +49 -0
  50. cmdbox/common/__init__.py +0 -0
  51. cmdbox/common/io.py +34 -0
  52. cmdbox/container.py +156 -0
  53. cmdbox/core/__init__.py +0 -0
  54. cmdbox/core/fields.py +48 -0
  55. cmdbox/core/paths.py +52 -0
  56. cmdbox/database.py +65 -0
  57. cmdbox/exceptions.py +10 -0
  58. cmdbox/init/__init__.py +0 -0
  59. cmdbox/init/detect.py +82 -0
  60. cmdbox/init/integrations/bash.sh +10 -0
  61. cmdbox/init/integrations/cmd.bat +14 -0
  62. cmdbox/init/integrations/fish.fish +11 -0
  63. cmdbox/init/integrations/powershell.ps1 +14 -0
  64. cmdbox/init/integrations/zsh.sh +10 -0
  65. cmdbox/init/io.py +68 -0
  66. cmdbox/init/specs.py +54 -0
  67. cmdbox/logging_setup/__init__.py +0 -0
  68. cmdbox/logging_setup/log_config.py +123 -0
  69. cmdbox/logging_setup/log_decorators.py +40 -0
  70. cmdbox/logging_setup/log_handlers.py +94 -0
  71. cmdbox/migrations/__init__.py +1 -0
  72. cmdbox/migrations/errors.py +10 -0
  73. cmdbox/migrations/runner.py +127 -0
  74. cmdbox/migrations/versions/__init__.py +0 -0
  75. cmdbox/models.py +165 -0
  76. cmdbox/repositories/__init__.py +0 -0
  77. cmdbox/repositories/base_repository.py +181 -0
  78. cmdbox/repositories/command_repository.py +391 -0
  79. cmdbox/repositories/errors.py +120 -0
  80. cmdbox/repositories/history_repository.py +155 -0
  81. cmdbox/repositories/results.py +37 -0
  82. cmdbox/repositories/tag_repository.py +91 -0
  83. cmdbox/repositories/validators.py +256 -0
  84. cmdbox/repositories/variable_repository.py +324 -0
  85. cmdbox/resolve/__init__.py +0 -0
  86. cmdbox/resolve/errors.py +65 -0
  87. cmdbox/resolve/lookup.py +137 -0
  88. cmdbox/resolve/resolver.py +402 -0
  89. cmdbox/resolve/type_defs.py +96 -0
  90. cmdbox/runtime/__init__.py +0 -0
  91. cmdbox/runtime/executor.py +454 -0
  92. cmdbox/runtime/results.py +25 -0
  93. cmdbox/runtime/shell.py +90 -0
  94. cmdbox/services/__init__.py +0 -0
  95. cmdbox/services/command_services.py +261 -0
  96. cmdbox/services/errors.py +37 -0
  97. cmdbox/services/field_selection.py +162 -0
  98. cmdbox/services/history_service.py +68 -0
  99. cmdbox/services/run_service.py +204 -0
  100. cmdbox/services/tag_services.py +134 -0
  101. cmdbox/services/variable_services.py +224 -0
  102. cmdbox/settings/__init__.py +0 -0
  103. cmdbox/settings/models.py +129 -0
  104. cmdbox/settings/settings_repository.py +36 -0
  105. cmdbox/settings/settings_service.py +144 -0
  106. cmdbox/version.py +1 -0
  107. cmdbox_cli-1.0.0.dist-info/METADATA +125 -0
  108. cmdbox_cli-1.0.0.dist-info/RECORD +112 -0
  109. cmdbox_cli-1.0.0.dist-info/WHEEL +5 -0
  110. cmdbox_cli-1.0.0.dist-info/entry_points.txt +2 -0
  111. cmdbox_cli-1.0.0.dist-info/licenses/LICENSE +21 -0
  112. cmdbox_cli-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,255 @@
1
+ from typing import Annotated, Optional
2
+ import logging
3
+
4
+ import typer
5
+
6
+ from cmdbox import container
7
+ from cmdbox.cli.common.errors import make_cli_guard
8
+ from cmdbox.cli.completions.commands import complete_command_aliases
9
+ from cmdbox.cli.handlers.run_handler import (
10
+ run_preview_command,
11
+ RawRunContext,
12
+ run_run_command,
13
+ )
14
+
15
+ app = typer.Typer(no_args_is_help=True)
16
+
17
+ cli_guard = make_cli_guard(container.get_console)
18
+
19
+ log = logging.getLogger(__name__)
20
+
21
+
22
+ @app.command(
23
+ context_settings={"allow_extra_args": True, "ignore_unknown_options": True}
24
+ )
25
+ @cli_guard
26
+ def run(
27
+ alias: Annotated[
28
+ str,
29
+ typer.Argument(
30
+ help="The alias of the command to run.",
31
+ autocompletion=complete_command_aliases,
32
+ ),
33
+ ],
34
+ *,
35
+ preview_cmd: Annotated[
36
+ bool,
37
+ typer.Option(
38
+ "--preview",
39
+ "-p",
40
+ help="Output the command that will be executed without actually running it.",
41
+ ),
42
+ ] = False,
43
+ cwd: Annotated[
44
+ str | None,
45
+ typer.Option(
46
+ "--cwd", "-d", help="The working directory for the command execution."
47
+ ),
48
+ ] = None,
49
+ env: Annotated[
50
+ list[str] | None,
51
+ typer.Option("--env", help="The environment variables to set for the command."),
52
+ ] = None,
53
+ capture: Annotated[
54
+ bool,
55
+ typer.Option("--capture", "-c", help="Capture the command output."),
56
+ ] = False,
57
+ shell: Annotated[
58
+ str | None,
59
+ typer.Option(
60
+ "--shell", "-s", help="The shell to use for the command execution."
61
+ ),
62
+ ] = None,
63
+ timeout: Annotated[
64
+ int | None,
65
+ typer.Option(
66
+ "--timeout",
67
+ "-t",
68
+ help="The number of seconds before the process is killed.",
69
+ ),
70
+ ] = None,
71
+ emit: Annotated[
72
+ bool,
73
+ typer.Option(
74
+ "--emit",
75
+ "-e",
76
+ is_flag=True,
77
+ help="Print the command output to stdout instead of running it in a separate process. "
78
+ "You must then press enter to run the command in your current terminal window.",
79
+ hidden=True,
80
+ ),
81
+ ] = False,
82
+ verbose: Annotated[
83
+ Optional[bool],
84
+ typer.Option(
85
+ "--verbose/--no-verbose",
86
+ help="Outputs additional information alongside the command output.",
87
+ ),
88
+ ] = None,
89
+ ctx: typer.Context,
90
+ ) -> None:
91
+ """
92
+ Run stored commands by using their alias.
93
+ """
94
+ log.debug(
95
+ "run.run called. alias=%s, preview=%s, cwd_used=%s, env=%s, capture=%s, shell=%s, timeout=%s, emit=%s, verbose=%s",
96
+ alias,
97
+ preview_cmd,
98
+ cwd,
99
+ env,
100
+ capture,
101
+ shell,
102
+ timeout,
103
+ emit,
104
+ verbose,
105
+ )
106
+ if preview_cmd:
107
+ preview(
108
+ alias=alias,
109
+ cwd=cwd,
110
+ env=env,
111
+ capture=capture,
112
+ shell=shell,
113
+ timeout=timeout,
114
+ verbose=verbose,
115
+ ctx=ctx,
116
+ )
117
+ return
118
+
119
+ extra_args = ctx.args if ctx.args else ctx.meta.get("_extra_args", [])
120
+ runtime_vars = parse_runtime_vars(extra_args)
121
+
122
+ ctx = RawRunContext(
123
+ cwd=cwd,
124
+ env=env,
125
+ capture=capture,
126
+ shell=shell,
127
+ timeout=timeout,
128
+ emit=emit,
129
+ verbose=verbose,
130
+ )
131
+ run_run_command(
132
+ alias=alias,
133
+ runtime_vars=runtime_vars,
134
+ run_ctx=ctx,
135
+ get_run_service=container.get_run_service,
136
+ get_settings=container.get_settings,
137
+ get_console=container.get_console,
138
+ )
139
+
140
+
141
+ @app.command(
142
+ "preview",
143
+ context_settings={"allow_extra_args": True, "ignore_unknown_options": True},
144
+ )
145
+ @cli_guard
146
+ def preview(
147
+ alias: Annotated[
148
+ str,
149
+ typer.Argument(
150
+ help="The alias of the command to run.",
151
+ autocompletion=complete_command_aliases,
152
+ ),
153
+ ],
154
+ *,
155
+ cwd: Annotated[
156
+ str | None,
157
+ typer.Option(
158
+ "--cwd", "-d", help="The working directory for the command execution."
159
+ ),
160
+ ] = None,
161
+ env: Annotated[
162
+ list[str] | None,
163
+ typer.Option(
164
+ "--env", "-e", help="The environment variables to set for the command."
165
+ ),
166
+ ] = None,
167
+ capture: Annotated[
168
+ bool,
169
+ typer.Option(
170
+ "--capture", "-c", is_flag=True, help="Capture the command output."
171
+ ),
172
+ ] = False,
173
+ shell: Annotated[
174
+ str | None,
175
+ typer.Option(
176
+ "--shell", "-s", help="The shell to use for the command execution."
177
+ ),
178
+ ] = None,
179
+ timeout: Annotated[
180
+ int | None,
181
+ typer.Option(
182
+ "--timeout",
183
+ "-t",
184
+ help="The number of seconds before the process is killed.",
185
+ ),
186
+ ] = None,
187
+ verbose: Annotated[
188
+ Optional[bool],
189
+ typer.Option(
190
+ "--verbose/--no-verbose",
191
+ help="Outputs additional information alongside the command output.",
192
+ ),
193
+ ] = None,
194
+ ctx: typer.Context,
195
+ ) -> None:
196
+ """
197
+ Output the command that will be executed without actually running it.
198
+ """
199
+ log.debug(
200
+ "run.preview called. alias=%s, cwd=%s, env=%s, capture=%s, shell=%s, timeout=%s, verbose=%s",
201
+ alias,
202
+ cwd,
203
+ env,
204
+ capture,
205
+ shell,
206
+ timeout,
207
+ verbose,
208
+ )
209
+ runtime_vars = parse_runtime_vars(ctx.args)
210
+ ctx = RawRunContext(
211
+ cwd=cwd, env=env, capture=capture, shell=shell, timeout=timeout, verbose=verbose
212
+ )
213
+ run_preview_command(
214
+ alias=alias,
215
+ runtime_vars=runtime_vars,
216
+ run_ctx=ctx,
217
+ get_run_service=container.get_run_service,
218
+ get_settings=container.get_settings,
219
+ get_console=container.get_console,
220
+ )
221
+
222
+
223
+ def parse_runtime_vars(args: list[str]) -> dict[str, str]:
224
+ """
225
+ Parses a list of runtime arguments into a dictionary of key-value pairs.
226
+
227
+ This function processes a list of command-line arguments, extracting argument
228
+ keys prefixed with `--` and their corresponding values. Arguments without
229
+ values will not be included in the resulting dictionary. Unrecognized or
230
+ improperly formatted tokens are ignored.
231
+
232
+ Args:
233
+ args (list[str]): A list of strings, where each string represents a
234
+ command-line argument. Keys should be prefixed with `--` and may
235
+ optionally be followed by a value.
236
+
237
+ Returns:
238
+ dict[str, str]: A dictionary where keys are argument names (without the
239
+ `--` prefix) and values are their associated arguments. Only valid
240
+ key-value pairs are included.
241
+ """
242
+ result = {}
243
+ x = 0
244
+ while x < len(args):
245
+ token = args[x]
246
+ if token.startswith("--"):
247
+ key = token.lstrip("-")
248
+ if x + 1 < len(args) and not args[x + 1].startswith("--"):
249
+ result[key] = args[x + 1]
250
+ x += 2
251
+ else:
252
+ x += 1
253
+ else:
254
+ x += 1
255
+ return result
@@ -0,0 +1,109 @@
1
+ import logging
2
+ from typing import Annotated, Optional
3
+
4
+ import typer
5
+
6
+ from cmdbox import container
7
+ from cmdbox.cli.handlers.history_handlers import (
8
+ run_history_list,
9
+ run_history_show,
10
+ run_history_rerun,
11
+ run_history_clear,
12
+ run_rerun_last,
13
+ )
14
+ from cmdbox.cli.common.errors import make_cli_guard
15
+
16
+ app = typer.Typer(help="View and re-run command execution history.")
17
+
18
+ cli_guard = make_cli_guard(container.get_console)
19
+
20
+ log = logging.getLogger(__name__)
21
+
22
+
23
+ @app.command("list")
24
+ @cli_guard
25
+ def history_list(
26
+ alias: Annotated[
27
+ Optional[str],
28
+ typer.Option("--alias", "-a", help="Filter history to a specific alias."),
29
+ ] = None,
30
+ limit: Annotated[
31
+ int,
32
+ typer.Option("--limit", "-l", help="The number of history entries to show."),
33
+ ] = 25,
34
+ ) -> None:
35
+ """List recent command executions."""
36
+ run_history_list(
37
+ alias=alias,
38
+ limit=limit,
39
+ get_history_service=container.get_history_service,
40
+ get_console=container.get_console,
41
+ )
42
+
43
+
44
+ @app.command("show")
45
+ @cli_guard
46
+ def history_show(
47
+ ref: Annotated[
48
+ str,
49
+ typer.Argument(help="Entry index (from list) or ID prefix."),
50
+ ],
51
+ ) -> None:
52
+ """Show full details for a single history entry."""
53
+ run_history_show(
54
+ ref=ref,
55
+ get_history_service=container.get_history_service,
56
+ get_console=container.get_console,
57
+ )
58
+
59
+
60
+ @app.command("rerun")
61
+ @cli_guard
62
+ def history_rerun(
63
+ ref: Annotated[
64
+ str,
65
+ typer.Argument(help="Entry index (from list) or ID prefix."),
66
+ ],
67
+ ) -> None:
68
+ """Re-execute a past command invocation using the same variables."""
69
+ run_history_rerun(
70
+ ref=ref,
71
+ get_history_service=container.get_history_service,
72
+ get_run_service=container.get_run_service,
73
+ )
74
+
75
+
76
+ @app.command("clear")
77
+ @cli_guard
78
+ def history_clear(
79
+ alias: Annotated[
80
+ Optional[str],
81
+ typer.Option("--alias", "-a", help="Clear history only for a specific alias."),
82
+ ] = None,
83
+ yes: Annotated[
84
+ bool,
85
+ typer.Option(
86
+ "--yes",
87
+ "-y",
88
+ help="Skip confirmation prompt.",
89
+ ),
90
+ ] = False,
91
+ ) -> None:
92
+ """Clear command history."""
93
+ run_history_clear(
94
+ alias=alias,
95
+ yes=yes,
96
+ get_history_service=container.get_history_service,
97
+ get_console=container.get_console,
98
+ )
99
+
100
+
101
+ @app.command("last")
102
+ @cli_guard
103
+ def rerun_last() -> None:
104
+ """Re-executes the last command run."""
105
+ run_rerun_last(
106
+ get_run_service=container.get_run_service,
107
+ get_history_service=container.get_history_service,
108
+ get_console=container.get_console,
109
+ )
@@ -0,0 +1,54 @@
1
+ import logging
2
+ from typing import Annotated
3
+
4
+ import typer
5
+
6
+ from cmdbox import container
7
+ from cmdbox.cli.common.errors import make_cli_guard
8
+ from cmdbox.cli.handlers.init_handler import run_detect_shell, run_init_command
9
+
10
+ app = typer.Typer(no_args_is_help=False)
11
+
12
+ cli_guard = make_cli_guard(container.get_console)
13
+
14
+ log = logging.getLogger(__name__)
15
+
16
+
17
+ @app.command()
18
+ @cli_guard
19
+ def init(
20
+ shell: Annotated[
21
+ str,
22
+ typer.Argument(
23
+ help="The shell to initialize. bash, zsh, fish, powershell, or cmd"
24
+ ),
25
+ ] = None,
26
+ install: Annotated[
27
+ bool,
28
+ typer.Option(
29
+ "--install",
30
+ "-i",
31
+ is_flag=True,
32
+ help="Install into the shell profile where applicable. If False, the profile modification will be"
33
+ "printed for you to make the profile changes manually. This may not work on all profiles.",
34
+ ),
35
+ ] = False,
36
+ path: Annotated[
37
+ str, typer.Option("--path", "-p", help="The path to the shell profile.")
38
+ ] = None,
39
+ ) -> None:
40
+ """
41
+ Initialize CmdBox for a shell environment.
42
+ """
43
+ log.debug("init.init called. shell=%s, install=%s", shell, install)
44
+ run_init_command(
45
+ shell=shell, install=install, path=path, get_console=container.get_console
46
+ )
47
+
48
+
49
+ @app.command(name="shell", hidden=True)
50
+ @cli_guard
51
+ def detect_shell() -> None:
52
+ """Detects and prints the current shell being used."""
53
+ log.debug("init.shell called.")
54
+ run_detect_shell(get_console=container.get_console)
@@ -0,0 +1,62 @@
1
+ import logging
2
+ from typing import Annotated
3
+
4
+ import typer
5
+
6
+ from cmdbox import container
7
+ from cmdbox.cli.common.errors import make_cli_guard
8
+ from cmdbox.cli.handlers import settings_handler
9
+
10
+ app = typer.Typer(no_args_is_help=True)
11
+
12
+ cli_guard = make_cli_guard(container.get_console)
13
+
14
+ log = logging.getLogger(__name__)
15
+
16
+
17
+ @app.command("edit")
18
+ @cli_guard
19
+ def edit(
20
+ external: Annotated[
21
+ bool,
22
+ typer.Option(
23
+ "--external",
24
+ "-e",
25
+ help="Edit settings file directly in terminal.",
26
+ ),
27
+ ] = False,
28
+ ) -> None:
29
+ """
30
+ Edits the settings file. If the `--external` flag is used, the settings file will be
31
+ opened in the default text editor. Otherwise, the settings will be edited interactively
32
+ in the terminal.
33
+ """
34
+ log.debug("settings.edit called. external=%s", external)
35
+ settings_handler.run_edit_settings(
36
+ external,
37
+ get_settings_service=container.get_settings_service,
38
+ get_console=container.get_console,
39
+ )
40
+
41
+
42
+ @app.command("show")
43
+ @cli_guard
44
+ def show(
45
+ fields: Annotated[
46
+ str | None,
47
+ typer.Option(
48
+ "--fields",
49
+ "-f",
50
+ help="List of fields to show separated by comma. If not provided, all fields will be shown.",
51
+ ),
52
+ ] = None,
53
+ ) -> None:
54
+ """
55
+ Outputs the current settings in a stylized table view.
56
+ """
57
+ log.debug("settings.show called. fields=%s", fields)
58
+ settings_handler.run_show_settings(
59
+ fields=fields,
60
+ get_settings_service=container.get_settings_service,
61
+ get_console=container.get_console,
62
+ )