omdev 0.0.0.dev78__tar.gz → 0.0.0.dev79__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.
Potentially problematic release.
This version of omdev might be problematic. Click here for more details.
- {omdev-0.0.0.dev78/omdev.egg-info → omdev-0.0.0.dev79}/PKG-INFO +2 -2
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/.manifests.json +6 -6
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/classdot.py +1 -1
- omdev-0.0.0.dev79/omdev/cli/main.py +288 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/scripts/execrss.py +1 -1
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/scripts/exectime.py +1 -1
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/scripts/importtrace.py +1 -1
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/tools/importscan.py +1 -1
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/tools/mkrelimp.py +1 -1
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79/omdev.egg-info}/PKG-INFO +2 -2
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev.egg-info/requires.txt +1 -1
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/pyproject.toml +2 -2
- omdev-0.0.0.dev78/omdev/cli/main.py +0 -167
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/LICENSE +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/MANIFEST.in +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/README.rst +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/__about__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/__init__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/amalg/__init__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/amalg/__main__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/amalg/amalg.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/antlr/__init__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/antlr/_antlr/__init__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/antlr/consts.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/antlr/gen.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/bracepy.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cache/__init__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cache/compute/__init__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cache/compute/cache.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cache/compute/contexts.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cache/compute/currents.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cache/compute/fns.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cache/compute/resolvers.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cache/compute/storage.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cache/compute/types.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cache/data/__init__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cache/data/actions.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cache/data/cache.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cache/data/consts.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cache/data/defaults.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cache/data/manifests.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cache/data/specs.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/__init__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/_boilerplate.cc +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/_distutils/LICENSE +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/_distutils/__init__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/_distutils/build_ext.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/_distutils/compilers/__init__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/_distutils/compilers/ccompiler.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/_distutils/compilers/options.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/_distutils/compilers/unixccompiler.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/_distutils/dir_util.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/_distutils/errors.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/_distutils/extension.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/_distutils/file_util.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/_distutils/modified.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/_distutils/spawn.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/_distutils/sysconfig.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/_distutils/util.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/_distutils/version.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/build.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/cmake.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/importhook.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/magic.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cexts/scan.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cli/__init__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cli/__main__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cli/_pathhack.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cli/clicli.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cli/install.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cli/managers.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cli/types.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/cmake.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/findimports.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/findmagic.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/git.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/imgur.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/interp/__init__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/interp/__main__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/interp/cli.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/interp/inspect.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/interp/providers.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/interp/pyenv.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/interp/resolvers.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/interp/standalone.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/interp/system.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/interp/types.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/manifests/__init__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/manifests/build.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/manifests/load.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/manifests/types.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/mypy/__init__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/mypy/debug.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/packaging/__init__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/packaging/names.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/packaging/requires.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/packaging/specifiers.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/packaging/versions.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/precheck/__init__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/precheck/__main__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/precheck/base.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/precheck/git.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/precheck/lite.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/precheck/precheck.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/precheck/scripts.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/pyproject/__init__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/pyproject/__main__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/pyproject/cexts.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/pyproject/cli.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/pyproject/configs.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/pyproject/pkg.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/pyproject/reqs.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/revisions.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/scripts/__init__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/scripts/bumpversion.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/scripts/interp.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/scripts/pyproject.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/secrets.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/tokens.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/toml/__init__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/toml/parser.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/toml/writer.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/tools/__init__.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/tools/dockertools.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/tools/gittools.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/tools/nbtools.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/tools/piptools.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/tools/proftools.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/tools/rsttool.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/tools/sqlrepl.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev/wheelfile.py +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev.egg-info/SOURCES.txt +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev.egg-info/dependency_links.txt +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev.egg-info/entry_points.txt +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/omdev.egg-info/top_level.txt +0 -0
- {omdev-0.0.0.dev78 → omdev-0.0.0.dev79}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: omdev
|
|
3
|
-
Version: 0.0.0.
|
|
3
|
+
Version: 0.0.0.dev79
|
|
4
4
|
Summary: omdev
|
|
5
5
|
Author: wrmsr
|
|
6
6
|
License: BSD-3-Clause
|
|
@@ -12,7 +12,7 @@ Classifier: Operating System :: OS Independent
|
|
|
12
12
|
Classifier: Operating System :: POSIX
|
|
13
13
|
Requires-Python: ~=3.12
|
|
14
14
|
License-File: LICENSE
|
|
15
|
-
Requires-Dist: omlish==0.0.0.
|
|
15
|
+
Requires-Dist: omlish==0.0.0.dev79
|
|
16
16
|
Provides-Extra: all
|
|
17
17
|
Requires-Dist: black~=24.10; extra == "all"
|
|
18
18
|
Requires-Dist: pycparser~=2.22; extra == "all"
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"line": 62,
|
|
31
31
|
"value": {
|
|
32
32
|
"$.cli.types.CliModule": {
|
|
33
|
-
"cmd_name": "classdot",
|
|
33
|
+
"cmd_name": "py/classdot",
|
|
34
34
|
"mod_name": "omdev.classdot"
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
"line": 11,
|
|
103
103
|
"value": {
|
|
104
104
|
"$.cli.types.CliModule": {
|
|
105
|
-
"cmd_name": "execrss",
|
|
105
|
+
"cmd_name": "py/execrss",
|
|
106
106
|
"mod_name": "omdev.scripts.execrss"
|
|
107
107
|
}
|
|
108
108
|
}
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
"line": 7,
|
|
115
115
|
"value": {
|
|
116
116
|
"$.cli.types.CliModule": {
|
|
117
|
-
"cmd_name": "exectime",
|
|
117
|
+
"cmd_name": "py/exectime",
|
|
118
118
|
"mod_name": "omdev.scripts.exectime"
|
|
119
119
|
}
|
|
120
120
|
}
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
"line": 481,
|
|
127
127
|
"value": {
|
|
128
128
|
"$.cli.types.CliModule": {
|
|
129
|
-
"cmd_name": "importtrace",
|
|
129
|
+
"cmd_name": "py/importtrace",
|
|
130
130
|
"mod_name": "omdev.scripts.importtrace"
|
|
131
131
|
}
|
|
132
132
|
}
|
|
@@ -162,7 +162,7 @@
|
|
|
162
162
|
"line": 166,
|
|
163
163
|
"value": {
|
|
164
164
|
"$.cli.types.CliModule": {
|
|
165
|
-
"cmd_name": "importscan",
|
|
165
|
+
"cmd_name": "py/importscan",
|
|
166
166
|
"mod_name": "omdev.tools.importscan"
|
|
167
167
|
}
|
|
168
168
|
}
|
|
@@ -174,7 +174,7 @@
|
|
|
174
174
|
"line": 148,
|
|
175
175
|
"value": {
|
|
176
176
|
"$.cli.types.CliModule": {
|
|
177
|
-
"cmd_name": "mkrelimp",
|
|
177
|
+
"cmd_name": "py/mkrelimp",
|
|
178
178
|
"mod_name": "omdev.tools.mkrelimp"
|
|
179
179
|
}
|
|
180
180
|
}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TODO:
|
|
3
|
+
- py/foo - root command 'py'
|
|
4
|
+
- cache ldr.discover() somehow if in uvx/pipx - very slow
|
|
5
|
+
- <venv-root>/.omdev-cli-manifest-cache.json - {pkg_name: manifests_json}
|
|
6
|
+
- allow manually specifying manifest packages
|
|
7
|
+
"""
|
|
8
|
+
import argparse
|
|
9
|
+
import dataclasses as dc
|
|
10
|
+
import os
|
|
11
|
+
import runpy
|
|
12
|
+
import sys
|
|
13
|
+
import typing as ta
|
|
14
|
+
|
|
15
|
+
from omlish import check
|
|
16
|
+
from omlish.lite.cached import cached_nullary
|
|
17
|
+
|
|
18
|
+
from ..manifests.load import ManifestLoader
|
|
19
|
+
from .types import CliCmd
|
|
20
|
+
from .types import CliFunc
|
|
21
|
+
from .types import CliModule
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
##
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _post_install(cli_pkg: str) -> None:
|
|
28
|
+
from .managers import setup_install_manager
|
|
29
|
+
|
|
30
|
+
setup_install_manager(cli_pkg)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
##
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
_CLI_FUNCS: ta.Sequence[CliFunc] = [
|
|
37
|
+
CliFunc('_post_install', _post_install),
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
##
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
StrTuple: ta.TypeAlias = tuple[str, ...]
|
|
45
|
+
RecStrMap: ta.TypeAlias = ta.Mapping[str, ta.Union[str, 'RecStrMap']]
|
|
46
|
+
RecCmdMap: ta.TypeAlias = ta.Mapping[str, ta.Union[CliCmd, 'RecCmdMap']]
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class CliCmdSet:
|
|
50
|
+
def __init__(self, cmds: ta.Iterable[CliCmd]) -> None:
|
|
51
|
+
super().__init__()
|
|
52
|
+
|
|
53
|
+
self._cmds = list(cmds)
|
|
54
|
+
|
|
55
|
+
@dc.dataclass(frozen=True)
|
|
56
|
+
class Entry:
|
|
57
|
+
cmd: CliCmd
|
|
58
|
+
|
|
59
|
+
exec_paths: ta.Sequence[StrTuple] # len > 1, len([0]) > 1
|
|
60
|
+
help_path: StrTuple | None
|
|
61
|
+
|
|
62
|
+
def _make_entry(self, cmd: CliCmd) -> Entry:
|
|
63
|
+
help_path: StrTuple | None
|
|
64
|
+
|
|
65
|
+
if isinstance(cmd.cmd_name, str):
|
|
66
|
+
ns = [cmd.cmd_name]
|
|
67
|
+
else:
|
|
68
|
+
ns = list(cmd.cmd_name)
|
|
69
|
+
exec_paths = [tuple(n.split('/')) for n in ns]
|
|
70
|
+
|
|
71
|
+
if isinstance(cmd.cmd_name, str) and cmd.cmd_name[0] == '_':
|
|
72
|
+
help_path = None
|
|
73
|
+
|
|
74
|
+
elif isinstance(cmd, CliFunc):
|
|
75
|
+
help_path = ('-', *exec_paths[0])
|
|
76
|
+
|
|
77
|
+
elif isinstance(cmd, CliModule):
|
|
78
|
+
help_path = (cmd.mod_name.partition('.')[0], *exec_paths[0])
|
|
79
|
+
|
|
80
|
+
else:
|
|
81
|
+
raise TypeError(cmd)
|
|
82
|
+
|
|
83
|
+
return CliCmdSet.Entry(
|
|
84
|
+
cmd,
|
|
85
|
+
|
|
86
|
+
exec_paths=exec_paths,
|
|
87
|
+
help_path=help_path,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
@cached_nullary
|
|
91
|
+
def entries(self) -> ta.Sequence[Entry]:
|
|
92
|
+
return [self._make_entry(c) for c in self._cmds]
|
|
93
|
+
|
|
94
|
+
@cached_nullary
|
|
95
|
+
def exec_tree(self) -> RecCmdMap:
|
|
96
|
+
d: dict = {}
|
|
97
|
+
for e in self.entries():
|
|
98
|
+
for ep in e.exec_paths:
|
|
99
|
+
c = d
|
|
100
|
+
for p in ep[:-1]:
|
|
101
|
+
n = c.setdefault(p, {})
|
|
102
|
+
if not isinstance(n, dict):
|
|
103
|
+
raise NameError(e) # noqa
|
|
104
|
+
c = n
|
|
105
|
+
|
|
106
|
+
h = ep[-1]
|
|
107
|
+
if h in c:
|
|
108
|
+
raise NameError(e) # noqa
|
|
109
|
+
|
|
110
|
+
c[h] = e.cmd
|
|
111
|
+
|
|
112
|
+
return d
|
|
113
|
+
|
|
114
|
+
@cached_nullary
|
|
115
|
+
def help_tree(self) -> RecStrMap:
|
|
116
|
+
d: dict = {}
|
|
117
|
+
for e in self.entries():
|
|
118
|
+
if not e.help_path:
|
|
119
|
+
continue
|
|
120
|
+
|
|
121
|
+
c = d
|
|
122
|
+
for p in e.help_path[:-1]:
|
|
123
|
+
n = c.setdefault(p, {})
|
|
124
|
+
if not isinstance(n, dict):
|
|
125
|
+
raise NameError(e) # noqa
|
|
126
|
+
c = n
|
|
127
|
+
|
|
128
|
+
h = e.help_path[-1]
|
|
129
|
+
if h in c:
|
|
130
|
+
raise NameError(e)
|
|
131
|
+
|
|
132
|
+
if isinstance(e.cmd.cmd_name, str):
|
|
133
|
+
l = [e.cmd.cmd_name]
|
|
134
|
+
else:
|
|
135
|
+
l = list(e.cmd.cmd_name)
|
|
136
|
+
|
|
137
|
+
s = (
|
|
138
|
+
f'{l[0].split("/")[-1]}'
|
|
139
|
+
f'{(" (" + ", ".join(l[1:]) + ")") if len(l) > 1 else ""}'
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
c[h] = s
|
|
143
|
+
|
|
144
|
+
return d
|
|
145
|
+
|
|
146
|
+
class SelectedCmd(ta.NamedTuple):
|
|
147
|
+
cmd: CliCmd
|
|
148
|
+
args: ta.Sequence[str]
|
|
149
|
+
|
|
150
|
+
class InvalidCmd(ta.NamedTuple):
|
|
151
|
+
path: ta.Sequence[str]
|
|
152
|
+
|
|
153
|
+
def select_cmd(self, args: ta.Sequence[str]) -> SelectedCmd | InvalidCmd:
|
|
154
|
+
check.not_isinstance(args, str)
|
|
155
|
+
|
|
156
|
+
d = self.exec_tree()
|
|
157
|
+
for i in range(len(args)):
|
|
158
|
+
n = args[i]
|
|
159
|
+
if n not in d:
|
|
160
|
+
return CliCmdSet.InvalidCmd(args[:i + 1])
|
|
161
|
+
|
|
162
|
+
c = d[n]
|
|
163
|
+
|
|
164
|
+
if isinstance(c, CliCmd):
|
|
165
|
+
return CliCmdSet.SelectedCmd(c, args[i + 1:])
|
|
166
|
+
elif isinstance(c, ta.Mapping):
|
|
167
|
+
d = c
|
|
168
|
+
else:
|
|
169
|
+
raise TypeError(c)
|
|
170
|
+
|
|
171
|
+
return CliCmdSet.InvalidCmd([])
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
##
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def _build_arg_parser() -> argparse.ArgumentParser:
|
|
178
|
+
parser = argparse.ArgumentParser()
|
|
179
|
+
parser.add_argument('--cli-pkg-root', action='append')
|
|
180
|
+
parser.add_argument('--cli-debug', action='store_true')
|
|
181
|
+
parser.add_argument('cmd', nargs='?')
|
|
182
|
+
parser.add_argument('args', nargs=argparse.REMAINDER)
|
|
183
|
+
return parser
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def _build_cmd_set(args: ta.Any) -> CliCmdSet:
|
|
187
|
+
ldr = ManifestLoader.from_entry_point(globals())
|
|
188
|
+
|
|
189
|
+
pkgs: list[str] = []
|
|
190
|
+
|
|
191
|
+
def scan_pkg_root(r: str) -> None:
|
|
192
|
+
r = os.path.expanduser(r)
|
|
193
|
+
for n in os.listdir(r):
|
|
194
|
+
if os.path.isdir(p := os.path.join(r, n)) and os.path.exists(os.path.join(p, '__init__.py')):
|
|
195
|
+
pkgs.append(n)
|
|
196
|
+
|
|
197
|
+
if args.cli_pkg_root:
|
|
198
|
+
for r in args.cli_pkg_root:
|
|
199
|
+
scan_pkg_root(r)
|
|
200
|
+
|
|
201
|
+
else:
|
|
202
|
+
pkgs.extend(ldr.discover())
|
|
203
|
+
|
|
204
|
+
if not pkgs:
|
|
205
|
+
scan_pkg_root(os.getcwd())
|
|
206
|
+
|
|
207
|
+
#
|
|
208
|
+
|
|
209
|
+
lst: list[CliCmd] = []
|
|
210
|
+
|
|
211
|
+
for m in ldr.load(*pkgs, only=[CliModule]):
|
|
212
|
+
lst.append(check.isinstance(m.value, CliModule))
|
|
213
|
+
|
|
214
|
+
lst.extend(_CLI_FUNCS)
|
|
215
|
+
|
|
216
|
+
#
|
|
217
|
+
|
|
218
|
+
return CliCmdSet(lst)
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def _select_cmd(args: ta.Any, cmds: CliCmdSet) -> CliCmdSet.SelectedCmd | int:
|
|
222
|
+
def print_err(*args, **kwargs): # noqa
|
|
223
|
+
print(*args, **kwargs, file=sys.stderr)
|
|
224
|
+
|
|
225
|
+
if args.cmd:
|
|
226
|
+
sel_cmd = cmds.select_cmd([args.cmd, *args.args])
|
|
227
|
+
if isinstance(sel_cmd, CliCmdSet.SelectedCmd):
|
|
228
|
+
return sel_cmd
|
|
229
|
+
elif isinstance(sel_cmd, CliCmdSet.InvalidCmd):
|
|
230
|
+
print_err(f'Invalid command: {" ".join(sel_cmd.path)}\n')
|
|
231
|
+
else:
|
|
232
|
+
raise TypeError(sel_cmd)
|
|
233
|
+
rc = 1
|
|
234
|
+
else:
|
|
235
|
+
rc = 0
|
|
236
|
+
|
|
237
|
+
print_err('Subcommands:\n')
|
|
238
|
+
|
|
239
|
+
def rec(d, pfx=''):
|
|
240
|
+
for k, v in sorted(d.items(), key=lambda t: t[0]):
|
|
241
|
+
if isinstance(v, str):
|
|
242
|
+
print_err(pfx + v)
|
|
243
|
+
else:
|
|
244
|
+
print_err(pfx + k)
|
|
245
|
+
rec(v, pfx + ' ')
|
|
246
|
+
if not pfx:
|
|
247
|
+
print_err('')
|
|
248
|
+
|
|
249
|
+
rec(cmds.help_tree())
|
|
250
|
+
|
|
251
|
+
return rc
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def _main() -> ta.Any:
|
|
255
|
+
parser = _build_arg_parser()
|
|
256
|
+
args = parser.parse_args()
|
|
257
|
+
|
|
258
|
+
def inner():
|
|
259
|
+
cmds = _build_cmd_set(args)
|
|
260
|
+
sel = _select_cmd(args, cmds)
|
|
261
|
+
|
|
262
|
+
if isinstance(sel, int):
|
|
263
|
+
return sel
|
|
264
|
+
|
|
265
|
+
cmd = sel.cmd
|
|
266
|
+
if isinstance(cmd, CliModule):
|
|
267
|
+
sys.argv = [args.cmd, *(sel.args or ())]
|
|
268
|
+
runpy._run_module_as_main(cmd.mod_name) # type: ignore # noqa
|
|
269
|
+
return 0
|
|
270
|
+
|
|
271
|
+
elif isinstance(cmd, CliFunc):
|
|
272
|
+
return cmd.fn(*(sel.args or ()))
|
|
273
|
+
|
|
274
|
+
else:
|
|
275
|
+
raise TypeError(cmd)
|
|
276
|
+
|
|
277
|
+
if args.cli_debug:
|
|
278
|
+
from omlish.diag.debug import debugging_on_exception
|
|
279
|
+
|
|
280
|
+
with debugging_on_exception():
|
|
281
|
+
return inner()
|
|
282
|
+
|
|
283
|
+
else:
|
|
284
|
+
return inner()
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
if __name__ == '__main__':
|
|
288
|
+
sys.exit(rc if isinstance(rc := _main(), int) else 0)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: omdev
|
|
3
|
-
Version: 0.0.0.
|
|
3
|
+
Version: 0.0.0.dev79
|
|
4
4
|
Summary: omdev
|
|
5
5
|
Author: wrmsr
|
|
6
6
|
License: BSD-3-Clause
|
|
@@ -12,7 +12,7 @@ Classifier: Operating System :: OS Independent
|
|
|
12
12
|
Classifier: Operating System :: POSIX
|
|
13
13
|
Requires-Python: ~=3.12
|
|
14
14
|
License-File: LICENSE
|
|
15
|
-
Requires-Dist: omlish==0.0.0.
|
|
15
|
+
Requires-Dist: omlish==0.0.0.dev79
|
|
16
16
|
Provides-Extra: all
|
|
17
17
|
Requires-Dist: black~=24.10; extra == "all"
|
|
18
18
|
Requires-Dist: pycparser~=2.22; extra == "all"
|
|
@@ -12,7 +12,7 @@ authors = [
|
|
|
12
12
|
urls = {source = 'https://github.com/wrmsr/omlish'}
|
|
13
13
|
license = {text = 'BSD-3-Clause'}
|
|
14
14
|
requires-python = '~=3.12'
|
|
15
|
-
version = '0.0.0.
|
|
15
|
+
version = '0.0.0.dev79'
|
|
16
16
|
classifiers = [
|
|
17
17
|
'License :: OSI Approved :: BSD License',
|
|
18
18
|
'Development Status :: 2 - Pre-Alpha',
|
|
@@ -22,7 +22,7 @@ classifiers = [
|
|
|
22
22
|
]
|
|
23
23
|
description = 'omdev'
|
|
24
24
|
dependencies = [
|
|
25
|
-
'omlish == 0.0.0.
|
|
25
|
+
'omlish == 0.0.0.dev79',
|
|
26
26
|
]
|
|
27
27
|
|
|
28
28
|
[project.optional-dependencies]
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
TODO:
|
|
3
|
-
- cache ldr.discover() somehow if in uvx/pipx - very slow
|
|
4
|
-
- <venv-root>/.omdev-cli-manifest-cache.json - {pkg_name: manifests_json}
|
|
5
|
-
- allow manually specifying manifest packages
|
|
6
|
-
"""
|
|
7
|
-
import argparse
|
|
8
|
-
import os
|
|
9
|
-
import runpy
|
|
10
|
-
import sys
|
|
11
|
-
import typing as ta
|
|
12
|
-
|
|
13
|
-
from omlish import check
|
|
14
|
-
|
|
15
|
-
from ..manifests.load import ManifestLoader
|
|
16
|
-
from .types import CliCmd
|
|
17
|
-
from .types import CliFunc
|
|
18
|
-
from .types import CliModule
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
##
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def _post_install(cli_pkg: str) -> None:
|
|
25
|
-
from .managers import setup_install_manager
|
|
26
|
-
|
|
27
|
-
setup_install_manager(cli_pkg)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
##
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
_CLI_FUNCS: ta.Sequence[CliFunc] = [
|
|
34
|
-
CliFunc('_post_install', _post_install),
|
|
35
|
-
]
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
##
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def _build_arg_parser() -> argparse.ArgumentParser:
|
|
42
|
-
parser = argparse.ArgumentParser()
|
|
43
|
-
parser.add_argument('--cli-pkg-root', action='append')
|
|
44
|
-
parser.add_argument('--cli-debug', action='store_true')
|
|
45
|
-
parser.add_argument('cmd', nargs='?')
|
|
46
|
-
parser.add_argument('args', nargs=argparse.REMAINDER)
|
|
47
|
-
return parser
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def _build_cmd_dct(args: ta.Any) -> ta.Mapping[str, CliCmd]:
|
|
51
|
-
ccs: list[CliCmd] = []
|
|
52
|
-
|
|
53
|
-
ldr = ManifestLoader.from_entry_point(globals())
|
|
54
|
-
|
|
55
|
-
pkgs: list[str] = []
|
|
56
|
-
|
|
57
|
-
def scan_pkg_root(r: str) -> None:
|
|
58
|
-
r = os.path.expanduser(r)
|
|
59
|
-
for n in os.listdir(r):
|
|
60
|
-
if os.path.isdir(p := os.path.join(r, n)) and os.path.exists(os.path.join(p, '__init__.py')):
|
|
61
|
-
pkgs.append(n)
|
|
62
|
-
|
|
63
|
-
if args.cli_pkg_root:
|
|
64
|
-
for r in args.cli_pkg_root:
|
|
65
|
-
scan_pkg_root(r)
|
|
66
|
-
|
|
67
|
-
else:
|
|
68
|
-
pkgs.extend(ldr.discover())
|
|
69
|
-
|
|
70
|
-
if not pkgs:
|
|
71
|
-
scan_pkg_root(os.getcwd())
|
|
72
|
-
|
|
73
|
-
for m in ldr.load(*pkgs, only=[CliModule]):
|
|
74
|
-
ccs.append(check.isinstance(m.value, CliModule))
|
|
75
|
-
|
|
76
|
-
ccs.extend(_CLI_FUNCS)
|
|
77
|
-
|
|
78
|
-
dct: dict[str, CliCmd] = {}
|
|
79
|
-
for cc in ccs:
|
|
80
|
-
for cn in [cc.cmd_name] if isinstance(cc.cmd_name, str) else cc.cmd_name:
|
|
81
|
-
if cn in dct:
|
|
82
|
-
raise NameError(cc)
|
|
83
|
-
dct[cn] = cc
|
|
84
|
-
|
|
85
|
-
return dct
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def _select_cmd(args: ta.Any, cmds: ta.Mapping[str, CliCmd]) -> CliCmd | int:
|
|
89
|
-
cmd = args.cmd
|
|
90
|
-
if cmd and cmd in cmds:
|
|
91
|
-
return cmds[cmd]
|
|
92
|
-
|
|
93
|
-
def print_err(*args, **kwargs): # noqa
|
|
94
|
-
print(*args, **kwargs, file=sys.stderr)
|
|
95
|
-
|
|
96
|
-
if cmd:
|
|
97
|
-
print_err(f'Invalid command: {cmd}\n')
|
|
98
|
-
rc = 1
|
|
99
|
-
else:
|
|
100
|
-
rc = 0
|
|
101
|
-
|
|
102
|
-
mset = set()
|
|
103
|
-
mdct: dict = {}
|
|
104
|
-
for cc in cmds.values():
|
|
105
|
-
if id(cc) in mset:
|
|
106
|
-
continue
|
|
107
|
-
mset.add(id(cc))
|
|
108
|
-
if isinstance(cc.cmd_name, str) and cc.cmd_name[0] == '_':
|
|
109
|
-
continue
|
|
110
|
-
if isinstance(cc, CliFunc):
|
|
111
|
-
mdct.setdefault('-', []).append(cc)
|
|
112
|
-
elif isinstance(cc, CliModule):
|
|
113
|
-
mdct.setdefault(cc.mod_name.partition('.')[0], []).append(cc)
|
|
114
|
-
else:
|
|
115
|
-
raise TypeError(cc)
|
|
116
|
-
|
|
117
|
-
print_err('Subcommands:\n')
|
|
118
|
-
for m, l in sorted(mdct.items(), key=lambda t: (t[0] == '-', t[0])):
|
|
119
|
-
print_err(f' {m}')
|
|
120
|
-
for cc in sorted(l, key=lambda c: c.primary_name):
|
|
121
|
-
if isinstance(cc.cmd_name, str):
|
|
122
|
-
print_err(f' {cc.cmd_name}')
|
|
123
|
-
else:
|
|
124
|
-
print_err(
|
|
125
|
-
f' {cc.cmd_name[0]}'
|
|
126
|
-
f'{(" (" + ", ".join(cc.cmd_name[1:]) + ")") if len(cc.cmd_name) > 1 else ""}',
|
|
127
|
-
)
|
|
128
|
-
print_err()
|
|
129
|
-
|
|
130
|
-
return rc
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
def _main() -> ta.Any:
|
|
134
|
-
parser = _build_arg_parser()
|
|
135
|
-
args = parser.parse_args()
|
|
136
|
-
|
|
137
|
-
def inner():
|
|
138
|
-
cmds = _build_cmd_dct(args)
|
|
139
|
-
sel = _select_cmd(args, cmds)
|
|
140
|
-
|
|
141
|
-
match sel:
|
|
142
|
-
case int():
|
|
143
|
-
return sel
|
|
144
|
-
|
|
145
|
-
case CliModule() as cm:
|
|
146
|
-
sys.argv = [args.cmd, *(args.args or ())]
|
|
147
|
-
runpy._run_module_as_main(cm.mod_name) # type: ignore # noqa
|
|
148
|
-
return 0
|
|
149
|
-
|
|
150
|
-
case CliFunc() as cf:
|
|
151
|
-
return cf.fn(*(args.args or ()))
|
|
152
|
-
|
|
153
|
-
case _:
|
|
154
|
-
raise TypeError(sel)
|
|
155
|
-
|
|
156
|
-
if args.cli_debug:
|
|
157
|
-
from omlish.diag.debug import debugging_on_exception
|
|
158
|
-
|
|
159
|
-
with debugging_on_exception():
|
|
160
|
-
return inner()
|
|
161
|
-
|
|
162
|
-
else:
|
|
163
|
-
return inner()
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
if __name__ == '__main__':
|
|
167
|
-
sys.exit(rc if isinstance(rc := _main(), int) else 0)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|