omdev 0.0.0.dev441__py3-none-any.whl → 0.0.0.dev442__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- omdev/interp/venvs.py +1 -0
- omdev/packaging/requires.py +6 -6
- omdev/pyproject/reqs.py +31 -9
- omdev/pyproject/venvs.py +8 -1
- omdev/scripts/ci.py +0 -2
- omdev/scripts/interp.py +0 -2
- omdev/scripts/lib/inject.py +0 -2
- omdev/scripts/pyproject.py +523 -12
- {omdev-0.0.0.dev441.dist-info → omdev-0.0.0.dev442.dist-info}/METADATA +2 -2
- {omdev-0.0.0.dev441.dist-info → omdev-0.0.0.dev442.dist-info}/RECORD +14 -14
- {omdev-0.0.0.dev441.dist-info → omdev-0.0.0.dev442.dist-info}/WHEEL +0 -0
- {omdev-0.0.0.dev441.dist-info → omdev-0.0.0.dev442.dist-info}/entry_points.txt +0 -0
- {omdev-0.0.0.dev441.dist-info → omdev-0.0.0.dev442.dist-info}/licenses/LICENSE +0 -0
- {omdev-0.0.0.dev441.dist-info → omdev-0.0.0.dev442.dist-info}/top_level.txt +0 -0
omdev/interp/venvs.py
CHANGED
omdev/packaging/requires.py
CHANGED
@@ -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
|
omdev/pyproject/reqs.py
CHANGED
@@ -4,12 +4,16 @@ TODO:
|
|
4
4
|
"""
|
5
5
|
# ruff: noqa: UP007 UP045
|
6
6
|
import os.path
|
7
|
+
import re
|
7
8
|
import tempfile
|
8
9
|
import typing as ta
|
9
10
|
|
10
11
|
from omlish.lite.cached import cached_nullary
|
11
12
|
from omlish.logs.modules import get_module_logger
|
12
13
|
|
14
|
+
from ..packaging.requires import RequiresParserSyntaxError
|
15
|
+
from ..packaging.requires import parse_requirement
|
16
|
+
|
13
17
|
|
14
18
|
log = get_module_logger(globals()) # noqa
|
15
19
|
|
@@ -20,11 +24,14 @@ log = get_module_logger(globals()) # noqa
|
|
20
24
|
class RequirementsRewriter:
|
21
25
|
def __init__(
|
22
26
|
self,
|
27
|
+
*,
|
23
28
|
venv: ta.Optional[str] = None,
|
29
|
+
only_pats: ta.Optional[ta.Sequence[re.Pattern]] = None,
|
24
30
|
) -> None:
|
25
31
|
super().__init__()
|
26
32
|
|
27
33
|
self._venv = venv
|
34
|
+
self._only_pats = only_pats
|
28
35
|
|
29
36
|
@cached_nullary
|
30
37
|
def _tmp_dir(self) -> str:
|
@@ -40,17 +47,32 @@ class RequirementsRewriter:
|
|
40
47
|
out_lines = []
|
41
48
|
|
42
49
|
for l in in_lines:
|
43
|
-
if
|
44
|
-
lp, _, rp = l.partition(self.VENV_MAGIC)
|
45
|
-
rp = rp.partition('#')[0]
|
50
|
+
if l.split('#')[0].strip():
|
46
51
|
omit = False
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
+
|
53
|
+
if self.VENV_MAGIC in l:
|
54
|
+
lp, _, rp = l.partition(self.VENV_MAGIC)
|
55
|
+
rp = rp.partition('#')[0]
|
56
|
+
for v in rp.split():
|
57
|
+
if v[0] == '!':
|
58
|
+
if self._venv is not None and self._venv == v[1:]:
|
59
|
+
omit = True
|
60
|
+
break
|
61
|
+
else:
|
62
|
+
raise NotImplementedError
|
63
|
+
|
64
|
+
if (
|
65
|
+
not omit and
|
66
|
+
(ops := self._only_pats) is not None and
|
67
|
+
not l.strip().startswith('-')
|
68
|
+
):
|
69
|
+
try:
|
70
|
+
pr = parse_requirement(l.split('#')[0].strip())
|
71
|
+
except RequiresParserSyntaxError:
|
72
|
+
pass
|
52
73
|
else:
|
53
|
-
|
74
|
+
if not any(op.fullmatch(pr.name) for op in ops):
|
75
|
+
omit = True
|
54
76
|
|
55
77
|
if omit:
|
56
78
|
out_lines.append('# OMITTED: ' + l)
|
omdev/pyproject/venvs.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# ruff: noqa: UP006 UP007 UP045
|
2
2
|
import glob
|
3
3
|
import os.path
|
4
|
+
import re
|
4
5
|
import typing as ta
|
5
6
|
|
6
7
|
from omlish.lite.cached import async_cached_nullary
|
@@ -42,7 +43,13 @@ class Venv:
|
|
42
43
|
|
43
44
|
@cached_nullary
|
44
45
|
def _iv(self) -> InterpVenv:
|
45
|
-
rr = RequirementsRewriter(
|
46
|
+
rr = RequirementsRewriter(
|
47
|
+
venv=self._name,
|
48
|
+
only_pats=(
|
49
|
+
[re.compile(p) for p in self._cfg.requires_pats]
|
50
|
+
if self._cfg.requires_pats is not None else None
|
51
|
+
),
|
52
|
+
)
|
46
53
|
|
47
54
|
return InterpVenv(
|
48
55
|
self.dir_name,
|
omdev/scripts/ci.py
CHANGED
omdev/scripts/interp.py
CHANGED
omdev/scripts/lib/inject.py
CHANGED
omdev/scripts/pyproject.py
CHANGED
@@ -27,6 +27,7 @@ See:
|
|
27
27
|
"""
|
28
28
|
import abc
|
29
29
|
import argparse
|
30
|
+
import ast
|
30
31
|
import asyncio
|
31
32
|
import asyncio.base_subprocess
|
32
33
|
import asyncio.subprocess
|
@@ -137,6 +138,11 @@ LoggingExcInfo = ta.Union[BaseException, LoggingExcInfoTuple] # ta.TypeAlias
|
|
137
138
|
LoggingExcInfoArg = ta.Union[LoggingExcInfo, bool, None] # ta.TypeAlias
|
138
139
|
LoggingContextInfo = ta.Any # ta.TypeAlias
|
139
140
|
|
141
|
+
# ../packaging/requires.py
|
142
|
+
RequiresMarkerVar = ta.Union['RequiresVariable', 'RequiresValue'] # ta.TypeAlias
|
143
|
+
RequiresMarkerAtom = ta.Union['RequiresMarkerItem', ta.Sequence['RequiresMarkerAtom']] # ta.TypeAlias
|
144
|
+
RequiresMarkerList = ta.Sequence[ta.Union['RequiresMarkerList', 'RequiresMarkerAtom', str]] # ta.TypeAlias
|
145
|
+
|
140
146
|
# ../../omlish/asyncs/asyncio/timeouts.py
|
141
147
|
AwaitableT = ta.TypeVar('AwaitableT', bound=ta.Awaitable)
|
142
148
|
|
@@ -5221,8 +5227,6 @@ class _JustMaybe(_Maybe[T]):
|
|
5221
5227
|
__slots__ = ('_v', '_hash')
|
5222
5228
|
|
5223
5229
|
def __init__(self, v: T) -> None:
|
5224
|
-
super().__init__()
|
5225
|
-
|
5226
5230
|
self._v = v
|
5227
5231
|
|
5228
5232
|
@property
|
@@ -6050,6 +6054,488 @@ class Interp:
|
|
6050
6054
|
version: InterpVersion
|
6051
6055
|
|
6052
6056
|
|
6057
|
+
########################################
|
6058
|
+
# ../../packaging/requires.py
|
6059
|
+
# Copyright (c) Donald Stufft and individual contributors.
|
6060
|
+
# All rights reserved.
|
6061
|
+
#
|
6062
|
+
# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
6063
|
+
# following conditions are met:
|
6064
|
+
#
|
6065
|
+
# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
|
6066
|
+
# following disclaimer.
|
6067
|
+
#
|
6068
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
6069
|
+
# following disclaimer in the documentation and/or other materials provided with the distribution.
|
6070
|
+
#
|
6071
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
6072
|
+
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
6073
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
6074
|
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
6075
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
6076
|
+
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
6077
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This file is dual licensed under the terms of the
|
6078
|
+
# Apache License, Version 2.0, and the BSD License. See the LICENSE file in the root of this repository for complete
|
6079
|
+
# details.
|
6080
|
+
# https://github.com/pypa/packaging/blob/cf2cbe2aec28f87c6228a6fb136c27931c9af407/src/packaging/_parser.py#L65
|
6081
|
+
|
6082
|
+
|
6083
|
+
##
|
6084
|
+
|
6085
|
+
|
6086
|
+
@dc.dataclass()
|
6087
|
+
class RequiresToken:
|
6088
|
+
name: str
|
6089
|
+
text: str
|
6090
|
+
position: int
|
6091
|
+
|
6092
|
+
|
6093
|
+
class RequiresParserSyntaxError(Exception):
|
6094
|
+
def __init__(
|
6095
|
+
self,
|
6096
|
+
message: str,
|
6097
|
+
*,
|
6098
|
+
source: str,
|
6099
|
+
span: ta.Tuple[int, int],
|
6100
|
+
) -> None:
|
6101
|
+
self.span = span
|
6102
|
+
self.message = message
|
6103
|
+
self.source = source
|
6104
|
+
|
6105
|
+
super().__init__()
|
6106
|
+
|
6107
|
+
def __str__(self) -> str:
|
6108
|
+
marker = ' ' * self.span[0] + '~' * (self.span[1] - self.span[0]) + '^'
|
6109
|
+
return '\n '.join([self.message, self.source, marker])
|
6110
|
+
|
6111
|
+
|
6112
|
+
REQUIRES_DEFAULT_RULES: ta.Dict[str, ta.Union[str, ta.Pattern[str]]] = {
|
6113
|
+
'LEFT_PARENTHESIS': r'\(',
|
6114
|
+
'RIGHT_PARENTHESIS': r'\)',
|
6115
|
+
'LEFT_BRACKET': r'\[',
|
6116
|
+
'RIGHT_BRACKET': r'\]',
|
6117
|
+
'SEMICOLON': r';',
|
6118
|
+
'COMMA': r',',
|
6119
|
+
'QUOTED_STRING': re.compile(
|
6120
|
+
r"""
|
6121
|
+
(
|
6122
|
+
('[^']*')
|
6123
|
+
|
|
6124
|
+
("[^"]*")
|
6125
|
+
)
|
6126
|
+
""",
|
6127
|
+
re.VERBOSE,
|
6128
|
+
),
|
6129
|
+
'OP': r'(===|==|~=|!=|<=|>=|<|>)',
|
6130
|
+
'BOOLOP': r'\b(or|and)\b',
|
6131
|
+
'IN': r'\bin\b',
|
6132
|
+
'NOT': r'\bnot\b',
|
6133
|
+
'VARIABLE': re.compile(
|
6134
|
+
r"""
|
6135
|
+
\b(
|
6136
|
+
python_version
|
6137
|
+
|python_full_version
|
6138
|
+
|os[._]name
|
6139
|
+
|sys[._]platform
|
6140
|
+
|platform_(release|system)
|
6141
|
+
|platform[._](version|machine|python_implementation)
|
6142
|
+
|python_implementation
|
6143
|
+
|implementation_(name|version)
|
6144
|
+
|extra
|
6145
|
+
)\b
|
6146
|
+
""",
|
6147
|
+
re.VERBOSE,
|
6148
|
+
),
|
6149
|
+
'SPECIFIER': re.compile(
|
6150
|
+
Specifier._operator_regex_str + Specifier._version_regex_str, # noqa
|
6151
|
+
re.VERBOSE | re.IGNORECASE,
|
6152
|
+
),
|
6153
|
+
'AT': r'\@',
|
6154
|
+
'URL': r'[^ \t]+',
|
6155
|
+
'IDENTIFIER': r'\b[a-zA-Z0-9][a-zA-Z0-9._-]*\b',
|
6156
|
+
'VERSION_PREFIX_TRAIL': r'\.\*',
|
6157
|
+
'VERSION_LOCAL_LABEL_TRAIL': r'\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*',
|
6158
|
+
'WS': r'[ \t]+',
|
6159
|
+
'END': r'$',
|
6160
|
+
}
|
6161
|
+
|
6162
|
+
|
6163
|
+
class RequiresTokenizer:
|
6164
|
+
def __init__(
|
6165
|
+
self,
|
6166
|
+
source: str,
|
6167
|
+
*,
|
6168
|
+
rules: ta.Dict[str, ta.Union[str, ta.Pattern[str]]],
|
6169
|
+
) -> None:
|
6170
|
+
super().__init__()
|
6171
|
+
|
6172
|
+
self.source = source
|
6173
|
+
self.rules: ta.Dict[str, ta.Pattern[str]] = {name: re.compile(pattern) for name, pattern in rules.items()}
|
6174
|
+
self.next_token: ta.Optional[RequiresToken] = None
|
6175
|
+
self.position = 0
|
6176
|
+
|
6177
|
+
def consume(self, name: str) -> None:
|
6178
|
+
if self.check(name):
|
6179
|
+
self.read()
|
6180
|
+
|
6181
|
+
def check(self, name: str, *, peek: bool = False) -> bool:
|
6182
|
+
check.state(self.next_token is None, f'Cannot check for {name!r}, already have {self.next_token!r}')
|
6183
|
+
check.state(name in self.rules, f'Unknown token name: {name!r}')
|
6184
|
+
|
6185
|
+
expression = self.rules[name]
|
6186
|
+
|
6187
|
+
match = expression.match(self.source, self.position)
|
6188
|
+
if match is None:
|
6189
|
+
return False
|
6190
|
+
if not peek:
|
6191
|
+
self.next_token = RequiresToken(name, match[0], self.position)
|
6192
|
+
return True
|
6193
|
+
|
6194
|
+
def expect(self, name: str, *, expected: str) -> RequiresToken:
|
6195
|
+
if not self.check(name):
|
6196
|
+
raise self.raise_syntax_error(f'Expected {expected}')
|
6197
|
+
return self.read()
|
6198
|
+
|
6199
|
+
def read(self) -> RequiresToken:
|
6200
|
+
token = self.next_token
|
6201
|
+
check.state(token is not None)
|
6202
|
+
|
6203
|
+
self.position += len(check.not_none(token).text)
|
6204
|
+
self.next_token = None
|
6205
|
+
|
6206
|
+
return check.not_none(token)
|
6207
|
+
|
6208
|
+
def raise_syntax_error(
|
6209
|
+
self,
|
6210
|
+
message: str,
|
6211
|
+
*,
|
6212
|
+
span_start: ta.Optional[int] = None,
|
6213
|
+
span_end: ta.Optional[int] = None,
|
6214
|
+
) -> ta.NoReturn:
|
6215
|
+
span = (
|
6216
|
+
self.position if span_start is None else span_start,
|
6217
|
+
self.position if span_end is None else span_end,
|
6218
|
+
)
|
6219
|
+
raise RequiresParserSyntaxError(
|
6220
|
+
message,
|
6221
|
+
source=self.source,
|
6222
|
+
span=span,
|
6223
|
+
)
|
6224
|
+
|
6225
|
+
@contextlib.contextmanager
|
6226
|
+
def enclosing_tokens(self, open_token: str, close_token: str, *, around: str) -> ta.Iterator[None]:
|
6227
|
+
if self.check(open_token):
|
6228
|
+
open_position = self.position
|
6229
|
+
self.read()
|
6230
|
+
else:
|
6231
|
+
open_position = None
|
6232
|
+
|
6233
|
+
yield
|
6234
|
+
|
6235
|
+
if open_position is None:
|
6236
|
+
return
|
6237
|
+
|
6238
|
+
if not self.check(close_token):
|
6239
|
+
self.raise_syntax_error(
|
6240
|
+
f'Expected matching {close_token} for {open_token}, after {around}',
|
6241
|
+
span_start=open_position,
|
6242
|
+
)
|
6243
|
+
|
6244
|
+
self.read()
|
6245
|
+
|
6246
|
+
|
6247
|
+
@dc.dataclass(frozen=True)
|
6248
|
+
class RequiresNode:
|
6249
|
+
value: str
|
6250
|
+
|
6251
|
+
def __str__(self) -> str:
|
6252
|
+
return self.value
|
6253
|
+
|
6254
|
+
def __repr__(self) -> str:
|
6255
|
+
return f"<{self.__class__.__name__}('{self}')>"
|
6256
|
+
|
6257
|
+
def serialize(self) -> str:
|
6258
|
+
raise NotImplementedError
|
6259
|
+
|
6260
|
+
|
6261
|
+
@dc.dataclass(frozen=True)
|
6262
|
+
class RequiresVariable(RequiresNode):
|
6263
|
+
def serialize(self) -> str:
|
6264
|
+
return str(self)
|
6265
|
+
|
6266
|
+
|
6267
|
+
@dc.dataclass(frozen=True)
|
6268
|
+
class RequiresValue(RequiresNode):
|
6269
|
+
def serialize(self) -> str:
|
6270
|
+
return f'"{self}"'
|
6271
|
+
|
6272
|
+
|
6273
|
+
@dc.dataclass(frozen=True)
|
6274
|
+
class RequiresOp(RequiresNode):
|
6275
|
+
def serialize(self) -> str:
|
6276
|
+
return str(self)
|
6277
|
+
|
6278
|
+
|
6279
|
+
class RequiresMarkerItem(ta.NamedTuple):
|
6280
|
+
l: ta.Union[RequiresVariable, RequiresValue]
|
6281
|
+
op: RequiresOp
|
6282
|
+
r: ta.Union[RequiresVariable, RequiresValue]
|
6283
|
+
|
6284
|
+
|
6285
|
+
class ParsedRequirement(ta.NamedTuple):
|
6286
|
+
name: str
|
6287
|
+
url: str
|
6288
|
+
extras: ta.List[str]
|
6289
|
+
specifier: str
|
6290
|
+
marker: ta.Optional[RequiresMarkerList]
|
6291
|
+
|
6292
|
+
|
6293
|
+
def parse_requirement(source: str) -> ParsedRequirement:
|
6294
|
+
return _parse_requirement(RequiresTokenizer(source, rules=REQUIRES_DEFAULT_RULES))
|
6295
|
+
|
6296
|
+
|
6297
|
+
def _parse_requirement(tokenizer: RequiresTokenizer) -> ParsedRequirement:
|
6298
|
+
tokenizer.consume('WS')
|
6299
|
+
|
6300
|
+
name_token = tokenizer.expect('IDENTIFIER', expected='package name at the start of dependency specifier')
|
6301
|
+
name = name_token.text
|
6302
|
+
tokenizer.consume('WS')
|
6303
|
+
|
6304
|
+
extras = _parse_requires_extras(tokenizer)
|
6305
|
+
tokenizer.consume('WS')
|
6306
|
+
|
6307
|
+
url, specifier, marker = _parse_requirement_details(tokenizer)
|
6308
|
+
tokenizer.expect('END', expected='end of dependency specifier')
|
6309
|
+
|
6310
|
+
return ParsedRequirement(name, url, extras, specifier, marker)
|
6311
|
+
|
6312
|
+
|
6313
|
+
def _parse_requirement_details(tokenizer: RequiresTokenizer) -> ta.Tuple[str, str, ta.Optional[RequiresMarkerList]]:
|
6314
|
+
specifier = ''
|
6315
|
+
url = ''
|
6316
|
+
marker = None
|
6317
|
+
|
6318
|
+
if tokenizer.check('AT'):
|
6319
|
+
tokenizer.read()
|
6320
|
+
tokenizer.consume('WS')
|
6321
|
+
|
6322
|
+
url_start = tokenizer.position
|
6323
|
+
url = tokenizer.expect('URL', expected='URL after @').text
|
6324
|
+
if tokenizer.check('END', peek=True):
|
6325
|
+
return (url, specifier, marker)
|
6326
|
+
|
6327
|
+
tokenizer.expect('WS', expected='whitespace after URL')
|
6328
|
+
|
6329
|
+
# The input might end after whitespace.
|
6330
|
+
if tokenizer.check('END', peek=True):
|
6331
|
+
return (url, specifier, marker)
|
6332
|
+
|
6333
|
+
marker = _parse_requirement_marker(
|
6334
|
+
tokenizer, span_start=url_start, after='URL and whitespace',
|
6335
|
+
)
|
6336
|
+
else:
|
6337
|
+
specifier_start = tokenizer.position
|
6338
|
+
specifier = _parse_requires_specifier(tokenizer)
|
6339
|
+
tokenizer.consume('WS')
|
6340
|
+
|
6341
|
+
if tokenizer.check('END', peek=True):
|
6342
|
+
return (url, specifier, marker)
|
6343
|
+
|
6344
|
+
marker = _parse_requirement_marker(
|
6345
|
+
tokenizer,
|
6346
|
+
span_start=specifier_start,
|
6347
|
+
after=(
|
6348
|
+
'version specifier'
|
6349
|
+
if specifier
|
6350
|
+
else 'name and no valid version specifier'
|
6351
|
+
),
|
6352
|
+
)
|
6353
|
+
|
6354
|
+
return (url, specifier, marker)
|
6355
|
+
|
6356
|
+
|
6357
|
+
def _parse_requirement_marker(
|
6358
|
+
tokenizer: RequiresTokenizer, *, span_start: int, after: str,
|
6359
|
+
) -> RequiresMarkerList:
|
6360
|
+
if not tokenizer.check('SEMICOLON'):
|
6361
|
+
tokenizer.raise_syntax_error(
|
6362
|
+
f'Expected end or semicolon (after {after})',
|
6363
|
+
span_start=span_start,
|
6364
|
+
)
|
6365
|
+
tokenizer.read()
|
6366
|
+
|
6367
|
+
marker = _parse_requires_marker(tokenizer)
|
6368
|
+
tokenizer.consume('WS')
|
6369
|
+
|
6370
|
+
return marker
|
6371
|
+
|
6372
|
+
|
6373
|
+
def _parse_requires_extras(tokenizer: RequiresTokenizer) -> ta.List[str]:
|
6374
|
+
if not tokenizer.check('LEFT_BRACKET', peek=True):
|
6375
|
+
return []
|
6376
|
+
|
6377
|
+
with tokenizer.enclosing_tokens(
|
6378
|
+
'LEFT_BRACKET',
|
6379
|
+
'RIGHT_BRACKET',
|
6380
|
+
around='extras',
|
6381
|
+
):
|
6382
|
+
tokenizer.consume('WS')
|
6383
|
+
extras = _parse_requires_extras_list(tokenizer)
|
6384
|
+
tokenizer.consume('WS')
|
6385
|
+
|
6386
|
+
return extras
|
6387
|
+
|
6388
|
+
|
6389
|
+
def _parse_requires_extras_list(tokenizer: RequiresTokenizer) -> ta.List[str]:
|
6390
|
+
extras: ta.List[str] = []
|
6391
|
+
|
6392
|
+
if not tokenizer.check('IDENTIFIER'):
|
6393
|
+
return extras
|
6394
|
+
|
6395
|
+
extras.append(tokenizer.read().text)
|
6396
|
+
|
6397
|
+
while True:
|
6398
|
+
tokenizer.consume('WS')
|
6399
|
+
if tokenizer.check('IDENTIFIER', peek=True):
|
6400
|
+
tokenizer.raise_syntax_error('Expected comma between extra names')
|
6401
|
+
elif not tokenizer.check('COMMA'):
|
6402
|
+
break
|
6403
|
+
|
6404
|
+
tokenizer.read()
|
6405
|
+
tokenizer.consume('WS')
|
6406
|
+
|
6407
|
+
extra_token = tokenizer.expect('IDENTIFIER', expected='extra name after comma')
|
6408
|
+
extras.append(extra_token.text)
|
6409
|
+
|
6410
|
+
return extras
|
6411
|
+
|
6412
|
+
|
6413
|
+
def _parse_requires_specifier(tokenizer: RequiresTokenizer) -> str:
|
6414
|
+
with tokenizer.enclosing_tokens(
|
6415
|
+
'LEFT_PARENTHESIS',
|
6416
|
+
'RIGHT_PARENTHESIS',
|
6417
|
+
around='version specifier',
|
6418
|
+
):
|
6419
|
+
tokenizer.consume('WS')
|
6420
|
+
parsed_specifiers = _parse_requires_version_many(tokenizer)
|
6421
|
+
tokenizer.consume('WS')
|
6422
|
+
|
6423
|
+
return parsed_specifiers
|
6424
|
+
|
6425
|
+
|
6426
|
+
def _parse_requires_version_many(tokenizer: RequiresTokenizer) -> str:
|
6427
|
+
parsed_specifiers = ''
|
6428
|
+
while tokenizer.check('SPECIFIER'):
|
6429
|
+
span_start = tokenizer.position
|
6430
|
+
parsed_specifiers += tokenizer.read().text
|
6431
|
+
if tokenizer.check('VERSION_PREFIX_TRAIL', peek=True):
|
6432
|
+
tokenizer.raise_syntax_error(
|
6433
|
+
'.* suffix can only be used with `==` or `!=` operators',
|
6434
|
+
span_start=span_start,
|
6435
|
+
span_end=tokenizer.position + 1,
|
6436
|
+
)
|
6437
|
+
if tokenizer.check('VERSION_LOCAL_LABEL_TRAIL', peek=True):
|
6438
|
+
tokenizer.raise_syntax_error(
|
6439
|
+
'Local version label can only be used with `==` or `!=` operators',
|
6440
|
+
span_start=span_start,
|
6441
|
+
span_end=tokenizer.position,
|
6442
|
+
)
|
6443
|
+
tokenizer.consume('WS')
|
6444
|
+
if not tokenizer.check('COMMA'):
|
6445
|
+
break
|
6446
|
+
parsed_specifiers += tokenizer.read().text
|
6447
|
+
tokenizer.consume('WS')
|
6448
|
+
|
6449
|
+
return parsed_specifiers
|
6450
|
+
|
6451
|
+
|
6452
|
+
def parse_requires_marker(source: str) -> RequiresMarkerList:
|
6453
|
+
return _parse_requires_full_marker(RequiresTokenizer(source, rules=REQUIRES_DEFAULT_RULES))
|
6454
|
+
|
6455
|
+
|
6456
|
+
def _parse_requires_full_marker(tokenizer: RequiresTokenizer) -> RequiresMarkerList:
|
6457
|
+
retval = _parse_requires_marker(tokenizer)
|
6458
|
+
tokenizer.expect('END', expected='end of marker expression')
|
6459
|
+
return retval
|
6460
|
+
|
6461
|
+
|
6462
|
+
def _parse_requires_marker(tokenizer: RequiresTokenizer) -> RequiresMarkerList:
|
6463
|
+
expression = [_parse_requires_marker_atom(tokenizer)]
|
6464
|
+
while tokenizer.check('BOOLOP'):
|
6465
|
+
token = tokenizer.read()
|
6466
|
+
expr_right = _parse_requires_marker_atom(tokenizer)
|
6467
|
+
expression.extend((token.text, expr_right))
|
6468
|
+
return expression
|
6469
|
+
|
6470
|
+
|
6471
|
+
def _parse_requires_marker_atom(tokenizer: RequiresTokenizer) -> RequiresMarkerAtom:
|
6472
|
+
tokenizer.consume('WS')
|
6473
|
+
if tokenizer.check('LEFT_PARENTHESIS', peek=True):
|
6474
|
+
with tokenizer.enclosing_tokens(
|
6475
|
+
'LEFT_PARENTHESIS',
|
6476
|
+
'RIGHT_PARENTHESIS',
|
6477
|
+
around='marker expression',
|
6478
|
+
):
|
6479
|
+
tokenizer.consume('WS')
|
6480
|
+
marker: RequiresMarkerAtom = _parse_requires_marker(tokenizer)
|
6481
|
+
tokenizer.consume('WS')
|
6482
|
+
else:
|
6483
|
+
marker = _parse_requires_marker_item(tokenizer)
|
6484
|
+
tokenizer.consume('WS')
|
6485
|
+
return marker
|
6486
|
+
|
6487
|
+
|
6488
|
+
def _parse_requires_marker_item(tokenizer: RequiresTokenizer) -> RequiresMarkerItem:
|
6489
|
+
tokenizer.consume('WS')
|
6490
|
+
marker_var_left = _parse_requires_marker_var(tokenizer)
|
6491
|
+
tokenizer.consume('WS')
|
6492
|
+
marker_op = _parse_requires_marker_op(tokenizer)
|
6493
|
+
tokenizer.consume('WS')
|
6494
|
+
marker_var_right = _parse_requires_marker_var(tokenizer)
|
6495
|
+
tokenizer.consume('WS')
|
6496
|
+
return RequiresMarkerItem(marker_var_left, marker_op, marker_var_right)
|
6497
|
+
|
6498
|
+
|
6499
|
+
def _parse_requires_marker_var(tokenizer: RequiresTokenizer) -> RequiresMarkerVar:
|
6500
|
+
if tokenizer.check('VARIABLE'):
|
6501
|
+
return process_requires_env_var(tokenizer.read().text.replace('.', '_'))
|
6502
|
+
elif tokenizer.check('QUOTED_STRING'):
|
6503
|
+
return process_requires_python_str(tokenizer.read().text)
|
6504
|
+
else:
|
6505
|
+
tokenizer.raise_syntax_error(message='Expected a marker variable or quoted string')
|
6506
|
+
raise RuntimeError # noqa
|
6507
|
+
|
6508
|
+
|
6509
|
+
def process_requires_env_var(env_var: str) -> RequiresVariable:
|
6510
|
+
if env_var in ('platform_python_implementation', 'python_implementation'):
|
6511
|
+
return RequiresVariable('platform_python_implementation')
|
6512
|
+
else:
|
6513
|
+
return RequiresVariable(env_var)
|
6514
|
+
|
6515
|
+
|
6516
|
+
def process_requires_python_str(python_str: str) -> RequiresValue:
|
6517
|
+
value = ast.literal_eval(python_str)
|
6518
|
+
return RequiresValue(str(value))
|
6519
|
+
|
6520
|
+
|
6521
|
+
def _parse_requires_marker_op(tokenizer: RequiresTokenizer) -> RequiresOp:
|
6522
|
+
if tokenizer.check('IN'):
|
6523
|
+
tokenizer.read()
|
6524
|
+
return RequiresOp('in')
|
6525
|
+
elif tokenizer.check('NOT'):
|
6526
|
+
tokenizer.read()
|
6527
|
+
tokenizer.expect('WS', expected="whitespace after 'not'")
|
6528
|
+
tokenizer.expect('IN', expected="'in' after 'not'")
|
6529
|
+
return RequiresOp('not in')
|
6530
|
+
elif tokenizer.check('OP'):
|
6531
|
+
return RequiresOp(tokenizer.read().text)
|
6532
|
+
else:
|
6533
|
+
return tokenizer.raise_syntax_error(
|
6534
|
+
'Expected marker operator, one of '
|
6535
|
+
'<=, <, !=, ==, >=, >, ~=, ===, in, not in',
|
6536
|
+
)
|
6537
|
+
|
6538
|
+
|
6053
6539
|
########################################
|
6054
6540
|
# ../../../omlish/asyncs/asyncio/timeouts.py
|
6055
6541
|
|
@@ -9740,11 +10226,14 @@ log = get_module_logger(globals()) # noqa
|
|
9740
10226
|
class RequirementsRewriter:
|
9741
10227
|
def __init__(
|
9742
10228
|
self,
|
10229
|
+
*,
|
9743
10230
|
venv: ta.Optional[str] = None,
|
10231
|
+
only_pats: ta.Optional[ta.Sequence[re.Pattern]] = None,
|
9744
10232
|
) -> None:
|
9745
10233
|
super().__init__()
|
9746
10234
|
|
9747
10235
|
self._venv = venv
|
10236
|
+
self._only_pats = only_pats
|
9748
10237
|
|
9749
10238
|
@cached_nullary
|
9750
10239
|
def _tmp_dir(self) -> str:
|
@@ -9760,17 +10249,32 @@ class RequirementsRewriter:
|
|
9760
10249
|
out_lines = []
|
9761
10250
|
|
9762
10251
|
for l in in_lines:
|
9763
|
-
if
|
9764
|
-
lp, _, rp = l.partition(self.VENV_MAGIC)
|
9765
|
-
rp = rp.partition('#')[0]
|
10252
|
+
if l.split('#')[0].strip():
|
9766
10253
|
omit = False
|
9767
|
-
|
9768
|
-
|
9769
|
-
|
9770
|
-
|
9771
|
-
|
10254
|
+
|
10255
|
+
if self.VENV_MAGIC in l:
|
10256
|
+
lp, _, rp = l.partition(self.VENV_MAGIC)
|
10257
|
+
rp = rp.partition('#')[0]
|
10258
|
+
for v in rp.split():
|
10259
|
+
if v[0] == '!':
|
10260
|
+
if self._venv is not None and self._venv == v[1:]:
|
10261
|
+
omit = True
|
10262
|
+
break
|
10263
|
+
else:
|
10264
|
+
raise NotImplementedError
|
10265
|
+
|
10266
|
+
if (
|
10267
|
+
not omit and
|
10268
|
+
(ops := self._only_pats) is not None and
|
10269
|
+
not l.strip().startswith('-')
|
10270
|
+
):
|
10271
|
+
try:
|
10272
|
+
pr = parse_requirement(l.split('#')[0].strip())
|
10273
|
+
except RequiresParserSyntaxError:
|
10274
|
+
pass
|
9772
10275
|
else:
|
9773
|
-
|
10276
|
+
if not any(op.fullmatch(pr.name) for op in ops):
|
10277
|
+
omit = True
|
9774
10278
|
|
9775
10279
|
if omit:
|
9776
10280
|
out_lines.append('# OMITTED: ' + l)
|
@@ -11076,6 +11580,7 @@ def get_default_interp_resolver() -> InterpResolver:
|
|
11076
11580
|
class InterpVenvConfig:
|
11077
11581
|
interp: ta.Optional[str] = None
|
11078
11582
|
requires: ta.Optional[ta.Sequence[str]] = None
|
11583
|
+
requires_pats: ta.Optional[ta.Sequence[str]] = None
|
11079
11584
|
use_uv: ta.Optional[bool] = None
|
11080
11585
|
|
11081
11586
|
|
@@ -11300,7 +11805,13 @@ class Venv:
|
|
11300
11805
|
|
11301
11806
|
@cached_nullary
|
11302
11807
|
def _iv(self) -> InterpVenv:
|
11303
|
-
rr = RequirementsRewriter(
|
11808
|
+
rr = RequirementsRewriter(
|
11809
|
+
venv=self._name,
|
11810
|
+
only_pats=(
|
11811
|
+
[re.compile(p) for p in self._cfg.requires_pats]
|
11812
|
+
if self._cfg.requires_pats is not None else None
|
11813
|
+
),
|
11814
|
+
)
|
11304
11815
|
|
11305
11816
|
return InterpVenv(
|
11306
11817
|
self.dir_name,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: omdev
|
3
|
-
Version: 0.0.0.
|
3
|
+
Version: 0.0.0.dev442
|
4
4
|
Summary: omdev
|
5
5
|
Author: wrmsr
|
6
6
|
License-Expression: BSD-3-Clause
|
@@ -14,7 +14,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
14
14
|
Requires-Python: >=3.13
|
15
15
|
Description-Content-Type: text/markdown
|
16
16
|
License-File: LICENSE
|
17
|
-
Requires-Dist: omlish==0.0.0.
|
17
|
+
Requires-Dist: omlish==0.0.0.dev442
|
18
18
|
Provides-Extra: all
|
19
19
|
Requires-Dist: black~=25.1; extra == "all"
|
20
20
|
Requires-Dist: pycparser~=2.23; extra == "all"
|
@@ -159,7 +159,7 @@ omdev/interp/inject.py,sha256=MOppFILGFCp2f4-2uwmH5fN-7erHI3RyMQJaG0kw0Gc,1569
|
|
159
159
|
omdev/interp/inspect.py,sha256=GLjqRkmNr3H0CZsiFqizM_2yfUL7hSD-BGYysNcVi_Q,3018
|
160
160
|
omdev/interp/resolvers.py,sha256=9ExwP0wcQ4mzyTLNurSG4Dg1AQ_IqLfR2ZyqR4VRANE,2590
|
161
161
|
omdev/interp/types.py,sha256=Pr0wrVpNasoCw-ThEvKC5LG30Civ7YJ4EONwrwBLpy0,2516
|
162
|
-
omdev/interp/venvs.py,sha256=
|
162
|
+
omdev/interp/venvs.py,sha256=KAnkHGP8jV8KmiarRl2wuMbya-CEgyN6hEM68irGOxs,3362
|
163
163
|
omdev/interp/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
164
164
|
omdev/interp/providers/base.py,sha256=zMtzMJIDvaI0q1gtsZTCvFiTc7qdhGbUcXRs6LCBmgo,1333
|
165
165
|
omdev/interp/providers/inject.py,sha256=NSDFBQVD3ZR9Mf162XB9_VvTUAXGCRhPcrjVlYcFDJk,857
|
@@ -208,7 +208,7 @@ omdev/oci/pack/unpacking.py,sha256=tVYw8REKuYd4ciGXwMmXxlp4CRLHdET_gB9ShYh1d_M,6
|
|
208
208
|
omdev/packaging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
209
209
|
omdev/packaging/marshal.py,sha256=nr7wN-Pi3FGAuh3HaladzDgOgyQl1-vtmxJ_AUOo4d8,2355
|
210
210
|
omdev/packaging/names.py,sha256=-orp16m20gSFeKRiGkRNyqFVV4S1y_Djvjdq_5hNwpY,2533
|
211
|
-
omdev/packaging/requires.py,sha256=
|
211
|
+
omdev/packaging/requires.py,sha256=nn4ff8mlgfsdZooKzQjhASFS7mMVUCCmcb-150F0Lcg,15739
|
212
212
|
omdev/packaging/revisions.py,sha256=tLNDVtPiygB8mSxwp-kDxeEHhpBzD0jayndjsgUOfkM,5055
|
213
213
|
omdev/packaging/specifiers.py,sha256=t6UhvSlmwHmSvqqPb4XnCq9H41HiqeAqRvCUy2DF_P8,17487
|
214
214
|
omdev/packaging/versions.py,sha256=SBh4LYfBYVi8SXMoWcOWY-Y3llOF-6cxayVaIM1NXMs,12371
|
@@ -267,19 +267,19 @@ omdev/pyproject/cli.py,sha256=Umsu2bcJUYeeVXICaZFhKckUBT6VWuYDL4htgCGGQIs,8749
|
|
267
267
|
omdev/pyproject/configs.py,sha256=baNRwHtUW8S8DKCxuKlMbV3Gduujd1PyNURxQ48Nnxk,2813
|
268
268
|
omdev/pyproject/inject.py,sha256=Von8_8ofkITLoCEwDHNRAwY0AEdFQg7r2ILS8kcTMuY,325
|
269
269
|
omdev/pyproject/pkg.py,sha256=CcWBhsOgim8MYe5ryKDGB8ClRIyiCX6YmYUHRbQ5q_Y,14964
|
270
|
-
omdev/pyproject/reqs.py,sha256=
|
271
|
-
omdev/pyproject/venvs.py,sha256=
|
270
|
+
omdev/pyproject/reqs.py,sha256=DU7NBNpFTjU06VgqRYZj5jZRQxpIWbzL9q9Vm13_o0o,3317
|
271
|
+
omdev/pyproject/venvs.py,sha256=PNgfVrGlw9NFKJgUyzyWH5H5nAIzUDPTHRVUNBM0bKs,2187
|
272
272
|
omdev/pyproject/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
273
273
|
omdev/pyproject/resources/docker-dev.sh,sha256=DHkz5D18jok_oDolfg2mqrvGRWFoCe9GQo04dR1czcc,838
|
274
274
|
omdev/pyproject/resources/python.sh,sha256=rFaN4SiJ9hdLDXXsDTwugI6zsw6EPkgYMmtacZeTbvw,749
|
275
275
|
omdev/scripts/__init__.py,sha256=MKCvUAEQwsIvwLixwtPlpBqmkMXLCnjjXyAXvVpDwVk,91
|
276
|
-
omdev/scripts/ci.py,sha256=
|
277
|
-
omdev/scripts/interp.py,sha256=
|
278
|
-
omdev/scripts/pyproject.py,sha256=
|
276
|
+
omdev/scripts/ci.py,sha256=0mb5CkL2y6_ZkMM5xXLEoVkPlh-c5_mb-Ezk45xYdCI,426377
|
277
|
+
omdev/scripts/interp.py,sha256=EaKZtDiopNF0i8Wf_DSYyM8c10aAGL41_1FUxCpSjxE,168417
|
278
|
+
omdev/scripts/pyproject.py,sha256=8V1bQYXcFRidO2y2adAiyX8VZyG4RMuFzW9DzSqOrgU,349087
|
279
279
|
omdev/scripts/slowcat.py,sha256=PwdT-pg62imEEb6kcOozl9_YUi-4KopvjvzWT1OmGb0,2717
|
280
280
|
omdev/scripts/tmpexec.py,sha256=t0nErDRALjTk7H0X8ADjZUIDFjlPNzOOokmjCjBHdzs,1431
|
281
281
|
omdev/scripts/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
282
|
-
omdev/scripts/lib/inject.py,sha256=
|
282
|
+
omdev/scripts/lib/inject.py,sha256=dregGw2IK_yBHR8rUKamV-sRx4YW_NUZAy-xrnfyie0,53675
|
283
283
|
omdev/scripts/lib/logs.py,sha256=zRZYc-P9B0-uSETpIXNkNmb874jVvTfKtmUSJ47yZFw,63073
|
284
284
|
omdev/scripts/lib/marshal.py,sha256=DOsUKJ1U3mwsNN1Et20cqJUBlzZZcmAv1m-zxMKHYEQ,46835
|
285
285
|
omdev/tokens/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -323,9 +323,9 @@ omdev/tools/jsonview/resources/jsonview.js,sha256=faDvXDOXKvEvjOuIlz4D3F2ReQXb_b
|
|
323
323
|
omdev/tools/pawk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
324
324
|
omdev/tools/pawk/__main__.py,sha256=VCqeRVnqT1RPEoIrqHFSu4PXVMg4YEgF4qCQm90-eRI,66
|
325
325
|
omdev/tools/pawk/pawk.py,sha256=ao5mdrpiSU4AZ8mBozoEaV3UVlmVTnRG9wD9XP70MZE,11429
|
326
|
-
omdev-0.0.0.
|
327
|
-
omdev-0.0.0.
|
328
|
-
omdev-0.0.0.
|
329
|
-
omdev-0.0.0.
|
330
|
-
omdev-0.0.0.
|
331
|
-
omdev-0.0.0.
|
326
|
+
omdev-0.0.0.dev442.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
327
|
+
omdev-0.0.0.dev442.dist-info/METADATA,sha256=4k0ARrn_Yw1duxD03gcbzVeFcT6qrTO3ncUSCkVNpvc,5100
|
328
|
+
omdev-0.0.0.dev442.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
329
|
+
omdev-0.0.0.dev442.dist-info/entry_points.txt,sha256=dHLXFmq5D9B8qUyhRtFqTGWGxlbx3t5ejedjrnXNYLU,33
|
330
|
+
omdev-0.0.0.dev442.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
|
331
|
+
omdev-0.0.0.dev442.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|