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,130 @@
1
+ from dataclasses import asdict
2
+
3
+ from cmdbox.cli.ui.primitives import stack, kv_table, section
4
+ from cmdbox.settings.models import Settings
5
+
6
+
7
+ def render_settings_show(settings: Settings, fields: list[str] | None = None):
8
+ """
9
+ Renders the settings to display either fully or partially, based on the input.
10
+
11
+ This function takes in a settings object and an optional list of fields. If the
12
+ fields list is provided, only the specified fields from the settings object
13
+ will be rendered. Otherwise, the entire settings object will be rendered.
14
+
15
+ Args:
16
+ settings (Settings): The settings object to be rendered.
17
+ fields (list[str] | None): An optional list of field names to render. If
18
+ None, the full settings object is rendered.
19
+
20
+ Returns:
21
+ str: The rendered representation of the settings.
22
+ """
23
+ if fields is None:
24
+ return render_full_settings(settings)
25
+ else:
26
+ return render_settings_fields(settings, fields)
27
+
28
+
29
+ def render_full_settings(settings: Settings):
30
+ """
31
+ Renders the full configuration settings into a styled section format.
32
+
33
+ This function iterates through the provided settings object, extracts sections
34
+ and their respective values, and organizes them into a structured visual
35
+ presentation. Each section is assigned a styled border to enhance readability.
36
+
37
+ Args:
38
+ settings (Settings): The settings object containing configuration data,
39
+ structured as key-value pairs.
40
+
41
+ Returns:
42
+ Section: A styled section containing all rendered sub-sections representing
43
+ the settings in a visually organized format.
44
+ """
45
+ ret = []
46
+ for _section, values in asdict(settings).items():
47
+ ret.append(
48
+ section(
49
+ title=_section, body=render_section(values), border_style="status.info"
50
+ )
51
+ )
52
+ return section(title="Settings", body=stack(*ret), border_style="status.info")
53
+
54
+
55
+ def render_section(_section: dict):
56
+ """
57
+ Renders a nested dictionary structure into a visual representation using specific rendering functions.
58
+
59
+ This function processes a nested dictionary and generates a rendered output. It recursively handles
60
+ dictionaries as nested sections and renders key-value pairs as a table. Special handling is provided
61
+ for dictionary items with the key 'alias_mapping'.
62
+
63
+ Args:
64
+ _section (dict): The nested dictionary structure to be rendered.
65
+
66
+ Returns:
67
+ Any: The final rendered output based on the processed structure.
68
+ """
69
+ ret = []
70
+ for key, value in _section.items():
71
+ if isinstance(value, dict):
72
+ sub = render_section(value)
73
+ if key == "alias_mapping":
74
+ body = sub
75
+ else:
76
+ body = section(title=key, body=sub)
77
+ else:
78
+ body = kv_table(rows=[(key, value)])
79
+ ret.append(body)
80
+ return stack(*ret)
81
+
82
+
83
+ def render_settings_fields(settings: Settings, fields: list[str]):
84
+ """
85
+ Renders the settings fields as a formatted table.
86
+
87
+ This function takes settings and a list of field names, extracts the relevant
88
+ fields from the settings object, and displays them as rows in a table. The
89
+ output is a styled section containing the table.
90
+
91
+ Args:
92
+ settings (Settings): An object containing configuration settings, structured
93
+ as fields and their respective values.
94
+ fields (list[str]): A list of field names to extract and display from the
95
+ settings object.
96
+
97
+ Returns:
98
+ str: A styled section containing a table representation of the settings
99
+ fields.
100
+ """
101
+ display_fields = []
102
+ for key, value in asdict(settings).items():
103
+ display_fields.extend(parse_settings_fields(value, fields))
104
+ table = kv_table(rows=display_fields)
105
+ return section(title="Settings", body=table, border_style="status.info")
106
+
107
+
108
+ def parse_settings_fields(_section: dict, fields: list[str]):
109
+ """
110
+ Parses a nested dictionary to extract specific fields and their
111
+ associated values.
112
+
113
+ This function traverses a given dictionary recursively and collects
114
+ key-value pairs from the dictionary that match the specified fields.
115
+
116
+ Args:
117
+ _section (dict): A nested dictionary to search for matching fields.
118
+ fields (list[str]): A list of field names to look for in _section.
119
+
120
+ Returns:
121
+ list[tuple]: A list of tuples containing key-value pairs for
122
+ the fields found in _section, including from nested dictionaries.
123
+ """
124
+ ret = []
125
+ for key, value in _section.items():
126
+ if isinstance(value, dict):
127
+ ret.extend(parse_settings_fields(value, fields))
128
+ if key in fields:
129
+ ret.append((key, value))
130
+ return ret
@@ -0,0 +1,97 @@
1
+ from typing import Sequence, Callable
2
+
3
+ from cmdbox.cli.ui.primitives import (
4
+ col,
5
+ pluralize,
6
+ table_panel,
7
+ kv_table,
8
+ section,
9
+ )
10
+ from cmdbox.models import Tag
11
+
12
+ TAG_COLUMNS: dict[str, tuple[str, dict, Callable[[Tag], object]]] = {
13
+ "name": (
14
+ "Name",
15
+ {"style": "entity.name", "no_wrap": True},
16
+ lambda t: t.name,
17
+ ),
18
+ "description": (
19
+ "Description",
20
+ {"overflow": "fold"},
21
+ lambda t: t.description,
22
+ ),
23
+ "date_created": (
24
+ "Created",
25
+ {"style": "entity.time", "no_wrap": True},
26
+ lambda t: t.date_created,
27
+ ),
28
+ "last_updated": (
29
+ "Updated",
30
+ {"style": "entity.time", "no_wrap": True},
31
+ lambda t: t.last_updated,
32
+ ),
33
+ }
34
+
35
+
36
+ DEFAULT_FIELDS = ["name", "description"]
37
+
38
+
39
+ def render_tag_created(tag: Tag):
40
+ rendered_tag = render_tag(tag)
41
+ return section(
42
+ title=f"Tag '{tag.name}' created",
43
+ body=rendered_tag,
44
+ border_style="status.success",
45
+ )
46
+
47
+
48
+ def render_tag(tag: Tag):
49
+ rows = []
50
+ for value in TAG_COLUMNS.values():
51
+ header, _, extractor = value
52
+ rows.append((header, extractor(tag)))
53
+ return kv_table(rows)
54
+
55
+
56
+ def render_tag_list(
57
+ tags: Sequence[Tag], *, title: str = None, fields: list[str] | None = None
58
+ ):
59
+ active_fields = fields or DEFAULT_FIELDS
60
+ active_fields = [f for f in active_fields if f in TAG_COLUMNS]
61
+
62
+ columns = []
63
+ extractors = []
64
+
65
+ for field in active_fields:
66
+ header, col_args, extractor = TAG_COLUMNS[field]
67
+ columns.append(col(header, **col_args))
68
+ extractors.append(extractor)
69
+
70
+ rows = [tuple(extractor(t) for extractor in extractors) for t in tags]
71
+
72
+ caption = f"{pluralize(len(tags), 'tag')} found"
73
+
74
+ return table_panel(
75
+ title=title or "Tags",
76
+ columns=columns,
77
+ rows=rows,
78
+ caption=caption,
79
+ )
80
+
81
+
82
+ def render_tag_updated(tag: Tag):
83
+ rendered_tag = render_tag(tag)
84
+ return section(
85
+ title=f"Tag '{tag.name}' updated",
86
+ body=rendered_tag,
87
+ border_style="status.success",
88
+ )
89
+
90
+
91
+ def render_tag_deleted(tag: Tag):
92
+ rendered_tag = render_tag(tag)
93
+ return section(
94
+ title=f"Tag '{tag.name}' deleted",
95
+ body=rendered_tag,
96
+ border_style="status.success",
97
+ )
@@ -0,0 +1,103 @@
1
+ from typing import Sequence, Callable
2
+
3
+ from cmdbox.cli.ui.primitives import (
4
+ col,
5
+ pluralize,
6
+ table_panel,
7
+ kv_table,
8
+ section,
9
+ tag_block,
10
+ )
11
+ from cmdbox.models import Variable
12
+
13
+ VARIABLE_COLUMNS: dict[str, tuple[str, dict, Callable[[Variable], object]]] = {
14
+ "name": (
15
+ "Name",
16
+ {"style": "entity.name", "no_wrap": True},
17
+ lambda v: v.name,
18
+ ),
19
+ "value": (
20
+ "Value",
21
+ {"style": "code.inline", "overflow": "fold"},
22
+ lambda v: v.value,
23
+ ),
24
+ "date_created": (
25
+ "Created",
26
+ {"style": "entity.time", "no_wrap": True},
27
+ lambda v: v.date_created,
28
+ ),
29
+ "last_updated": (
30
+ "Updated",
31
+ {"style": "entity.time", "no_wrap": True},
32
+ lambda v: v.last_updated,
33
+ ),
34
+ "tags": (
35
+ "Tags",
36
+ {"overflow": "fold"},
37
+ lambda v: tag_block([x.tag.name for x in v.tags]),
38
+ ),
39
+ }
40
+
41
+ DEFAULT_FIELDS = ["name", "value"]
42
+
43
+
44
+ def render_variable_created(variable: Variable):
45
+ rendered_variable = render_variable(variable)
46
+ return section(
47
+ title=f'Variable "{variable.name}" created',
48
+ body=rendered_variable,
49
+ border_style="status.success",
50
+ )
51
+
52
+
53
+ def render_variable(variable: Variable):
54
+ rows = []
55
+ for value in VARIABLE_COLUMNS.values():
56
+ header, _, extractor = value
57
+ rows.append((header, extractor(variable)))
58
+ var_display = kv_table(rows)
59
+ return var_display
60
+
61
+
62
+ def render_variable_list(
63
+ variables: Sequence[Variable], *, title: str = None, fields: list[str] | None = None
64
+ ):
65
+ active_fields = fields or DEFAULT_FIELDS
66
+ active_fields = [f for f in active_fields if f in VARIABLE_COLUMNS]
67
+
68
+ columns = []
69
+ extractors = []
70
+
71
+ for field in active_fields:
72
+ header, col_args, extractor = VARIABLE_COLUMNS[field]
73
+ columns.append(col(header, **col_args))
74
+ extractors.append(extractor)
75
+
76
+ rows = [tuple(extractor(v) for extractor in extractors) for v in variables]
77
+
78
+ caption = f"{pluralize(len(variables), 'variable')} found"
79
+
80
+ return table_panel(
81
+ title=title or "Variables",
82
+ caption=caption,
83
+ columns=columns,
84
+ rows=rows,
85
+ )
86
+
87
+
88
+ def render_variable_updated(variable: Variable):
89
+ rendered_variable = render_variable(variable)
90
+ return section(
91
+ title=f"Variable '{variable.name}' updated",
92
+ body=rendered_variable,
93
+ border_style="status.success",
94
+ )
95
+
96
+
97
+ def render_variable_deleted(variable: Variable):
98
+ rendered_variable = render_variable(variable)
99
+ return section(
100
+ title=f"Variable '{variable.name}' deleted",
101
+ body=rendered_variable,
102
+ border_style="status.success",
103
+ )