omdev 0.0.0.dev179__py3-none-any.whl → 0.0.0.dev181__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.
- omdev/.manifests.json +5 -5
- omdev/cli/clicli.py +6 -6
- omdev/imgur.py +1 -1
- omdev/interp/cli.py +3 -3
- omdev/interp/inspect.py +9 -4
- omdev/interp/providers/system.py +5 -2
- omdev/interp/pyenv/pyenv.py +5 -2
- omdev/interp/venvs.py +114 -0
- omdev/magic/__main__.py +11 -0
- omdev/magic/cli.py +54 -0
- omdev/magic/find.py +0 -45
- omdev/pycharm/cli.py +3 -3
- omdev/pyproject/cli.py +3 -3
- omdev/pyproject/configs.py +3 -4
- omdev/pyproject/inject.py +12 -0
- omdev/pyproject/venvs.py +16 -52
- omdev/scripts/interp.py +32 -27
- omdev/scripts/pyproject.py +267 -145
- omdev/tools/doc.py +2 -2
- omdev/tools/docker.py +8 -8
- omdev/tools/git.py +7 -7
- omdev/tools/notebook.py +1 -1
- omdev/tools/pip.py +4 -4
- omdev/tools/prof.py +1 -1
- omdev/tools/sqlrepl.py +1 -1
- {omdev-0.0.0.dev179.dist-info → omdev-0.0.0.dev181.dist-info}/METADATA +2 -2
- {omdev-0.0.0.dev179.dist-info → omdev-0.0.0.dev181.dist-info}/RECORD +31 -27
- {omdev-0.0.0.dev179.dist-info → omdev-0.0.0.dev181.dist-info}/LICENSE +0 -0
- {omdev-0.0.0.dev179.dist-info → omdev-0.0.0.dev181.dist-info}/WHEEL +0 -0
- {omdev-0.0.0.dev179.dist-info → omdev-0.0.0.dev181.dist-info}/entry_points.txt +0 -0
- {omdev-0.0.0.dev179.dist-info → omdev-0.0.0.dev181.dist-info}/top_level.txt +0 -0
omdev/scripts/pyproject.py
CHANGED
@@ -66,7 +66,7 @@ import time
|
|
66
66
|
import types
|
67
67
|
import typing as ta
|
68
68
|
import uuid
|
69
|
-
import weakref
|
69
|
+
import weakref
|
70
70
|
import zipfile
|
71
71
|
|
72
72
|
|
@@ -108,13 +108,18 @@ CheckOnRaiseFn = ta.Callable[[Exception], None] # ta.TypeAlias
|
|
108
108
|
CheckExceptionFactory = ta.Callable[..., Exception] # ta.TypeAlias
|
109
109
|
CheckArgsRenderer = ta.Callable[..., ta.Optional[str]] # ta.TypeAlias
|
110
110
|
|
111
|
+
# ../../omlish/lite/typing.py
|
112
|
+
A0 = ta.TypeVar('A0')
|
113
|
+
A1 = ta.TypeVar('A1')
|
114
|
+
A2 = ta.TypeVar('A2')
|
115
|
+
|
111
116
|
# ../packaging/specifiers.py
|
112
117
|
UnparsedVersion = ta.Union['Version', str]
|
113
118
|
UnparsedVersionVar = ta.TypeVar('UnparsedVersionVar', bound=UnparsedVersion)
|
114
119
|
CallableVersionOperator = ta.Callable[['Version', str], bool]
|
115
120
|
|
116
121
|
# ../../omlish/argparse/cli.py
|
117
|
-
|
122
|
+
ArgparseCmdFn = ta.Callable[[], ta.Optional[int]] # ta.TypeAlias
|
118
123
|
|
119
124
|
# ../../omlish/lite/inject.py
|
120
125
|
U = ta.TypeVar('U')
|
@@ -2575,6 +2580,54 @@ def format_num_bytes(num_bytes: int) -> str:
|
|
2575
2580
|
return f'{num_bytes / 1024 ** (len(FORMAT_NUM_BYTES_SUFFIXES) - 1):.2f}{FORMAT_NUM_BYTES_SUFFIXES[-1]}'
|
2576
2581
|
|
2577
2582
|
|
2583
|
+
########################################
|
2584
|
+
# ../../../omlish/lite/typing.py
|
2585
|
+
|
2586
|
+
|
2587
|
+
##
|
2588
|
+
# A workaround for typing deficiencies (like `Argument 2 to NewType(...) must be subclassable`).
|
2589
|
+
|
2590
|
+
|
2591
|
+
@dc.dataclass(frozen=True)
|
2592
|
+
class AnyFunc(ta.Generic[T]):
|
2593
|
+
fn: ta.Callable[..., T]
|
2594
|
+
|
2595
|
+
def __call__(self, *args: ta.Any, **kwargs: ta.Any) -> T:
|
2596
|
+
return self.fn(*args, **kwargs)
|
2597
|
+
|
2598
|
+
|
2599
|
+
@dc.dataclass(frozen=True)
|
2600
|
+
class Func0(ta.Generic[T]):
|
2601
|
+
fn: ta.Callable[[], T]
|
2602
|
+
|
2603
|
+
def __call__(self) -> T:
|
2604
|
+
return self.fn()
|
2605
|
+
|
2606
|
+
|
2607
|
+
@dc.dataclass(frozen=True)
|
2608
|
+
class Func1(ta.Generic[A0, T]):
|
2609
|
+
fn: ta.Callable[[A0], T]
|
2610
|
+
|
2611
|
+
def __call__(self, a0: A0) -> T:
|
2612
|
+
return self.fn(a0)
|
2613
|
+
|
2614
|
+
|
2615
|
+
@dc.dataclass(frozen=True)
|
2616
|
+
class Func2(ta.Generic[A0, A1, T]):
|
2617
|
+
fn: ta.Callable[[A0, A1], T]
|
2618
|
+
|
2619
|
+
def __call__(self, a0: A0, a1: A1) -> T:
|
2620
|
+
return self.fn(a0, a1)
|
2621
|
+
|
2622
|
+
|
2623
|
+
@dc.dataclass(frozen=True)
|
2624
|
+
class Func3(ta.Generic[A0, A1, A2, T]):
|
2625
|
+
fn: ta.Callable[[A0, A1, A2], T]
|
2626
|
+
|
2627
|
+
def __call__(self, a0: A0, a1: A1, a2: A2) -> T:
|
2628
|
+
return self.fn(a0, a1, a2)
|
2629
|
+
|
2630
|
+
|
2578
2631
|
########################################
|
2579
2632
|
# ../../../omlish/logs/filters.py
|
2580
2633
|
|
@@ -2910,16 +2963,6 @@ def find_magic_py_modules(
|
|
2910
2963
|
yield fp
|
2911
2964
|
|
2912
2965
|
|
2913
|
-
##
|
2914
|
-
|
2915
|
-
|
2916
|
-
# # @omlish-manifest
|
2917
|
-
# _CLI_MODULE = {'$omdev.cli.types.CliModule': {
|
2918
|
-
# 'cmd_name': 'py/findmagic',
|
2919
|
-
# 'mod_name': __name__,
|
2920
|
-
# }}
|
2921
|
-
|
2922
|
-
|
2923
2966
|
########################################
|
2924
2967
|
# ../../packaging/specifiers.py
|
2925
2968
|
# Copyright (c) Donald Stufft and individual contributors.
|
@@ -3553,15 +3596,15 @@ def argparse_arg(*args, **kwargs) -> ArgparseArg:
|
|
3553
3596
|
|
3554
3597
|
|
3555
3598
|
@dc.dataclass(eq=False)
|
3556
|
-
class
|
3599
|
+
class ArgparseCmd:
|
3557
3600
|
name: str
|
3558
|
-
fn:
|
3601
|
+
fn: ArgparseCmdFn
|
3559
3602
|
args: ta.Sequence[ArgparseArg] = () # noqa
|
3560
3603
|
|
3561
3604
|
# _: dc.KW_ONLY
|
3562
3605
|
|
3563
3606
|
aliases: ta.Optional[ta.Sequence[str]] = None
|
3564
|
-
parent: ta.Optional['
|
3607
|
+
parent: ta.Optional['ArgparseCmd'] = None
|
3565
3608
|
accepts_unknown: bool = False
|
3566
3609
|
|
3567
3610
|
def __post_init__(self) -> None:
|
@@ -3576,7 +3619,7 @@ class ArgparseCommand:
|
|
3576
3619
|
|
3577
3620
|
check.arg(callable(self.fn))
|
3578
3621
|
check.arg(all(isinstance(a, ArgparseArg) for a in self.args))
|
3579
|
-
check.isinstance(self.parent, (
|
3622
|
+
check.isinstance(self.parent, (ArgparseCmd, type(None)))
|
3580
3623
|
check.isinstance(self.accepts_unknown, bool)
|
3581
3624
|
|
3582
3625
|
functools.update_wrapper(self, self.fn)
|
@@ -3590,21 +3633,21 @@ class ArgparseCommand:
|
|
3590
3633
|
return self.fn(*args, **kwargs)
|
3591
3634
|
|
3592
3635
|
|
3593
|
-
def
|
3636
|
+
def argparse_cmd(
|
3594
3637
|
*args: ArgparseArg,
|
3595
3638
|
name: ta.Optional[str] = None,
|
3596
3639
|
aliases: ta.Optional[ta.Iterable[str]] = None,
|
3597
|
-
parent: ta.Optional[
|
3640
|
+
parent: ta.Optional[ArgparseCmd] = None,
|
3598
3641
|
accepts_unknown: bool = False,
|
3599
|
-
) -> ta.Any: # ta.Callable[[
|
3642
|
+
) -> ta.Any: # ta.Callable[[ArgparseCmdFn], ArgparseCmd]: # FIXME
|
3600
3643
|
for arg in args:
|
3601
3644
|
check.isinstance(arg, ArgparseArg)
|
3602
3645
|
check.isinstance(name, (str, type(None)))
|
3603
|
-
check.isinstance(parent, (
|
3646
|
+
check.isinstance(parent, (ArgparseCmd, type(None)))
|
3604
3647
|
check.not_isinstance(aliases, str)
|
3605
3648
|
|
3606
3649
|
def inner(fn):
|
3607
|
-
return
|
3650
|
+
return ArgparseCmd(
|
3608
3651
|
(name if name is not None else fn.__name__).replace('_', '-'),
|
3609
3652
|
fn,
|
3610
3653
|
args,
|
@@ -3659,7 +3702,7 @@ class ArgparseCli:
|
|
3659
3702
|
for bns in [bcls.__dict__ for bcls in reversed(mro)] + [ns]:
|
3660
3703
|
bseen = set() # type: ignore
|
3661
3704
|
for k, v in bns.items():
|
3662
|
-
if isinstance(v, (
|
3705
|
+
if isinstance(v, (ArgparseCmd, ArgparseArg)):
|
3663
3706
|
check.not_in(v, bseen)
|
3664
3707
|
bseen.add(v)
|
3665
3708
|
objs[k] = v
|
@@ -3686,7 +3729,7 @@ class ArgparseCli:
|
|
3686
3729
|
subparsers = parser.add_subparsers()
|
3687
3730
|
|
3688
3731
|
for att, obj in objs.items():
|
3689
|
-
if isinstance(obj,
|
3732
|
+
if isinstance(obj, ArgparseCmd):
|
3690
3733
|
if obj.parent is not None:
|
3691
3734
|
raise NotImplementedError
|
3692
3735
|
|
@@ -3748,7 +3791,7 @@ class ArgparseCli:
|
|
3748
3791
|
|
3749
3792
|
#
|
3750
3793
|
|
3751
|
-
def _bind_cli_cmd(self, cmd:
|
3794
|
+
def _bind_cli_cmd(self, cmd: ArgparseCmd) -> ta.Callable:
|
3752
3795
|
return cmd.__get__(self, type(self))
|
3753
3796
|
|
3754
3797
|
def prepare_cli_run(self) -> ta.Optional[ta.Callable]:
|
@@ -5557,104 +5600,6 @@ def bind_interp_uv() -> InjectorBindings:
|
|
5557
5600
|
return inj.as_bindings(*lst)
|
5558
5601
|
|
5559
5602
|
|
5560
|
-
########################################
|
5561
|
-
# ../configs.py
|
5562
|
-
|
5563
|
-
|
5564
|
-
@dc.dataclass(frozen=True)
|
5565
|
-
class VenvConfig:
|
5566
|
-
inherits: ta.Optional[ta.Sequence[str]] = None
|
5567
|
-
interp: ta.Optional[str] = None
|
5568
|
-
requires: ta.Optional[ta.List[str]] = None
|
5569
|
-
docker: ta.Optional[str] = None
|
5570
|
-
srcs: ta.Optional[ta.List[str]] = None
|
5571
|
-
use_uv: ta.Optional[bool] = None
|
5572
|
-
|
5573
|
-
|
5574
|
-
@dc.dataclass(frozen=True)
|
5575
|
-
class PyprojectConfig:
|
5576
|
-
pkgs: ta.Sequence[str] = dc.field(default_factory=list)
|
5577
|
-
srcs: ta.Mapping[str, ta.Sequence[str]] = dc.field(default_factory=dict)
|
5578
|
-
venvs: ta.Mapping[str, VenvConfig] = dc.field(default_factory=dict)
|
5579
|
-
|
5580
|
-
venvs_dir: str = '.venvs'
|
5581
|
-
versions_file: ta.Optional[str] = '.versions'
|
5582
|
-
|
5583
|
-
|
5584
|
-
class PyprojectConfigPreparer:
|
5585
|
-
def __init__(
|
5586
|
-
self,
|
5587
|
-
*,
|
5588
|
-
python_versions: ta.Optional[ta.Mapping[str, str]] = None,
|
5589
|
-
) -> None:
|
5590
|
-
super().__init__()
|
5591
|
-
|
5592
|
-
self._python_versions = python_versions or {}
|
5593
|
-
|
5594
|
-
def _inherit_venvs(self, m: ta.Mapping[str, VenvConfig]) -> ta.Mapping[str, VenvConfig]:
|
5595
|
-
done: ta.Dict[str, VenvConfig] = {}
|
5596
|
-
|
5597
|
-
def rec(k):
|
5598
|
-
try:
|
5599
|
-
return done[k]
|
5600
|
-
except KeyError:
|
5601
|
-
pass
|
5602
|
-
|
5603
|
-
c = m[k]
|
5604
|
-
kw = dc.asdict(c)
|
5605
|
-
for i in c.inherits or ():
|
5606
|
-
ic = rec(i)
|
5607
|
-
kw.update({k: v for k, v in dc.asdict(ic).items() if v is not None and kw.get(k) is None})
|
5608
|
-
del kw['inherits']
|
5609
|
-
|
5610
|
-
d = done[k] = VenvConfig(**kw)
|
5611
|
-
return d
|
5612
|
-
|
5613
|
-
for k in m:
|
5614
|
-
rec(k)
|
5615
|
-
return done
|
5616
|
-
|
5617
|
-
def _resolve_srcs(
|
5618
|
-
self,
|
5619
|
-
lst: ta.Sequence[str],
|
5620
|
-
aliases: ta.Mapping[str, ta.Sequence[str]],
|
5621
|
-
) -> ta.List[str]:
|
5622
|
-
todo = list(reversed(lst))
|
5623
|
-
raw: ta.List[str] = []
|
5624
|
-
seen: ta.Set[str] = set()
|
5625
|
-
|
5626
|
-
while todo:
|
5627
|
-
cur = todo.pop()
|
5628
|
-
if cur in seen:
|
5629
|
-
continue
|
5630
|
-
|
5631
|
-
seen.add(cur)
|
5632
|
-
if not cur.startswith('@'):
|
5633
|
-
raw.append(cur)
|
5634
|
-
continue
|
5635
|
-
|
5636
|
-
todo.extend(aliases[cur[1:]][::-1])
|
5637
|
-
|
5638
|
-
return raw
|
5639
|
-
|
5640
|
-
def _fixup_interp(self, s: ta.Optional[str]) -> ta.Optional[str]:
|
5641
|
-
if not s or not s.startswith('@'):
|
5642
|
-
return s
|
5643
|
-
return self._python_versions[s[1:]]
|
5644
|
-
|
5645
|
-
def prepare_config(self, dct: ta.Mapping[str, ta.Any]) -> PyprojectConfig:
|
5646
|
-
pcfg: PyprojectConfig = unmarshal_obj(dct, PyprojectConfig)
|
5647
|
-
|
5648
|
-
ivs = dict(self._inherit_venvs(pcfg.venvs or {}))
|
5649
|
-
for k, v in ivs.items():
|
5650
|
-
v = dc.replace(v, srcs=self._resolve_srcs(v.srcs or [], pcfg.srcs or {}))
|
5651
|
-
v = dc.replace(v, interp=self._fixup_interp(v.interp))
|
5652
|
-
ivs[k] = v
|
5653
|
-
|
5654
|
-
pcfg = dc.replace(pcfg, venvs=ivs)
|
5655
|
-
return pcfg
|
5656
|
-
|
5657
|
-
|
5658
5603
|
########################################
|
5659
5604
|
# ../../../omlish/logs/standard.py
|
5660
5605
|
"""
|
@@ -6453,9 +6398,15 @@ class InterpInspection:
|
|
6453
6398
|
|
6454
6399
|
|
6455
6400
|
class InterpInspector:
|
6456
|
-
def __init__(
|
6401
|
+
def __init__(
|
6402
|
+
self,
|
6403
|
+
*,
|
6404
|
+
log: ta.Optional[logging.Logger] = None,
|
6405
|
+
) -> None:
|
6457
6406
|
super().__init__()
|
6458
6407
|
|
6408
|
+
self._log = log
|
6409
|
+
|
6459
6410
|
self._cache: ta.Dict[str, ta.Optional[InterpInspection]] = {}
|
6460
6411
|
|
6461
6412
|
_RAW_INSPECTION_CODE = """
|
@@ -6504,8 +6455,8 @@ class InterpInspector:
|
|
6504
6455
|
try:
|
6505
6456
|
ret = await self._inspect(exe)
|
6506
6457
|
except Exception as e: # noqa
|
6507
|
-
if
|
6508
|
-
|
6458
|
+
if self._log is not None and self._log.isEnabledFor(logging.DEBUG):
|
6459
|
+
self._log.exception('Failed to inspect interp: %s', exe)
|
6509
6460
|
ret = None
|
6510
6461
|
self._cache[exe] = ret
|
6511
6462
|
return ret
|
@@ -6765,12 +6716,14 @@ class SystemInterpProvider(InterpProvider):
|
|
6765
6716
|
options: Options = Options(),
|
6766
6717
|
*,
|
6767
6718
|
inspector: ta.Optional[InterpInspector] = None,
|
6719
|
+
log: ta.Optional[logging.Logger] = None,
|
6768
6720
|
) -> None:
|
6769
6721
|
super().__init__()
|
6770
6722
|
|
6771
6723
|
self._options = options
|
6772
6724
|
|
6773
6725
|
self._inspector = inspector
|
6726
|
+
self._log = log
|
6774
6727
|
|
6775
6728
|
#
|
6776
6729
|
|
@@ -6844,7 +6797,8 @@ class SystemInterpProvider(InterpProvider):
|
|
6844
6797
|
lst = []
|
6845
6798
|
for e in self.exes():
|
6846
6799
|
if (ev := await self.get_exe_version(e)) is None:
|
6847
|
-
|
6800
|
+
if self._log is not None:
|
6801
|
+
self._log.debug('Invalid system version: %s', e)
|
6848
6802
|
continue
|
6849
6803
|
lst.append((e, ev))
|
6850
6804
|
return lst
|
@@ -7201,6 +7155,7 @@ class PyenvInterpProvider(InterpProvider):
|
|
7201
7155
|
*,
|
7202
7156
|
pyenv: Pyenv,
|
7203
7157
|
inspector: InterpInspector,
|
7158
|
+
log: ta.Optional[logging.Logger] = None,
|
7204
7159
|
) -> None:
|
7205
7160
|
super().__init__()
|
7206
7161
|
|
@@ -7208,6 +7163,7 @@ class PyenvInterpProvider(InterpProvider):
|
|
7208
7163
|
|
7209
7164
|
self._pyenv = pyenv
|
7210
7165
|
self._inspector = inspector
|
7166
|
+
self._log = log
|
7211
7167
|
|
7212
7168
|
#
|
7213
7169
|
|
@@ -7252,7 +7208,8 @@ class PyenvInterpProvider(InterpProvider):
|
|
7252
7208
|
ret: ta.List[PyenvInterpProvider.Installed] = []
|
7253
7209
|
for vn, ep in await self._pyenv.version_exes():
|
7254
7210
|
if (i := await self._make_installed(vn, ep)) is None:
|
7255
|
-
|
7211
|
+
if self._log is not None:
|
7212
|
+
self._log.debug('Invalid pyenv version: %s', vn)
|
7256
7213
|
continue
|
7257
7214
|
ret.append(i)
|
7258
7215
|
return ret
|
@@ -7955,31 +7912,47 @@ def get_default_interp_resolver() -> InterpResolver:
|
|
7955
7912
|
|
7956
7913
|
|
7957
7914
|
########################################
|
7958
|
-
#
|
7915
|
+
# ../../interp/venvs.py
|
7959
7916
|
|
7960
7917
|
|
7961
7918
|
##
|
7962
7919
|
|
7963
7920
|
|
7964
|
-
|
7921
|
+
@dc.dataclass(frozen=True)
|
7922
|
+
class InterpVenvConfig:
|
7923
|
+
interp: ta.Optional[str] = None
|
7924
|
+
requires: ta.Optional[ta.Sequence[str]] = None
|
7925
|
+
use_uv: ta.Optional[bool] = None
|
7926
|
+
|
7927
|
+
|
7928
|
+
class InterpVenvRequirementsProcessor(Func2['InterpVenv', ta.Sequence[str], ta.Sequence[str]]):
|
7929
|
+
pass
|
7930
|
+
|
7931
|
+
|
7932
|
+
class InterpVenv:
|
7965
7933
|
def __init__(
|
7966
7934
|
self,
|
7967
|
-
|
7968
|
-
cfg:
|
7935
|
+
path: str,
|
7936
|
+
cfg: InterpVenvConfig,
|
7937
|
+
*,
|
7938
|
+
requirements_processor: ta.Optional[InterpVenvRequirementsProcessor] = None,
|
7939
|
+
log: ta.Optional[logging.Logger] = None,
|
7969
7940
|
) -> None:
|
7970
7941
|
super().__init__()
|
7971
|
-
|
7942
|
+
|
7943
|
+
self._path = path
|
7972
7944
|
self._cfg = cfg
|
7973
7945
|
|
7974
|
-
|
7975
|
-
|
7976
|
-
return self._cfg
|
7946
|
+
self._requirements_processor = requirements_processor
|
7947
|
+
self._log = log
|
7977
7948
|
|
7978
|
-
|
7949
|
+
@property
|
7950
|
+
def path(self) -> str:
|
7951
|
+
return self._path
|
7979
7952
|
|
7980
7953
|
@property
|
7981
|
-
def
|
7982
|
-
return
|
7954
|
+
def cfg(self) -> InterpVenvConfig:
|
7955
|
+
return self._cfg
|
7983
7956
|
|
7984
7957
|
@async_cached_nullary
|
7985
7958
|
async def interp_exe(self) -> str:
|
@@ -7988,19 +7961,23 @@ class Venv:
|
|
7988
7961
|
|
7989
7962
|
@cached_nullary
|
7990
7963
|
def exe(self) -> str:
|
7991
|
-
ve = os.path.join(self.
|
7964
|
+
ve = os.path.join(self._path, 'bin/python')
|
7992
7965
|
if not os.path.isfile(ve):
|
7993
7966
|
raise Exception(f'venv exe {ve} does not exist or is not a file!')
|
7994
7967
|
return ve
|
7995
7968
|
|
7996
7969
|
@async_cached_nullary
|
7997
7970
|
async def create(self) -> bool:
|
7998
|
-
if os.path.exists(dn := self.
|
7971
|
+
if os.path.exists(dn := self._path):
|
7999
7972
|
if not os.path.isdir(dn):
|
8000
7973
|
raise Exception(f'{dn} exists but is not a directory!')
|
8001
7974
|
return False
|
8002
7975
|
|
8003
|
-
|
7976
|
+
ie = await self.interp_exe()
|
7977
|
+
|
7978
|
+
if self._log is not None:
|
7979
|
+
self._log.info('Using interpreter %s', ie)
|
7980
|
+
|
8004
7981
|
await asyncio_subprocesses.check_call(ie, '-m', 'venv', dn)
|
8005
7982
|
|
8006
7983
|
ve = self.exe()
|
@@ -8017,8 +7994,9 @@ class Venv:
|
|
8017
7994
|
)
|
8018
7995
|
|
8019
7996
|
if sr := self._cfg.requires:
|
8020
|
-
|
8021
|
-
|
7997
|
+
reqs = list(sr)
|
7998
|
+
if self._requirements_processor is not None:
|
7999
|
+
reqs = list(self._requirements_processor(self, reqs))
|
8022
8000
|
|
8023
8001
|
# TODO: automatically try slower uv download when it fails? lol
|
8024
8002
|
# Caused by: Failed to download distribution due to network timeout. Try increasing UV_HTTP_TIMEOUT (current value: 30s). # noqa
|
@@ -8036,6 +8014,150 @@ class Venv:
|
|
8036
8014
|
|
8037
8015
|
return True
|
8038
8016
|
|
8017
|
+
|
8018
|
+
########################################
|
8019
|
+
# ../configs.py
|
8020
|
+
|
8021
|
+
|
8022
|
+
@dc.dataclass(frozen=True)
|
8023
|
+
class VenvConfig(InterpVenvConfig):
|
8024
|
+
inherits: ta.Optional[ta.Sequence[str]] = None
|
8025
|
+
docker: ta.Optional[str] = None
|
8026
|
+
srcs: ta.Optional[ta.List[str]] = None
|
8027
|
+
|
8028
|
+
|
8029
|
+
@dc.dataclass(frozen=True)
|
8030
|
+
class PyprojectConfig:
|
8031
|
+
pkgs: ta.Sequence[str] = dc.field(default_factory=list)
|
8032
|
+
srcs: ta.Mapping[str, ta.Sequence[str]] = dc.field(default_factory=dict)
|
8033
|
+
venvs: ta.Mapping[str, VenvConfig] = dc.field(default_factory=dict)
|
8034
|
+
|
8035
|
+
venvs_dir: str = '.venvs'
|
8036
|
+
versions_file: ta.Optional[str] = '.versions'
|
8037
|
+
|
8038
|
+
|
8039
|
+
class PyprojectConfigPreparer:
|
8040
|
+
def __init__(
|
8041
|
+
self,
|
8042
|
+
*,
|
8043
|
+
python_versions: ta.Optional[ta.Mapping[str, str]] = None,
|
8044
|
+
) -> None:
|
8045
|
+
super().__init__()
|
8046
|
+
|
8047
|
+
self._python_versions = python_versions or {}
|
8048
|
+
|
8049
|
+
def _inherit_venvs(self, m: ta.Mapping[str, VenvConfig]) -> ta.Mapping[str, VenvConfig]:
|
8050
|
+
done: ta.Dict[str, VenvConfig] = {}
|
8051
|
+
|
8052
|
+
def rec(k):
|
8053
|
+
try:
|
8054
|
+
return done[k]
|
8055
|
+
except KeyError:
|
8056
|
+
pass
|
8057
|
+
|
8058
|
+
c = m[k]
|
8059
|
+
kw = dc.asdict(c)
|
8060
|
+
for i in c.inherits or ():
|
8061
|
+
ic = rec(i)
|
8062
|
+
kw.update({k: v for k, v in dc.asdict(ic).items() if v is not None and kw.get(k) is None})
|
8063
|
+
del kw['inherits']
|
8064
|
+
|
8065
|
+
d = done[k] = VenvConfig(**kw)
|
8066
|
+
return d
|
8067
|
+
|
8068
|
+
for k in m:
|
8069
|
+
rec(k)
|
8070
|
+
return done
|
8071
|
+
|
8072
|
+
def _resolve_srcs(
|
8073
|
+
self,
|
8074
|
+
lst: ta.Sequence[str],
|
8075
|
+
aliases: ta.Mapping[str, ta.Sequence[str]],
|
8076
|
+
) -> ta.List[str]:
|
8077
|
+
todo = list(reversed(lst))
|
8078
|
+
raw: ta.List[str] = []
|
8079
|
+
seen: ta.Set[str] = set()
|
8080
|
+
|
8081
|
+
while todo:
|
8082
|
+
cur = todo.pop()
|
8083
|
+
if cur in seen:
|
8084
|
+
continue
|
8085
|
+
|
8086
|
+
seen.add(cur)
|
8087
|
+
if not cur.startswith('@'):
|
8088
|
+
raw.append(cur)
|
8089
|
+
continue
|
8090
|
+
|
8091
|
+
todo.extend(aliases[cur[1:]][::-1])
|
8092
|
+
|
8093
|
+
return raw
|
8094
|
+
|
8095
|
+
def _fixup_interp(self, s: ta.Optional[str]) -> ta.Optional[str]:
|
8096
|
+
if not s or not s.startswith('@'):
|
8097
|
+
return s
|
8098
|
+
return self._python_versions[s[1:]]
|
8099
|
+
|
8100
|
+
def prepare_config(self, dct: ta.Mapping[str, ta.Any]) -> PyprojectConfig:
|
8101
|
+
pcfg: PyprojectConfig = unmarshal_obj(dct, PyprojectConfig)
|
8102
|
+
|
8103
|
+
ivs = dict(self._inherit_venvs(pcfg.venvs or {}))
|
8104
|
+
for k, v in ivs.items():
|
8105
|
+
v = dc.replace(v, srcs=self._resolve_srcs(v.srcs or [], pcfg.srcs or {}))
|
8106
|
+
v = dc.replace(v, interp=self._fixup_interp(v.interp))
|
8107
|
+
ivs[k] = v
|
8108
|
+
|
8109
|
+
pcfg = dc.replace(pcfg, venvs=ivs)
|
8110
|
+
return pcfg
|
8111
|
+
|
8112
|
+
|
8113
|
+
########################################
|
8114
|
+
# ../venvs.py
|
8115
|
+
|
8116
|
+
|
8117
|
+
##
|
8118
|
+
|
8119
|
+
|
8120
|
+
class Venv:
|
8121
|
+
def __init__(
|
8122
|
+
self,
|
8123
|
+
name: str,
|
8124
|
+
cfg: VenvConfig,
|
8125
|
+
) -> None:
|
8126
|
+
super().__init__()
|
8127
|
+
self._name = name
|
8128
|
+
self._cfg = cfg
|
8129
|
+
|
8130
|
+
@property
|
8131
|
+
def cfg(self) -> VenvConfig:
|
8132
|
+
return self._cfg
|
8133
|
+
|
8134
|
+
DIR_NAME = '.venvs'
|
8135
|
+
|
8136
|
+
@property
|
8137
|
+
def dir_name(self) -> str:
|
8138
|
+
return os.path.join(self.DIR_NAME, self._name)
|
8139
|
+
|
8140
|
+
@cached_nullary
|
8141
|
+
def _iv(self) -> InterpVenv:
|
8142
|
+
rr = RequirementsRewriter(self._name)
|
8143
|
+
|
8144
|
+
return InterpVenv(
|
8145
|
+
self.dir_name,
|
8146
|
+
self._cfg,
|
8147
|
+
requirements_processor=InterpVenvRequirementsProcessor(
|
8148
|
+
lambda iv, reqs: [rr.rewrite(req) for req in reqs] # noqa
|
8149
|
+
),
|
8150
|
+
log=log,
|
8151
|
+
)
|
8152
|
+
|
8153
|
+
@cached_nullary
|
8154
|
+
def exe(self) -> str:
|
8155
|
+
return self._iv().exe()
|
8156
|
+
|
8157
|
+
@async_cached_nullary
|
8158
|
+
async def create(self) -> bool:
|
8159
|
+
return await self._iv().create()
|
8160
|
+
|
8039
8161
|
@staticmethod
|
8040
8162
|
def _resolve_srcs(raw: ta.List[str]) -> ta.List[str]:
|
8041
8163
|
out: list[str] = []
|
@@ -8152,7 +8274,7 @@ class Run:
|
|
8152
8274
|
class PyprojectCli(ArgparseCli):
|
8153
8275
|
_docker_container = argparse_arg('--_docker_container', help=argparse.SUPPRESS)
|
8154
8276
|
|
8155
|
-
@
|
8277
|
+
@argparse_cmd(
|
8156
8278
|
argparse_arg('name'),
|
8157
8279
|
argparse_arg('-e', '--docker-env', action='append'),
|
8158
8280
|
argparse_arg('cmd', nargs='?'),
|
@@ -8234,7 +8356,7 @@ class PyprojectCli(ArgparseCli):
|
|
8234
8356
|
else:
|
8235
8357
|
raise Exception(f'unknown subcommand: {cmd}')
|
8236
8358
|
|
8237
|
-
@
|
8359
|
+
@argparse_cmd(
|
8238
8360
|
argparse_arg('-b', '--build', action='store_true'),
|
8239
8361
|
argparse_arg('-r', '--revision', action='store_true'),
|
8240
8362
|
argparse_arg('-j', '--jobs', type=int),
|
omdev/tools/doc.py
CHANGED
@@ -64,7 +64,7 @@ class Cli(ap.Cli):
|
|
64
64
|
|
65
65
|
return src, name
|
66
66
|
|
67
|
-
@ap.
|
67
|
+
@ap.cmd(
|
68
68
|
ap.arg('input-file', nargs='?'),
|
69
69
|
ap.arg('--report-level', type=int),
|
70
70
|
ap.arg('-O', '--open', action='store_true'),
|
@@ -85,7 +85,7 @@ class Cli(ap.Cli):
|
|
85
85
|
else:
|
86
86
|
print(html)
|
87
87
|
|
88
|
-
@ap.
|
88
|
+
@ap.cmd(
|
89
89
|
ap.arg('input-file', nargs='?'),
|
90
90
|
ap.arg('-O', '--open', action='store_true'),
|
91
91
|
)
|