socx-cli 0.13.7__tar.gz → 0.13.9__tar.gz
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.
- {socx_cli-0.13.7 → socx_cli-0.13.9}/PKG-INFO +3 -1
- {socx_cli-0.13.7 → socx_cli-0.13.9}/pyproject.toml +4 -2
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/__init__.py +2 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/cli/callbacks.py +2 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/config/_config.py +5 -1
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/config/converters.py +8 -9
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/core/__init__.py +2 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/core/enums.py +4 -7
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/core/schema/__init__.py +2 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/core/schema/plugin.py +59 -63
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/core/schema/types.py +10 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/io/console.py +2 -2
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/io/log.py +14 -14
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/regression/regression.py +73 -40
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/regression/test.py +117 -82
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/static/settings/cli.yaml +1 -6
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/static/settings/logging.yaml +6 -6
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/static/settings/regression.yaml +51 -1
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/static/settings/settings.yaml +1 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/regression/callbacks.py +1 -1
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/regression/cli.py +2 -0
- socx_cli-0.13.9/socx_plugins/regression/serve.py +29 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/regression/tui.py +5 -2
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_tui/regression/app.py +33 -40
- socx_cli-0.13.9/socx_tui/regression/details.py +323 -0
- socx_cli-0.13.9/socx_tui/regression/dialog.py +223 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_tui/regression/tree.py +15 -9
- socx_cli-0.13.9/socx_tui/regression/widget.py +701 -0
- socx_cli-0.13.9/socx_tui/static/tcss/regression/app.tcss +276 -0
- socx_cli-0.13.7/socx_tui/regression/details.py +0 -178
- socx_cli-0.13.7/socx_tui/regression/dialog.py +0 -184
- socx_cli-0.13.7/socx_tui/regression/widget.py +0 -487
- socx_cli-0.13.7/socx_tui/static/tcss/regression/app.tcss +0 -224
- {socx_cli-0.13.7 → socx_cli-0.13.9}/.gitignore +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/LICENSE +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/README.md +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/__main__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/cli/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/cli/_cli.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/cli/_jinja.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/cli/cfg.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/cli/cli.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/cli/params.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/cli/types.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/config/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/config/_settings.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/config/encoders.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/config/formatters.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/config/serializers.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/config/validators.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/core/_paths.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/core/encoder.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/core/funcs.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/core/metadata.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/core/paths.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/core/schema/git/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/core/schema/git/git.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/core/schema/git/manifest.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/core/serializer.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/git/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/git/_git.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/git/_manifest.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/git/_ssh.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/io/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/io/decorators.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/patterns/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/patterns/mixins/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/patterns/mixins/proxy.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/patterns/mixins/uid.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/patterns/singleton/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/patterns/singleton/singleton.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/patterns/visitor/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/patterns/visitor/protocol.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/patterns/visitor/traversal.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/regression/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/regression/progress.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/regression/status.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/regression/validator.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/regression/visitor.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/static/settings/console.yaml +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/static/settings/git.yaml +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/static/settings/plugins.yaml +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/static/settings/rich_click.yaml +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/static/sql/socx.sql +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/utils/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx/utils/decorators.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/config/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/config/_config.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/config/edit.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/git/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/git/arguments.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/git/callbacks.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/git/cli.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/git/manifest.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/git/renderables.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/git/summary.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/git/utils.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/plugin/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/plugin/example.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/plugin/schema.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/regression/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/regression/_run.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/regression/run.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/version/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_plugins/version/__main__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_tui/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_tui/regression/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_tui/regression/__main__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_tui/regression/bindings/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_tui/regression/bindings/vim/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_tui/regression/bindings/vim/mode.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_tui/regression/bindings/vim/vim.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_tui/regression/containers.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_tui/regression/mixins/__init__.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_tui/regression/mixins/composable.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_tui/regression/mixins/configurable.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_tui/regression/preview.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_tui/regression/table.py +0 -0
- {socx_cli-0.13.7 → socx_cli-0.13.9}/socx_tui/static/tcss/regression/preview.tcss +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: socx-cli
|
|
3
|
-
Version: 0.13.
|
|
3
|
+
Version: 0.13.9
|
|
4
4
|
Summary: System on chip verification and tooling infrastructure.
|
|
5
5
|
Project-URL: Issues, https://github.com/sagikimhi/socx-cli/issues
|
|
6
6
|
Project-URL: Homepage, https://sagikimhi.dev/socx-cli
|
|
@@ -29,6 +29,7 @@ Classifier: Topic :: Software Development
|
|
|
29
29
|
Classifier: Topic :: Utilities
|
|
30
30
|
Requires-Python: >=3.12
|
|
31
31
|
Requires-Dist: anyio[trio]>=4.12.1
|
|
32
|
+
Requires-Dist: blinker>=1.9.0
|
|
32
33
|
Requires-Dist: click
|
|
33
34
|
Requires-Dist: copier~=9.11
|
|
34
35
|
Requires-Dist: declare
|
|
@@ -53,6 +54,7 @@ Requires-Dist: sh~=2.2
|
|
|
53
54
|
Requires-Dist: sqlmodel>=0.0.31
|
|
54
55
|
Requires-Dist: textual
|
|
55
56
|
Requires-Dist: textual-fspicker>=0.6.0
|
|
57
|
+
Requires-Dist: textual-serve>=1.1.3
|
|
56
58
|
Requires-Dist: textual-speedups
|
|
57
59
|
Requires-Dist: typer~=0.19
|
|
58
60
|
Requires-Dist: uv
|
|
@@ -29,7 +29,7 @@ socx = 'socx.__main__:main'
|
|
|
29
29
|
[project]
|
|
30
30
|
name = "socx-cli"
|
|
31
31
|
readme = "README.md"
|
|
32
|
-
version = "0.13.
|
|
32
|
+
version = "0.13.9"
|
|
33
33
|
license = "Apache-2.0"
|
|
34
34
|
authors = [{ name = "Sagi Kimhi", email = "sagi.kim5@gmail.com" }]
|
|
35
35
|
maintainers = [{ name = "Sagi Kimhi", email = "sagi.kim5@gmail.com" }]
|
|
@@ -83,6 +83,8 @@ dependencies = [
|
|
|
83
83
|
"pydantic-settings>=2.12.0",
|
|
84
84
|
"sqlmodel>=0.0.31",
|
|
85
85
|
"anyio[trio]>=4.12.1",
|
|
86
|
+
"blinker>=1.9.0",
|
|
87
|
+
"textual-serve>=1.1.3",
|
|
86
88
|
]
|
|
87
89
|
|
|
88
90
|
[project.urls]
|
|
@@ -129,7 +131,7 @@ docs = [
|
|
|
129
131
|
"mkdocs-llmstxt>=0.4.0",
|
|
130
132
|
"mkdocs-coverage",
|
|
131
133
|
"mkdocs-glightbox",
|
|
132
|
-
"mkdocstrings
|
|
134
|
+
"mkdocstrings[python]>=0.18",
|
|
133
135
|
"mkdocs-material[git, recommended, imaging]",
|
|
134
136
|
"mkdocs-section-index",
|
|
135
137
|
"griffe-typingdoc>=0.3.0",
|
|
@@ -90,6 +90,7 @@ __all__ = (
|
|
|
90
90
|
# config
|
|
91
91
|
"schema",
|
|
92
92
|
"settings",
|
|
93
|
+
"Model",
|
|
93
94
|
"Script",
|
|
94
95
|
"NewPath",
|
|
95
96
|
"FilePath",
|
|
@@ -139,6 +140,7 @@ __all__ = (
|
|
|
139
140
|
|
|
140
141
|
from socx.core import enums as enums
|
|
141
142
|
from socx.core import schema as schema
|
|
143
|
+
from socx.core import Model as Model
|
|
142
144
|
from socx.core import Script as Script
|
|
143
145
|
from socx.core import NewPath as NewPath
|
|
144
146
|
from socx.core import FilePath as FilePath
|
|
@@ -46,10 +46,12 @@ def cwd_cb(ctx: Context, param: Parameter, value: Path) -> Path:
|
|
|
46
46
|
def debug_cb(_: Context, param: Parameter, value: bool) -> bool:
|
|
47
47
|
"""Enable debug logging and persist the CLI switch to settings."""
|
|
48
48
|
socx_logger = _get_logger()
|
|
49
|
+
settings[param.name] = value
|
|
49
50
|
settings.cli.params[param.name] = value
|
|
50
51
|
if value:
|
|
51
52
|
set_level(Level.DEBUG, socx_logger)
|
|
52
53
|
settings.cli.params["verbosity"] = get_level().name
|
|
54
|
+
settings.logging.handlers.console.level = Level.DEBUG.name
|
|
53
55
|
return value
|
|
54
56
|
|
|
55
57
|
|
|
@@ -10,6 +10,7 @@ from typing import Any
|
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
|
|
12
12
|
from werkzeug.local import LocalProxy
|
|
13
|
+
from dynaconf.base import Settings as DynaSettings
|
|
13
14
|
|
|
14
15
|
from socx.config import converters
|
|
15
16
|
from socx.core import (
|
|
@@ -21,7 +22,10 @@ from socx.config._settings import Settings
|
|
|
21
22
|
from socx.patterns.mixins.proxy import ProxyMixin
|
|
22
23
|
|
|
23
24
|
|
|
24
|
-
class
|
|
25
|
+
class SettingsProxyBase(Settings, DynaSettings): ...
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class SettingsProxy(ProxyMixin[SettingsProxyBase], SettingsProxyBase): ...
|
|
25
29
|
|
|
26
30
|
|
|
27
31
|
logger = logging.getLogger(__name__)
|
|
@@ -25,7 +25,6 @@ from importlib import import_module
|
|
|
25
25
|
from functools import cached_property, singledispatchmethod
|
|
26
26
|
from collections.abc import Iterable, Callable
|
|
27
27
|
|
|
28
|
-
import sh
|
|
29
28
|
import rich_click as click
|
|
30
29
|
import rich_click.patch as click_patch
|
|
31
30
|
import rich_click.rich_click_theme as click_theme
|
|
@@ -310,8 +309,8 @@ class SymbolConverter(Converter[str | Lazy, Any]):
|
|
|
310
309
|
|
|
311
310
|
class CommandConverter(
|
|
312
311
|
Converter[
|
|
313
|
-
str | Lazy |
|
|
314
|
-
str | Lazy | click.Command,
|
|
312
|
+
str | Lazy | BaseCommand | click.Command | PluginModel,
|
|
313
|
+
str | Lazy | click.Command | click.Group,
|
|
315
314
|
]
|
|
316
315
|
):
|
|
317
316
|
"""Turn module or script references into Rich Click commands."""
|
|
@@ -351,7 +350,7 @@ class CommandConverter(
|
|
|
351
350
|
@overload
|
|
352
351
|
def __call__(
|
|
353
352
|
self,
|
|
354
|
-
value:
|
|
353
|
+
value: BaseCommand,
|
|
355
354
|
*args: Any,
|
|
356
355
|
**kwargs: Any,
|
|
357
356
|
) -> click.Command: ...
|
|
@@ -374,10 +373,10 @@ class CommandConverter(
|
|
|
374
373
|
@_validate
|
|
375
374
|
def __call__(
|
|
376
375
|
self,
|
|
377
|
-
value: str | Lazy |
|
|
376
|
+
value: str | Lazy | BaseCommand | click.Command | PluginModel,
|
|
378
377
|
*args: Any,
|
|
379
378
|
**kwargs: Any,
|
|
380
|
-
) -> Lazy | click.Command | click.Group:
|
|
379
|
+
) -> str | Lazy | click.Command | click.Group:
|
|
381
380
|
"""Build a Click command from dotted paths or reuse existing ones."""
|
|
382
381
|
if isinstance(value, Lazy):
|
|
383
382
|
if value.casting is self:
|
|
@@ -401,9 +400,9 @@ class CommandConverter(
|
|
|
401
400
|
nonlocal value
|
|
402
401
|
|
|
403
402
|
if TYPE_CHECKING:
|
|
404
|
-
value = cast(str |
|
|
403
|
+
value = cast(str | BaseCommand | PluginModel, value)
|
|
405
404
|
|
|
406
|
-
if isinstance(value,
|
|
405
|
+
if isinstance(value, str | BaseCommand):
|
|
407
406
|
return self._run_shell_script(value, *args)
|
|
408
407
|
|
|
409
408
|
if isinstance(value, PluginModel) and value.is_script():
|
|
@@ -679,7 +678,7 @@ class CommandConverter(
|
|
|
679
678
|
)
|
|
680
679
|
|
|
681
680
|
def is_shell_command(self, value: Any) -> bool:
|
|
682
|
-
return isinstance(value,
|
|
681
|
+
return isinstance(value, BaseCommand)
|
|
683
682
|
|
|
684
683
|
def is_click_command(self, value: Any) -> bool:
|
|
685
684
|
return isinstance(value, click.Command)
|
|
@@ -7,6 +7,7 @@ __all__ = (
|
|
|
7
7
|
"schema",
|
|
8
8
|
"metadata",
|
|
9
9
|
# types
|
|
10
|
+
"Model",
|
|
10
11
|
"Script",
|
|
11
12
|
"NewPath",
|
|
12
13
|
"FilePath",
|
|
@@ -57,6 +58,7 @@ from . import paths as paths
|
|
|
57
58
|
from . import schema as schema
|
|
58
59
|
from . import metadata as metadata
|
|
59
60
|
|
|
61
|
+
from socx.core.schema import Model as Model
|
|
60
62
|
from socx.core.schema import Script as Script
|
|
61
63
|
from socx.core.schema import NewPath as NewPath
|
|
62
64
|
from socx.core.schema import FilePath as FilePath
|
|
@@ -3,7 +3,6 @@ from __future__ import annotations
|
|
|
3
3
|
import enum
|
|
4
4
|
from typing import Self
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from functools import cache
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
class AutoNumber(int, enum.ReprEnum):
|
|
@@ -18,22 +17,20 @@ class AutoNumber(int, enum.ReprEnum):
|
|
|
18
17
|
|
|
19
18
|
|
|
20
19
|
class SettingsFormat(AutoNumber):
|
|
21
|
-
|
|
22
|
-
Yaml = ".yaml", ".yml"
|
|
20
|
+
Ini = ".ini", ".conf"
|
|
23
21
|
Toml = ".toml"
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
Yaml = ".yaml", ".yml"
|
|
23
|
+
Json = ".json", ".jsonc", ".json5"
|
|
24
|
+
Python = ".py"
|
|
26
25
|
|
|
27
26
|
def __init__(self, extension: str, *extensions: str) -> None:
|
|
28
27
|
self.extensions = {extension, *extensions}
|
|
29
28
|
|
|
30
29
|
@classmethod
|
|
31
|
-
@cache
|
|
32
30
|
def all_extensions(cls) -> set[str]:
|
|
33
31
|
return {extension for member in cls for extension in member.extensions}
|
|
34
32
|
|
|
35
33
|
@classmethod
|
|
36
|
-
@cache
|
|
37
34
|
def from_path(cls, path: str | Path) -> SettingsFormat:
|
|
38
35
|
if isinstance(path, str):
|
|
39
36
|
path = Path(path)
|
|
@@ -2,6 +2,7 @@ __all__ = (
|
|
|
2
2
|
"git",
|
|
3
3
|
"types",
|
|
4
4
|
"plugin",
|
|
5
|
+
"Model",
|
|
5
6
|
"Script",
|
|
6
7
|
"NewPath",
|
|
7
8
|
"FilePath",
|
|
@@ -15,6 +16,7 @@ from . import plugin as plugin
|
|
|
15
16
|
|
|
16
17
|
from .git import git as git
|
|
17
18
|
|
|
19
|
+
from socx.core.schema.types import Model as Model
|
|
18
20
|
from socx.core.schema.types import Script as Script
|
|
19
21
|
from socx.core.schema.types import NewPath as NewPath
|
|
20
22
|
from socx.core.schema.types import FilePath as FilePath
|
|
@@ -7,18 +7,14 @@ from pathlib import Path
|
|
|
7
7
|
|
|
8
8
|
from box import SBox
|
|
9
9
|
import rich_click as click
|
|
10
|
-
from pydantic import Field
|
|
10
|
+
from pydantic import Field
|
|
11
11
|
|
|
12
|
-
from socx.core.schema.types import DirectoryPath, Script
|
|
12
|
+
from socx.core.schema.types import DirectoryPath, Script, Model
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
class PluginModel(
|
|
15
|
+
class PluginModel(Model):
|
|
16
16
|
"""Metadata describing a plugin-backed CLI command."""
|
|
17
17
|
|
|
18
|
-
name: str = Field(
|
|
19
|
-
..., pattern=r"[a-zA-Z0-9_-]+", description="Name of the plugin."
|
|
20
|
-
)
|
|
21
|
-
|
|
22
18
|
cwd: DirectoryPath = Field(
|
|
23
19
|
default_factory=Path.cwd,
|
|
24
20
|
description=dedent("""
|
|
@@ -29,83 +25,89 @@ class PluginModel(BaseModel):
|
|
|
29
25
|
|
|
30
26
|
env: dict[str, str] = Field(
|
|
31
27
|
default_factory=dict,
|
|
32
|
-
description="""
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"""
|
|
28
|
+
description=dedent("""
|
|
29
|
+
Environment variables that should be present when the
|
|
30
|
+
command/script is invoked
|
|
31
|
+
"""),
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
name: str = Field(
|
|
35
|
+
..., pattern=r"[a-zA-Z0-9_-]+", description="Name of the plugin."
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
help: str = Field(
|
|
39
|
+
default="",
|
|
40
|
+
description=dedent("""
|
|
41
|
+
Description of what the plugin does to be printed during plugin
|
|
42
|
+
invocation if any of -h or --help flags were passed with the
|
|
43
|
+
command.
|
|
44
|
+
"""),
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
enabled: bool = Field(
|
|
48
|
+
True,
|
|
49
|
+
description=dedent("""
|
|
50
|
+
Enable/disable the plugin. Disabled plugins are hidden and cannot be
|
|
51
|
+
invoked from the commandline. Defaults to True.
|
|
52
|
+
"""),
|
|
36
53
|
)
|
|
37
54
|
|
|
38
55
|
timeout: float | None = Field(
|
|
39
|
-
|
|
56
|
+
None,
|
|
40
57
|
ge=0,
|
|
41
|
-
description="""
|
|
58
|
+
description=dedent("""
|
|
42
59
|
An optional timeout in seconds for the plugin execution.
|
|
43
60
|
If left unspecified, then plugin execution may last indefinitely.
|
|
44
|
-
""",
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
enabled: bool = Field(
|
|
48
|
-
default=True,
|
|
49
|
-
description="""
|
|
50
|
-
Whether or not the plugin should be enabled.
|
|
51
|
-
If left unspecified, defaults to True.
|
|
52
|
-
""",
|
|
61
|
+
"""),
|
|
53
62
|
)
|
|
54
63
|
|
|
55
64
|
fresh_env: bool = Field(
|
|
56
|
-
|
|
57
|
-
description="""
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
""",
|
|
65
|
+
False,
|
|
66
|
+
description=dedent("""
|
|
67
|
+
Whether or not to execute the plugin in a fresh environment.
|
|
68
|
+
A fresh environment is an environment with no environment
|
|
69
|
+
variables defined other than those defined in the ``env`` field.
|
|
70
|
+
A non-fresh environment will contain all environment variables of
|
|
71
|
+
the current process, as well as any variables defined in the
|
|
72
|
+
``env`` field.
|
|
73
|
+
If left unspecified, defaults to False.
|
|
74
|
+
"""),
|
|
66
75
|
)
|
|
67
76
|
|
|
68
77
|
script: Script = Field(
|
|
69
|
-
|
|
70
|
-
description="""
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
"""
|
|
78
|
+
"",
|
|
79
|
+
description=dedent("""
|
|
80
|
+
A shell command or a path to an executable file to run on plugin
|
|
81
|
+
invocation.
|
|
82
|
+
"""),
|
|
83
|
+
exclude_if=bool,
|
|
74
84
|
)
|
|
75
85
|
|
|
76
86
|
command: str | click.Command = Field(
|
|
77
87
|
default="",
|
|
78
88
|
pattern=r"(((((\w+)(.|/))*)(\w+))(:(\w+))?)?",
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
help: str = Field(
|
|
87
|
-
default="",
|
|
88
|
-
description="""
|
|
89
|
-
Description of what the plugin does to be printed during plugin
|
|
90
|
-
invocation if any of -h or --help flags were passed with the
|
|
91
|
-
command.
|
|
92
|
-
""".strip(),
|
|
89
|
+
exclude_if=bool,
|
|
90
|
+
description=dedent("""
|
|
91
|
+
A path to a python module or symbol that will be called upon
|
|
92
|
+
plugin invocation specified in the form of
|
|
93
|
+
`<module_path/file_path>[:<symbol_name>]`.
|
|
94
|
+
"""),
|
|
93
95
|
)
|
|
94
96
|
|
|
95
97
|
panel: str = Field(
|
|
96
98
|
default="Plugins",
|
|
97
|
-
description="""
|
|
99
|
+
description=dedent("""
|
|
98
100
|
Custom panel name in which plugin help text will be displayed when
|
|
99
101
|
CLI is invoked with the -h/--help flag.
|
|
100
|
-
"""
|
|
102
|
+
"""),
|
|
101
103
|
)
|
|
102
104
|
|
|
103
105
|
epilog: str = Field(
|
|
104
106
|
default="",
|
|
105
|
-
description="""
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
"""
|
|
107
|
+
description=dedent("""
|
|
108
|
+
Help string printed at the end of the help page after everything
|
|
109
|
+
else.
|
|
110
|
+
"""),
|
|
109
111
|
)
|
|
110
112
|
|
|
111
113
|
aliases: tuple[str, ...] = Field(
|
|
@@ -118,12 +120,6 @@ class PluginModel(BaseModel):
|
|
|
118
120
|
description="The short help to use for this command",
|
|
119
121
|
)
|
|
120
122
|
|
|
121
|
-
model_config = ConfigDict(
|
|
122
|
-
extra="allow",
|
|
123
|
-
from_attributes=True,
|
|
124
|
-
arbitrary_types_allowed=True,
|
|
125
|
-
)
|
|
126
|
-
|
|
127
123
|
def is_script(self) -> bool:
|
|
128
124
|
return bool(self.script)
|
|
129
125
|
|
|
@@ -13,6 +13,8 @@ from pydantic import (
|
|
|
13
13
|
GetJsonSchemaHandler,
|
|
14
14
|
BeforeValidator,
|
|
15
15
|
PlainSerializer,
|
|
16
|
+
ConfigDict,
|
|
17
|
+
BaseModel,
|
|
16
18
|
)
|
|
17
19
|
|
|
18
20
|
|
|
@@ -232,3 +234,11 @@ Script = Annotated[
|
|
|
232
234
|
BeforeValidator(validate_script),
|
|
233
235
|
PlainSerializer(str, str),
|
|
234
236
|
]
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
class Model(BaseModel):
|
|
240
|
+
model_config = ConfigDict(
|
|
241
|
+
extra="allow",
|
|
242
|
+
from_attributes=True,
|
|
243
|
+
arbitrary_types_allowed=True,
|
|
244
|
+
)
|
|
@@ -121,7 +121,7 @@ _console_cv = contextvars.ContextVar[Console]("console")
|
|
|
121
121
|
|
|
122
122
|
_console_cv.set(_console)
|
|
123
123
|
|
|
124
|
-
console: ConsoleProxy = LocalProxy(
|
|
124
|
+
console: ConsoleProxy = LocalProxy(
|
|
125
125
|
_console_cv,
|
|
126
126
|
unbound_message="""
|
|
127
127
|
Working outside of application context.
|
|
@@ -129,4 +129,4 @@ console: ConsoleProxy = LocalProxy( # type: ignore[assignment]
|
|
|
129
129
|
Attempted to use functionality that expected a current application to
|
|
130
130
|
be set. To solve this, set up an app context.
|
|
131
131
|
""",
|
|
132
|
-
)
|
|
132
|
+
) # ty:ignore[invalid-assignment]
|
|
@@ -139,26 +139,26 @@ def _get_file_handler(
|
|
|
139
139
|
tracebacks_suppress: Iterable[ModuleType] | None = None,
|
|
140
140
|
tracebacks_show_locals: bool = True,
|
|
141
141
|
) -> logging.Handler:
|
|
142
|
-
import atexit
|
|
143
142
|
|
|
144
143
|
def close_if_open(file: IO) -> None:
|
|
145
144
|
if not file.closed:
|
|
146
145
|
file.close()
|
|
147
146
|
|
|
148
147
|
mode = mode or "a"
|
|
149
|
-
file = open(path, mode=mode)
|
|
150
|
-
atexit.register(close_if_open, file)
|
|
151
|
-
handler = _get_console_handler(
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
)
|
|
148
|
+
# file = open(path, mode=mode)
|
|
149
|
+
# atexit.register(close_if_open, file)
|
|
150
|
+
# handler = _get_console_handler(
|
|
151
|
+
# file=file,
|
|
152
|
+
# level=level,
|
|
153
|
+
# stderr=stderr,
|
|
154
|
+
# tab_size=tab_size,
|
|
155
|
+
# tracebacks=tracebacks,
|
|
156
|
+
# force_terminal=force_terminal,
|
|
157
|
+
# tracebacks_theme=tracebacks_theme,
|
|
158
|
+
# tracebacks_suppress=tracebacks_suppress,
|
|
159
|
+
# tracebacks_show_locals=tracebacks_show_locals,
|
|
160
|
+
# )
|
|
161
|
+
handler = logging.handlers.WatchedFileHandler(path, mode)
|
|
162
162
|
handler.name = "file"
|
|
163
163
|
handler.setFormatter(DEFAULT_CHILD_FORMATTER)
|
|
164
164
|
return handler
|