omdev 0.0.0.dev416__py3-none-any.whl → 0.0.0.dev500__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.

Files changed (211) hide show
  1. omdev/{.manifests.json → .omlish-manifests.json} +23 -47
  2. omdev/README.md +51 -0
  3. omdev/__about__.py +12 -8
  4. omdev/amalg/cli/main.py +1 -2
  5. omdev/amalg/gen/gen.py +49 -6
  6. omdev/amalg/gen/imports.py +1 -1
  7. omdev/amalg/gen/manifests.py +1 -1
  8. omdev/amalg/gen/resources.py +1 -1
  9. omdev/amalg/gen/srcfiles.py +26 -3
  10. omdev/amalg/gen/strip.py +1 -1
  11. omdev/amalg/gen/types.py +1 -1
  12. omdev/amalg/gen/typing.py +1 -1
  13. omdev/amalg/info.py +32 -0
  14. omdev/cache/compute/storage.py +3 -1
  15. omdev/cache/data/actions.py +1 -1
  16. omdev/cache/data/cache.py +2 -2
  17. omdev/cache/data/specs.py +1 -1
  18. omdev/cexts/_boilerplate.cc +2 -3
  19. omdev/cexts/_distutils/build_ext.py +5 -2
  20. omdev/cexts/_distutils/compilers/ccompiler.py +5 -2
  21. omdev/cexts/_distutils/compilers/options.py +3 -0
  22. omdev/cexts/_distutils/compilers/unixccompiler.py +6 -2
  23. omdev/cexts/_distutils/dir_util.py +6 -2
  24. omdev/cexts/_distutils/errors.py +3 -0
  25. omdev/cexts/_distutils/extension.py +3 -0
  26. omdev/cexts/_distutils/file_util.py +6 -2
  27. omdev/cexts/_distutils/modified.py +3 -0
  28. omdev/cexts/_distutils/spawn.py +6 -2
  29. omdev/cexts/_distutils/sysconfig.py +3 -0
  30. omdev/cexts/_distutils/util.py +6 -2
  31. omdev/cexts/_distutils/version.py +3 -0
  32. omdev/cexts/cmake.py +5 -3
  33. omdev/cexts/scan.py +1 -2
  34. omdev/ci/cache.py +7 -3
  35. omdev/ci/cli.py +6 -4
  36. omdev/ci/docker/buildcaching.py +3 -1
  37. omdev/ci/docker/cache.py +2 -1
  38. omdev/ci/docker/cacheserved/cache.py +4 -1
  39. omdev/ci/docker/cacheserved/manifests.py +2 -2
  40. omdev/ci/docker/dataserver.py +2 -2
  41. omdev/ci/docker/imagepulling.py +2 -1
  42. omdev/ci/docker/packing.py +1 -1
  43. omdev/ci/docker/repositories.py +2 -1
  44. omdev/ci/github/api/clients.py +8 -4
  45. omdev/ci/github/api/v1/client.py +4 -1
  46. omdev/ci/github/api/v2/api.py +2 -0
  47. omdev/ci/github/api/v2/azure.py +4 -1
  48. omdev/ci/github/api/v2/client.py +4 -1
  49. omdev/cli/clicli.py +37 -7
  50. omdev/clipboard/clipboard.py +1 -1
  51. omdev/cmake.py +2 -1
  52. omdev/cmdlog/cli.py +1 -2
  53. omdev/dataclasses/_dumping.py +1960 -0
  54. omdev/dataclasses/_template.py +22 -0
  55. omdev/dataclasses/cli.py +7 -2
  56. omdev/dataclasses/codegen.py +342 -62
  57. omdev/dataclasses/dumping.py +200 -0
  58. omdev/dataserver/handlers.py +3 -2
  59. omdev/dataserver/targets.py +2 -2
  60. omdev/imgur.py +2 -2
  61. omdev/interp/cli.py +1 -1
  62. omdev/interp/inspect.py +2 -1
  63. omdev/interp/providers/base.py +3 -2
  64. omdev/interp/providers/standalone.py +4 -1
  65. omdev/interp/providers/system.py +2 -2
  66. omdev/interp/pyenv/install.py +2 -1
  67. omdev/interp/pyenv/provider.py +2 -2
  68. omdev/interp/types.py +3 -2
  69. omdev/interp/uv/provider.py +40 -2
  70. omdev/interp/uv/uv.py +2 -2
  71. omdev/interp/venvs.py +3 -2
  72. omdev/irc/messages/base.py +50 -0
  73. omdev/irc/messages/formats.py +92 -0
  74. omdev/irc/messages/messages.py +775 -0
  75. omdev/irc/messages/parsing.py +99 -0
  76. omdev/irc/numerics/formats.py +97 -0
  77. omdev/irc/numerics/numerics.py +865 -0
  78. omdev/irc/numerics/types.py +59 -0
  79. omdev/irc/protocol/LICENSE +11 -0
  80. omdev/irc/protocol/__init__.py +61 -0
  81. omdev/irc/protocol/consts.py +6 -0
  82. omdev/irc/protocol/errors.py +30 -0
  83. omdev/irc/protocol/message.py +21 -0
  84. omdev/irc/protocol/nuh.py +55 -0
  85. omdev/irc/protocol/parsing.py +158 -0
  86. omdev/irc/protocol/rendering.py +153 -0
  87. omdev/irc/protocol/tags.py +102 -0
  88. omdev/irc/protocol/utils.py +30 -0
  89. omdev/manifests/_dumping.py +529 -136
  90. omdev/manifests/building.py +6 -3
  91. omdev/manifests/main.py +1 -1
  92. omdev/markdown/__init__.py +0 -0
  93. omdev/markdown/incparse.py +116 -0
  94. omdev/markdown/tokens.py +51 -0
  95. omdev/oci/data.py +2 -2
  96. omdev/oci/datarefs.py +2 -2
  97. omdev/oci/media.py +2 -2
  98. omdev/oci/repositories.py +3 -2
  99. omdev/packaging/marshal.py +9 -9
  100. omdev/packaging/requires.py +6 -6
  101. omdev/packaging/revisions.py +5 -2
  102. omdev/packaging/specifiers.py +41 -42
  103. omdev/packaging/versions.py +10 -10
  104. omdev/packaging/wheelfile.py +4 -2
  105. omdev/precheck/blanklines.py +66 -0
  106. omdev/precheck/caches.py +1 -1
  107. omdev/precheck/imports.py +14 -1
  108. omdev/precheck/lite.py +2 -2
  109. omdev/precheck/main.py +5 -5
  110. omdev/precheck/unicode.py +39 -15
  111. omdev/py/asts/__init__.py +0 -0
  112. omdev/py/asts/parents.py +28 -0
  113. omdev/py/asts/toplevel.py +123 -0
  114. omdev/py/asts/visitors.py +18 -0
  115. omdev/py/attrdocs.py +6 -7
  116. omdev/py/bracepy.py +12 -4
  117. omdev/py/docstrings/numpydoc.py +4 -4
  118. omdev/py/reprs.py +32 -0
  119. omdev/py/scripts/execstat.py +31 -26
  120. omdev/py/srcheaders.py +1 -1
  121. omdev/py/tokens/__init__.py +0 -0
  122. omdev/{tokens → py/tokens}/utils.py +2 -1
  123. omdev/py/tools/importscan.py +2 -2
  124. omdev/py/tools/mkrelimp.py +3 -4
  125. omdev/py/tools/pipdepup.py +686 -0
  126. omdev/pyproject/cli.py +1 -1
  127. omdev/pyproject/pkg.py +197 -48
  128. omdev/pyproject/reqs.py +36 -10
  129. omdev/pyproject/tools/__init__.py +0 -0
  130. omdev/pyproject/tools/aboutdeps.py +60 -0
  131. omdev/pyproject/venvs.py +12 -2
  132. omdev/rs/__init__.py +0 -0
  133. omdev/scripts/ci.py +9551 -6982
  134. omdev/scripts/interp.py +1323 -892
  135. omdev/scripts/lib/__init__.py +0 -0
  136. omdev/scripts/lib/inject.py +2086 -0
  137. omdev/scripts/lib/logs.py +2175 -0
  138. omdev/scripts/lib/marshal.py +1731 -0
  139. omdev/scripts/pyproject.py +4979 -1874
  140. omdev/tools/docker.py +19 -7
  141. omdev/tools/git/cli.py +56 -16
  142. omdev/tools/git/messages.py +2 -2
  143. omdev/tools/json/cli.py +6 -6
  144. omdev/tools/json/formats.py +2 -0
  145. omdev/tools/json/parsing.py +5 -5
  146. omdev/tools/json/processing.py +6 -3
  147. omdev/tools/json/rendering.py +2 -2
  148. omdev/tools/jsonview/cli.py +49 -65
  149. omdev/tools/jsonview/resources/jsonview.html.j2 +43 -0
  150. omdev/tools/pawk/README.md +195 -0
  151. omdev/tools/pawk/pawk.py +2 -2
  152. omdev/tools/pip.py +8 -0
  153. omdev/tui/__init__.py +0 -0
  154. omdev/tui/apps/__init__.py +0 -0
  155. omdev/tui/apps/edit/__init__.py +0 -0
  156. omdev/tui/apps/edit/main.py +167 -0
  157. omdev/tui/apps/irc/__init__.py +0 -0
  158. omdev/tui/apps/irc/__main__.py +4 -0
  159. omdev/tui/apps/irc/app.py +286 -0
  160. omdev/tui/apps/irc/client.py +187 -0
  161. omdev/tui/apps/irc/commands.py +175 -0
  162. omdev/tui/apps/irc/main.py +26 -0
  163. omdev/tui/apps/markdown/__init__.py +0 -0
  164. omdev/tui/apps/markdown/__main__.py +11 -0
  165. omdev/{ptk → tui/apps}/markdown/cli.py +5 -7
  166. omdev/tui/rich/__init__.py +46 -0
  167. omdev/tui/rich/console2.py +20 -0
  168. omdev/tui/rich/markdown2.py +186 -0
  169. omdev/tui/textual/__init__.py +265 -0
  170. omdev/tui/textual/app2.py +16 -0
  171. omdev/tui/textual/autocomplete/LICENSE +21 -0
  172. omdev/tui/textual/autocomplete/__init__.py +33 -0
  173. omdev/tui/textual/autocomplete/matching.py +226 -0
  174. omdev/tui/textual/autocomplete/paths.py +202 -0
  175. omdev/tui/textual/autocomplete/widget.py +612 -0
  176. omdev/tui/textual/debug/__init__.py +10 -0
  177. omdev/tui/textual/debug/dominfo.py +151 -0
  178. omdev/tui/textual/debug/screen.py +24 -0
  179. omdev/tui/textual/devtools.py +187 -0
  180. omdev/tui/textual/drivers2.py +55 -0
  181. omdev/tui/textual/logging2.py +20 -0
  182. omdev/tui/textual/types.py +45 -0
  183. {omdev-0.0.0.dev416.dist-info → omdev-0.0.0.dev500.dist-info}/METADATA +18 -12
  184. omdev-0.0.0.dev500.dist-info/RECORD +386 -0
  185. omdev/ptk/__init__.py +0 -103
  186. omdev/ptk/apps/ncdu.py +0 -167
  187. omdev/ptk/confirm.py +0 -60
  188. omdev/ptk/markdown/LICENSE +0 -22
  189. omdev/ptk/markdown/__init__.py +0 -10
  190. omdev/ptk/markdown/__main__.py +0 -11
  191. omdev/ptk/markdown/border.py +0 -94
  192. omdev/ptk/markdown/markdown.py +0 -390
  193. omdev/ptk/markdown/parser.py +0 -42
  194. omdev/ptk/markdown/styles.py +0 -29
  195. omdev/ptk/markdown/tags.py +0 -299
  196. omdev/ptk/markdown/utils.py +0 -366
  197. omdev/pyproject/cexts.py +0 -110
  198. omdev/tools/antlr/__main__.py +0 -11
  199. omdev/tools/antlr/cli.py +0 -62
  200. omdev/tools/antlr/consts.py +0 -7
  201. omdev/tools/antlr/gen.py +0 -188
  202. omdev-0.0.0.dev416.dist-info/RECORD +0 -332
  203. /omdev/{ptk/apps → irc}/__init__.py +0 -0
  204. /omdev/{tokens → irc/messages}/__init__.py +0 -0
  205. /omdev/{tools/antlr → irc/numerics}/__init__.py +0 -0
  206. /omdev/{tokens → py/tokens}/all.py +0 -0
  207. /omdev/{tokens → py/tokens}/tokenizert.py +0 -0
  208. {omdev-0.0.0.dev416.dist-info → omdev-0.0.0.dev500.dist-info}/WHEEL +0 -0
  209. {omdev-0.0.0.dev416.dist-info → omdev-0.0.0.dev500.dist-info}/entry_points.txt +0 -0
  210. {omdev-0.0.0.dev416.dist-info → omdev-0.0.0.dev500.dist-info}/licenses/LICENSE +0 -0
  211. {omdev-0.0.0.dev416.dist-info → omdev-0.0.0.dev500.dist-info}/top_level.txt +0 -0
@@ -39,7 +39,7 @@ from omlish.lite.cached import cached_nullary
39
39
  from omlish.lite.check import check
40
40
  from omlish.lite.imports import import_attr
41
41
  from omlish.lite.json import json_dumps_pretty
42
- from omlish.lite.logs import log
42
+ from omlish.logs.modules import get_module_logger
43
43
  from omlish.manifests.base import ModAttrManifest
44
44
  from omlish.manifests.globals import GlobalManifestLoader
45
45
  from omlish.manifests.types import Manifest
@@ -53,6 +53,9 @@ T = ta.TypeVar('T')
53
53
  ManifestDumperTarget = ta.Union['InlineManifestDumperTarget', 'AttrManifestDumperTarget'] # ta.TypeAlias
54
54
 
55
55
 
56
+ log = get_module_logger(globals()) # noqa
57
+
58
+
56
59
  ##
57
60
 
58
61
 
@@ -407,7 +410,7 @@ class ManifestBuilder:
407
410
  ])))
408
411
 
409
412
  if write:
410
- with open(os.path.join(pkg_dir, '.manifests.json'), 'w') as f: # noqa
413
+ with open(os.path.join(pkg_dir, '.omlish-manifests.json'), 'w') as f: # noqa
411
414
  f.write(json_dumps_pretty([dc.asdict(m) for m in manifests]))
412
415
  f.write('\n')
413
416
 
@@ -425,7 +428,7 @@ def check_package_manifests(
425
428
  if not os.path.isdir(pkg_dir) or not os.path.isfile(os.path.join(pkg_dir, '__init__.py')):
426
429
  raise Exception(pkg_dir)
427
430
 
428
- manifests_file = os.path.join(pkg_dir, '.manifests.json')
431
+ manifests_file = os.path.join(pkg_dir, '.omlish-manifests.json')
429
432
  if not os.path.isfile(manifests_file):
430
433
  raise Exception(f'No manifests file: {manifests_file}')
431
434
 
omdev/manifests/main.py CHANGED
@@ -5,7 +5,7 @@ import multiprocessing as mp
5
5
  import os.path
6
6
 
7
7
  from omlish.lite.json import json_dumps_pretty
8
- from omlish.logs.standard import configure_standard_logging
8
+ from omlish.logs.std.standard import configure_standard_logging
9
9
 
10
10
  from .building import ManifestBuilder
11
11
  from .building import check_package_manifests
File without changes
@@ -0,0 +1,116 @@
1
+ import dataclasses as dc
2
+ import typing as ta
3
+
4
+ from omlish import lang
5
+
6
+
7
+ with lang.auto_proxy_import(globals()):
8
+ import markdown_it as md
9
+ import markdown_it.token # noqa
10
+
11
+
12
+ ##
13
+
14
+
15
+ class IncrementalMarkdownParser:
16
+ def __init__(
17
+ self,
18
+ *,
19
+ parser: ta.Optional['md.MarkdownIt'] = None,
20
+ ) -> None:
21
+ super().__init__()
22
+
23
+ if parser is None:
24
+ parser = md.MarkdownIt()
25
+ self._parser = parser
26
+
27
+ self._stable_tokens: list[md.token.Token] = []
28
+ self._buffer = ''
29
+ self._num_stable_lines = 0 # Number of lines in stable tokens
30
+
31
+ class FeedOutput(ta.NamedTuple):
32
+ stable: ta.Sequence['md.token.Token']
33
+ new_stable: ta.Sequence['md.token.Token']
34
+ unstable: ta.Sequence['md.token.Token']
35
+
36
+ def feed2(self, chunk: str) -> FeedOutput:
37
+ self._buffer += chunk
38
+
39
+ # Parse the current buffer
40
+ new_tokens = self._parser.parse(self._buffer)
41
+
42
+ # Adjust ALL tokens to account for stable lines from previous parses (new_tokens have line numbers relative to
43
+ # current buffer)
44
+ adjusted_tokens = self._adjust_token_line_numbers(new_tokens, self._num_stable_lines)
45
+
46
+ # Find stable tokens (all but the last parent and its children)
47
+ stable_count = self._find_stable_token_count(adjusted_tokens)
48
+
49
+ newly_stable: ta.Sequence[md.token.Token]
50
+ if stable_count > 0:
51
+ # Extract newly stable tokens (already have adjusted line numbers)
52
+ newly_stable = adjusted_tokens[:stable_count]
53
+
54
+ # Calculate how many lines these stable tokens cover
55
+ max_line = 0
56
+ for token in newly_stable:
57
+ if token.map:
58
+ max_line = max(max_line, token.map[1])
59
+
60
+ # Update buffer to only contain unstable content
61
+ if max_line > self._num_stable_lines:
62
+ # max_line is absolute, num_stable_lines is the current buffer offset
63
+ lines_to_remove = max_line - self._num_stable_lines
64
+ lines = self._buffer.split('\n')
65
+ self._buffer = '\n'.join(lines[lines_to_remove:])
66
+
67
+ # Store newly stable tokens (with adjusted line numbers)
68
+ self._stable_tokens.extend(newly_stable)
69
+ self._num_stable_lines = max_line
70
+
71
+ else:
72
+ newly_stable = ()
73
+
74
+ return IncrementalMarkdownParser.FeedOutput(
75
+ stable=self._stable_tokens,
76
+ new_stable=newly_stable,
77
+ unstable=adjusted_tokens[stable_count:],
78
+ )
79
+
80
+ def feed(self, chunk: str) -> list['md.token.Token']:
81
+ out = self.feed2(chunk)
82
+ return [*out.stable, *out.unstable]
83
+
84
+ def _find_stable_token_count(self, tokens: list['md.token.Token']) -> int:
85
+ if not tokens:
86
+ return 0
87
+
88
+ # Find indices of all parent-level tokens (nesting = 0)
89
+ parent_indices = []
90
+ for i, token in enumerate(tokens):
91
+ if token.nesting in (1, 0) and token.level == 0:
92
+ parent_indices.append(i)
93
+
94
+ if len(parent_indices) < 2:
95
+ # Need at least 2 parent tokens to have stable content
96
+ return 0
97
+
98
+ # The last parent and everything after it is unstable. Everything before the second-to-last parent is stable.
99
+ return parent_indices[-2]
100
+
101
+ def _adjust_token_line_numbers(
102
+ self,
103
+ tokens: list['md.token.Token'],
104
+ line_offset: int,
105
+ ) -> list['md.token.Token']:
106
+ adjusted = []
107
+ for token in tokens:
108
+ if token.map:
109
+ token = dc.replace(
110
+ token,
111
+ map=[token.map[0] + line_offset, token.map[1] + line_offset],
112
+ )
113
+
114
+ adjusted.append(token)
115
+
116
+ return adjusted
@@ -0,0 +1,51 @@
1
+ # ruff: noqa: TC002
2
+ import typing as ta
3
+
4
+ from omlish import lang
5
+
6
+
7
+ with lang.auto_proxy_import(globals()):
8
+ import markdown_it as md
9
+ import markdown_it.token # noqa
10
+
11
+
12
+ ##
13
+
14
+
15
+ def token_repr(t: 'md.token.Token') -> str:
16
+ return ''.join([
17
+ 'Token(',
18
+ f'type={t.type!r}',
19
+ *([f', tag={t.tag!r}'] if t.tag else []),
20
+ *([f', nesting={t.nesting!r}'] if t.nesting else []),
21
+ *([f', attrs={t.attrs!r}'] if t.attrs else []),
22
+ *([f', map={t.map!r}'] if t.map else []),
23
+ *([f', level={t.level!r}'] if t.level else []),
24
+ *([f', children={t.children!r}'] if t.children else []),
25
+ *([f', content={t.content!r}'] if t.content else []),
26
+ *([f', markup={t.markup!r}'] if t.markup else []),
27
+ *([f', info={t.info!r}'] if t.info else []),
28
+ *([f', meta={t.meta!r}'] if t.meta else []),
29
+ *([f', block={t.block!r}'] if t.block else []),
30
+ *([f', hidden={t.hidden!r}'] if t.hidden else []),
31
+ ')',
32
+ ])
33
+
34
+
35
+ ##
36
+
37
+
38
+ def flatten_tokens(
39
+ tokens: ta.Iterable['md.token.Token'],
40
+ *,
41
+ filter: ta.Callable[['md.token.Token'], bool] | None = None, # noqa
42
+ ) -> ta.Iterable['md.token.Token']:
43
+ def rec(tks: ta.Iterable['md.token.Token']) -> ta.Iterator['md.token.Token']:
44
+ for tk in tks:
45
+ if tk.children and not (filter is not None and not filter(tk)):
46
+ yield from rec(tk.children)
47
+
48
+ else:
49
+ yield tk
50
+
51
+ return rec(tokens)
omdev/oci/data.py CHANGED
@@ -1,10 +1,10 @@
1
1
  # ruff: noqa: UP006 UP007 UP045
2
2
  # @omlish-lite
3
- import abc
4
3
  import dataclasses as dc
5
4
  import enum
6
5
  import typing as ta
7
6
 
7
+ from omlish.lite.abstract import Abstract
8
8
  from omlish.lite.check import check
9
9
  from omlish.lite.marshal import OBJ_MARSHALER_FIELD_KEY
10
10
  from omlish.lite.marshal import OBJ_MARSHALER_OMIT_IF_NONE
@@ -17,7 +17,7 @@ from .datarefs import OciDataRef
17
17
 
18
18
 
19
19
  @dc.dataclass()
20
- class OciDataclass(abc.ABC): # noqa
20
+ class OciDataclass(Abstract):
21
21
  pass
22
22
 
23
23
 
omdev/oci/datarefs.py CHANGED
@@ -1,6 +1,5 @@
1
1
  # ruff: noqa: UP006 UP007 UP045
2
2
  # @omlish-lite
3
- import abc
4
3
  import dataclasses as dc
5
4
  import functools
6
5
  import hashlib
@@ -10,6 +9,7 @@ import shutil
10
9
  import tarfile
11
10
  import typing as ta
12
11
 
12
+ from omlish.lite.abstract import Abstract
13
13
  from omlish.lite.cached import cached_nullary
14
14
  from omlish.lite.check import check
15
15
 
@@ -18,7 +18,7 @@ from omlish.lite.check import check
18
18
 
19
19
 
20
20
  @dc.dataclass(frozen=True)
21
- class OciDataRef(abc.ABC): # noqa
21
+ class OciDataRef(Abstract):
22
22
  pass
23
23
 
24
24
 
omdev/oci/media.py CHANGED
@@ -1,9 +1,9 @@
1
1
  # ruff: noqa: UP006 UP007 UP045
2
2
  # @omlish-lite
3
- import abc
4
3
  import dataclasses as dc
5
4
  import typing as ta
6
5
 
6
+ from omlish.lite.abstract import Abstract
7
7
  from omlish.lite.check import check
8
8
  from omlish.lite.marshal import OBJ_MARSHALER_FIELD_KEY
9
9
  from omlish.lite.marshal import OBJ_MARSHALER_OMIT_IF_NONE
@@ -23,7 +23,7 @@ OCI_MEDIA_FIELDS: ta.Collection[str] = frozenset([
23
23
 
24
24
 
25
25
  @dc.dataclass()
26
- class OciMediaDataclass(abc.ABC): # noqa
26
+ class OciMediaDataclass(Abstract):
27
27
  SCHEMA_VERSION: ta.ClassVar[int]
28
28
 
29
29
  @property
omdev/oci/repositories.py CHANGED
@@ -5,6 +5,7 @@ import os.path
5
5
  import tarfile
6
6
  import typing as ta
7
7
 
8
+ from omlish.lite.abstract import Abstract
8
9
  from omlish.lite.check import check
9
10
  from omlish.os.paths import is_path_in_dir
10
11
 
@@ -17,7 +18,7 @@ from .datarefs import TarFileOciDataRef
17
18
  ##
18
19
 
19
20
 
20
- class OciRepository(abc.ABC):
21
+ class OciRepository(Abstract):
21
22
  @abc.abstractmethod
22
23
  def contains_blob(self, digest: str) -> bool:
23
24
  raise NotImplementedError
@@ -57,7 +58,7 @@ class OciRepository(abc.ABC):
57
58
  raise TypeError(obj)
58
59
 
59
60
 
60
- class FileOciRepository(OciRepository, abc.ABC):
61
+ class FileOciRepository(OciRepository, Abstract):
61
62
  @abc.abstractmethod
62
63
  def read_file(self, path: str) -> bytes:
63
64
  raise NotImplementedError
@@ -8,7 +8,6 @@ import typing as ta
8
8
  from omlish import lang
9
9
  from omlish import marshal as msh
10
10
  from omlish import reflect as rfl
11
- from omlish.funcs import match as mfs
12
11
 
13
12
  from .requires import RequiresMarkerItem
14
13
  from .requires import RequiresMarkerList
@@ -43,12 +42,13 @@ class RequiresMarkerListMarshaler(msh.Marshaler):
43
42
  return [inner(e) for e in o]
44
43
 
45
44
 
46
- class RequiresMarkerListMarshalerFactory(msh.MarshalerFactoryMatchClass):
47
- @mfs.simple(lambda _, ctx, rty: rty is MarshalRequiresMarkerList)
48
- def _build(self, ctx: msh.MarshalContext, rty: rfl.Type) -> msh.Marshaler:
49
- return RequiresMarkerListMarshaler(
50
- ctx.make(RequiresMarkerItem),
51
- ctx.make(RequiresNode),
45
+ class RequiresMarkerListMarshalerFactory(msh.MarshalerFactory):
46
+ def make_marshaler(self, ctx: msh.MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], msh.Marshaler] | None:
47
+ if rty is not MarshalRequiresMarkerList:
48
+ return None
49
+ return lambda: RequiresMarkerListMarshaler(
50
+ ctx.make_marshaler(RequiresMarkerItem),
51
+ ctx.make_marshaler(RequiresNode),
52
52
  )
53
53
 
54
54
 
@@ -56,7 +56,7 @@ class RequiresMarkerListMarshalerFactory(msh.MarshalerFactoryMatchClass):
56
56
 
57
57
 
58
58
  @lang.static_init
59
- def _install_standard_marshalling() -> None:
59
+ def _install_standard_marshaling() -> None:
60
60
  requires_node_poly = msh.Polymorphism(
61
61
  RequiresNode,
62
62
  [
@@ -75,7 +75,7 @@ def _install_standard_marshalling() -> None:
75
75
  RequiresMarkerListMarshalerFactory(),
76
76
  )
77
77
 
78
- msh.register_global(
78
+ msh.register_global_config(
79
79
  RequiresMarkerList,
80
80
  msh.ReflectOverride(MarshalRequiresMarkerList),
81
81
  identity=True,
@@ -33,6 +33,12 @@ from omlish.lite.check import check
33
33
  from .specifiers import Specifier
34
34
 
35
35
 
36
+ RequiresMarkerVar = ta.Union['RequiresVariable', 'RequiresValue'] # ta.TypeAlias
37
+
38
+ RequiresMarkerAtom = ta.Union['RequiresMarkerItem', ta.Sequence['RequiresMarkerAtom']] # ta.TypeAlias
39
+ RequiresMarkerList = ta.Sequence[ta.Union['RequiresMarkerList', 'RequiresMarkerAtom', str]] # ta.TypeAlias
40
+
41
+
36
42
  ##
37
43
 
38
44
 
@@ -229,12 +235,6 @@ class RequiresOp(RequiresNode):
229
235
  return str(self)
230
236
 
231
237
 
232
- RequiresMarkerVar = ta.Union['RequiresVariable', 'RequiresValue']
233
-
234
- RequiresMarkerAtom = ta.Union['RequiresMarkerItem', ta.Sequence['RequiresMarkerAtom']]
235
- RequiresMarkerList = ta.Sequence[ta.Union['RequiresMarkerList', 'RequiresMarkerAtom', str]]
236
-
237
-
238
238
  class RequiresMarkerItem(ta.NamedTuple):
239
239
  l: ta.Union[RequiresVariable, RequiresValue]
240
240
  op: RequiresOp
@@ -14,13 +14,16 @@ import zipfile
14
14
 
15
15
  from omlish.lite.cached import cached_nullary
16
16
  from omlish.lite.check import check
17
- from omlish.lite.logs import log
18
- from omlish.logs.standard import configure_standard_logging
17
+ from omlish.logs.modules import get_module_logger
18
+ from omlish.logs.std.standard import configure_standard_logging
19
19
 
20
20
  from ..git.revisions import get_git_revision
21
21
  from .wheelfile import WheelFile
22
22
 
23
23
 
24
+ log = get_module_logger(globals()) # noqa
25
+
26
+
24
27
  ##
25
28
 
26
29
 
@@ -1,3 +1,4 @@
1
+ # ruff: noqa: UP006 UP007 UP045
1
2
  # @omlish-lite
2
3
  # Copyright (c) Donald Stufft and individual contributors.
3
4
  # All rights reserved.
@@ -20,8 +21,7 @@
20
21
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This file is dual licensed under the terms of the
21
22
  # Apache License, Version 2.0, and the BSD License. See the LICENSE file in the root of this repository for complete
22
23
  # details.
23
- # https://github.com/pypa/packaging/blob/2c885fe91a54559e2382902dce28428ad2887be5/src/packaging/specifiers.py
24
- # ruff: noqa: UP006 UP007 UP045
24
+ # https://github.com/pypa/packaging/blob/48125006684bb2d7d28c50af48a03176da45942d/src/packaging/specifiers.py
25
25
  import abc
26
26
  import itertools
27
27
  import re
@@ -31,9 +31,9 @@ from .versions import Version
31
31
  from .versions import canonicalize_version
32
32
 
33
33
 
34
- UnparsedVersion = ta.Union['Version', str]
34
+ UnparsedVersion = ta.Union['Version', str] # ta.TypeAlias
35
35
  UnparsedVersionVar = ta.TypeVar('UnparsedVersionVar', bound=UnparsedVersion)
36
- CallableVersionOperator = ta.Callable[['Version', str], bool]
36
+ CallableVersionOperator = ta.Callable[['Version', str], bool] # ta.TypeAlias
37
37
 
38
38
 
39
39
  ##
@@ -181,7 +181,7 @@ class Specifier(BaseSpecifier):
181
181
  ) -> None:
182
182
  match = self._regex.search(spec)
183
183
  if not match:
184
- raise InvalidSpecifier(f"Invalid specifier: '{spec}'")
184
+ raise InvalidSpecifier(f'Invalid specifier: {spec!r}')
185
185
 
186
186
  self._spec: ta.Tuple[str, str] = (
187
187
  match.group('operator').strip(),
@@ -196,7 +196,7 @@ class Specifier(BaseSpecifier):
196
196
  return self._prereleases
197
197
 
198
198
  operator, version = self._spec
199
- if operator in ['==', '>=', '<=', '~=', '===']:
199
+ if operator in ['==', '>=', '<=', '~=', '===', '>', '<']:
200
200
  if operator == '==' and version.endswith('.*'):
201
201
  version = version[:-2]
202
202
 
@@ -322,40 +322,38 @@ class Specifier(BaseSpecifier):
322
322
  return self.contains(item)
323
323
 
324
324
  def contains(self, item: UnparsedVersion, prereleases: ta.Optional[bool] = None) -> bool:
325
- if prereleases is None:
326
- prereleases = self.prereleases
327
-
328
- normalized_item = _coerce_version(item)
329
-
330
- if normalized_item.is_prerelease and not prereleases:
331
- return False
332
-
333
- operator_callable: CallableVersionOperator = self._get_operator(self.operator)
334
- return operator_callable(normalized_item, self.version)
325
+ return bool(list(self.filter([item], prereleases=prereleases)))
335
326
 
336
327
  def filter(
337
328
  self,
338
329
  iterable: ta.Iterable[UnparsedVersionVar],
339
330
  prereleases: ta.Optional[bool] = None,
340
331
  ) -> ta.Iterator[UnparsedVersionVar]:
341
- yielded = False
342
- found_prereleases = []
332
+ prereleases_versions = []
333
+ found_non_prereleases = False
334
+
335
+ include_prereleases = (
336
+ prereleases if prereleases is not None else self.prereleases
337
+ )
343
338
 
344
- kw = {'prereleases': prereleases if prereleases is not None else True}
339
+ operator_callable = self._get_operator(self.operator)
345
340
 
346
341
  for version in iterable:
347
342
  parsed_version = _coerce_version(version)
348
343
 
349
- if self.contains(parsed_version, **kw):
350
- if parsed_version.is_prerelease and not (prereleases or self.prereleases):
351
- found_prereleases.append(version)
352
- else:
353
- yielded = True
344
+ if operator_callable(parsed_version, self.version):
345
+ if not parsed_version.is_prerelease or include_prereleases:
346
+ found_non_prereleases = True
354
347
  yield version
348
+ elif prereleases is None and self._prereleases is not False:
349
+ prereleases_versions.append(version)
355
350
 
356
- if not yielded and found_prereleases:
357
- for version in found_prereleases:
358
- yield version
351
+ if (
352
+ not found_non_prereleases and
353
+ prereleases is None and
354
+ self._prereleases is not False
355
+ ):
356
+ yield from prereleases_versions
359
357
 
360
358
 
361
359
  _version_prefix_regex = re.compile(r'^([0-9]+)((?:a|b|c|rc)[0-9]+)$')
@@ -406,12 +404,15 @@ def _pad_version(left: ta.List[str], right: ta.List[str]) -> ta.Tuple[ta.List[st
406
404
  class SpecifierSet(BaseSpecifier):
407
405
  def __init__(
408
406
  self,
409
- specifiers: str = '',
407
+ specifiers: ta.Union[str, ta.Iterable['Specifier']] = '',
410
408
  prereleases: ta.Optional[bool] = None,
411
409
  ) -> None:
412
- split_specifiers = [s.strip() for s in specifiers.split(',') if s.strip()]
410
+ if isinstance(specifiers, str):
411
+ split_specifiers = [s.strip() for s in specifiers.split(',') if s.strip()]
412
+ self._specs = frozenset(map(Specifier, split_specifiers))
413
+ else:
414
+ self._specs = frozenset(specifiers)
413
415
 
414
- self._specs = frozenset(map(Specifier, split_specifiers))
415
416
  self._prereleases = prereleases
416
417
 
417
418
  @property
@@ -422,7 +423,10 @@ class SpecifierSet(BaseSpecifier):
422
423
  if not self._specs:
423
424
  return None
424
425
 
425
- return any(s.prereleases for s in self._specs)
426
+ if any(s.prereleases for s in self._specs):
427
+ return True
428
+
429
+ return None
426
430
 
427
431
  @prereleases.setter
428
432
  def prereleases(self, value: bool) -> None:
@@ -447,7 +451,7 @@ class SpecifierSet(BaseSpecifier):
447
451
  if isinstance(other, str):
448
452
  other = SpecifierSet(other)
449
453
  elif not isinstance(other, SpecifierSet):
450
- return NotImplemented # type: ignore
454
+ return NotImplemented
451
455
 
452
456
  specifier = SpecifierSet()
453
457
  specifier._specs = frozenset(self._specs | other._specs)
@@ -467,6 +471,7 @@ class SpecifierSet(BaseSpecifier):
467
471
  if isinstance(other, (str, Specifier)):
468
472
  other = SpecifierSet(str(other))
469
473
  elif not isinstance(other, SpecifierSet):
474
+
470
475
  return NotImplemented
471
476
 
472
477
  return self._specs == other._specs
@@ -489,28 +494,22 @@ class SpecifierSet(BaseSpecifier):
489
494
  if not isinstance(item, Version):
490
495
  item = Version(item)
491
496
 
492
- if prereleases is None:
493
- prereleases = self.prereleases
494
-
495
- if not prereleases and item.is_prerelease:
496
- return False
497
-
498
497
  if installed and item.is_prerelease:
499
- item = Version(item.base_version)
498
+ prereleases = True
500
499
 
501
- return all(s.contains(item, prereleases=prereleases) for s in self._specs)
500
+ return bool(list(self.filter([item], prereleases=prereleases)))
502
501
 
503
502
  def filter(
504
503
  self,
505
504
  iterable: ta.Iterable[UnparsedVersionVar],
506
505
  prereleases: ta.Optional[bool] = None,
507
506
  ) -> ta.Iterator[UnparsedVersionVar]:
508
- if prereleases is None:
507
+ if prereleases is None and self.prereleases is not None:
509
508
  prereleases = self.prereleases
510
509
 
511
510
  if self._specs:
512
511
  for spec in self._specs:
513
- iterable = spec.filter(iterable, prereleases=bool(prereleases))
512
+ iterable = spec.filter(iterable, prereleases=prereleases)
514
513
  return iter(iterable)
515
514
 
516
515
  else:
@@ -27,13 +27,13 @@ import re
27
27
  import typing as ta
28
28
 
29
29
 
30
- VersionLocalType = ta.Tuple[ta.Union[int, str], ...]
30
+ VersionLocalType = ta.Tuple[ta.Union[int, str], ...] # ta.TypeAlias
31
31
 
32
- VersionCmpPrePostDevType = ta.Union['InfinityVersionType', 'NegativeInfinityVersionType', ta.Tuple[str, int]]
33
- _VersionCmpLocalType0 = ta.Tuple[ta.Union[ta.Tuple[int, str], ta.Tuple['NegativeInfinityVersionType', ta.Union[int, str]]], ...] # noqa
34
- VersionCmpLocalType = ta.Union['NegativeInfinityVersionType', _VersionCmpLocalType0]
35
- VersionCmpKey = ta.Tuple[int, ta.Tuple[int, ...], VersionCmpPrePostDevType, VersionCmpPrePostDevType, VersionCmpPrePostDevType, VersionCmpLocalType] # noqa
36
- VersionComparisonMethod = ta.Callable[[VersionCmpKey, VersionCmpKey], bool]
32
+ VersionCmpPrePostDevType = ta.Union['InfinityVersionType', 'NegativeInfinityVersionType', ta.Tuple[str, int]] # ta.TypeAlias # noqa
33
+ _VersionCmpLocalType0 = ta.Tuple[ta.Union[ta.Tuple[int, str], ta.Tuple['NegativeInfinityVersionType', ta.Union[int, str]]], ...] # ta.TypeAlias # noqa
34
+ VersionCmpLocalType = ta.Union['NegativeInfinityVersionType', _VersionCmpLocalType0] # ta.TypeAlias
35
+ VersionCmpKey = ta.Tuple[int, ta.Tuple[int, ...], VersionCmpPrePostDevType, VersionCmpPrePostDevType, VersionCmpPrePostDevType, VersionCmpLocalType] # ta.TypeAlias # noqa
36
+ VersionComparisonMethod = ta.Callable[[VersionCmpKey, VersionCmpKey], bool] # ta.TypeAlias
37
37
 
38
38
 
39
39
  ##
@@ -121,12 +121,12 @@ class _BaseVersion:
121
121
 
122
122
  def __lt__(self, other: '_BaseVersion') -> bool:
123
123
  if not isinstance(other, _BaseVersion):
124
- return NotImplemented # type: ignore
124
+ return NotImplemented
125
125
  return self._key < other._key
126
126
 
127
127
  def __le__(self, other: '_BaseVersion') -> bool:
128
128
  if not isinstance(other, _BaseVersion):
129
- return NotImplemented # type: ignore
129
+ return NotImplemented
130
130
  return self._key <= other._key
131
131
 
132
132
  def __eq__(self, other: object) -> bool:
@@ -136,12 +136,12 @@ class _BaseVersion:
136
136
 
137
137
  def __ge__(self, other: '_BaseVersion') -> bool:
138
138
  if not isinstance(other, _BaseVersion):
139
- return NotImplemented # type: ignore
139
+ return NotImplemented
140
140
  return self._key >= other._key
141
141
 
142
142
  def __gt__(self, other: '_BaseVersion') -> bool:
143
143
  if not isinstance(other, _BaseVersion):
144
- return NotImplemented # type: ignore
144
+ return NotImplemented
145
145
  return self._key > other._key
146
146
 
147
147
  def __ne__(self, other: object) -> bool:
@@ -1,6 +1,5 @@
1
- # @omlish-lite
2
1
  # ruff: noqa: UP006 UP007 UP045
3
- # https://github.com/pypa/wheel/blob/7bb46d7727e6e89fe56b3c78297b3af2672bbbe2/src/wheel/wheelfile.py
2
+ # @omlish-lite
4
3
  # MIT License
5
4
  #
6
5
  # Copyright (c) 2012 Daniel Holth <dholth@fastmail.fm> and contributors
@@ -17,6 +16,7 @@
17
16
  # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
17
  # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
18
  # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+ # https://github.com/pypa/wheel/blob/7bb46d7727e6e89fe56b3c78297b3af2672bbbe2/src/wheel/wheelfile.py
20
20
  import base64
21
21
  import csv
22
22
  import hashlib
@@ -116,11 +116,13 @@ class WheelFile(zipfile.ZipFile):
116
116
  @staticmethod
117
117
  def _urlsafe_b64encode(data: bytes) -> bytes:
118
118
  """urlsafe_b64encode without padding"""
119
+
119
120
  return base64.urlsafe_b64encode(data).rstrip(b'=')
120
121
 
121
122
  @staticmethod
122
123
  def _urlsafe_b64decode(data: bytes) -> bytes:
123
124
  """urlsafe_b64decode without padding"""
125
+
124
126
  pad = b'=' * (4 - (len(data) & 3))
125
127
  return base64.urlsafe_b64decode(data + pad)
126
128