omdev 0.0.0.dev500__py3-none-any.whl → 0.0.0.dev509__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.
Potentially problematic release.
This version of omdev might be problematic. Click here for more details.
- omdev/.omlish-manifests.json +2 -2
- omdev/__about__.py +2 -2
- omdev/cache/data/specs.py +1 -1
- omdev/cexts/cmake.py +41 -1
- omdev/imgur.py +2 -2
- omdev/markdown/incparse.py +392 -0
- omdev/py/tools/pipdepup.py +16 -0
- omdev/pyproject/cli.py +1 -35
- omdev/pyproject/configs.py +1 -1
- omdev/pyproject/tools/buildrs.py +85 -0
- omdev/pyproject/tools/pyversions.py +47 -0
- omdev/pyproject/versions.py +40 -0
- omdev/scripts/ci.py +8 -1
- omdev/scripts/interp.py +8 -1
- omdev/scripts/lib/inject.py +8 -1
- omdev/scripts/pyproject.py +66 -39
- omdev/tools/sqlrepl.py +189 -78
- omdev/tui/rich/markdown2.py +219 -18
- {omdev-0.0.0.dev500.dist-info → omdev-0.0.0.dev509.dist-info}/METADATA +6 -6
- {omdev-0.0.0.dev500.dist-info → omdev-0.0.0.dev509.dist-info}/RECORD +24 -21
- {omdev-0.0.0.dev500.dist-info → omdev-0.0.0.dev509.dist-info}/WHEEL +0 -0
- {omdev-0.0.0.dev500.dist-info → omdev-0.0.0.dev509.dist-info}/entry_points.txt +0 -0
- {omdev-0.0.0.dev500.dist-info → omdev-0.0.0.dev509.dist-info}/licenses/LICENSE +0 -0
- {omdev-0.0.0.dev500.dist-info → omdev-0.0.0.dev509.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import os.path
|
|
3
|
+
import shlex
|
|
4
|
+
import shutil
|
|
5
|
+
import subprocess
|
|
6
|
+
import sys
|
|
7
|
+
import zipfile
|
|
8
|
+
|
|
9
|
+
from omlish.lite.check import check
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _main() -> None:
|
|
16
|
+
parser = argparse.ArgumentParser()
|
|
17
|
+
parser.add_argument('rs_pkg', nargs='*')
|
|
18
|
+
args = parser.parse_args()
|
|
19
|
+
|
|
20
|
+
pkgs_dir = '.pkg'
|
|
21
|
+
if not os.path.isdir(pkgs_dir):
|
|
22
|
+
raise RuntimeError(f'{pkgs_dir=} does not exist')
|
|
23
|
+
|
|
24
|
+
if not (rs_pkgs := args.rs_pkg):
|
|
25
|
+
rs_pkgs = sorted(
|
|
26
|
+
n
|
|
27
|
+
for n in os.listdir(pkgs_dir)
|
|
28
|
+
if os.path.isdir(p := os.path.join(pkgs_dir, n))
|
|
29
|
+
and n.endswith('-rs')
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
for rs_pkg in rs_pkgs:
|
|
33
|
+
print(rs_pkg)
|
|
34
|
+
|
|
35
|
+
rs_pkg_dir = os.path.join(pkgs_dir, rs_pkg)
|
|
36
|
+
|
|
37
|
+
for n in os.listdir(rs_pkg_dir):
|
|
38
|
+
p = os.path.join(rs_pkg_dir, n)
|
|
39
|
+
if not os.path.isdir(p):
|
|
40
|
+
continue
|
|
41
|
+
if n == 'dist' or n.endswith('.egg-info'):
|
|
42
|
+
shutil.rmtree(p)
|
|
43
|
+
|
|
44
|
+
subprocess.run(
|
|
45
|
+
[
|
|
46
|
+
'sh', '-c', f'{shlex.quote(sys.executable)} "$@"', '--', # sys.executable,
|
|
47
|
+
'-m',
|
|
48
|
+
'build',
|
|
49
|
+
],
|
|
50
|
+
cwd=rs_pkg_dir,
|
|
51
|
+
env={
|
|
52
|
+
**os.environ,
|
|
53
|
+
'OMLISH_PYCHARM_RUNHACK_ENABLED': '0',
|
|
54
|
+
},
|
|
55
|
+
check=True,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
dist_dir = os.path.join(rs_pkg_dir, 'dist')
|
|
59
|
+
whl_ns = [
|
|
60
|
+
n
|
|
61
|
+
for n in os.listdir(dist_dir)
|
|
62
|
+
if os.path.isfile(os.path.join(dist_dir, n))
|
|
63
|
+
and n.endswith('.whl')
|
|
64
|
+
]
|
|
65
|
+
whl_n = check.single(whl_ns)
|
|
66
|
+
whl_path = os.path.join(dist_dir, whl_n)
|
|
67
|
+
|
|
68
|
+
with zipfile.ZipFile(whl_path) as zf:
|
|
69
|
+
for zn in zf.namelist():
|
|
70
|
+
if not zn.endswith('.so'):
|
|
71
|
+
continue
|
|
72
|
+
|
|
73
|
+
zi = zf.getinfo(zn)
|
|
74
|
+
if zi.is_dir():
|
|
75
|
+
continue
|
|
76
|
+
|
|
77
|
+
print(zn)
|
|
78
|
+
|
|
79
|
+
zf.extract(zi)
|
|
80
|
+
|
|
81
|
+
print()
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
if __name__ == '__main__':
|
|
85
|
+
_main()
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# ruff: noqa: UP006 UP045
|
|
2
|
+
import dataclasses as dc
|
|
3
|
+
import json
|
|
4
|
+
import typing as ta
|
|
5
|
+
import urllib.request
|
|
6
|
+
|
|
7
|
+
from ..versions import VersionsFile
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
##
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dc.dataclass(frozen=True)
|
|
14
|
+
class PyVersion:
|
|
15
|
+
name: str # "Python 3.13.11",
|
|
16
|
+
slug: str # "python-31311"
|
|
17
|
+
version: int # 3
|
|
18
|
+
is_published: bool
|
|
19
|
+
is_latest: bool
|
|
20
|
+
release_date: str # "2025-12-05T19:24:49Z"
|
|
21
|
+
pre_release: bool
|
|
22
|
+
release_page: ta.Optional[str]
|
|
23
|
+
release_notes_url: str # "https://docs.python.org/release/3.13.11/whatsnew/changelog.html"
|
|
24
|
+
show_on_download_page: bool
|
|
25
|
+
resource_uri: str # "https://www.python.org/api/v2/downloads/release/1083/"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
PY_VERSIONS_URL = 'https://www.python.org/api/v2/downloads/release/?is_published=true'
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def get_py_versions() -> ta.List[PyVersion]:
|
|
32
|
+
with urllib.request.urlopen(PY_VERSIONS_URL) as r: # noqa
|
|
33
|
+
data = json.load(r)
|
|
34
|
+
|
|
35
|
+
return [PyVersion(**dct) for dct in data]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
##
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _main() -> None:
|
|
42
|
+
print(get_py_versions())
|
|
43
|
+
print(VersionsFile().pythons())
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
if __name__ == '__main__':
|
|
47
|
+
_main()
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# ruff: noqa: UP045
|
|
2
|
+
import dataclasses as dc
|
|
3
|
+
import os.path
|
|
4
|
+
import typing as ta
|
|
5
|
+
|
|
6
|
+
from omlish.lite.cached import cached_nullary
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
##
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dc.dataclass(frozen=True)
|
|
13
|
+
class VersionsFile:
|
|
14
|
+
name: ta.Optional[str] = '.versions'
|
|
15
|
+
|
|
16
|
+
@staticmethod
|
|
17
|
+
def parse(s: str) -> ta.Mapping[str, str]:
|
|
18
|
+
return {
|
|
19
|
+
k: v
|
|
20
|
+
for l in s.splitlines()
|
|
21
|
+
if (sl := l.split('#')[0].strip())
|
|
22
|
+
for k, _, v in (sl.partition('='),)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@cached_nullary
|
|
26
|
+
def contents(self) -> ta.Mapping[str, str]:
|
|
27
|
+
if not self.name or not os.path.exists(self.name):
|
|
28
|
+
return {}
|
|
29
|
+
with open(self.name) as f:
|
|
30
|
+
s = f.read()
|
|
31
|
+
return self.parse(s)
|
|
32
|
+
|
|
33
|
+
@staticmethod
|
|
34
|
+
def get_pythons(d: ta.Mapping[str, str]) -> ta.Mapping[str, str]:
|
|
35
|
+
pfx = 'PYTHON_'
|
|
36
|
+
return {k[len(pfx):].lower(): v for k, v in d.items() if k.startswith(pfx)}
|
|
37
|
+
|
|
38
|
+
@cached_nullary
|
|
39
|
+
def pythons(self) -> ta.Mapping[str, str]:
|
|
40
|
+
return self.get_pythons(self.contents())
|
omdev/scripts/ci.py
CHANGED
|
@@ -125,7 +125,7 @@ def __omlish_amalg__(): # noqa
|
|
|
125
125
|
dict(path='../../omlish/http/coro/io.py', sha1='2cdf6529c37a37cc0c1db2e02032157cf906d5d6'),
|
|
126
126
|
dict(path='../../omlish/http/parsing.py', sha1='3fea28dc6341908ba7c8fad42bf7bbe711f21b82'),
|
|
127
127
|
dict(path='../../omlish/lite/marshal.py', sha1='96348f5f2a26dc27d842d33cc3927e9da163436b'),
|
|
128
|
-
dict(path='../../omlish/lite/maybes.py', sha1='
|
|
128
|
+
dict(path='../../omlish/lite/maybes.py', sha1='04d2fcbea17028a5e6b8e7a7fb742375495ed233'),
|
|
129
129
|
dict(path='../../omlish/lite/runtime.py', sha1='2e752a27ae2bf89b1bb79b4a2da522a3ec360c70'),
|
|
130
130
|
dict(path='../../omlish/lite/timeouts.py', sha1='a0f673033a6943f242e35848d78a41892b9c62a1'),
|
|
131
131
|
dict(path='../../omlish/logs/infos.py', sha1='4dd104bd468a8c438601dd0bbda619b47d2f1620'),
|
|
@@ -5015,6 +5015,13 @@ class Maybe(ta.Generic[T]):
|
|
|
5015
5015
|
else:
|
|
5016
5016
|
return other
|
|
5017
5017
|
|
|
5018
|
+
@ta.final
|
|
5019
|
+
def or_none(self) -> ta.Optional[T]:
|
|
5020
|
+
if self.present:
|
|
5021
|
+
return self.must()
|
|
5022
|
+
else:
|
|
5023
|
+
return None
|
|
5024
|
+
|
|
5018
5025
|
@ta.final
|
|
5019
5026
|
def or_else_get(self, supplier: ta.Callable[[], ta.Union[T, U]]) -> ta.Union[T, U]:
|
|
5020
5027
|
if self.present:
|
omdev/scripts/interp.py
CHANGED
|
@@ -65,7 +65,7 @@ def __omlish_amalg__(): # noqa
|
|
|
65
65
|
dict(path='../../omlish/logs/std/proxy.py', sha1='3e7301a2aa351127f9c85f61b2f85dcc3f15aafb'),
|
|
66
66
|
dict(path='../packaging/specifiers.py', sha1='a56ab4e8c9b174adb523921f6280ac41e0fce749'),
|
|
67
67
|
dict(path='../../omlish/argparse/cli.py', sha1='f4dc3cd353d14386b5da0306768700e396afd2b3'),
|
|
68
|
-
dict(path='../../omlish/lite/maybes.py', sha1='
|
|
68
|
+
dict(path='../../omlish/lite/maybes.py', sha1='04d2fcbea17028a5e6b8e7a7fb742375495ed233'),
|
|
69
69
|
dict(path='../../omlish/lite/runtime.py', sha1='2e752a27ae2bf89b1bb79b4a2da522a3ec360c70'),
|
|
70
70
|
dict(path='../../omlish/lite/timeouts.py', sha1='a0f673033a6943f242e35848d78a41892b9c62a1'),
|
|
71
71
|
dict(path='../../omlish/logs/protocols.py', sha1='05ca4d1d7feb50c4e3b9f22ee371aa7bf4b3dbd1'),
|
|
@@ -2668,6 +2668,13 @@ class Maybe(ta.Generic[T]):
|
|
|
2668
2668
|
else:
|
|
2669
2669
|
return other
|
|
2670
2670
|
|
|
2671
|
+
@ta.final
|
|
2672
|
+
def or_none(self) -> ta.Optional[T]:
|
|
2673
|
+
if self.present:
|
|
2674
|
+
return self.must()
|
|
2675
|
+
else:
|
|
2676
|
+
return None
|
|
2677
|
+
|
|
2671
2678
|
@ta.final
|
|
2672
2679
|
def or_else_get(self, supplier: ta.Callable[[], ta.Union[T, U]]) -> ta.Union[T, U]:
|
|
2673
2680
|
if self.present:
|
omdev/scripts/lib/inject.py
CHANGED
|
@@ -34,7 +34,7 @@ def __omlish_amalg__(): # noqa
|
|
|
34
34
|
dict(path='abstract.py', sha1='a2fc3f3697fa8de5247761e9d554e70176f37aac'),
|
|
35
35
|
dict(path='check.py', sha1='bb6b6b63333699b84462951a854d99ae83195b94'),
|
|
36
36
|
dict(path='reflect.py', sha1='c4fec44bf144e9d93293c996af06f6c65fc5e63d'),
|
|
37
|
-
dict(path='maybes.py', sha1='
|
|
37
|
+
dict(path='maybes.py', sha1='04d2fcbea17028a5e6b8e7a7fb742375495ed233'),
|
|
38
38
|
dict(path='inject.py', sha1='6f097e3170019a34ff6834d36fcc9cbeed3a7ab4'),
|
|
39
39
|
],
|
|
40
40
|
)
|
|
@@ -884,6 +884,13 @@ class Maybe(ta.Generic[T]):
|
|
|
884
884
|
else:
|
|
885
885
|
return other
|
|
886
886
|
|
|
887
|
+
@ta.final
|
|
888
|
+
def or_none(self) -> ta.Optional[T]:
|
|
889
|
+
if self.present:
|
|
890
|
+
return self.must()
|
|
891
|
+
else:
|
|
892
|
+
return None
|
|
893
|
+
|
|
887
894
|
@ta.final
|
|
888
895
|
def or_else_get(self, supplier: ta.Callable[[], ta.Union[T, U]]) -> ta.Union[T, U]:
|
|
889
896
|
if self.present:
|
omdev/scripts/pyproject.py
CHANGED
|
@@ -101,7 +101,7 @@ def __omlish_amalg__(): # noqa
|
|
|
101
101
|
dict(path='../../omlish/lite/objects.py', sha1='9566bbf3530fd71fcc56321485216b592fae21e9'),
|
|
102
102
|
dict(path='../../omlish/lite/reflect.py', sha1='c4fec44bf144e9d93293c996af06f6c65fc5e63d'),
|
|
103
103
|
dict(path='../../omlish/lite/strings.py', sha1='89831ecbc34ad80e118a865eceb390ed399dc4d6'),
|
|
104
|
-
dict(path='../../omlish/lite/typing.py', sha1='
|
|
104
|
+
dict(path='../../omlish/lite/typing.py', sha1='048bb5fb8ecad5be101516f8f3b7996707f5bc42'),
|
|
105
105
|
dict(path='../../omlish/logs/levels.py', sha1='91405563d082a5eba874da82aac89d83ce7b6152'),
|
|
106
106
|
dict(path='../../omlish/logs/std/filters.py', sha1='f36aab646d84d31e295b33aaaaa6f8b67ff38b3d'),
|
|
107
107
|
dict(path='../../omlish/logs/std/proxy.py', sha1='3e7301a2aa351127f9c85f61b2f85dcc3f15aafb'),
|
|
@@ -109,9 +109,10 @@ def __omlish_amalg__(): # noqa
|
|
|
109
109
|
dict(path='../cexts/magic.py', sha1='4e5ce6732454f75c9dd27352959708d8fa7b1666'),
|
|
110
110
|
dict(path='../magic/find.py', sha1='436228a9cf1d8bab6b9234d09f72913b0960382f'),
|
|
111
111
|
dict(path='../packaging/specifiers.py', sha1='a56ab4e8c9b174adb523921f6280ac41e0fce749'),
|
|
112
|
+
dict(path='versions.py', sha1='99aa1788f4eccb1901f21f2265862716d7580192'),
|
|
112
113
|
dict(path='../../omlish/argparse/cli.py', sha1='f4dc3cd353d14386b5da0306768700e396afd2b3'),
|
|
113
114
|
dict(path='../../omlish/lite/marshal.py', sha1='96348f5f2a26dc27d842d33cc3927e9da163436b'),
|
|
114
|
-
dict(path='../../omlish/lite/maybes.py', sha1='
|
|
115
|
+
dict(path='../../omlish/lite/maybes.py', sha1='04d2fcbea17028a5e6b8e7a7fb742375495ed233'),
|
|
115
116
|
dict(path='../../omlish/lite/runtime.py', sha1='2e752a27ae2bf89b1bb79b4a2da522a3ec360c70'),
|
|
116
117
|
dict(path='../../omlish/lite/timeouts.py', sha1='a0f673033a6943f242e35848d78a41892b9c62a1'),
|
|
117
118
|
dict(path='../../omlish/logs/infos.py', sha1='4dd104bd468a8c438601dd0bbda619b47d2f1620'),
|
|
@@ -154,9 +155,9 @@ def __omlish_amalg__(): # noqa
|
|
|
154
155
|
dict(path='../interp/inject.py', sha1='b039abbadf0b096d2724182af2e0ebda2a230852'),
|
|
155
156
|
dict(path='../interp/default.py', sha1='a799969a0d3f4b57538587b13ceb08f6334ebc16'),
|
|
156
157
|
dict(path='../interp/venvs.py', sha1='9ba8f2c3131d7d519d5cf36ca69b75f9c6fe2b27'),
|
|
157
|
-
dict(path='configs.py', sha1='
|
|
158
|
+
dict(path='configs.py', sha1='28d20c0288eef4a5c61dd9b95071b7b15958b575'),
|
|
158
159
|
dict(path='venvs.py', sha1='9f1935171017aeb802da56e14d7f41d632a7aa25'),
|
|
159
|
-
dict(path='cli.py', sha1='
|
|
160
|
+
dict(path='cli.py', sha1='ecf31ccef6b0e1d1505b46d24faf076b6be32760'),
|
|
160
161
|
],
|
|
161
162
|
)
|
|
162
163
|
|
|
@@ -3292,6 +3293,21 @@ class CachedFunc0(ta.Generic[T]):
|
|
|
3292
3293
|
return value
|
|
3293
3294
|
|
|
3294
3295
|
|
|
3296
|
+
@dc.dataclass(frozen=True)
|
|
3297
|
+
class AsyncCachedFunc0(ta.Generic[T]):
|
|
3298
|
+
fn: ta.Callable[[], ta.Awaitable[T]]
|
|
3299
|
+
|
|
3300
|
+
async def __call__(self) -> T:
|
|
3301
|
+
try:
|
|
3302
|
+
return object.__getattribute__(self, '_value')
|
|
3303
|
+
except AttributeError:
|
|
3304
|
+
pass
|
|
3305
|
+
|
|
3306
|
+
value = await self.fn()
|
|
3307
|
+
object.__setattr__(self, '_value', value)
|
|
3308
|
+
return value
|
|
3309
|
+
|
|
3310
|
+
|
|
3295
3311
|
##
|
|
3296
3312
|
|
|
3297
3313
|
|
|
@@ -4289,6 +4305,44 @@ class SpecifierSet(BaseSpecifier):
|
|
|
4289
4305
|
return iter(filtered)
|
|
4290
4306
|
|
|
4291
4307
|
|
|
4308
|
+
########################################
|
|
4309
|
+
# ../versions.py
|
|
4310
|
+
|
|
4311
|
+
|
|
4312
|
+
##
|
|
4313
|
+
|
|
4314
|
+
|
|
4315
|
+
@dc.dataclass(frozen=True)
|
|
4316
|
+
class VersionsFile:
|
|
4317
|
+
name: ta.Optional[str] = '.versions'
|
|
4318
|
+
|
|
4319
|
+
@staticmethod
|
|
4320
|
+
def parse(s: str) -> ta.Mapping[str, str]:
|
|
4321
|
+
return {
|
|
4322
|
+
k: v
|
|
4323
|
+
for l in s.splitlines()
|
|
4324
|
+
if (sl := l.split('#')[0].strip())
|
|
4325
|
+
for k, _, v in (sl.partition('='),)
|
|
4326
|
+
}
|
|
4327
|
+
|
|
4328
|
+
@cached_nullary
|
|
4329
|
+
def contents(self) -> ta.Mapping[str, str]:
|
|
4330
|
+
if not self.name or not os.path.exists(self.name):
|
|
4331
|
+
return {}
|
|
4332
|
+
with open(self.name) as f:
|
|
4333
|
+
s = f.read()
|
|
4334
|
+
return self.parse(s)
|
|
4335
|
+
|
|
4336
|
+
@staticmethod
|
|
4337
|
+
def get_pythons(d: ta.Mapping[str, str]) -> ta.Mapping[str, str]:
|
|
4338
|
+
pfx = 'PYTHON_'
|
|
4339
|
+
return {k[len(pfx):].lower(): v for k, v in d.items() if k.startswith(pfx)}
|
|
4340
|
+
|
|
4341
|
+
@cached_nullary
|
|
4342
|
+
def pythons(self) -> ta.Mapping[str, str]:
|
|
4343
|
+
return self.get_pythons(self.contents())
|
|
4344
|
+
|
|
4345
|
+
|
|
4292
4346
|
########################################
|
|
4293
4347
|
# ../../../omlish/argparse/cli.py
|
|
4294
4348
|
"""
|
|
@@ -5466,6 +5520,13 @@ class Maybe(ta.Generic[T]):
|
|
|
5466
5520
|
else:
|
|
5467
5521
|
return other
|
|
5468
5522
|
|
|
5523
|
+
@ta.final
|
|
5524
|
+
def or_none(self) -> ta.Optional[T]:
|
|
5525
|
+
if self.present:
|
|
5526
|
+
return self.must()
|
|
5527
|
+
else:
|
|
5528
|
+
return None
|
|
5529
|
+
|
|
5469
5530
|
@ta.final
|
|
5470
5531
|
def or_else_get(self, supplier: ta.Callable[[], ta.Union[T, U]]) -> ta.Union[T, U]:
|
|
5471
5532
|
if self.present:
|
|
@@ -12355,7 +12416,7 @@ class PyprojectConfig:
|
|
|
12355
12416
|
venvs: ta.Mapping[str, VenvConfig] = dc.field(default_factory=dict)
|
|
12356
12417
|
|
|
12357
12418
|
venvs_dir: str = '.venvs'
|
|
12358
|
-
versions_file: ta.Optional[str] = '.versions'
|
|
12419
|
+
# versions_file: ta.Optional[str] = '.versions' # FIXME:
|
|
12359
12420
|
|
|
12360
12421
|
|
|
12361
12422
|
class PyprojectConfigPreparer:
|
|
@@ -12518,40 +12579,6 @@ class Venv:
|
|
|
12518
12579
|
##
|
|
12519
12580
|
|
|
12520
12581
|
|
|
12521
|
-
@dc.dataclass(frozen=True)
|
|
12522
|
-
class VersionsFile:
|
|
12523
|
-
name: ta.Optional[str] = '.versions'
|
|
12524
|
-
|
|
12525
|
-
@staticmethod
|
|
12526
|
-
def parse(s: str) -> ta.Mapping[str, str]:
|
|
12527
|
-
return {
|
|
12528
|
-
k: v
|
|
12529
|
-
for l in s.splitlines()
|
|
12530
|
-
if (sl := l.split('#')[0].strip())
|
|
12531
|
-
for k, _, v in (sl.partition('='),)
|
|
12532
|
-
}
|
|
12533
|
-
|
|
12534
|
-
@cached_nullary
|
|
12535
|
-
def contents(self) -> ta.Mapping[str, str]:
|
|
12536
|
-
if not self.name or not os.path.exists(self.name):
|
|
12537
|
-
return {}
|
|
12538
|
-
with open(self.name) as f:
|
|
12539
|
-
s = f.read()
|
|
12540
|
-
return self.parse(s)
|
|
12541
|
-
|
|
12542
|
-
@staticmethod
|
|
12543
|
-
def get_pythons(d: ta.Mapping[str, str]) -> ta.Mapping[str, str]:
|
|
12544
|
-
pfx = 'PYTHON_'
|
|
12545
|
-
return {k[len(pfx):].lower(): v for k, v in d.items() if k.startswith(pfx)}
|
|
12546
|
-
|
|
12547
|
-
@cached_nullary
|
|
12548
|
-
def pythons(self) -> ta.Mapping[str, str]:
|
|
12549
|
-
return self.get_pythons(self.contents())
|
|
12550
|
-
|
|
12551
|
-
|
|
12552
|
-
##
|
|
12553
|
-
|
|
12554
|
-
|
|
12555
12582
|
@cached_nullary
|
|
12556
12583
|
def _script_rel_path() -> str:
|
|
12557
12584
|
cwd = os.getcwd()
|