omdev 0.0.0.dev7__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/__about__.py +35 -0
- omdev/__init__.py +0 -0
- omdev/amalg/__init__.py +0 -0
- omdev/amalg/__main__.py +4 -0
- omdev/amalg/amalg.py +513 -0
- omdev/classdot.py +61 -0
- omdev/cmake.py +164 -0
- omdev/exts/__init__.py +0 -0
- omdev/exts/_distutils/__init__.py +10 -0
- omdev/exts/_distutils/build_ext.py +367 -0
- omdev/exts/_distutils/compilers/__init__.py +3 -0
- omdev/exts/_distutils/compilers/ccompiler.py +1032 -0
- omdev/exts/_distutils/compilers/options.py +80 -0
- omdev/exts/_distutils/compilers/unixccompiler.py +385 -0
- omdev/exts/_distutils/dir_util.py +76 -0
- omdev/exts/_distutils/errors.py +62 -0
- omdev/exts/_distutils/extension.py +107 -0
- omdev/exts/_distutils/file_util.py +216 -0
- omdev/exts/_distutils/modified.py +47 -0
- omdev/exts/_distutils/spawn.py +103 -0
- omdev/exts/_distutils/sysconfig.py +349 -0
- omdev/exts/_distutils/util.py +201 -0
- omdev/exts/_distutils/version.py +308 -0
- omdev/exts/build.py +43 -0
- omdev/exts/cmake.py +195 -0
- omdev/exts/importhook.py +88 -0
- omdev/exts/scan.py +74 -0
- omdev/interp/__init__.py +1 -0
- omdev/interp/__main__.py +4 -0
- omdev/interp/cli.py +63 -0
- omdev/interp/inspect.py +105 -0
- omdev/interp/providers.py +67 -0
- omdev/interp/pyenv.py +353 -0
- omdev/interp/resolvers.py +76 -0
- omdev/interp/standalone.py +187 -0
- omdev/interp/system.py +125 -0
- omdev/interp/types.py +92 -0
- omdev/mypy/__init__.py +0 -0
- omdev/mypy/debug.py +86 -0
- omdev/pyproject/__init__.py +1 -0
- omdev/pyproject/__main__.py +4 -0
- omdev/pyproject/cli.py +319 -0
- omdev/pyproject/configs.py +97 -0
- omdev/pyproject/ext.py +107 -0
- omdev/pyproject/pkg.py +196 -0
- omdev/scripts/__init__.py +0 -0
- omdev/scripts/execrss.py +19 -0
- omdev/scripts/findimports.py +62 -0
- omdev/scripts/findmagic.py +70 -0
- omdev/scripts/interp.py +2118 -0
- omdev/scripts/pyproject.py +3584 -0
- omdev/scripts/traceimport.py +502 -0
- omdev/tokens.py +42 -0
- omdev/toml/__init__.py +1 -0
- omdev/toml/parser.py +823 -0
- omdev/toml/writer.py +104 -0
- omdev/tools/__init__.py +0 -0
- omdev/tools/dockertools.py +81 -0
- omdev/tools/sqlrepl.py +193 -0
- omdev/versioning/__init__.py +1 -0
- omdev/versioning/specifiers.py +531 -0
- omdev/versioning/versions.py +416 -0
- omdev-0.0.0.dev7.dist-info/LICENSE +21 -0
- omdev-0.0.0.dev7.dist-info/METADATA +24 -0
- omdev-0.0.0.dev7.dist-info/RECORD +67 -0
- omdev-0.0.0.dev7.dist-info/WHEEL +5 -0
- omdev-0.0.0.dev7.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
# Copyright (c) Donald Stufft and individual contributors.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
#
|
|
4
|
+
# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
|
5
|
+
# following conditions are met:
|
|
6
|
+
#
|
|
7
|
+
# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
|
|
8
|
+
# following disclaimer.
|
|
9
|
+
#
|
|
10
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
|
11
|
+
# following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
12
|
+
#
|
|
13
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
14
|
+
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
15
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
16
|
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
17
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
18
|
+
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
19
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This file is dual licensed under the terms of the
|
|
20
|
+
# Apache License, Version 2.0, and the BSD License. See the LICENSE file in the root of this repository for complete
|
|
21
|
+
# details.
|
|
22
|
+
# https://github.com/pypa/packaging/blob/2c885fe91a54559e2382902dce28428ad2887be5/src/packaging/specifiers.py
|
|
23
|
+
# ruff: noqa: UP006 UP007
|
|
24
|
+
import abc
|
|
25
|
+
import itertools
|
|
26
|
+
import re
|
|
27
|
+
import typing as ta
|
|
28
|
+
|
|
29
|
+
from .versions import Version
|
|
30
|
+
from .versions import canonicalize_version
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
UnparsedVersion = ta.Union['Version', str]
|
|
34
|
+
UnparsedVersionVar = ta.TypeVar('UnparsedVersionVar', bound=UnparsedVersion)
|
|
35
|
+
CallableVersionOperator = ta.Callable[['Version', str], bool]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
##
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _coerce_version(version: UnparsedVersion) -> Version:
|
|
42
|
+
if not isinstance(version, Version):
|
|
43
|
+
version = Version(version)
|
|
44
|
+
return version
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class InvalidSpecifier(ValueError): # noqa
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class BaseSpecifier(metaclass=abc.ABCMeta):
|
|
52
|
+
@abc.abstractmethod
|
|
53
|
+
def __str__(self) -> str:
|
|
54
|
+
raise NotImplementedError
|
|
55
|
+
|
|
56
|
+
@abc.abstractmethod
|
|
57
|
+
def __hash__(self) -> int:
|
|
58
|
+
raise NotImplementedError
|
|
59
|
+
|
|
60
|
+
@abc.abstractmethod
|
|
61
|
+
def __eq__(self, other: object) -> bool:
|
|
62
|
+
raise NotImplementedError
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
@abc.abstractmethod
|
|
66
|
+
def prereleases(self) -> ta.Optional[bool]:
|
|
67
|
+
raise NotImplementedError
|
|
68
|
+
|
|
69
|
+
@prereleases.setter
|
|
70
|
+
def prereleases(self, value: bool) -> None:
|
|
71
|
+
raise NotImplementedError
|
|
72
|
+
|
|
73
|
+
@abc.abstractmethod
|
|
74
|
+
def contains(self, item: str, prereleases: ta.Optional[bool] = None) -> bool:
|
|
75
|
+
raise NotImplementedError
|
|
76
|
+
|
|
77
|
+
@abc.abstractmethod
|
|
78
|
+
def filter(
|
|
79
|
+
self,
|
|
80
|
+
iterable: ta.Iterable[UnparsedVersionVar],
|
|
81
|
+
prereleases: ta.Optional[bool] = None,
|
|
82
|
+
) -> ta.Iterator[UnparsedVersionVar]:
|
|
83
|
+
raise NotImplementedError
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class Specifier(BaseSpecifier):
|
|
87
|
+
_operator_regex_str = r"""
|
|
88
|
+
(?P<operator>(~=|==|!=|<=|>=|<|>|===))
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
_version_regex_str = r"""
|
|
92
|
+
(?P<version>
|
|
93
|
+
(?:
|
|
94
|
+
(?<====)
|
|
95
|
+
\s*
|
|
96
|
+
[^\s;)]*
|
|
97
|
+
)
|
|
98
|
+
|
|
|
99
|
+
(?:
|
|
100
|
+
(?<===|!=)
|
|
101
|
+
\s*
|
|
102
|
+
v?
|
|
103
|
+
(?:[0-9]+!)?
|
|
104
|
+
[0-9]+(?:\.[0-9]+)*
|
|
105
|
+
(?:
|
|
106
|
+
\.\*
|
|
107
|
+
|
|
|
108
|
+
(?:
|
|
109
|
+
[-_\.]?
|
|
110
|
+
(alpha|beta|preview|pre|a|b|c|rc)
|
|
111
|
+
[-_\.]?
|
|
112
|
+
[0-9]*
|
|
113
|
+
)?
|
|
114
|
+
(?:
|
|
115
|
+
(?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
|
|
116
|
+
)?
|
|
117
|
+
(?:[-_\.]?dev[-_\.]?[0-9]*)?
|
|
118
|
+
(?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)?
|
|
119
|
+
)?
|
|
120
|
+
)
|
|
121
|
+
|
|
|
122
|
+
(?:
|
|
123
|
+
(?<=~=)
|
|
124
|
+
\s*
|
|
125
|
+
v?
|
|
126
|
+
(?:[0-9]+!)?
|
|
127
|
+
[0-9]+(?:\.[0-9]+)+
|
|
128
|
+
(?:
|
|
129
|
+
[-_\.]?
|
|
130
|
+
(alpha|beta|preview|pre|a|b|c|rc)
|
|
131
|
+
[-_\.]?
|
|
132
|
+
[0-9]*
|
|
133
|
+
)?
|
|
134
|
+
(?:
|
|
135
|
+
(?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
|
|
136
|
+
)?
|
|
137
|
+
(?:[-_\.]?dev[-_\.]?[0-9]*)?
|
|
138
|
+
)
|
|
139
|
+
|
|
|
140
|
+
(?:
|
|
141
|
+
(?<!==|!=|~=)
|
|
142
|
+
\s*
|
|
143
|
+
v?
|
|
144
|
+
(?:[0-9]+!)?
|
|
145
|
+
[0-9]+(?:\.[0-9]+)*
|
|
146
|
+
(?:
|
|
147
|
+
[-_\.]?
|
|
148
|
+
(alpha|beta|preview|pre|a|b|c|rc)
|
|
149
|
+
[-_\.]?
|
|
150
|
+
[0-9]*
|
|
151
|
+
)?
|
|
152
|
+
(?:
|
|
153
|
+
(?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
|
|
154
|
+
)?
|
|
155
|
+
(?:[-_\.]?dev[-_\.]?[0-9]*)?
|
|
156
|
+
)
|
|
157
|
+
)
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
_regex = re.compile(
|
|
161
|
+
r'^\s*' + _operator_regex_str + _version_regex_str + r'\s*$',
|
|
162
|
+
re.VERBOSE | re.IGNORECASE,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
OPERATORS: ta.ClassVar[ta.Mapping[str, str]] = {
|
|
166
|
+
'~=': 'compatible',
|
|
167
|
+
'==': 'equal',
|
|
168
|
+
'!=': 'not_equal',
|
|
169
|
+
'<=': 'less_than_equal',
|
|
170
|
+
'>=': 'greater_than_equal',
|
|
171
|
+
'<': 'less_than',
|
|
172
|
+
'>': 'greater_than',
|
|
173
|
+
'===': 'arbitrary',
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
def __init__(
|
|
177
|
+
self,
|
|
178
|
+
spec: str = '',
|
|
179
|
+
prereleases: ta.Optional[bool] = None,
|
|
180
|
+
) -> None:
|
|
181
|
+
match = self._regex.search(spec)
|
|
182
|
+
if not match:
|
|
183
|
+
raise InvalidSpecifier(f"Invalid specifier: '{spec}'")
|
|
184
|
+
|
|
185
|
+
self._spec: ta.Tuple[str, str] = (
|
|
186
|
+
match.group('operator').strip(),
|
|
187
|
+
match.group('version').strip(),
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
self._prereleases = prereleases
|
|
191
|
+
|
|
192
|
+
@property # type: ignore
|
|
193
|
+
def prereleases(self) -> bool:
|
|
194
|
+
if self._prereleases is not None:
|
|
195
|
+
return self._prereleases
|
|
196
|
+
|
|
197
|
+
operator, version = self._spec
|
|
198
|
+
if operator in ['==', '>=', '<=', '~=', '===']:
|
|
199
|
+
if operator == '==' and version.endswith('.*'):
|
|
200
|
+
version = version[:-2]
|
|
201
|
+
|
|
202
|
+
if Version(version).is_prerelease:
|
|
203
|
+
return True
|
|
204
|
+
|
|
205
|
+
return False
|
|
206
|
+
|
|
207
|
+
@prereleases.setter
|
|
208
|
+
def prereleases(self, value: bool) -> None:
|
|
209
|
+
self._prereleases = value
|
|
210
|
+
|
|
211
|
+
@property
|
|
212
|
+
def operator(self) -> str:
|
|
213
|
+
return self._spec[0]
|
|
214
|
+
|
|
215
|
+
@property
|
|
216
|
+
def version(self) -> str:
|
|
217
|
+
return self._spec[1]
|
|
218
|
+
|
|
219
|
+
def __repr__(self) -> str:
|
|
220
|
+
pre = (
|
|
221
|
+
f', prereleases={self.prereleases!r}'
|
|
222
|
+
if self._prereleases is not None
|
|
223
|
+
else ''
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
return f'<{self.__class__.__name__}({str(self)!r}{pre})>'
|
|
227
|
+
|
|
228
|
+
def __str__(self) -> str:
|
|
229
|
+
return '{}{}'.format(*self._spec)
|
|
230
|
+
|
|
231
|
+
@property
|
|
232
|
+
def _canonical_spec(self) -> ta.Tuple[str, str]:
|
|
233
|
+
canonical_version = canonicalize_version(
|
|
234
|
+
self._spec[1],
|
|
235
|
+
strip_trailing_zero=(self._spec[0] != '~='),
|
|
236
|
+
)
|
|
237
|
+
return self._spec[0], canonical_version
|
|
238
|
+
|
|
239
|
+
def __hash__(self) -> int:
|
|
240
|
+
return hash(self._canonical_spec)
|
|
241
|
+
|
|
242
|
+
def __eq__(self, other: object) -> bool:
|
|
243
|
+
if isinstance(other, str):
|
|
244
|
+
try:
|
|
245
|
+
other = self.__class__(str(other))
|
|
246
|
+
except InvalidSpecifier:
|
|
247
|
+
return NotImplemented
|
|
248
|
+
elif not isinstance(other, self.__class__):
|
|
249
|
+
return NotImplemented
|
|
250
|
+
|
|
251
|
+
return self._canonical_spec == other._canonical_spec
|
|
252
|
+
|
|
253
|
+
def _get_operator(self, op: str) -> CallableVersionOperator:
|
|
254
|
+
operator_callable: CallableVersionOperator = getattr(self, f'_compare_{self.OPERATORS[op]}')
|
|
255
|
+
return operator_callable
|
|
256
|
+
|
|
257
|
+
def _compare_compatible(self, prospective: Version, spec: str) -> bool:
|
|
258
|
+
prefix = _version_join(list(itertools.takewhile(_is_not_version_suffix, _version_split(spec)))[:-1])
|
|
259
|
+
prefix += '.*'
|
|
260
|
+
return self._get_operator('>=')(prospective, spec) and self._get_operator('==')(prospective, prefix)
|
|
261
|
+
|
|
262
|
+
def _compare_equal(self, prospective: Version, spec: str) -> bool:
|
|
263
|
+
if spec.endswith('.*'):
|
|
264
|
+
normalized_prospective = canonicalize_version(prospective.public, strip_trailing_zero=False)
|
|
265
|
+
normalized_spec = canonicalize_version(spec[:-2], strip_trailing_zero=False)
|
|
266
|
+
split_spec = _version_split(normalized_spec)
|
|
267
|
+
|
|
268
|
+
split_prospective = _version_split(normalized_prospective)
|
|
269
|
+
padded_prospective, _ = _pad_version(split_prospective, split_spec)
|
|
270
|
+
shortened_prospective = padded_prospective[: len(split_spec)]
|
|
271
|
+
|
|
272
|
+
return shortened_prospective == split_spec
|
|
273
|
+
|
|
274
|
+
else:
|
|
275
|
+
spec_version = Version(spec)
|
|
276
|
+
if not spec_version.local:
|
|
277
|
+
prospective = Version(prospective.public)
|
|
278
|
+
return prospective == spec_version
|
|
279
|
+
|
|
280
|
+
def _compare_not_equal(self, prospective: Version, spec: str) -> bool:
|
|
281
|
+
return not self._compare_equal(prospective, spec)
|
|
282
|
+
|
|
283
|
+
def _compare_less_than_equal(self, prospective: Version, spec: str) -> bool:
|
|
284
|
+
return Version(prospective.public) <= Version(spec)
|
|
285
|
+
|
|
286
|
+
def _compare_greater_than_equal(self, prospective: Version, spec: str) -> bool:
|
|
287
|
+
return Version(prospective.public) >= Version(spec)
|
|
288
|
+
|
|
289
|
+
def _compare_less_than(self, prospective: Version, spec_str: str) -> bool:
|
|
290
|
+
spec = Version(spec_str)
|
|
291
|
+
|
|
292
|
+
if not prospective < spec:
|
|
293
|
+
return False
|
|
294
|
+
|
|
295
|
+
if not spec.is_prerelease and prospective.is_prerelease:
|
|
296
|
+
if Version(prospective.base_version) == Version(spec.base_version):
|
|
297
|
+
return False
|
|
298
|
+
|
|
299
|
+
return True
|
|
300
|
+
|
|
301
|
+
def _compare_greater_than(self, prospective: Version, spec_str: str) -> bool:
|
|
302
|
+
spec = Version(spec_str)
|
|
303
|
+
|
|
304
|
+
if not prospective > spec:
|
|
305
|
+
return False
|
|
306
|
+
|
|
307
|
+
if not spec.is_postrelease and prospective.is_postrelease:
|
|
308
|
+
if Version(prospective.base_version) == Version(spec.base_version):
|
|
309
|
+
return False
|
|
310
|
+
|
|
311
|
+
if prospective.local is not None:
|
|
312
|
+
if Version(prospective.base_version) == Version(spec.base_version):
|
|
313
|
+
return False
|
|
314
|
+
|
|
315
|
+
return True
|
|
316
|
+
|
|
317
|
+
def _compare_arbitrary(self, prospective: Version, spec: str) -> bool:
|
|
318
|
+
return str(prospective).lower() == str(spec).lower()
|
|
319
|
+
|
|
320
|
+
def __contains__(self, item: ta.Union[str, Version]) -> bool:
|
|
321
|
+
return self.contains(item)
|
|
322
|
+
|
|
323
|
+
def contains(self, item: UnparsedVersion, prereleases: ta.Optional[bool] = None) -> bool:
|
|
324
|
+
if prereleases is None:
|
|
325
|
+
prereleases = self.prereleases
|
|
326
|
+
|
|
327
|
+
normalized_item = _coerce_version(item)
|
|
328
|
+
|
|
329
|
+
if normalized_item.is_prerelease and not prereleases:
|
|
330
|
+
return False
|
|
331
|
+
|
|
332
|
+
operator_callable: CallableVersionOperator = self._get_operator(self.operator)
|
|
333
|
+
return operator_callable(normalized_item, self.version)
|
|
334
|
+
|
|
335
|
+
def filter(
|
|
336
|
+
self,
|
|
337
|
+
iterable: ta.Iterable[UnparsedVersionVar],
|
|
338
|
+
prereleases: ta.Optional[bool] = None,
|
|
339
|
+
) -> ta.Iterator[UnparsedVersionVar]:
|
|
340
|
+
yielded = False
|
|
341
|
+
found_prereleases = []
|
|
342
|
+
|
|
343
|
+
kw = {'prereleases': prereleases if prereleases is not None else True}
|
|
344
|
+
|
|
345
|
+
for version in iterable:
|
|
346
|
+
parsed_version = _coerce_version(version)
|
|
347
|
+
|
|
348
|
+
if self.contains(parsed_version, **kw):
|
|
349
|
+
if parsed_version.is_prerelease and not (prereleases or self.prereleases):
|
|
350
|
+
found_prereleases.append(version)
|
|
351
|
+
else:
|
|
352
|
+
yielded = True
|
|
353
|
+
yield version
|
|
354
|
+
|
|
355
|
+
if not yielded and found_prereleases:
|
|
356
|
+
for version in found_prereleases:
|
|
357
|
+
yield version
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
_version_prefix_regex = re.compile(r'^([0-9]+)((?:a|b|c|rc)[0-9]+)$')
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def _version_split(version: str) -> ta.List[str]:
|
|
364
|
+
result: ta.List[str] = []
|
|
365
|
+
|
|
366
|
+
epoch, _, rest = version.rpartition('!')
|
|
367
|
+
result.append(epoch or '0')
|
|
368
|
+
|
|
369
|
+
for item in rest.split('.'):
|
|
370
|
+
match = _version_prefix_regex.search(item)
|
|
371
|
+
if match:
|
|
372
|
+
result.extend(match.groups())
|
|
373
|
+
else:
|
|
374
|
+
result.append(item)
|
|
375
|
+
return result
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def _version_join(components: ta.List[str]) -> str:
|
|
379
|
+
epoch, *rest = components
|
|
380
|
+
return f"{epoch}!{'.'.join(rest)}"
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
def _is_not_version_suffix(segment: str) -> bool:
|
|
384
|
+
return not any(segment.startswith(prefix) for prefix in ('dev', 'a', 'b', 'rc', 'post'))
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
def _pad_version(left: ta.List[str], right: ta.List[str]) -> ta.Tuple[ta.List[str], ta.List[str]]:
|
|
388
|
+
left_split, right_split = [], []
|
|
389
|
+
|
|
390
|
+
left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left)))
|
|
391
|
+
right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right)))
|
|
392
|
+
|
|
393
|
+
left_split.append(left[len(left_split[0]):])
|
|
394
|
+
right_split.append(right[len(right_split[0]):])
|
|
395
|
+
|
|
396
|
+
left_split.insert(1, ['0'] * max(0, len(right_split[0]) - len(left_split[0])))
|
|
397
|
+
right_split.insert(1, ['0'] * max(0, len(left_split[0]) - len(right_split[0])))
|
|
398
|
+
|
|
399
|
+
return (
|
|
400
|
+
list(itertools.chain.from_iterable(left_split)),
|
|
401
|
+
list(itertools.chain.from_iterable(right_split)),
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
class SpecifierSet(BaseSpecifier):
|
|
406
|
+
def __init__(
|
|
407
|
+
self,
|
|
408
|
+
specifiers: str = '',
|
|
409
|
+
prereleases: ta.Optional[bool] = None,
|
|
410
|
+
) -> None:
|
|
411
|
+
split_specifiers = [s.strip() for s in specifiers.split(',') if s.strip()]
|
|
412
|
+
|
|
413
|
+
self._specs = frozenset(map(Specifier, split_specifiers))
|
|
414
|
+
self._prereleases = prereleases
|
|
415
|
+
|
|
416
|
+
@property
|
|
417
|
+
def prereleases(self) -> ta.Optional[bool]:
|
|
418
|
+
if self._prereleases is not None:
|
|
419
|
+
return self._prereleases
|
|
420
|
+
|
|
421
|
+
if not self._specs:
|
|
422
|
+
return None
|
|
423
|
+
|
|
424
|
+
return any(s.prereleases for s in self._specs)
|
|
425
|
+
|
|
426
|
+
@prereleases.setter
|
|
427
|
+
def prereleases(self, value: bool) -> None:
|
|
428
|
+
self._prereleases = value
|
|
429
|
+
|
|
430
|
+
def __repr__(self) -> str:
|
|
431
|
+
pre = (
|
|
432
|
+
f', prereleases={self.prereleases!r}'
|
|
433
|
+
if self._prereleases is not None
|
|
434
|
+
else ''
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
return f'<SpecifierSet({str(self)!r}{pre})>'
|
|
438
|
+
|
|
439
|
+
def __str__(self) -> str:
|
|
440
|
+
return ','.join(sorted(str(s) for s in self._specs))
|
|
441
|
+
|
|
442
|
+
def __hash__(self) -> int:
|
|
443
|
+
return hash(self._specs)
|
|
444
|
+
|
|
445
|
+
def __and__(self, other: ta.Union['SpecifierSet', str]) -> 'SpecifierSet':
|
|
446
|
+
if isinstance(other, str):
|
|
447
|
+
other = SpecifierSet(other)
|
|
448
|
+
elif not isinstance(other, SpecifierSet):
|
|
449
|
+
return NotImplemented # type: ignore
|
|
450
|
+
|
|
451
|
+
specifier = SpecifierSet()
|
|
452
|
+
specifier._specs = frozenset(self._specs | other._specs)
|
|
453
|
+
|
|
454
|
+
if self._prereleases is None and other._prereleases is not None:
|
|
455
|
+
specifier._prereleases = other._prereleases
|
|
456
|
+
elif self._prereleases is not None and other._prereleases is None:
|
|
457
|
+
specifier._prereleases = self._prereleases
|
|
458
|
+
elif self._prereleases == other._prereleases:
|
|
459
|
+
specifier._prereleases = self._prereleases
|
|
460
|
+
else:
|
|
461
|
+
raise ValueError('Cannot combine SpecifierSets with True and False prerelease overrides.')
|
|
462
|
+
|
|
463
|
+
return specifier
|
|
464
|
+
|
|
465
|
+
def __eq__(self, other: object) -> bool:
|
|
466
|
+
if isinstance(other, (str, Specifier)):
|
|
467
|
+
other = SpecifierSet(str(other))
|
|
468
|
+
elif not isinstance(other, SpecifierSet):
|
|
469
|
+
return NotImplemented
|
|
470
|
+
|
|
471
|
+
return self._specs == other._specs
|
|
472
|
+
|
|
473
|
+
def __len__(self) -> int:
|
|
474
|
+
return len(self._specs)
|
|
475
|
+
|
|
476
|
+
def __iter__(self) -> ta.Iterator[Specifier]:
|
|
477
|
+
return iter(self._specs)
|
|
478
|
+
|
|
479
|
+
def __contains__(self, item: UnparsedVersion) -> bool:
|
|
480
|
+
return self.contains(item)
|
|
481
|
+
|
|
482
|
+
def contains(
|
|
483
|
+
self,
|
|
484
|
+
item: UnparsedVersion,
|
|
485
|
+
prereleases: ta.Optional[bool] = None,
|
|
486
|
+
installed: ta.Optional[bool] = None,
|
|
487
|
+
) -> bool:
|
|
488
|
+
if not isinstance(item, Version):
|
|
489
|
+
item = Version(item)
|
|
490
|
+
|
|
491
|
+
if prereleases is None:
|
|
492
|
+
prereleases = self.prereleases
|
|
493
|
+
|
|
494
|
+
if not prereleases and item.is_prerelease:
|
|
495
|
+
return False
|
|
496
|
+
|
|
497
|
+
if installed and item.is_prerelease:
|
|
498
|
+
item = Version(item.base_version)
|
|
499
|
+
|
|
500
|
+
return all(s.contains(item, prereleases=prereleases) for s in self._specs)
|
|
501
|
+
|
|
502
|
+
def filter(
|
|
503
|
+
self,
|
|
504
|
+
iterable: ta.Iterable[UnparsedVersionVar],
|
|
505
|
+
prereleases: ta.Optional[bool] = None,
|
|
506
|
+
) -> ta.Iterator[UnparsedVersionVar]:
|
|
507
|
+
if prereleases is None:
|
|
508
|
+
prereleases = self.prereleases
|
|
509
|
+
|
|
510
|
+
if self._specs:
|
|
511
|
+
for spec in self._specs:
|
|
512
|
+
iterable = spec.filter(iterable, prereleases=bool(prereleases))
|
|
513
|
+
return iter(iterable)
|
|
514
|
+
|
|
515
|
+
else:
|
|
516
|
+
filtered: ta.List[UnparsedVersionVar] = []
|
|
517
|
+
found_prereleases: ta.List[UnparsedVersionVar] = []
|
|
518
|
+
|
|
519
|
+
for item in iterable:
|
|
520
|
+
parsed_version = _coerce_version(item)
|
|
521
|
+
|
|
522
|
+
if parsed_version.is_prerelease and not prereleases:
|
|
523
|
+
if not filtered:
|
|
524
|
+
found_prereleases.append(item)
|
|
525
|
+
else:
|
|
526
|
+
filtered.append(item)
|
|
527
|
+
|
|
528
|
+
if not filtered and found_prereleases and prereleases is None:
|
|
529
|
+
return iter(found_prereleases)
|
|
530
|
+
|
|
531
|
+
return iter(filtered)
|