pip 25.2__py3-none-any.whl → 26.0__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.
- pip/__init__.py +1 -1
- pip/_internal/__init__.py +0 -0
- pip/_internal/build_env.py +265 -8
- pip/_internal/cache.py +1 -1
- pip/_internal/cli/base_command.py +11 -0
- pip/_internal/cli/cmdoptions.py +200 -71
- pip/_internal/cli/index_command.py +20 -0
- pip/_internal/cli/main.py +11 -6
- pip/_internal/cli/main_parser.py +3 -1
- pip/_internal/cli/parser.py +96 -36
- pip/_internal/cli/progress_bars.py +4 -2
- pip/_internal/cli/req_command.py +126 -30
- pip/_internal/commands/cache.py +24 -0
- pip/_internal/commands/completion.py +2 -1
- pip/_internal/commands/download.py +12 -11
- pip/_internal/commands/index.py +13 -6
- pip/_internal/commands/install.py +55 -43
- pip/_internal/commands/list.py +14 -16
- pip/_internal/commands/lock.py +19 -14
- pip/_internal/commands/wheel.py +13 -23
- pip/_internal/configuration.py +1 -2
- pip/_internal/distributions/sdist.py +13 -14
- pip/_internal/exceptions.py +96 -6
- pip/_internal/index/collector.py +2 -3
- pip/_internal/index/package_finder.py +87 -21
- pip/_internal/locations/__init__.py +1 -2
- pip/_internal/locations/_sysconfig.py +4 -1
- pip/_internal/metadata/__init__.py +7 -2
- pip/_internal/metadata/importlib/_dists.py +8 -2
- pip/_internal/models/link.py +18 -14
- pip/_internal/models/release_control.py +92 -0
- pip/_internal/models/selection_prefs.py +6 -3
- pip/_internal/models/wheel.py +5 -66
- pip/_internal/network/auth.py +6 -2
- pip/_internal/network/cache.py +6 -11
- pip/_internal/network/download.py +4 -5
- pip/_internal/network/lazy_wheel.py +5 -3
- pip/_internal/network/session.py +14 -10
- pip/_internal/operations/build/wheel.py +4 -4
- pip/_internal/operations/build/wheel_editable.py +4 -4
- pip/_internal/operations/install/wheel.py +1 -2
- pip/_internal/operations/prepare.py +9 -4
- pip/_internal/pyproject.py +2 -61
- pip/_internal/req/__init__.py +1 -3
- pip/_internal/req/constructors.py +45 -39
- pip/_internal/req/pep723.py +41 -0
- pip/_internal/req/req_file.py +10 -2
- pip/_internal/req/req_install.py +32 -141
- pip/_internal/resolution/resolvelib/candidates.py +20 -11
- pip/_internal/resolution/resolvelib/factory.py +43 -1
- pip/_internal/resolution/resolvelib/provider.py +9 -0
- pip/_internal/resolution/resolvelib/reporter.py +21 -8
- pip/_internal/resolution/resolvelib/requirements.py +7 -3
- pip/_internal/resolution/resolvelib/resolver.py +2 -6
- pip/_internal/self_outdated_check.py +17 -16
- pip/_internal/utils/datetime.py +18 -0
- pip/_internal/utils/filesystem.py +52 -1
- pip/_internal/utils/logging.py +34 -2
- pip/_internal/utils/misc.py +18 -12
- pip/_internal/utils/pylock.py +116 -0
- pip/_internal/utils/unpacking.py +26 -1
- pip/_internal/vcs/versioncontrol.py +3 -1
- pip/_internal/wheel_builder.py +23 -96
- pip/_vendor/README.rst +180 -0
- pip/_vendor/cachecontrol/LICENSE.txt +13 -0
- pip/_vendor/cachecontrol/__init__.py +6 -3
- pip/_vendor/cachecontrol/adapter.py +0 -1
- pip/_vendor/cachecontrol/controller.py +1 -1
- pip/_vendor/cachecontrol/filewrapper.py +3 -1
- pip/_vendor/certifi/LICENSE +20 -0
- pip/_vendor/certifi/__init__.py +1 -1
- pip/_vendor/certifi/cacert.pem +62 -372
- pip/_vendor/dependency_groups/LICENSE.txt +9 -0
- pip/_vendor/distlib/LICENSE.txt +284 -0
- pip/_vendor/distro/LICENSE +202 -0
- pip/_vendor/idna/LICENSE.md +31 -0
- pip/_vendor/idna/codec.py +1 -1
- pip/_vendor/idna/core.py +1 -1
- pip/_vendor/idna/idnadata.py +72 -6
- pip/_vendor/idna/package_data.py +1 -1
- pip/_vendor/idna/uts46data.py +891 -731
- pip/_vendor/msgpack/COPYING +14 -0
- pip/_vendor/msgpack/__init__.py +2 -2
- pip/_vendor/packaging/LICENSE +3 -0
- pip/_vendor/packaging/LICENSE.APACHE +177 -0
- pip/_vendor/packaging/LICENSE.BSD +23 -0
- pip/_vendor/packaging/__init__.py +1 -1
- pip/_vendor/packaging/_elffile.py +0 -1
- pip/_vendor/packaging/_manylinux.py +36 -36
- pip/_vendor/packaging/_musllinux.py +1 -1
- pip/_vendor/packaging/_parser.py +22 -10
- pip/_vendor/packaging/_structures.py +8 -0
- pip/_vendor/packaging/_tokenizer.py +23 -25
- pip/_vendor/packaging/licenses/__init__.py +13 -11
- pip/_vendor/packaging/licenses/_spdx.py +41 -1
- pip/_vendor/packaging/markers.py +64 -38
- pip/_vendor/packaging/metadata.py +143 -27
- pip/_vendor/packaging/pylock.py +635 -0
- pip/_vendor/packaging/requirements.py +5 -10
- pip/_vendor/packaging/specifiers.py +219 -170
- pip/_vendor/packaging/tags.py +15 -20
- pip/_vendor/packaging/utils.py +19 -24
- pip/_vendor/packaging/version.py +315 -105
- pip/_vendor/pkg_resources/LICENSE +17 -0
- pip/_vendor/platformdirs/LICENSE +21 -0
- pip/_vendor/platformdirs/api.py +1 -1
- pip/_vendor/platformdirs/macos.py +10 -8
- pip/_vendor/platformdirs/version.py +16 -3
- pip/_vendor/platformdirs/windows.py +7 -1
- pip/_vendor/pygments/LICENSE +25 -0
- pip/_vendor/pyproject_hooks/LICENSE +21 -0
- pip/_vendor/requests/LICENSE +175 -0
- pip/_vendor/requests/__version__.py +2 -2
- pip/_vendor/requests/adapters.py +17 -40
- pip/_vendor/requests/sessions.py +1 -1
- pip/_vendor/resolvelib/LICENSE +13 -0
- pip/_vendor/resolvelib/__init__.py +1 -1
- pip/_vendor/resolvelib/resolvers/abstract.py +3 -3
- pip/_vendor/resolvelib/resolvers/resolution.py +5 -0
- pip/_vendor/rich/LICENSE +19 -0
- pip/_vendor/rich/style.py +7 -11
- pip/_vendor/tomli/LICENSE +21 -0
- pip/_vendor/tomli/__init__.py +1 -1
- pip/_vendor/tomli/_parser.py +28 -21
- pip/_vendor/tomli/_re.py +8 -5
- pip/_vendor/tomli_w/LICENSE +21 -0
- pip/_vendor/truststore/LICENSE +21 -0
- pip/_vendor/truststore/__init__.py +1 -1
- pip/_vendor/truststore/_api.py +14 -6
- pip/_vendor/truststore/_openssl.py +3 -1
- pip/_vendor/urllib3/LICENSE.txt +21 -0
- pip/_vendor/vendor.txt +11 -11
- {pip-25.2.dist-info → pip-26.0.dist-info}/METADATA +10 -11
- {pip-25.2.dist-info → pip-26.0.dist-info}/RECORD +158 -139
- {pip-25.2.dist-info → pip-26.0.dist-info}/WHEEL +1 -2
- pip-26.0.dist-info/entry_points.txt +4 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/AUTHORS.txt +27 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/idna/LICENSE.md +1 -1
- pip/_internal/models/pylock.py +0 -188
- pip/_internal/operations/build/metadata_legacy.py +0 -73
- pip/_internal/operations/build/wheel_legacy.py +0 -119
- pip/_internal/operations/install/editable_legacy.py +0 -48
- pip/_internal/utils/setuptools_build.py +0 -149
- pip-25.2.dist-info/entry_points.txt +0 -3
- pip-25.2.dist-info/licenses/src/pip/_vendor/tomli/LICENSE-HEADER +0 -3
- pip-25.2.dist-info/top_level.txt +0 -1
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/LICENSE.txt +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/certifi/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/dependency_groups/LICENSE.txt +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/distlib/LICENSE.txt +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/distro/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/msgpack/COPYING +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE.APACHE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE.BSD +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/pkg_resources/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/platformdirs/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/pygments/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/pyproject_hooks/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/requests/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/resolvelib/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/rich/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/tomli/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/tomli_w/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/truststore/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/urllib3/LICENSE.txt +0 -0
pip/_vendor/packaging/version.py
CHANGED
|
@@ -9,12 +9,59 @@
|
|
|
9
9
|
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
|
|
12
|
-
import itertools
|
|
13
12
|
import re
|
|
14
|
-
|
|
13
|
+
import sys
|
|
14
|
+
import typing
|
|
15
|
+
from typing import (
|
|
16
|
+
Any,
|
|
17
|
+
Callable,
|
|
18
|
+
Literal,
|
|
19
|
+
NamedTuple,
|
|
20
|
+
SupportsInt,
|
|
21
|
+
Tuple,
|
|
22
|
+
TypedDict,
|
|
23
|
+
Union,
|
|
24
|
+
)
|
|
15
25
|
|
|
16
26
|
from ._structures import Infinity, InfinityType, NegativeInfinity, NegativeInfinityType
|
|
17
27
|
|
|
28
|
+
if typing.TYPE_CHECKING:
|
|
29
|
+
from typing_extensions import Self, Unpack
|
|
30
|
+
|
|
31
|
+
if sys.version_info >= (3, 13): # pragma: no cover
|
|
32
|
+
from warnings import deprecated as _deprecated
|
|
33
|
+
elif typing.TYPE_CHECKING:
|
|
34
|
+
from typing_extensions import deprecated as _deprecated
|
|
35
|
+
else: # pragma: no cover
|
|
36
|
+
import functools
|
|
37
|
+
import warnings
|
|
38
|
+
|
|
39
|
+
def _deprecated(message: str) -> object:
|
|
40
|
+
def decorator(func: object) -> object:
|
|
41
|
+
@functools.wraps(func)
|
|
42
|
+
def wrapper(*args: object, **kwargs: object) -> object:
|
|
43
|
+
warnings.warn(
|
|
44
|
+
message,
|
|
45
|
+
category=DeprecationWarning,
|
|
46
|
+
stacklevel=2,
|
|
47
|
+
)
|
|
48
|
+
return func(*args, **kwargs)
|
|
49
|
+
|
|
50
|
+
return wrapper
|
|
51
|
+
|
|
52
|
+
return decorator
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
_LETTER_NORMALIZATION = {
|
|
56
|
+
"alpha": "a",
|
|
57
|
+
"beta": "b",
|
|
58
|
+
"c": "rc",
|
|
59
|
+
"pre": "rc",
|
|
60
|
+
"preview": "rc",
|
|
61
|
+
"rev": "post",
|
|
62
|
+
"r": "post",
|
|
63
|
+
}
|
|
64
|
+
|
|
18
65
|
__all__ = ["VERSION_PATTERN", "InvalidVersion", "Version", "parse"]
|
|
19
66
|
|
|
20
67
|
LocalType = Tuple[Union[int, str], ...]
|
|
@@ -35,13 +82,13 @@ CmpKey = Tuple[
|
|
|
35
82
|
VersionComparisonMethod = Callable[[CmpKey, CmpKey], bool]
|
|
36
83
|
|
|
37
84
|
|
|
38
|
-
class
|
|
39
|
-
epoch: int
|
|
40
|
-
release: tuple[int, ...]
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
local:
|
|
85
|
+
class _VersionReplace(TypedDict, total=False):
|
|
86
|
+
epoch: int | None
|
|
87
|
+
release: tuple[int, ...] | None
|
|
88
|
+
pre: tuple[Literal["a", "b", "rc"], int] | None
|
|
89
|
+
post: int | None
|
|
90
|
+
dev: int | None
|
|
91
|
+
local: str | None
|
|
45
92
|
|
|
46
93
|
|
|
47
94
|
def parse(version: str) -> Version:
|
|
@@ -67,7 +114,15 @@ class InvalidVersion(ValueError):
|
|
|
67
114
|
|
|
68
115
|
|
|
69
116
|
class _BaseVersion:
|
|
70
|
-
|
|
117
|
+
__slots__ = ()
|
|
118
|
+
|
|
119
|
+
# This can also be a normal member (see the packaging_legacy package);
|
|
120
|
+
# we are just requiring it to be readable. Actually defining a property
|
|
121
|
+
# has runtime effect on subclasses, so it's typing only.
|
|
122
|
+
if typing.TYPE_CHECKING:
|
|
123
|
+
|
|
124
|
+
@property
|
|
125
|
+
def _key(self) -> tuple[Any, ...]: ...
|
|
71
126
|
|
|
72
127
|
def __hash__(self) -> int:
|
|
73
128
|
return hash(self._key)
|
|
@@ -114,38 +169,56 @@ class _BaseVersion:
|
|
|
114
169
|
|
|
115
170
|
# Deliberately not anchored to the start and end of the string, to make it
|
|
116
171
|
# easier for 3rd party code to reuse
|
|
172
|
+
|
|
173
|
+
# Note that ++ doesn't behave identically on CPython and PyPy, so not using it here
|
|
117
174
|
_VERSION_PATTERN = r"""
|
|
118
|
-
v
|
|
175
|
+
v?+ # optional leading v
|
|
119
176
|
(?:
|
|
120
|
-
(?:(?P<epoch>[0-9]+)!)
|
|
121
|
-
(?P<release>[0-9]+(?:\.[0-9]+)
|
|
177
|
+
(?:(?P<epoch>[0-9]+)!)?+ # epoch
|
|
178
|
+
(?P<release>[0-9]+(?:\.[0-9]+)*+) # release segment
|
|
122
179
|
(?P<pre> # pre-release
|
|
123
|
-
[-
|
|
180
|
+
[._-]?+
|
|
124
181
|
(?P<pre_l>alpha|a|beta|b|preview|pre|c|rc)
|
|
125
|
-
[-
|
|
182
|
+
[._-]?+
|
|
126
183
|
(?P<pre_n>[0-9]+)?
|
|
127
|
-
)
|
|
184
|
+
)?+
|
|
128
185
|
(?P<post> # post release
|
|
129
186
|
(?:-(?P<post_n1>[0-9]+))
|
|
130
187
|
|
|
|
131
188
|
(?:
|
|
132
|
-
[-
|
|
189
|
+
[._-]?
|
|
133
190
|
(?P<post_l>post|rev|r)
|
|
134
|
-
[-
|
|
191
|
+
[._-]?
|
|
135
192
|
(?P<post_n2>[0-9]+)?
|
|
136
193
|
)
|
|
137
|
-
)
|
|
194
|
+
)?+
|
|
138
195
|
(?P<dev> # dev release
|
|
139
|
-
[-
|
|
196
|
+
[._-]?+
|
|
140
197
|
(?P<dev_l>dev)
|
|
141
|
-
[-
|
|
198
|
+
[._-]?+
|
|
142
199
|
(?P<dev_n>[0-9]+)?
|
|
143
|
-
)
|
|
200
|
+
)?+
|
|
144
201
|
)
|
|
145
|
-
(?:\+
|
|
202
|
+
(?:\+
|
|
203
|
+
(?P<local> # local version
|
|
204
|
+
[a-z0-9]+
|
|
205
|
+
(?:[._-][a-z0-9]+)*+
|
|
206
|
+
)
|
|
207
|
+
)?+
|
|
146
208
|
"""
|
|
147
209
|
|
|
148
|
-
|
|
210
|
+
_VERSION_PATTERN_OLD = _VERSION_PATTERN.replace("*+", "*").replace("?+", "?")
|
|
211
|
+
|
|
212
|
+
# Possessive qualifiers were added in Python 3.11.
|
|
213
|
+
# CPython 3.11.0-3.11.4 had a bug: https://github.com/python/cpython/pull/107795
|
|
214
|
+
# Older PyPy also had a bug.
|
|
215
|
+
VERSION_PATTERN = (
|
|
216
|
+
_VERSION_PATTERN_OLD
|
|
217
|
+
if (sys.implementation.name == "cpython" and sys.version_info < (3, 11, 5))
|
|
218
|
+
or (sys.implementation.name == "pypy" and sys.version_info < (3, 11, 13))
|
|
219
|
+
or sys.version_info < (3, 11)
|
|
220
|
+
else _VERSION_PATTERN
|
|
221
|
+
)
|
|
149
222
|
"""
|
|
150
223
|
A string containing the regular expression used to match a valid version.
|
|
151
224
|
|
|
@@ -158,6 +231,82 @@ flags set.
|
|
|
158
231
|
"""
|
|
159
232
|
|
|
160
233
|
|
|
234
|
+
# Validation pattern for local version in replace()
|
|
235
|
+
_LOCAL_PATTERN = re.compile(r"[a-z0-9]+(?:[._-][a-z0-9]+)*", re.IGNORECASE)
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def _validate_epoch(value: object, /) -> int:
|
|
239
|
+
epoch = value or 0
|
|
240
|
+
if isinstance(epoch, int) and epoch >= 0:
|
|
241
|
+
return epoch
|
|
242
|
+
msg = f"epoch must be non-negative integer, got {epoch}"
|
|
243
|
+
raise InvalidVersion(msg)
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def _validate_release(value: object, /) -> tuple[int, ...]:
|
|
247
|
+
release = (0,) if value is None else value
|
|
248
|
+
if (
|
|
249
|
+
isinstance(release, tuple)
|
|
250
|
+
and len(release) > 0
|
|
251
|
+
and all(isinstance(i, int) and i >= 0 for i in release)
|
|
252
|
+
):
|
|
253
|
+
return release
|
|
254
|
+
msg = f"release must be a non-empty tuple of non-negative integers, got {release}"
|
|
255
|
+
raise InvalidVersion(msg)
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def _validate_pre(value: object, /) -> tuple[Literal["a", "b", "rc"], int] | None:
|
|
259
|
+
if value is None:
|
|
260
|
+
return value
|
|
261
|
+
if (
|
|
262
|
+
isinstance(value, tuple)
|
|
263
|
+
and len(value) == 2
|
|
264
|
+
and value[0] in ("a", "b", "rc")
|
|
265
|
+
and isinstance(value[1], int)
|
|
266
|
+
and value[1] >= 0
|
|
267
|
+
):
|
|
268
|
+
return value
|
|
269
|
+
msg = f"pre must be a tuple of ('a'|'b'|'rc', non-negative int), got {value}"
|
|
270
|
+
raise InvalidVersion(msg)
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def _validate_post(value: object, /) -> tuple[Literal["post"], int] | None:
|
|
274
|
+
if value is None:
|
|
275
|
+
return value
|
|
276
|
+
if isinstance(value, int) and value >= 0:
|
|
277
|
+
return ("post", value)
|
|
278
|
+
msg = f"post must be non-negative integer, got {value}"
|
|
279
|
+
raise InvalidVersion(msg)
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def _validate_dev(value: object, /) -> tuple[Literal["dev"], int] | None:
|
|
283
|
+
if value is None:
|
|
284
|
+
return value
|
|
285
|
+
if isinstance(value, int) and value >= 0:
|
|
286
|
+
return ("dev", value)
|
|
287
|
+
msg = f"dev must be non-negative integer, got {value}"
|
|
288
|
+
raise InvalidVersion(msg)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def _validate_local(value: object, /) -> LocalType | None:
|
|
292
|
+
if value is None:
|
|
293
|
+
return value
|
|
294
|
+
if isinstance(value, str) and _LOCAL_PATTERN.fullmatch(value):
|
|
295
|
+
return _parse_local_version(value)
|
|
296
|
+
msg = f"local must be a valid version string, got {value!r}"
|
|
297
|
+
raise InvalidVersion(msg)
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
# Backward compatibility for internals before 26.0. Do not use.
|
|
301
|
+
class _Version(NamedTuple):
|
|
302
|
+
epoch: int
|
|
303
|
+
release: tuple[int, ...]
|
|
304
|
+
dev: tuple[str, int] | None
|
|
305
|
+
pre: tuple[str, int] | None
|
|
306
|
+
post: tuple[str, int] | None
|
|
307
|
+
local: LocalType | None
|
|
308
|
+
|
|
309
|
+
|
|
161
310
|
class Version(_BaseVersion):
|
|
162
311
|
"""This class abstracts handling of a project's versions.
|
|
163
312
|
|
|
@@ -182,8 +331,19 @@ class Version(_BaseVersion):
|
|
|
182
331
|
True
|
|
183
332
|
"""
|
|
184
333
|
|
|
185
|
-
|
|
186
|
-
|
|
334
|
+
__slots__ = ("_dev", "_epoch", "_key_cache", "_local", "_post", "_pre", "_release")
|
|
335
|
+
__match_args__ = ("_str",)
|
|
336
|
+
|
|
337
|
+
_regex = re.compile(r"\s*" + VERSION_PATTERN + r"\s*", re.VERBOSE | re.IGNORECASE)
|
|
338
|
+
|
|
339
|
+
_epoch: int
|
|
340
|
+
_release: tuple[int, ...]
|
|
341
|
+
_dev: tuple[str, int] | None
|
|
342
|
+
_pre: tuple[str, int] | None
|
|
343
|
+
_post: tuple[str, int] | None
|
|
344
|
+
_local: LocalType | None
|
|
345
|
+
|
|
346
|
+
_key_cache: CmpKey | None
|
|
187
347
|
|
|
188
348
|
def __init__(self, version: str) -> None:
|
|
189
349
|
"""Initialize a Version object.
|
|
@@ -195,34 +355,86 @@ class Version(_BaseVersion):
|
|
|
195
355
|
If the ``version`` does not conform to PEP 440 in any way then this
|
|
196
356
|
exception will be raised.
|
|
197
357
|
"""
|
|
198
|
-
|
|
199
358
|
# Validate the version and parse it into pieces
|
|
200
|
-
match = self._regex.
|
|
359
|
+
match = self._regex.fullmatch(version)
|
|
201
360
|
if not match:
|
|
202
361
|
raise InvalidVersion(f"Invalid version: {version!r}")
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
self.
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
362
|
+
self._epoch = int(match.group("epoch")) if match.group("epoch") else 0
|
|
363
|
+
self._release = tuple(map(int, match.group("release").split(".")))
|
|
364
|
+
self._pre = _parse_letter_version(match.group("pre_l"), match.group("pre_n"))
|
|
365
|
+
self._post = _parse_letter_version(
|
|
366
|
+
match.group("post_l"), match.group("post_n1") or match.group("post_n2")
|
|
367
|
+
)
|
|
368
|
+
self._dev = _parse_letter_version(match.group("dev_l"), match.group("dev_n"))
|
|
369
|
+
self._local = _parse_local_version(match.group("local"))
|
|
370
|
+
|
|
371
|
+
# Key which will be used for sorting
|
|
372
|
+
self._key_cache = None
|
|
373
|
+
|
|
374
|
+
def __replace__(self, **kwargs: Unpack[_VersionReplace]) -> Self:
|
|
375
|
+
epoch = _validate_epoch(kwargs["epoch"]) if "epoch" in kwargs else self._epoch
|
|
376
|
+
release = (
|
|
377
|
+
_validate_release(kwargs["release"])
|
|
378
|
+
if "release" in kwargs
|
|
379
|
+
else self._release
|
|
214
380
|
)
|
|
381
|
+
pre = _validate_pre(kwargs["pre"]) if "pre" in kwargs else self._pre
|
|
382
|
+
post = _validate_post(kwargs["post"]) if "post" in kwargs else self._post
|
|
383
|
+
dev = _validate_dev(kwargs["dev"]) if "dev" in kwargs else self._dev
|
|
384
|
+
local = _validate_local(kwargs["local"]) if "local" in kwargs else self._local
|
|
385
|
+
|
|
386
|
+
if (
|
|
387
|
+
epoch == self._epoch
|
|
388
|
+
and release == self._release
|
|
389
|
+
and pre == self._pre
|
|
390
|
+
and post == self._post
|
|
391
|
+
and dev == self._dev
|
|
392
|
+
and local == self._local
|
|
393
|
+
):
|
|
394
|
+
return self
|
|
395
|
+
|
|
396
|
+
new_version = self.__class__.__new__(self.__class__)
|
|
397
|
+
new_version._key_cache = None
|
|
398
|
+
new_version._epoch = epoch
|
|
399
|
+
new_version._release = release
|
|
400
|
+
new_version._pre = pre
|
|
401
|
+
new_version._post = post
|
|
402
|
+
new_version._dev = dev
|
|
403
|
+
new_version._local = local
|
|
404
|
+
|
|
405
|
+
return new_version
|
|
406
|
+
|
|
407
|
+
@property
|
|
408
|
+
def _key(self) -> CmpKey:
|
|
409
|
+
if self._key_cache is None:
|
|
410
|
+
self._key_cache = _cmpkey(
|
|
411
|
+
self._epoch,
|
|
412
|
+
self._release,
|
|
413
|
+
self._pre,
|
|
414
|
+
self._post,
|
|
415
|
+
self._dev,
|
|
416
|
+
self._local,
|
|
417
|
+
)
|
|
418
|
+
return self._key_cache
|
|
215
419
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
self.
|
|
221
|
-
self._version.post,
|
|
222
|
-
self._version.dev,
|
|
223
|
-
self._version.local,
|
|
420
|
+
@property
|
|
421
|
+
@_deprecated("Version._version is private and will be removed soon")
|
|
422
|
+
def _version(self) -> _Version:
|
|
423
|
+
return _Version(
|
|
424
|
+
self._epoch, self._release, self._dev, self._pre, self._post, self._local
|
|
224
425
|
)
|
|
225
426
|
|
|
427
|
+
@_version.setter
|
|
428
|
+
@_deprecated("Version._version is private and will be removed soon")
|
|
429
|
+
def _version(self, value: _Version) -> None:
|
|
430
|
+
self._epoch = value.epoch
|
|
431
|
+
self._release = value.release
|
|
432
|
+
self._dev = value.dev
|
|
433
|
+
self._pre = value.pre
|
|
434
|
+
self._post = value.post
|
|
435
|
+
self._local = value.local
|
|
436
|
+
self._key_cache = None
|
|
437
|
+
|
|
226
438
|
def __repr__(self) -> str:
|
|
227
439
|
"""A representation of the Version that shows all internal state.
|
|
228
440
|
|
|
@@ -237,32 +449,35 @@ class Version(_BaseVersion):
|
|
|
237
449
|
>>> str(Version("1.0a5"))
|
|
238
450
|
'1.0a5'
|
|
239
451
|
"""
|
|
240
|
-
|
|
452
|
+
# This is a hot function, so not calling self.base_version
|
|
453
|
+
version = ".".join(map(str, self.release))
|
|
241
454
|
|
|
242
455
|
# Epoch
|
|
243
|
-
if self.epoch
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
# Release segment
|
|
247
|
-
parts.append(".".join(str(x) for x in self.release))
|
|
456
|
+
if self.epoch:
|
|
457
|
+
version = f"{self.epoch}!{version}"
|
|
248
458
|
|
|
249
459
|
# Pre-release
|
|
250
460
|
if self.pre is not None:
|
|
251
|
-
|
|
461
|
+
version += "".join(map(str, self.pre))
|
|
252
462
|
|
|
253
463
|
# Post-release
|
|
254
464
|
if self.post is not None:
|
|
255
|
-
|
|
465
|
+
version += f".post{self.post}"
|
|
256
466
|
|
|
257
467
|
# Development release
|
|
258
468
|
if self.dev is not None:
|
|
259
|
-
|
|
469
|
+
version += f".dev{self.dev}"
|
|
260
470
|
|
|
261
471
|
# Local version segment
|
|
262
472
|
if self.local is not None:
|
|
263
|
-
|
|
473
|
+
version += f"+{self.local}"
|
|
474
|
+
|
|
475
|
+
return version
|
|
264
476
|
|
|
265
|
-
|
|
477
|
+
@property
|
|
478
|
+
def _str(self) -> str:
|
|
479
|
+
"""Internal property for match_args"""
|
|
480
|
+
return str(self)
|
|
266
481
|
|
|
267
482
|
@property
|
|
268
483
|
def epoch(self) -> int:
|
|
@@ -273,7 +488,7 @@ class Version(_BaseVersion):
|
|
|
273
488
|
>>> Version("1!2.0.0").epoch
|
|
274
489
|
1
|
|
275
490
|
"""
|
|
276
|
-
return self.
|
|
491
|
+
return self._epoch
|
|
277
492
|
|
|
278
493
|
@property
|
|
279
494
|
def release(self) -> tuple[int, ...]:
|
|
@@ -289,7 +504,7 @@ class Version(_BaseVersion):
|
|
|
289
504
|
Includes trailing zeroes but not the epoch or any pre-release / development /
|
|
290
505
|
post-release suffixes.
|
|
291
506
|
"""
|
|
292
|
-
return self.
|
|
507
|
+
return self._release
|
|
293
508
|
|
|
294
509
|
@property
|
|
295
510
|
def pre(self) -> tuple[str, int] | None:
|
|
@@ -304,7 +519,7 @@ class Version(_BaseVersion):
|
|
|
304
519
|
>>> Version("1.2.3rc1").pre
|
|
305
520
|
('rc', 1)
|
|
306
521
|
"""
|
|
307
|
-
return self.
|
|
522
|
+
return self._pre
|
|
308
523
|
|
|
309
524
|
@property
|
|
310
525
|
def post(self) -> int | None:
|
|
@@ -315,7 +530,7 @@ class Version(_BaseVersion):
|
|
|
315
530
|
>>> Version("1.2.3.post1").post
|
|
316
531
|
1
|
|
317
532
|
"""
|
|
318
|
-
return self.
|
|
533
|
+
return self._post[1] if self._post else None
|
|
319
534
|
|
|
320
535
|
@property
|
|
321
536
|
def dev(self) -> int | None:
|
|
@@ -326,7 +541,7 @@ class Version(_BaseVersion):
|
|
|
326
541
|
>>> Version("1.2.3.dev1").dev
|
|
327
542
|
1
|
|
328
543
|
"""
|
|
329
|
-
return self.
|
|
544
|
+
return self._dev[1] if self._dev else None
|
|
330
545
|
|
|
331
546
|
@property
|
|
332
547
|
def local(self) -> str | None:
|
|
@@ -337,8 +552,8 @@ class Version(_BaseVersion):
|
|
|
337
552
|
>>> Version("1.2.3+abc").local
|
|
338
553
|
'abc'
|
|
339
554
|
"""
|
|
340
|
-
if self.
|
|
341
|
-
return ".".join(str(x) for x in self.
|
|
555
|
+
if self._local:
|
|
556
|
+
return ".".join(str(x) for x in self._local)
|
|
342
557
|
else:
|
|
343
558
|
return None
|
|
344
559
|
|
|
@@ -369,16 +584,8 @@ class Version(_BaseVersion):
|
|
|
369
584
|
The "base version" is the public version of the project without any pre or post
|
|
370
585
|
release markers.
|
|
371
586
|
"""
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
# Epoch
|
|
375
|
-
if self.epoch != 0:
|
|
376
|
-
parts.append(f"{self.epoch}!")
|
|
377
|
-
|
|
378
|
-
# Release segment
|
|
379
|
-
parts.append(".".join(str(x) for x in self.release))
|
|
380
|
-
|
|
381
|
-
return "".join(parts)
|
|
587
|
+
release_segment = ".".join(map(str, self.release))
|
|
588
|
+
return f"{self.epoch}!{release_segment}" if self.epoch else release_segment
|
|
382
589
|
|
|
383
590
|
@property
|
|
384
591
|
def is_prerelease(self) -> bool:
|
|
@@ -452,6 +659,20 @@ class Version(_BaseVersion):
|
|
|
452
659
|
|
|
453
660
|
|
|
454
661
|
class _TrimmedRelease(Version):
|
|
662
|
+
__slots__ = ()
|
|
663
|
+
|
|
664
|
+
def __init__(self, version: str | Version) -> None:
|
|
665
|
+
if isinstance(version, Version):
|
|
666
|
+
self._epoch = version._epoch
|
|
667
|
+
self._release = version._release
|
|
668
|
+
self._dev = version._dev
|
|
669
|
+
self._pre = version._pre
|
|
670
|
+
self._post = version._post
|
|
671
|
+
self._local = version._local
|
|
672
|
+
self._key_cache = version._key_cache
|
|
673
|
+
return
|
|
674
|
+
super().__init__(version) # pragma: no cover
|
|
675
|
+
|
|
455
676
|
@property
|
|
456
677
|
def release(self) -> tuple[int, ...]:
|
|
457
678
|
"""
|
|
@@ -462,45 +683,35 @@ class _TrimmedRelease(Version):
|
|
|
462
683
|
>>> _TrimmedRelease('0.0').release
|
|
463
684
|
(0,)
|
|
464
685
|
"""
|
|
686
|
+
# This leaves one 0.
|
|
465
687
|
rel = super().release
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
688
|
+
len_release = len(rel)
|
|
689
|
+
i = len_release
|
|
690
|
+
while i > 1 and rel[i - 1] == 0:
|
|
691
|
+
i -= 1
|
|
692
|
+
return rel if i == len_release else rel[:i]
|
|
469
693
|
|
|
470
694
|
|
|
471
695
|
def _parse_letter_version(
|
|
472
696
|
letter: str | None, number: str | bytes | SupportsInt | None
|
|
473
697
|
) -> tuple[str, int] | None:
|
|
474
698
|
if letter:
|
|
475
|
-
# We consider there to be an implicit 0 in a pre-release if there is
|
|
476
|
-
# not a numeral associated with it.
|
|
477
|
-
if number is None:
|
|
478
|
-
number = 0
|
|
479
|
-
|
|
480
699
|
# We normalize any letters to their lower case form
|
|
481
700
|
letter = letter.lower()
|
|
482
701
|
|
|
483
702
|
# We consider some words to be alternate spellings of other words and
|
|
484
703
|
# in those cases we want to normalize the spellings to our preferred
|
|
485
704
|
# spelling.
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
elif letter in ["rev", "r"]:
|
|
493
|
-
letter = "post"
|
|
494
|
-
|
|
495
|
-
return letter, int(number)
|
|
496
|
-
|
|
497
|
-
assert not letter
|
|
705
|
+
letter = _LETTER_NORMALIZATION.get(letter, letter)
|
|
706
|
+
|
|
707
|
+
# We consider there to be an implicit 0 in a pre-release if there is
|
|
708
|
+
# not a numeral associated with it.
|
|
709
|
+
return letter, int(number or 0)
|
|
710
|
+
|
|
498
711
|
if number:
|
|
499
712
|
# We assume if we are given a number, but we are not given a letter
|
|
500
713
|
# then this is using the implicit post release syntax (e.g. 1.0-1)
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
return letter, int(number)
|
|
714
|
+
return "post", int(number)
|
|
504
715
|
|
|
505
716
|
return None
|
|
506
717
|
|
|
@@ -529,13 +740,12 @@ def _cmpkey(
|
|
|
529
740
|
local: LocalType | None,
|
|
530
741
|
) -> CmpKey:
|
|
531
742
|
# When we compare a release version, we want to compare it with all of the
|
|
532
|
-
# trailing zeros removed.
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
)
|
|
743
|
+
# trailing zeros removed. We will use this for our sorting key.
|
|
744
|
+
len_release = len(release)
|
|
745
|
+
i = len_release
|
|
746
|
+
while i and release[i - 1] == 0:
|
|
747
|
+
i -= 1
|
|
748
|
+
_release = release if i == len_release else release[:i]
|
|
539
749
|
|
|
540
750
|
# We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
|
|
541
751
|
# We'll do this by abusing the pre segment, but we _only_ want to do this
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
2
|
+
of this software and associated documentation files (the "Software"), to
|
|
3
|
+
deal in the Software without restriction, including without limitation the
|
|
4
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
5
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
|
6
|
+
furnished to do so, subject to the following conditions:
|
|
7
|
+
|
|
8
|
+
The above copyright notice and this permission notice shall be included in
|
|
9
|
+
all copies or substantial portions of the Software.
|
|
10
|
+
|
|
11
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
12
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
13
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
14
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
15
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
16
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
17
|
+
IN THE SOFTWARE.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2010-202x The platformdirs developers
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
pip/_vendor/platformdirs/api.py
CHANGED
|
@@ -95,7 +95,7 @@ class PlatformDirsABC(ABC): # noqa: PLR0904
|
|
|
95
95
|
def _first_item_as_path_if_multipath(self, directory: str) -> Path:
|
|
96
96
|
if self.multipath:
|
|
97
97
|
# If multipath is True, the first path is returned.
|
|
98
|
-
directory = directory.
|
|
98
|
+
directory = directory.partition(os.pathsep)[0]
|
|
99
99
|
return Path(directory)
|
|
100
100
|
|
|
101
101
|
@property
|