omdev 0.0.0.dev158__py3-none-any.whl → 0.0.0.dev160__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/amalg/amalg.py +3 -3
- omdev/cache/data/cache.py +2 -2
- omdev/cache/data/manifests.py +1 -1
- omdev/git/__init__.py +0 -0
- omdev/git/revisions.py +50 -0
- omdev/{git.py → git/status.py} +0 -111
- omdev/git/subtrees.py +100 -0
- omdev/interp/cli.py +2 -2
- omdev/pyproject/cli.py +2 -2
- omdev/revisions.py +1 -1
- omdev/scripts/interp.py +16 -10
- omdev/scripts/pyproject.py +48 -389
- omdev/tools/git.py +2 -2
- {omdev-0.0.0.dev158.dist-info → omdev-0.0.0.dev160.dist-info}/METADATA +2 -2
- {omdev-0.0.0.dev158.dist-info → omdev-0.0.0.dev160.dist-info}/RECORD +19 -16
- {omdev-0.0.0.dev158.dist-info → omdev-0.0.0.dev160.dist-info}/LICENSE +0 -0
- {omdev-0.0.0.dev158.dist-info → omdev-0.0.0.dev160.dist-info}/WHEEL +0 -0
- {omdev-0.0.0.dev158.dist-info → omdev-0.0.0.dev160.dist-info}/entry_points.txt +0 -0
- {omdev-0.0.0.dev158.dist-info → omdev-0.0.0.dev160.dist-info}/top_level.txt +0 -0
omdev/amalg/amalg.py
CHANGED
|
@@ -41,7 +41,7 @@ import tokenize_rt as trt
|
|
|
41
41
|
from omlish import check
|
|
42
42
|
from omlish import collections as col
|
|
43
43
|
from omlish import lang
|
|
44
|
-
from omlish.lite.runtime import
|
|
44
|
+
from omlish.lite.runtime import LITE_REQUIRED_PYTHON_VERSION
|
|
45
45
|
from omlish.logs import all as logs
|
|
46
46
|
|
|
47
47
|
from .. import magic
|
|
@@ -595,11 +595,11 @@ def gen_amalg(
|
|
|
595
595
|
out.write('\n\n')
|
|
596
596
|
|
|
597
597
|
version_check_fail_msg = (
|
|
598
|
-
f'Requires python {
|
|
598
|
+
f'Requires python {LITE_REQUIRED_PYTHON_VERSION!r}, '
|
|
599
599
|
f'got {{sys.version_info}} from {{sys.executable}}'
|
|
600
600
|
)
|
|
601
601
|
out.write(textwrap.dedent(f"""
|
|
602
|
-
if sys.version_info < {
|
|
602
|
+
if sys.version_info < {LITE_REQUIRED_PYTHON_VERSION!r}:
|
|
603
603
|
raise OSError(f{version_check_fail_msg!r}) # noqa
|
|
604
604
|
""").lstrip())
|
|
605
605
|
out.write('\n\n')
|
omdev/cache/data/cache.py
CHANGED
|
@@ -27,7 +27,7 @@ from omlish import marshal as msh
|
|
|
27
27
|
from omlish.formats import json
|
|
28
28
|
from omlish.os.files import touch
|
|
29
29
|
|
|
30
|
-
from ... import
|
|
30
|
+
from ...git.subtrees import git_clone_subtree
|
|
31
31
|
from .actions import Action
|
|
32
32
|
from .actions import ExtractAction
|
|
33
33
|
from .manifests import Manifest
|
|
@@ -148,7 +148,7 @@ class Cache:
|
|
|
148
148
|
|
|
149
149
|
log.info('Cloning git repo: %s -> %s', spec.url, tmp_dir)
|
|
150
150
|
|
|
151
|
-
|
|
151
|
+
git_clone_subtree(
|
|
152
152
|
base_dir=tmp_dir,
|
|
153
153
|
repo_url=spec.url,
|
|
154
154
|
repo_dir='data',
|
omdev/cache/data/manifests.py
CHANGED
omdev/git/__init__.py
ADDED
|
File without changes
|
omdev/git/revisions.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
|
2
|
+
# @omlish-lite
|
|
3
|
+
import os.path
|
|
4
|
+
import subprocess
|
|
5
|
+
import typing as ta
|
|
6
|
+
|
|
7
|
+
from omlish.subprocesses import subprocess_maybe_shell_wrap_exec
|
|
8
|
+
from omlish.subprocesses import subprocesses
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_git_revision(
|
|
12
|
+
*,
|
|
13
|
+
cwd: ta.Optional[str] = None,
|
|
14
|
+
) -> ta.Optional[str]:
|
|
15
|
+
subprocesses.check_output('git', '--version')
|
|
16
|
+
|
|
17
|
+
if cwd is None:
|
|
18
|
+
cwd = os.getcwd()
|
|
19
|
+
|
|
20
|
+
if subprocess.run( # noqa
|
|
21
|
+
subprocess_maybe_shell_wrap_exec(
|
|
22
|
+
'git',
|
|
23
|
+
'rev-parse',
|
|
24
|
+
'--is-inside-work-tree',
|
|
25
|
+
),
|
|
26
|
+
stdout=subprocess.PIPE,
|
|
27
|
+
stderr=subprocess.PIPE,
|
|
28
|
+
).returncode:
|
|
29
|
+
return None
|
|
30
|
+
|
|
31
|
+
has_untracked = bool(subprocesses.check_output(
|
|
32
|
+
'git',
|
|
33
|
+
'ls-files',
|
|
34
|
+
'.',
|
|
35
|
+
'--exclude-standard',
|
|
36
|
+
'--others',
|
|
37
|
+
cwd=cwd,
|
|
38
|
+
).decode().strip())
|
|
39
|
+
|
|
40
|
+
dirty_rev = subprocesses.check_output(
|
|
41
|
+
'git',
|
|
42
|
+
'describe',
|
|
43
|
+
'--match=NeVeRmAtCh',
|
|
44
|
+
'--always',
|
|
45
|
+
'--abbrev=40',
|
|
46
|
+
'--dirty',
|
|
47
|
+
cwd=cwd,
|
|
48
|
+
).decode().strip()
|
|
49
|
+
|
|
50
|
+
return dirty_rev + ('-untracked' if has_untracked else '')
|
omdev/{git.py → git/status.py}
RENAMED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
# ruff: noqa: UP006 UP007
|
|
2
2
|
# @omlish-lite
|
|
3
|
-
"""
|
|
4
|
-
git status
|
|
5
|
-
--porcelain=v1
|
|
6
|
-
--ignore-submodules
|
|
7
|
-
2>/dev/null
|
|
8
|
-
"""
|
|
9
3
|
import dataclasses as dc
|
|
10
4
|
import enum
|
|
11
5
|
import os.path
|
|
@@ -16,111 +10,6 @@ from omlish.lite.check import check
|
|
|
16
10
|
from omlish.subprocesses import subprocess_maybe_shell_wrap_exec
|
|
17
11
|
|
|
18
12
|
|
|
19
|
-
##
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def git_clone_subtree(
|
|
23
|
-
*,
|
|
24
|
-
base_dir: str,
|
|
25
|
-
repo_url: str,
|
|
26
|
-
repo_dir: str,
|
|
27
|
-
branch: ta.Optional[str] = None,
|
|
28
|
-
rev: ta.Optional[str] = None,
|
|
29
|
-
repo_subtrees: ta.Sequence[str],
|
|
30
|
-
) -> None:
|
|
31
|
-
if not bool(branch) ^ bool(rev):
|
|
32
|
-
raise ValueError('must set branch or rev')
|
|
33
|
-
|
|
34
|
-
if isinstance(repo_subtrees, str):
|
|
35
|
-
raise TypeError(repo_subtrees)
|
|
36
|
-
|
|
37
|
-
git_opts = [
|
|
38
|
-
'-c', 'advice.detachedHead=false',
|
|
39
|
-
]
|
|
40
|
-
|
|
41
|
-
subprocess.check_call(
|
|
42
|
-
subprocess_maybe_shell_wrap_exec(
|
|
43
|
-
'git',
|
|
44
|
-
*git_opts,
|
|
45
|
-
'clone',
|
|
46
|
-
'-n',
|
|
47
|
-
'--depth=1',
|
|
48
|
-
'--filter=tree:0',
|
|
49
|
-
*(['-b', branch] if branch else []),
|
|
50
|
-
'--single-branch',
|
|
51
|
-
repo_url,
|
|
52
|
-
repo_dir,
|
|
53
|
-
),
|
|
54
|
-
cwd=base_dir,
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
rd = os.path.join(base_dir, repo_dir)
|
|
58
|
-
subprocess.check_call(
|
|
59
|
-
subprocess_maybe_shell_wrap_exec(
|
|
60
|
-
'git',
|
|
61
|
-
*git_opts,
|
|
62
|
-
'sparse-checkout',
|
|
63
|
-
'set',
|
|
64
|
-
'--no-cone',
|
|
65
|
-
*repo_subtrees,
|
|
66
|
-
),
|
|
67
|
-
cwd=rd,
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
subprocess.check_call(
|
|
71
|
-
subprocess_maybe_shell_wrap_exec(
|
|
72
|
-
'git',
|
|
73
|
-
*git_opts,
|
|
74
|
-
'checkout',
|
|
75
|
-
*([rev] if rev else []),
|
|
76
|
-
),
|
|
77
|
-
cwd=rd,
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
def get_git_revision(
|
|
82
|
-
*,
|
|
83
|
-
cwd: ta.Optional[str] = None,
|
|
84
|
-
) -> ta.Optional[str]:
|
|
85
|
-
subprocess.check_output(subprocess_maybe_shell_wrap_exec('git', '--version'))
|
|
86
|
-
|
|
87
|
-
if cwd is None:
|
|
88
|
-
cwd = os.getcwd()
|
|
89
|
-
|
|
90
|
-
if subprocess.run( # noqa
|
|
91
|
-
subprocess_maybe_shell_wrap_exec(
|
|
92
|
-
'git',
|
|
93
|
-
'rev-parse',
|
|
94
|
-
'--is-inside-work-tree',
|
|
95
|
-
),
|
|
96
|
-
stdout=subprocess.PIPE,
|
|
97
|
-
stderr=subprocess.PIPE,
|
|
98
|
-
).returncode:
|
|
99
|
-
return None
|
|
100
|
-
|
|
101
|
-
has_untracked = bool(subprocess.check_output(subprocess_maybe_shell_wrap_exec(
|
|
102
|
-
'git',
|
|
103
|
-
'ls-files',
|
|
104
|
-
'.',
|
|
105
|
-
'--exclude-standard',
|
|
106
|
-
'--others',
|
|
107
|
-
), cwd=cwd).decode().strip())
|
|
108
|
-
|
|
109
|
-
dirty_rev = subprocess.check_output(subprocess_maybe_shell_wrap_exec(
|
|
110
|
-
'git',
|
|
111
|
-
'describe',
|
|
112
|
-
'--match=NeVeRmAtCh',
|
|
113
|
-
'--always',
|
|
114
|
-
'--abbrev=40',
|
|
115
|
-
'--dirty',
|
|
116
|
-
), cwd=cwd).decode().strip()
|
|
117
|
-
|
|
118
|
-
return dirty_rev + ('-untracked' if has_untracked else '')
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
##
|
|
122
|
-
|
|
123
|
-
|
|
124
13
|
_GIT_STATUS_LINE_ESCAPE_CODES: ta.Mapping[str, str] = {
|
|
125
14
|
'\\': '\\',
|
|
126
15
|
'"': '"',
|
omdev/git/subtrees.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
|
2
|
+
# @omlish-lite
|
|
3
|
+
import dataclasses as dc
|
|
4
|
+
import os.path
|
|
5
|
+
import typing as ta
|
|
6
|
+
|
|
7
|
+
from omlish.subprocesses import subprocesses
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dc.dataclass(frozen=True)
|
|
11
|
+
class GitSubtreeCloner:
|
|
12
|
+
base_dir: str
|
|
13
|
+
repo_url: str
|
|
14
|
+
repo_dir: str
|
|
15
|
+
|
|
16
|
+
# _: dc.KW_ONLY
|
|
17
|
+
|
|
18
|
+
repo_subtrees: ta.Sequence[str]
|
|
19
|
+
|
|
20
|
+
branch: ta.Optional[str] = None
|
|
21
|
+
rev: ta.Optional[str] = None
|
|
22
|
+
|
|
23
|
+
def __post_init__(self) -> None:
|
|
24
|
+
if not bool(self.branch) ^ bool(self.rev):
|
|
25
|
+
raise ValueError('must set branch or rev')
|
|
26
|
+
|
|
27
|
+
if isinstance(self.repo_subtrees, str):
|
|
28
|
+
raise TypeError(self.repo_subtrees)
|
|
29
|
+
|
|
30
|
+
@dc.dataclass(frozen=True)
|
|
31
|
+
class Command:
|
|
32
|
+
cmd: ta.Sequence[str]
|
|
33
|
+
cwd: str
|
|
34
|
+
|
|
35
|
+
def build_commands(self) -> ta.Iterator[Command]:
|
|
36
|
+
git_opts = [
|
|
37
|
+
'-c', 'advice.detachedHead=false',
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
yield GitSubtreeCloner.Command(
|
|
41
|
+
cmd=(
|
|
42
|
+
'git',
|
|
43
|
+
*git_opts,
|
|
44
|
+
'clone',
|
|
45
|
+
'-n',
|
|
46
|
+
'--depth=1',
|
|
47
|
+
'--filter=tree:0',
|
|
48
|
+
*(['-b', self.branch] if self.branch else []),
|
|
49
|
+
'--single-branch',
|
|
50
|
+
self.repo_url,
|
|
51
|
+
self.repo_dir,
|
|
52
|
+
),
|
|
53
|
+
cwd=self.base_dir,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
rd = os.path.join(self.base_dir, self.repo_dir)
|
|
57
|
+
yield GitSubtreeCloner.Command(
|
|
58
|
+
cmd=(
|
|
59
|
+
'git',
|
|
60
|
+
*git_opts,
|
|
61
|
+
'sparse-checkout',
|
|
62
|
+
'set',
|
|
63
|
+
'--no-cone',
|
|
64
|
+
*self.repo_subtrees,
|
|
65
|
+
),
|
|
66
|
+
cwd=rd,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
yield GitSubtreeCloner.Command(
|
|
70
|
+
cmd=(
|
|
71
|
+
'git',
|
|
72
|
+
*git_opts,
|
|
73
|
+
'checkout',
|
|
74
|
+
*([self.rev] if self.rev else []),
|
|
75
|
+
),
|
|
76
|
+
cwd=rd,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def git_clone_subtree(
|
|
81
|
+
*,
|
|
82
|
+
base_dir: str,
|
|
83
|
+
repo_url: str,
|
|
84
|
+
repo_dir: str,
|
|
85
|
+
branch: ta.Optional[str] = None,
|
|
86
|
+
rev: ta.Optional[str] = None,
|
|
87
|
+
repo_subtrees: ta.Sequence[str],
|
|
88
|
+
) -> None:
|
|
89
|
+
for cmd in GitSubtreeCloner(
|
|
90
|
+
base_dir=base_dir,
|
|
91
|
+
repo_url=repo_url,
|
|
92
|
+
repo_dir=repo_dir,
|
|
93
|
+
branch=branch,
|
|
94
|
+
rev=rev,
|
|
95
|
+
repo_subtrees=repo_subtrees,
|
|
96
|
+
).build_commands():
|
|
97
|
+
subprocesses.check_call(
|
|
98
|
+
*cmd.cmd,
|
|
99
|
+
cwd=cmd.cwd,
|
|
100
|
+
)
|
omdev/interp/cli.py
CHANGED
|
@@ -12,7 +12,7 @@ import asyncio
|
|
|
12
12
|
import typing as ta
|
|
13
13
|
|
|
14
14
|
from omlish.lite.check import check
|
|
15
|
-
from omlish.lite.runtime import
|
|
15
|
+
from omlish.lite.runtime import check_lite_runtime_version
|
|
16
16
|
from omlish.logs.standard import configure_standard_logging
|
|
17
17
|
|
|
18
18
|
from .resolvers import DEFAULT_INTERP_RESOLVER
|
|
@@ -58,7 +58,7 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
async def _async_main(argv: ta.Optional[ta.Sequence[str]] = None) -> None:
|
|
61
|
-
|
|
61
|
+
check_lite_runtime_version()
|
|
62
62
|
configure_standard_logging()
|
|
63
63
|
|
|
64
64
|
parser = _build_parser()
|
omdev/pyproject/cli.py
CHANGED
|
@@ -39,7 +39,7 @@ from omlish.argparse.cli import argparse_command
|
|
|
39
39
|
from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
|
|
40
40
|
from omlish.lite.cached import cached_nullary
|
|
41
41
|
from omlish.lite.check import check
|
|
42
|
-
from omlish.lite.runtime import
|
|
42
|
+
from omlish.lite.runtime import check_lite_runtime_version
|
|
43
43
|
from omlish.logs.standard import configure_standard_logging
|
|
44
44
|
|
|
45
45
|
from ..toml.parser import toml_loads
|
|
@@ -288,7 +288,7 @@ class PyprojectCli(ArgparseCli):
|
|
|
288
288
|
|
|
289
289
|
|
|
290
290
|
async def _async_main(argv: ta.Optional[ta.Sequence[str]] = None) -> None:
|
|
291
|
-
|
|
291
|
+
check_lite_runtime_version()
|
|
292
292
|
configure_standard_logging()
|
|
293
293
|
|
|
294
294
|
await PyprojectCli(argv).async_cli_run()
|
omdev/revisions.py
CHANGED
|
@@ -18,7 +18,7 @@ from omlish.lite.check import check
|
|
|
18
18
|
from omlish.lite.logs import log
|
|
19
19
|
from omlish.logs.standard import configure_standard_logging
|
|
20
20
|
|
|
21
|
-
from .git import get_git_revision
|
|
21
|
+
from .git.revisions import get_git_revision
|
|
22
22
|
from .wheelfile import WheelFile
|
|
23
23
|
|
|
24
24
|
|
omdev/scripts/interp.py
CHANGED
|
@@ -1086,6 +1086,10 @@ def is_new_type(spec: ta.Any) -> bool:
|
|
|
1086
1086
|
return isinstance(spec, types.FunctionType) and spec.__code__ is ta.NewType.__code__.co_consts[1] # type: ignore # noqa
|
|
1087
1087
|
|
|
1088
1088
|
|
|
1089
|
+
def get_new_type_supertype(spec: ta.Any) -> ta.Any:
|
|
1090
|
+
return spec.__supertype__
|
|
1091
|
+
|
|
1092
|
+
|
|
1089
1093
|
def deep_subclasses(cls: ta.Type[T]) -> ta.Iterator[ta.Type[T]]:
|
|
1090
1094
|
seen = set()
|
|
1091
1095
|
todo = list(reversed(cls.__subclasses__()))
|
|
@@ -1806,12 +1810,12 @@ def is_debugger_attached() -> bool:
|
|
|
1806
1810
|
return any(frame[1].endswith('pydevd.py') for frame in inspect.stack())
|
|
1807
1811
|
|
|
1808
1812
|
|
|
1809
|
-
|
|
1813
|
+
LITE_REQUIRED_PYTHON_VERSION = (3, 8)
|
|
1810
1814
|
|
|
1811
1815
|
|
|
1812
|
-
def
|
|
1813
|
-
if sys.version_info <
|
|
1814
|
-
raise OSError(f'Requires python {
|
|
1816
|
+
def check_lite_runtime_version() -> None:
|
|
1817
|
+
if sys.version_info < LITE_REQUIRED_PYTHON_VERSION:
|
|
1818
|
+
raise OSError(f'Requires python {LITE_REQUIRED_PYTHON_VERSION}, got {sys.version_info} from {sys.executable}') # noqa
|
|
1815
1819
|
|
|
1816
1820
|
|
|
1817
1821
|
########################################
|
|
@@ -1968,6 +1972,7 @@ TODO:
|
|
|
1968
1972
|
- structured
|
|
1969
1973
|
- prefixed
|
|
1970
1974
|
- debug
|
|
1975
|
+
- optional noisy? noisy will never be lite - some kinda configure_standard callback mechanism?
|
|
1971
1976
|
"""
|
|
1972
1977
|
|
|
1973
1978
|
|
|
@@ -2004,8 +2009,9 @@ class StandardLogFormatter(logging.Formatter):
|
|
|
2004
2009
|
##
|
|
2005
2010
|
|
|
2006
2011
|
|
|
2007
|
-
class
|
|
2008
|
-
|
|
2012
|
+
class StandardConfiguredLogHandler(ProxyLogHandler):
|
|
2013
|
+
def __init_subclass__(cls, **kwargs):
|
|
2014
|
+
raise TypeError('This class serves only as a marker and should not be subclassed.')
|
|
2009
2015
|
|
|
2010
2016
|
|
|
2011
2017
|
##
|
|
@@ -2036,7 +2042,7 @@ def configure_standard_logging(
|
|
|
2036
2042
|
target: ta.Optional[logging.Logger] = None,
|
|
2037
2043
|
force: bool = False,
|
|
2038
2044
|
handler_factory: ta.Optional[ta.Callable[[], logging.Handler]] = None,
|
|
2039
|
-
) -> ta.Optional[
|
|
2045
|
+
) -> ta.Optional[StandardConfiguredLogHandler]:
|
|
2040
2046
|
with _locking_logging_module_lock():
|
|
2041
2047
|
if target is None:
|
|
2042
2048
|
target = logging.root
|
|
@@ -2044,7 +2050,7 @@ def configure_standard_logging(
|
|
|
2044
2050
|
#
|
|
2045
2051
|
|
|
2046
2052
|
if not force:
|
|
2047
|
-
if any(isinstance(h,
|
|
2053
|
+
if any(isinstance(h, StandardConfiguredLogHandler) for h in list(target.handlers)):
|
|
2048
2054
|
return None
|
|
2049
2055
|
|
|
2050
2056
|
#
|
|
@@ -2078,7 +2084,7 @@ def configure_standard_logging(
|
|
|
2078
2084
|
|
|
2079
2085
|
#
|
|
2080
2086
|
|
|
2081
|
-
return
|
|
2087
|
+
return StandardConfiguredLogHandler(handler)
|
|
2082
2088
|
|
|
2083
2089
|
|
|
2084
2090
|
########################################
|
|
@@ -3486,7 +3492,7 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
3486
3492
|
|
|
3487
3493
|
|
|
3488
3494
|
async def _async_main(argv: ta.Optional[ta.Sequence[str]] = None) -> None:
|
|
3489
|
-
|
|
3495
|
+
check_lite_runtime_version()
|
|
3490
3496
|
configure_standard_logging()
|
|
3491
3497
|
|
|
3492
3498
|
parser = _build_parser()
|
omdev/scripts/pyproject.py
CHANGED
|
@@ -2378,6 +2378,10 @@ def is_new_type(spec: ta.Any) -> bool:
|
|
|
2378
2378
|
return isinstance(spec, types.FunctionType) and spec.__code__ is ta.NewType.__code__.co_consts[1] # type: ignore # noqa
|
|
2379
2379
|
|
|
2380
2380
|
|
|
2381
|
+
def get_new_type_supertype(spec: ta.Any) -> ta.Any:
|
|
2382
|
+
return spec.__supertype__
|
|
2383
|
+
|
|
2384
|
+
|
|
2381
2385
|
def deep_subclasses(cls: ta.Type[T]) -> ta.Iterator[ta.Type[T]]:
|
|
2382
2386
|
seen = set()
|
|
2383
2387
|
todo = list(reversed(cls.__subclasses__()))
|
|
@@ -3680,9 +3684,7 @@ class ArgparseCli:
|
|
|
3680
3684
|
"""
|
|
3681
3685
|
TODO:
|
|
3682
3686
|
- pickle stdlib objs? have to pin to 3.8 pickle protocol, will be cross-version
|
|
3683
|
-
- namedtuple
|
|
3684
3687
|
- literals
|
|
3685
|
-
- newtypes?
|
|
3686
3688
|
"""
|
|
3687
3689
|
|
|
3688
3690
|
|
|
@@ -3692,7 +3694,7 @@ TODO:
|
|
|
3692
3694
|
@dc.dataclass(frozen=True)
|
|
3693
3695
|
class ObjMarshalOptions:
|
|
3694
3696
|
raw_bytes: bool = False
|
|
3695
|
-
|
|
3697
|
+
non_strict_fields: bool = False
|
|
3696
3698
|
|
|
3697
3699
|
|
|
3698
3700
|
class ObjMarshaler(abc.ABC):
|
|
@@ -3821,10 +3823,10 @@ class IterableObjMarshaler(ObjMarshaler):
|
|
|
3821
3823
|
|
|
3822
3824
|
|
|
3823
3825
|
@dc.dataclass(frozen=True)
|
|
3824
|
-
class
|
|
3826
|
+
class FieldsObjMarshaler(ObjMarshaler):
|
|
3825
3827
|
ty: type
|
|
3826
3828
|
fs: ta.Mapping[str, ObjMarshaler]
|
|
3827
|
-
|
|
3829
|
+
non_strict: bool = False
|
|
3828
3830
|
|
|
3829
3831
|
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
|
3830
3832
|
return {
|
|
@@ -3836,7 +3838,7 @@ class DataclassObjMarshaler(ObjMarshaler):
|
|
|
3836
3838
|
return self.ty(**{
|
|
3837
3839
|
k: self.fs[k].unmarshal(v, ctx)
|
|
3838
3840
|
for k, v in o.items()
|
|
3839
|
-
if not (self.
|
|
3841
|
+
if not (self.non_strict or ctx.options.non_strict_fields) or k in self.fs
|
|
3840
3842
|
})
|
|
3841
3843
|
|
|
3842
3844
|
|
|
@@ -3968,7 +3970,7 @@ class ObjMarshalerManager:
|
|
|
3968
3970
|
ty: ta.Any,
|
|
3969
3971
|
rec: ta.Callable[[ta.Any], ObjMarshaler],
|
|
3970
3972
|
*,
|
|
3971
|
-
|
|
3973
|
+
non_strict_fields: bool = False,
|
|
3972
3974
|
) -> ObjMarshaler:
|
|
3973
3975
|
if isinstance(ty, type):
|
|
3974
3976
|
if abc.ABC in ty.__bases__:
|
|
@@ -3990,12 +3992,22 @@ class ObjMarshalerManager:
|
|
|
3990
3992
|
return EnumObjMarshaler(ty)
|
|
3991
3993
|
|
|
3992
3994
|
if dc.is_dataclass(ty):
|
|
3993
|
-
return
|
|
3995
|
+
return FieldsObjMarshaler(
|
|
3994
3996
|
ty,
|
|
3995
3997
|
{f.name: rec(f.type) for f in dc.fields(ty)},
|
|
3996
|
-
|
|
3998
|
+
non_strict=non_strict_fields,
|
|
3999
|
+
)
|
|
4000
|
+
|
|
4001
|
+
if issubclass(ty, tuple) and hasattr(ty, '_fields'):
|
|
4002
|
+
return FieldsObjMarshaler(
|
|
4003
|
+
ty,
|
|
4004
|
+
{p.name: rec(p.annotation) for p in inspect.signature(ty).parameters.values()},
|
|
4005
|
+
non_strict=non_strict_fields,
|
|
3997
4006
|
)
|
|
3998
4007
|
|
|
4008
|
+
if is_new_type(ty):
|
|
4009
|
+
return rec(get_new_type_supertype(ty))
|
|
4010
|
+
|
|
3999
4011
|
if is_generic_alias(ty):
|
|
4000
4012
|
try:
|
|
4001
4013
|
mt = self._generic_mapping_types[ta.get_origin(ty)]
|
|
@@ -4129,12 +4141,12 @@ def is_debugger_attached() -> bool:
|
|
|
4129
4141
|
return any(frame[1].endswith('pydevd.py') for frame in inspect.stack())
|
|
4130
4142
|
|
|
4131
4143
|
|
|
4132
|
-
|
|
4144
|
+
LITE_REQUIRED_PYTHON_VERSION = (3, 8)
|
|
4133
4145
|
|
|
4134
4146
|
|
|
4135
|
-
def
|
|
4136
|
-
if sys.version_info <
|
|
4137
|
-
raise OSError(f'Requires python {
|
|
4147
|
+
def check_lite_runtime_version() -> None:
|
|
4148
|
+
if sys.version_info < LITE_REQUIRED_PYTHON_VERSION:
|
|
4149
|
+
raise OSError(f'Requires python {LITE_REQUIRED_PYTHON_VERSION}, got {sys.version_info} from {sys.executable}') # noqa
|
|
4138
4150
|
|
|
4139
4151
|
|
|
4140
4152
|
########################################
|
|
@@ -4389,6 +4401,7 @@ TODO:
|
|
|
4389
4401
|
- structured
|
|
4390
4402
|
- prefixed
|
|
4391
4403
|
- debug
|
|
4404
|
+
- optional noisy? noisy will never be lite - some kinda configure_standard callback mechanism?
|
|
4392
4405
|
"""
|
|
4393
4406
|
|
|
4394
4407
|
|
|
@@ -4425,8 +4438,9 @@ class StandardLogFormatter(logging.Formatter):
|
|
|
4425
4438
|
##
|
|
4426
4439
|
|
|
4427
4440
|
|
|
4428
|
-
class
|
|
4429
|
-
|
|
4441
|
+
class StandardConfiguredLogHandler(ProxyLogHandler):
|
|
4442
|
+
def __init_subclass__(cls, **kwargs):
|
|
4443
|
+
raise TypeError('This class serves only as a marker and should not be subclassed.')
|
|
4430
4444
|
|
|
4431
4445
|
|
|
4432
4446
|
##
|
|
@@ -4457,7 +4471,7 @@ def configure_standard_logging(
|
|
|
4457
4471
|
target: ta.Optional[logging.Logger] = None,
|
|
4458
4472
|
force: bool = False,
|
|
4459
4473
|
handler_factory: ta.Optional[ta.Callable[[], logging.Handler]] = None,
|
|
4460
|
-
) -> ta.Optional[
|
|
4474
|
+
) -> ta.Optional[StandardConfiguredLogHandler]:
|
|
4461
4475
|
with _locking_logging_module_lock():
|
|
4462
4476
|
if target is None:
|
|
4463
4477
|
target = logging.root
|
|
@@ -4465,7 +4479,7 @@ def configure_standard_logging(
|
|
|
4465
4479
|
#
|
|
4466
4480
|
|
|
4467
4481
|
if not force:
|
|
4468
|
-
if any(isinstance(h,
|
|
4482
|
+
if any(isinstance(h, StandardConfiguredLogHandler) for h in list(target.handlers)):
|
|
4469
4483
|
return None
|
|
4470
4484
|
|
|
4471
4485
|
#
|
|
@@ -4499,7 +4513,7 @@ def configure_standard_logging(
|
|
|
4499
4513
|
|
|
4500
4514
|
#
|
|
4501
4515
|
|
|
4502
|
-
return
|
|
4516
|
+
return StandardConfiguredLogHandler(handler)
|
|
4503
4517
|
|
|
4504
4518
|
|
|
4505
4519
|
########################################
|
|
@@ -4831,404 +4845,49 @@ class AbstractAsyncSubprocesses(BaseSubprocesses):
|
|
|
4831
4845
|
|
|
4832
4846
|
|
|
4833
4847
|
########################################
|
|
4834
|
-
# ../../git.py
|
|
4835
|
-
"""
|
|
4836
|
-
git status
|
|
4837
|
-
--porcelain=v1
|
|
4838
|
-
--ignore-submodules
|
|
4839
|
-
2>/dev/null
|
|
4840
|
-
"""
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
##
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
def git_clone_subtree(
|
|
4847
|
-
*,
|
|
4848
|
-
base_dir: str,
|
|
4849
|
-
repo_url: str,
|
|
4850
|
-
repo_dir: str,
|
|
4851
|
-
branch: ta.Optional[str] = None,
|
|
4852
|
-
rev: ta.Optional[str] = None,
|
|
4853
|
-
repo_subtrees: ta.Sequence[str],
|
|
4854
|
-
) -> None:
|
|
4855
|
-
if not bool(branch) ^ bool(rev):
|
|
4856
|
-
raise ValueError('must set branch or rev')
|
|
4857
|
-
|
|
4858
|
-
if isinstance(repo_subtrees, str):
|
|
4859
|
-
raise TypeError(repo_subtrees)
|
|
4860
|
-
|
|
4861
|
-
git_opts = [
|
|
4862
|
-
'-c', 'advice.detachedHead=false',
|
|
4863
|
-
]
|
|
4864
|
-
|
|
4865
|
-
subprocess.check_call(
|
|
4866
|
-
subprocess_maybe_shell_wrap_exec(
|
|
4867
|
-
'git',
|
|
4868
|
-
*git_opts,
|
|
4869
|
-
'clone',
|
|
4870
|
-
'-n',
|
|
4871
|
-
'--depth=1',
|
|
4872
|
-
'--filter=tree:0',
|
|
4873
|
-
*(['-b', branch] if branch else []),
|
|
4874
|
-
'--single-branch',
|
|
4875
|
-
repo_url,
|
|
4876
|
-
repo_dir,
|
|
4877
|
-
),
|
|
4878
|
-
cwd=base_dir,
|
|
4879
|
-
)
|
|
4880
|
-
|
|
4881
|
-
rd = os.path.join(base_dir, repo_dir)
|
|
4882
|
-
subprocess.check_call(
|
|
4883
|
-
subprocess_maybe_shell_wrap_exec(
|
|
4884
|
-
'git',
|
|
4885
|
-
*git_opts,
|
|
4886
|
-
'sparse-checkout',
|
|
4887
|
-
'set',
|
|
4888
|
-
'--no-cone',
|
|
4889
|
-
*repo_subtrees,
|
|
4890
|
-
),
|
|
4891
|
-
cwd=rd,
|
|
4892
|
-
)
|
|
4893
|
-
|
|
4894
|
-
subprocess.check_call(
|
|
4895
|
-
subprocess_maybe_shell_wrap_exec(
|
|
4896
|
-
'git',
|
|
4897
|
-
*git_opts,
|
|
4898
|
-
'checkout',
|
|
4899
|
-
*([rev] if rev else []),
|
|
4900
|
-
),
|
|
4901
|
-
cwd=rd,
|
|
4902
|
-
)
|
|
4848
|
+
# ../../git/revisions.py
|
|
4903
4849
|
|
|
4904
4850
|
|
|
4905
4851
|
def get_git_revision(
|
|
4906
4852
|
*,
|
|
4907
4853
|
cwd: ta.Optional[str] = None,
|
|
4908
4854
|
) -> ta.Optional[str]:
|
|
4909
|
-
|
|
4855
|
+
subprocesses.check_output('git', '--version')
|
|
4910
4856
|
|
|
4911
4857
|
if cwd is None:
|
|
4912
4858
|
cwd = os.getcwd()
|
|
4913
4859
|
|
|
4914
4860
|
if subprocess.run( # noqa
|
|
4915
|
-
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4861
|
+
subprocess_maybe_shell_wrap_exec(
|
|
4862
|
+
'git',
|
|
4863
|
+
'rev-parse',
|
|
4864
|
+
'--is-inside-work-tree',
|
|
4865
|
+
),
|
|
4866
|
+
stdout=subprocess.PIPE,
|
|
4867
|
+
stderr=subprocess.PIPE,
|
|
4922
4868
|
).returncode:
|
|
4923
4869
|
return None
|
|
4924
4870
|
|
|
4925
|
-
has_untracked = bool(
|
|
4871
|
+
has_untracked = bool(subprocesses.check_output(
|
|
4926
4872
|
'git',
|
|
4927
4873
|
'ls-files',
|
|
4928
4874
|
'.',
|
|
4929
4875
|
'--exclude-standard',
|
|
4930
4876
|
'--others',
|
|
4931
|
-
|
|
4877
|
+
cwd=cwd,
|
|
4878
|
+
).decode().strip())
|
|
4932
4879
|
|
|
4933
|
-
dirty_rev =
|
|
4880
|
+
dirty_rev = subprocesses.check_output(
|
|
4934
4881
|
'git',
|
|
4935
4882
|
'describe',
|
|
4936
4883
|
'--match=NeVeRmAtCh',
|
|
4937
4884
|
'--always',
|
|
4938
4885
|
'--abbrev=40',
|
|
4939
4886
|
'--dirty',
|
|
4940
|
-
), cwd=cwd).decode().strip()
|
|
4941
|
-
|
|
4942
|
-
return dirty_rev + ('-untracked' if has_untracked else '')
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
##
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
_GIT_STATUS_LINE_ESCAPE_CODES: ta.Mapping[str, str] = {
|
|
4949
|
-
'\\': '\\',
|
|
4950
|
-
'"': '"',
|
|
4951
|
-
'n': '\n',
|
|
4952
|
-
't': '\t',
|
|
4953
|
-
}
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
def yield_git_status_line_fields(l: str) -> ta.Iterator[str]:
|
|
4957
|
-
def find_any(chars: str, start: int = 0) -> int:
|
|
4958
|
-
ret = -1
|
|
4959
|
-
for c in chars:
|
|
4960
|
-
if (found := l.find(c, start)) >= 0 and (ret < 0 or ret > found):
|
|
4961
|
-
ret = found
|
|
4962
|
-
return ret
|
|
4963
|
-
|
|
4964
|
-
p = 0
|
|
4965
|
-
while True:
|
|
4966
|
-
if l[p] == '"':
|
|
4967
|
-
p += 1
|
|
4968
|
-
s = []
|
|
4969
|
-
while (n := find_any('\\"', p)) > 0:
|
|
4970
|
-
if (c := l[n]) == '\\':
|
|
4971
|
-
s.append(l[p:n])
|
|
4972
|
-
s.append(_GIT_STATUS_LINE_ESCAPE_CODES[l[n + 1]])
|
|
4973
|
-
p = n + 2
|
|
4974
|
-
elif c == '"':
|
|
4975
|
-
s.append(l[p:n])
|
|
4976
|
-
p = n
|
|
4977
|
-
break
|
|
4978
|
-
else:
|
|
4979
|
-
raise ValueError(l)
|
|
4980
|
-
|
|
4981
|
-
if l[p] != '"':
|
|
4982
|
-
raise ValueError(l)
|
|
4983
|
-
|
|
4984
|
-
yield ''.join(s)
|
|
4985
|
-
|
|
4986
|
-
p += 1
|
|
4987
|
-
if p == len(l):
|
|
4988
|
-
return
|
|
4989
|
-
elif l[p] != ' ':
|
|
4990
|
-
raise ValueError(l)
|
|
4991
|
-
|
|
4992
|
-
p += 1
|
|
4993
|
-
|
|
4994
|
-
else:
|
|
4995
|
-
if (e := l.find(' ', p)) < 0:
|
|
4996
|
-
yield l[p:]
|
|
4997
|
-
return
|
|
4998
|
-
|
|
4999
|
-
yield l[p:e]
|
|
5000
|
-
p = e + 1
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
"""
|
|
5004
|
-
When merge is occurring and was successful, or outside of a merge situation, X shows the status of the index and Y shows
|
|
5005
|
-
the status of the working tree:
|
|
5006
|
-
-------------------------------------------------
|
|
5007
|
-
X Y Meaning
|
|
5008
|
-
-------------------------------------------------
|
|
5009
|
-
[AMD] not updated
|
|
5010
|
-
M [ MTD] updated in index
|
|
5011
|
-
T [ MTD] type changed in index
|
|
5012
|
-
A [ MTD] added to index
|
|
5013
|
-
D deleted from index
|
|
5014
|
-
R [ MTD] renamed in index
|
|
5015
|
-
C [ MTD] copied in index
|
|
5016
|
-
[MTARC] index and work tree matches
|
|
5017
|
-
[ MTARC] M work tree changed since index
|
|
5018
|
-
[ MTARC] T type changed in work tree since index
|
|
5019
|
-
[ MTARC] D deleted in work tree
|
|
5020
|
-
R renamed in work tree
|
|
5021
|
-
C copied in work tree
|
|
5022
|
-
|
|
5023
|
-
When merge conflict has occurred and has not yet been resolved, X and Y show the state introduced by each head of the
|
|
5024
|
-
merge, relative to the common ancestor:
|
|
5025
|
-
-------------------------------------------------
|
|
5026
|
-
X Y Meaning
|
|
5027
|
-
-------------------------------------------------
|
|
5028
|
-
D D unmerged, both deleted
|
|
5029
|
-
A U unmerged, added by us
|
|
5030
|
-
U D unmerged, deleted by them
|
|
5031
|
-
U A unmerged, added by them
|
|
5032
|
-
D U unmerged, deleted by us
|
|
5033
|
-
A A unmerged, both added
|
|
5034
|
-
U U unmerged, both modified
|
|
5035
|
-
|
|
5036
|
-
When path is untracked, X and Y are always the same, since they are unknown to the index:
|
|
5037
|
-
-------------------------------------------------
|
|
5038
|
-
X Y Meaning
|
|
5039
|
-
-------------------------------------------------
|
|
5040
|
-
? ? untracked
|
|
5041
|
-
! ! ignored
|
|
5042
|
-
|
|
5043
|
-
Submodules have more state and instead report
|
|
5044
|
-
|
|
5045
|
-
- M = the submodule has a different HEAD than recorded in the index
|
|
5046
|
-
- m = the submodule has modified content
|
|
5047
|
-
- ? = the submodule has untracked files
|
|
5048
|
-
|
|
5049
|
-
This is since modified content or untracked files in a submodule cannot be added via git add in the superproject to
|
|
5050
|
-
prepare a commit. m and ? are applied recursively. For example if a nested submodule in a submodule contains an
|
|
5051
|
-
untracked file, this is reported as ? as well.
|
|
5052
|
-
""" # noqa
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
class GitStatusState(enum.Enum):
|
|
5056
|
-
UNMODIFIED = ' '
|
|
5057
|
-
MODIFIED = 'M'
|
|
5058
|
-
FILE_TYPE_CHANGED = 'T'
|
|
5059
|
-
ADDED = 'A'
|
|
5060
|
-
DELETED = 'D'
|
|
5061
|
-
RENAMED = 'R'
|
|
5062
|
-
COPIED = 'C'
|
|
5063
|
-
UPDATED_BUT_UNMERGED = 'U'
|
|
5064
|
-
UNTRACKED = '?'
|
|
5065
|
-
IGNORED = '!'
|
|
5066
|
-
SUBMODULE_MODIFIED_CONTENT = 'm'
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
_UNMERGED_GIT_STATUS_STATES: ta.FrozenSet[GitStatusState] = frozenset([
|
|
5070
|
-
GitStatusState.UPDATED_BUT_UNMERGED,
|
|
5071
|
-
])
|
|
5072
|
-
|
|
5073
|
-
_UNMERGED_GIT_STATUS_STATE_PAIRS: ta.FrozenSet[ta.Tuple[GitStatusState, GitStatusState]] = frozenset([
|
|
5074
|
-
(GitStatusState.ADDED, GitStatusState.ADDED),
|
|
5075
|
-
(GitStatusState.DELETED, GitStatusState.DELETED),
|
|
5076
|
-
])
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
@dc.dataclass(frozen=True)
|
|
5080
|
-
class GitStatusItem:
|
|
5081
|
-
x: GitStatusState
|
|
5082
|
-
y: GitStatusState
|
|
5083
|
-
|
|
5084
|
-
a: str
|
|
5085
|
-
b: ta.Optional[str]
|
|
5086
|
-
|
|
5087
|
-
@property
|
|
5088
|
-
def is_unmerged(self) -> bool:
|
|
5089
|
-
return (
|
|
5090
|
-
self.x in _UNMERGED_GIT_STATUS_STATE_PAIRS or
|
|
5091
|
-
self.y in _UNMERGED_GIT_STATUS_STATE_PAIRS or
|
|
5092
|
-
(self.x, self.y) in _UNMERGED_GIT_STATUS_STATE_PAIRS
|
|
5093
|
-
)
|
|
5094
|
-
|
|
5095
|
-
def __repr__(self) -> str:
|
|
5096
|
-
return (
|
|
5097
|
-
f'{self.__class__.__name__}('
|
|
5098
|
-
f'x={self.x.name}, '
|
|
5099
|
-
f'y={self.y.name}, '
|
|
5100
|
-
f'a={self.a!r}' +
|
|
5101
|
-
(f', b={self.b!r}' if self.b is not None else '') +
|
|
5102
|
-
')'
|
|
5103
|
-
)
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
def parse_git_status_line(l: str) -> GitStatusItem:
|
|
5107
|
-
if len(l) < 3 or l[2] != ' ':
|
|
5108
|
-
raise ValueError(l)
|
|
5109
|
-
x, y = l[0], l[1]
|
|
5110
|
-
|
|
5111
|
-
fields = list(yield_git_status_line_fields(l[3:]))
|
|
5112
|
-
if len(fields) == 1:
|
|
5113
|
-
a, b = fields[0], None
|
|
5114
|
-
elif len(fields) == 3:
|
|
5115
|
-
check.state(fields[1] == '->', l)
|
|
5116
|
-
a, b = fields[0], fields[2]
|
|
5117
|
-
else:
|
|
5118
|
-
raise ValueError(l)
|
|
5119
|
-
|
|
5120
|
-
return GitStatusItem(
|
|
5121
|
-
GitStatusState(x),
|
|
5122
|
-
GitStatusState(y),
|
|
5123
|
-
a,
|
|
5124
|
-
b,
|
|
5125
|
-
)
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
class GitStatus(ta.Sequence[GitStatusItem]):
|
|
5129
|
-
def __init__(self, lines: ta.Iterable[GitStatusItem]) -> None:
|
|
5130
|
-
super().__init__()
|
|
5131
|
-
|
|
5132
|
-
self._lst = list(lines)
|
|
5133
|
-
|
|
5134
|
-
by_x: ta.Dict[GitStatusState, list[GitStatusItem]] = {}
|
|
5135
|
-
by_y: ta.Dict[GitStatusState, list[GitStatusItem]] = {}
|
|
5136
|
-
|
|
5137
|
-
by_a: ta.Dict[str, GitStatusItem] = {}
|
|
5138
|
-
by_b: ta.Dict[str, GitStatusItem] = {}
|
|
5139
|
-
|
|
5140
|
-
for l in self._lst:
|
|
5141
|
-
by_x.setdefault(l.x, []).append(l)
|
|
5142
|
-
by_y.setdefault(l.y, []).append(l)
|
|
5143
|
-
|
|
5144
|
-
if l.a in by_a:
|
|
5145
|
-
raise KeyError(l.a)
|
|
5146
|
-
by_a[l.a] = l
|
|
5147
|
-
|
|
5148
|
-
if l.b is not None:
|
|
5149
|
-
if l.b in by_b:
|
|
5150
|
-
raise KeyError(l.b)
|
|
5151
|
-
by_b[l.b] = l
|
|
5152
|
-
|
|
5153
|
-
self._by_x = by_x
|
|
5154
|
-
self._by_y = by_y
|
|
5155
|
-
|
|
5156
|
-
self._by_a = by_a
|
|
5157
|
-
self._by_b = by_b
|
|
5158
|
-
|
|
5159
|
-
self._has_unmerged = any(l.is_unmerged for l in self)
|
|
5160
|
-
|
|
5161
|
-
#
|
|
5162
|
-
|
|
5163
|
-
def __iter__(self) -> ta.Iterator[GitStatusItem]:
|
|
5164
|
-
return iter(self._lst)
|
|
5165
|
-
|
|
5166
|
-
def __getitem__(self, index):
|
|
5167
|
-
return self._lst[index]
|
|
5168
|
-
|
|
5169
|
-
def __len__(self) -> int:
|
|
5170
|
-
return len(self._lst)
|
|
5171
|
-
|
|
5172
|
-
#
|
|
5173
|
-
|
|
5174
|
-
@property
|
|
5175
|
-
def by_x(self) -> ta.Mapping[GitStatusState, ta.Sequence[GitStatusItem]]:
|
|
5176
|
-
return self._by_x
|
|
5177
|
-
|
|
5178
|
-
@property
|
|
5179
|
-
def by_y(self) -> ta.Mapping[GitStatusState, ta.Sequence[GitStatusItem]]:
|
|
5180
|
-
return self._by_y
|
|
5181
|
-
|
|
5182
|
-
@property
|
|
5183
|
-
def by_a(self) -> ta.Mapping[str, GitStatusItem]:
|
|
5184
|
-
return self._by_a
|
|
5185
|
-
|
|
5186
|
-
@property
|
|
5187
|
-
def by_b(self) -> ta.Mapping[str, GitStatusItem]:
|
|
5188
|
-
return self._by_b
|
|
5189
|
-
|
|
5190
|
-
#
|
|
5191
|
-
|
|
5192
|
-
@property
|
|
5193
|
-
def has_unmerged(self) -> bool:
|
|
5194
|
-
return self._has_unmerged
|
|
5195
|
-
|
|
5196
|
-
@property
|
|
5197
|
-
def has_staged(self) -> bool:
|
|
5198
|
-
return any(l.x != GitStatusState.UNMODIFIED for l in self._lst)
|
|
5199
|
-
|
|
5200
|
-
@property
|
|
5201
|
-
def has_dirty(self) -> bool:
|
|
5202
|
-
return any(l.y != GitStatusState.UNMODIFIED for l in self._lst)
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
def parse_git_status(s: str) -> GitStatus:
|
|
5206
|
-
return GitStatus(parse_git_status_line(l) for l in s.splitlines())
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
def get_git_status(
|
|
5210
|
-
*,
|
|
5211
|
-
cwd: ta.Optional[str] = None,
|
|
5212
|
-
ignore_submodules: bool = False,
|
|
5213
|
-
verbose: bool = False,
|
|
5214
|
-
) -> GitStatus:
|
|
5215
|
-
if cwd is None:
|
|
5216
|
-
cwd = os.getcwd()
|
|
5217
|
-
|
|
5218
|
-
proc = subprocess.run( # type: ignore
|
|
5219
|
-
subprocess_maybe_shell_wrap_exec(
|
|
5220
|
-
'git',
|
|
5221
|
-
'status',
|
|
5222
|
-
'--porcelain=v1',
|
|
5223
|
-
*(['--ignore-submodules'] if ignore_submodules else []),
|
|
5224
|
-
),
|
|
5225
4887
|
cwd=cwd,
|
|
5226
|
-
|
|
5227
|
-
**(dict(stderr=subprocess.PIPE) if not verbose else {}),
|
|
5228
|
-
check=True,
|
|
5229
|
-
)
|
|
4888
|
+
).decode().strip()
|
|
5230
4889
|
|
|
5231
|
-
return
|
|
4890
|
+
return dirty_rev + ('-untracked' if has_untracked else '')
|
|
5232
4891
|
|
|
5233
4892
|
|
|
5234
4893
|
########################################
|
|
@@ -7290,7 +6949,7 @@ class PyprojectCli(ArgparseCli):
|
|
|
7290
6949
|
|
|
7291
6950
|
|
|
7292
6951
|
async def _async_main(argv: ta.Optional[ta.Sequence[str]] = None) -> None:
|
|
7293
|
-
|
|
6952
|
+
check_lite_runtime_version()
|
|
7294
6953
|
configure_standard_logging()
|
|
7295
6954
|
|
|
7296
6955
|
await PyprojectCli(argv).async_cli_run()
|
omdev/tools/git.py
CHANGED
|
@@ -15,8 +15,8 @@ from omlish.formats import json
|
|
|
15
15
|
from omlish.logs import all as logs
|
|
16
16
|
|
|
17
17
|
from ..cli import CliModule
|
|
18
|
-
from ..git import GitStatusItem
|
|
19
|
-
from ..git import get_git_status
|
|
18
|
+
from ..git.status import GitStatusItem
|
|
19
|
+
from ..git.status import get_git_status
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
def rev_parse(rev: str) -> str:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: omdev
|
|
3
|
-
Version: 0.0.0.
|
|
3
|
+
Version: 0.0.0.dev160
|
|
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.dev160
|
|
16
16
|
Provides-Extra: all
|
|
17
17
|
Requires-Dist: black~=24.10; extra == "all"
|
|
18
18
|
Requires-Dist: pycparser~=2.22; extra == "all"
|
|
@@ -5,16 +5,15 @@ omdev/bracepy.py,sha256=I8EdqtDvxzAi3I8TuMEW-RBfwXfqKbwp06CfOdj3L1o,2743
|
|
|
5
5
|
omdev/classdot.py,sha256=YOvgy6x295I_8NKBbBlRVd3AN7Osirm_Lqt4Wj0j9rY,1631
|
|
6
6
|
omdev/cmake.py,sha256=Diy2ry65806dQP125DAstD3w46z_wszMH7PwC2-6iik,4578
|
|
7
7
|
omdev/findimports.py,sha256=2t8QP852saEEJFeXySEzhi_nxRSxghlkXz2jVdvy08M,2392
|
|
8
|
-
omdev/git.py,sha256=sVTkHCXEXJTbSl9SRM7UnrQC775muYWVR6OB8IywUXQ,10532
|
|
9
8
|
omdev/imgur.py,sha256=NK-kqGqGu4rDfpPbRyLEnIMJ2GHQQft5nSuwxLgyhNQ,2996
|
|
10
9
|
omdev/pip.py,sha256=7cZ_IOpekQvgPm_gKnX3Pr8xjqUid50PPScTlZCYVlM,2118
|
|
11
|
-
omdev/revisions.py,sha256=
|
|
10
|
+
omdev/revisions.py,sha256=7Bgwd7cuKtcXJE4eDXmWP4Qx1aqZqf_LNFkOCuYS9I0,5008
|
|
12
11
|
omdev/secrets.py,sha256=bcquaBIDKqX4UIKOzUuKrX7nxVCenj67rRHIMIrd9bk,540
|
|
13
12
|
omdev/tokens.py,sha256=zh2TCAfCbcq8ZnoVdQ824jrTiwNy3XJ_oCqlZpLpcCY,1574
|
|
14
13
|
omdev/wheelfile.py,sha256=yfupGcGkbFlmzGzKU64k_vmOKpaKnUlDWxeGn2KdekU,10005
|
|
15
14
|
omdev/amalg/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
15
|
omdev/amalg/__main__.py,sha256=h94M-VqZ3AFBU2a8zOsjeKK7RF6uINhTHl6OiGbVMgw,163
|
|
17
|
-
omdev/amalg/amalg.py,sha256=
|
|
16
|
+
omdev/amalg/amalg.py,sha256=qJ-Kllp4mdmx28nt_JTlQnuO-o4XZnTTZP7Uh448b68,19333
|
|
18
17
|
omdev/antlr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
18
|
omdev/antlr/consts.py,sha256=8pR6r0m0P3hAiyiAoJZ-nptd2GYbZ98mxwPL9cpaRuw,279
|
|
20
19
|
omdev/antlr/gen.py,sha256=QnPyVWUrJYqHoOc3XsXA8fJdoiwAj6pyUwdG-DVrIeA,2953
|
|
@@ -29,10 +28,10 @@ omdev/cache/compute/storage.py,sha256=woCUqHg8ZrwLEejRG3zu1L5ZXxGNNXveh3E8FnlEkj
|
|
|
29
28
|
omdev/cache/compute/types.py,sha256=NpCTTJHDmpERjrbO6dh9TEzHuP6-vOuoX3ym9sA0ukc,2639
|
|
30
29
|
omdev/cache/data/__init__.py,sha256=SQXtugLceRif463rcoklpQ33pxYLgEIm0xiI6NvOI6M,301
|
|
31
30
|
omdev/cache/data/actions.py,sha256=KVYb3tBYP5c0g-wK1bXih_K7L0ER9UINKChhfc7mwKQ,1071
|
|
32
|
-
omdev/cache/data/cache.py,sha256=
|
|
31
|
+
omdev/cache/data/cache.py,sha256=mxO3RqEhj1UbPgnhSQGZZ5mSLy_r5f9O05sahlP29Q4,7742
|
|
33
32
|
omdev/cache/data/consts.py,sha256=d6W_aeMqgah6PmPYi9RA8Be54oQ4BcNCy8kDQ7FlB_Q,26
|
|
34
33
|
omdev/cache/data/defaults.py,sha256=HrapVUIf9Ozu3qSfRPyQj-vx-dz6Yyedjb-k3yV4CW8,277
|
|
35
|
-
omdev/cache/data/manifests.py,sha256=
|
|
34
|
+
omdev/cache/data/manifests.py,sha256=4BparztsMZo9DDVVPhv6iv5g4kK7QAi8Vqtj3PbKkco,989
|
|
36
35
|
omdev/cache/data/specs.py,sha256=0a9NPJ76Wz69s94KlNbr1Xma3UQ0z2oCAQN7s6uXe4w,2497
|
|
37
36
|
omdev/cexts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
37
|
omdev/cexts/_boilerplate.cc,sha256=sbpXEgdFrkdzZXgaNWFFNN27fL9TZu6VrwvMY4-nnFM,1726
|
|
@@ -69,9 +68,13 @@ omdev/clipboard/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
69
68
|
omdev/clipboard/clipboard.py,sha256=9HFpcijpn0XDTI89ZRm2WA1G7O4HsTdVXZHqMULu3N0,1630
|
|
70
69
|
omdev/clipboard/darwin_cf.py,sha256=SDUMfQtT_IJeDEwmsnxe6YyrZS5tPh_7ujkk1dg65Hg,7688
|
|
71
70
|
omdev/clipboard/linux_x11.py,sha256=oa-mxMRNaZJOdBAZ8Nki-CAGIb63X8OFUTXKjmiwfSo,6718
|
|
71
|
+
omdev/git/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
72
|
+
omdev/git/revisions.py,sha256=1YY3Kf2WSalNVE2TgLXmOETct8HfiVEOqfV-qcvMVr4,1161
|
|
73
|
+
omdev/git/status.py,sha256=s_5kzyaSO-ikimdi54A6DrjOQPMeM5SRXLTrb22Alp4,8106
|
|
74
|
+
omdev/git/subtrees.py,sha256=XFxE74PBqu_E5arpkCRRgsus5nof0TBfd2nmgh4cczA,2398
|
|
72
75
|
omdev/interp/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
|
|
73
76
|
omdev/interp/__main__.py,sha256=GMCqeGYltgt5dlJzHxY9gqisa8cRkrPfmZYuZnjg4WI,162
|
|
74
|
-
omdev/interp/cli.py,sha256=
|
|
77
|
+
omdev/interp/cli.py,sha256=kgqA-Pc2RVkvkEpAKde30R5JKemgwurUcG6uPaNJyFc,2234
|
|
75
78
|
omdev/interp/inspect.py,sha256=ORfO90xfGftyvEJHuEOD5yPk-9mxdxn27SYHwZywWFI,2888
|
|
76
79
|
omdev/interp/providers.py,sha256=yHZQ6gYjkvSmMBvrKy3I77D7PnW67Bf3igTKY8DD9K4,1839
|
|
77
80
|
omdev/interp/pyenv.py,sha256=8SromtT5y6f5q0hT__-r5PZSOHg-PQc-6t-ITdS5eo4,14302
|
|
@@ -113,7 +116,7 @@ omdev/pycharm/cli.py,sha256=dYRDCzRSLBTmoNg6Flswu3gI62yAGUtoh1aNcpBUBYU,3797
|
|
|
113
116
|
omdev/pyproject/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
|
|
114
117
|
omdev/pyproject/__main__.py,sha256=gn3Rl1aYPYdiTtEqa9ifi0t-e4ZwPY0vhJ4UXvYdJDY,165
|
|
115
118
|
omdev/pyproject/cexts.py,sha256=x13piOOnNrYbA17qZLDVuR0p1sqhgEwpk4FtImX-klM,4281
|
|
116
|
-
omdev/pyproject/cli.py,sha256=
|
|
119
|
+
omdev/pyproject/cli.py,sha256=TXoYDfX-FotgCT9LVFfNMwqmfhfvW0-I7dYTG2ub67Y,8765
|
|
117
120
|
omdev/pyproject/configs.py,sha256=K9H5cGwVLgHi8wKwtYvlXHZ9ThtmnI4jo8JAb-t1-70,2859
|
|
118
121
|
omdev/pyproject/pkg.py,sha256=x71WLK3Amnt2Wjhpqz3_lBRGEdsjN5vRGlAr5eDVFqE,14552
|
|
119
122
|
omdev/pyproject/reqs.py,sha256=8feZ71YnGzwKbLK4zO28CDQeNcZIIuq6cnkBhs6M-7E,2406
|
|
@@ -123,8 +126,8 @@ omdev/scripts/bumpversion.py,sha256=Kn7fo73Hs8uJh3Hi3EIyLOlzLPWAC6dwuD_lZ3cIzuY,
|
|
|
123
126
|
omdev/scripts/execrss.py,sha256=mR0G0wERBYtQmVIn63lCIIFb5zkCM6X_XOENDFYDBKc,651
|
|
124
127
|
omdev/scripts/exectime.py,sha256=sFb376GflU6s9gNX-2-we8hgH6w5MuQNS9g6i4SqJIo,610
|
|
125
128
|
omdev/scripts/importtrace.py,sha256=oa7CtcWJVMNDbyIEiRHej6ICfABfErMeo4_haIqe18Q,14041
|
|
126
|
-
omdev/scripts/interp.py,sha256=
|
|
127
|
-
omdev/scripts/pyproject.py,sha256=
|
|
129
|
+
omdev/scripts/interp.py,sha256=3_c7Kdni7-oZQVrS9Vb2h1gaW5XOy9ebgShPdCapHyM,99882
|
|
130
|
+
omdev/scripts/pyproject.py,sha256=d7LuBO6NzgQSjx97OMQ8r5QHABULEE2bN9-EQvBJu00,204901
|
|
128
131
|
omdev/scripts/slowcat.py,sha256=lssv4yrgJHiWfOiHkUut2p8E8Tq32zB-ujXESQxFFHY,2728
|
|
129
132
|
omdev/scripts/tmpexec.py,sha256=WTYcf56Tj2qjYV14AWmV8SfT0u6Y8eIU6cKgQRvEK3c,1442
|
|
130
133
|
omdev/toml/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
|
|
@@ -134,7 +137,7 @@ omdev/tools/__init__.py,sha256=iVJAOQ0viGTQOm0DLX4uZLro-9jOioYJGLg9s0kDx1A,78
|
|
|
134
137
|
omdev/tools/cloc.py,sha256=13lUsYLyn1LoelhsCeKrRkIwwPE0x54JmdhXJ_lvWh0,3811
|
|
135
138
|
omdev/tools/doc.py,sha256=iblgUq9_7JZN2i8qmvewrz4OX0paObscBaCj8u77WqI,2555
|
|
136
139
|
omdev/tools/docker.py,sha256=mu0sWnH_L1JjScfWCXXYaux03mcotCS03SD65I93qHI,7384
|
|
137
|
-
omdev/tools/git.py,sha256=
|
|
140
|
+
omdev/tools/git.py,sha256=zfdPnN-9WSeOQlLoTw5aqAX-UWvz-2p330dx_zaU0WQ,7014
|
|
138
141
|
omdev/tools/importscan.py,sha256=nhJIhtjDY6eFVlReP7fegvv6L5ZjN-Z2VeyhsBonev4,4639
|
|
139
142
|
omdev/tools/mkrelimp.py,sha256=kyu_BbUakKHEEOxNEvYWk7tH1ixCfVb3NqqT8U-BozE,4066
|
|
140
143
|
omdev/tools/notebook.py,sha256=lIQIG-ytxGistyt7twuTbquSKbd7HQzR2jgBcGApwu8,3498
|
|
@@ -153,9 +156,9 @@ omdev/tools/json/rendering.py,sha256=jNShMfCpFR9-Kcn6cUFuOChXHjg71diuTC4x7Ofmz-o
|
|
|
153
156
|
omdev/tools/pawk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
154
157
|
omdev/tools/pawk/__main__.py,sha256=VCqeRVnqT1RPEoIrqHFSu4PXVMg4YEgF4qCQm90-eRI,66
|
|
155
158
|
omdev/tools/pawk/pawk.py,sha256=Eckymn22GfychCQcQi96BFqRo_LmiJ-EPhC8TTUJdB4,11446
|
|
156
|
-
omdev-0.0.0.
|
|
157
|
-
omdev-0.0.0.
|
|
158
|
-
omdev-0.0.0.
|
|
159
|
-
omdev-0.0.0.
|
|
160
|
-
omdev-0.0.0.
|
|
161
|
-
omdev-0.0.0.
|
|
159
|
+
omdev-0.0.0.dev160.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
|
160
|
+
omdev-0.0.0.dev160.dist-info/METADATA,sha256=s2OLsw8nRKCVQHgJfv-UbxudBYvFl__fdyh86RJXeVI,1760
|
|
161
|
+
omdev-0.0.0.dev160.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
162
|
+
omdev-0.0.0.dev160.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
|
|
163
|
+
omdev-0.0.0.dev160.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
|
|
164
|
+
omdev-0.0.0.dev160.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|