pip 25.1.1__py3-none-any.whl → 25.2__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 +3 -3
- pip/_internal/__init__.py +2 -2
- pip/_internal/build_env.py +118 -94
- pip/_internal/cache.py +16 -14
- pip/_internal/cli/autocompletion.py +13 -4
- pip/_internal/cli/base_command.py +18 -7
- pip/_internal/cli/cmdoptions.py +14 -9
- pip/_internal/cli/command_context.py +4 -3
- pip/_internal/cli/index_command.py +11 -9
- pip/_internal/cli/main.py +3 -2
- pip/_internal/cli/main_parser.py +4 -3
- pip/_internal/cli/parser.py +26 -22
- pip/_internal/cli/progress_bars.py +19 -12
- pip/_internal/cli/req_command.py +16 -12
- pip/_internal/cli/spinners.py +81 -5
- pip/_internal/commands/__init__.py +5 -3
- pip/_internal/commands/cache.py +18 -15
- pip/_internal/commands/check.py +1 -2
- pip/_internal/commands/completion.py +1 -2
- pip/_internal/commands/configuration.py +26 -18
- pip/_internal/commands/debug.py +8 -6
- pip/_internal/commands/download.py +2 -3
- pip/_internal/commands/freeze.py +2 -3
- pip/_internal/commands/hash.py +1 -2
- pip/_internal/commands/help.py +1 -2
- pip/_internal/commands/index.py +15 -9
- pip/_internal/commands/inspect.py +4 -4
- pip/_internal/commands/install.py +44 -39
- pip/_internal/commands/list.py +35 -26
- pip/_internal/commands/lock.py +1 -2
- pip/_internal/commands/search.py +14 -12
- pip/_internal/commands/show.py +14 -11
- pip/_internal/commands/uninstall.py +1 -2
- pip/_internal/commands/wheel.py +2 -3
- pip/_internal/configuration.py +39 -25
- pip/_internal/distributions/base.py +6 -4
- pip/_internal/distributions/installed.py +8 -4
- pip/_internal/distributions/sdist.py +20 -13
- pip/_internal/distributions/wheel.py +6 -4
- pip/_internal/exceptions.py +58 -39
- pip/_internal/index/collector.py +24 -29
- pip/_internal/index/package_finder.py +70 -61
- pip/_internal/index/sources.py +17 -14
- pip/_internal/locations/__init__.py +18 -16
- pip/_internal/locations/_distutils.py +12 -11
- pip/_internal/locations/_sysconfig.py +5 -4
- pip/_internal/locations/base.py +4 -3
- pip/_internal/main.py +2 -2
- pip/_internal/metadata/__init__.py +8 -6
- pip/_internal/metadata/_json.py +5 -4
- pip/_internal/metadata/base.py +22 -27
- pip/_internal/metadata/importlib/_compat.py +6 -4
- pip/_internal/metadata/importlib/_dists.py +12 -17
- pip/_internal/metadata/importlib/_envs.py +9 -6
- pip/_internal/metadata/pkg_resources.py +11 -14
- pip/_internal/models/direct_url.py +24 -21
- pip/_internal/models/format_control.py +5 -5
- pip/_internal/models/installation_report.py +4 -3
- pip/_internal/models/link.py +39 -34
- pip/_internal/models/pylock.py +27 -22
- pip/_internal/models/search_scope.py +6 -7
- pip/_internal/models/selection_prefs.py +3 -3
- pip/_internal/models/target_python.py +10 -9
- pip/_internal/models/wheel.py +7 -5
- pip/_internal/network/auth.py +20 -22
- pip/_internal/network/cache.py +22 -6
- pip/_internal/network/download.py +169 -141
- pip/_internal/network/lazy_wheel.py +10 -7
- pip/_internal/network/session.py +32 -27
- pip/_internal/network/utils.py +2 -2
- pip/_internal/network/xmlrpc.py +2 -2
- pip/_internal/operations/build/build_tracker.py +10 -8
- pip/_internal/operations/build/wheel.py +3 -2
- pip/_internal/operations/build/wheel_editable.py +3 -2
- pip/_internal/operations/build/wheel_legacy.py +9 -8
- pip/_internal/operations/check.py +21 -26
- pip/_internal/operations/freeze.py +12 -9
- pip/_internal/operations/install/editable_legacy.py +5 -3
- pip/_internal/operations/install/wheel.py +49 -41
- pip/_internal/operations/prepare.py +35 -30
- pip/_internal/pyproject.py +7 -10
- pip/_internal/req/__init__.py +12 -10
- pip/_internal/req/constructors.py +33 -31
- pip/_internal/req/req_dependency_group.py +7 -11
- pip/_internal/req/req_file.py +32 -35
- pip/_internal/req/req_install.py +37 -34
- pip/_internal/req/req_set.py +4 -5
- pip/_internal/req/req_uninstall.py +20 -17
- pip/_internal/resolution/base.py +3 -3
- pip/_internal/resolution/legacy/resolver.py +21 -20
- pip/_internal/resolution/resolvelib/base.py +16 -13
- pip/_internal/resolution/resolvelib/candidates.py +29 -26
- pip/_internal/resolution/resolvelib/factory.py +41 -50
- pip/_internal/resolution/resolvelib/found_candidates.py +11 -9
- pip/_internal/resolution/resolvelib/provider.py +15 -20
- pip/_internal/resolution/resolvelib/reporter.py +5 -3
- pip/_internal/resolution/resolvelib/requirements.py +8 -6
- pip/_internal/resolution/resolvelib/resolver.py +39 -23
- pip/_internal/self_outdated_check.py +8 -6
- pip/_internal/utils/appdirs.py +1 -2
- pip/_internal/utils/compat.py +7 -1
- pip/_internal/utils/compatibility_tags.py +17 -16
- pip/_internal/utils/deprecation.py +11 -9
- pip/_internal/utils/direct_url_helpers.py +2 -2
- pip/_internal/utils/egg_link.py +6 -5
- pip/_internal/utils/entrypoints.py +3 -2
- pip/_internal/utils/filesystem.py +8 -5
- pip/_internal/utils/filetypes.py +4 -6
- pip/_internal/utils/glibc.py +6 -5
- pip/_internal/utils/hashes.py +9 -6
- pip/_internal/utils/logging.py +8 -5
- pip/_internal/utils/misc.py +37 -45
- pip/_internal/utils/packaging.py +3 -2
- pip/_internal/utils/retry.py +7 -4
- pip/_internal/utils/setuptools_build.py +12 -10
- pip/_internal/utils/subprocess.py +20 -17
- pip/_internal/utils/temp_dir.py +10 -12
- pip/_internal/utils/unpacking.py +6 -4
- pip/_internal/utils/urls.py +1 -1
- pip/_internal/utils/virtualenv.py +3 -2
- pip/_internal/utils/wheel.py +3 -4
- pip/_internal/vcs/bazaar.py +26 -8
- pip/_internal/vcs/git.py +59 -24
- pip/_internal/vcs/mercurial.py +34 -11
- pip/_internal/vcs/subversion.py +27 -16
- pip/_internal/vcs/versioncontrol.py +56 -51
- pip/_internal/wheel_builder.py +14 -12
- pip/_vendor/cachecontrol/__init__.py +1 -1
- pip/_vendor/certifi/__init__.py +1 -1
- pip/_vendor/certifi/cacert.pem +102 -221
- pip/_vendor/certifi/core.py +1 -32
- pip/_vendor/distlib/__init__.py +2 -2
- pip/_vendor/distlib/scripts.py +1 -1
- pip/_vendor/msgpack/__init__.py +2 -2
- pip/_vendor/pkg_resources/__init__.py +1 -1
- pip/_vendor/platformdirs/version.py +2 -2
- pip/_vendor/pygments/__init__.py +1 -1
- pip/_vendor/requests/__version__.py +2 -2
- pip/_vendor/requests/compat.py +12 -0
- pip/_vendor/requests/models.py +3 -1
- pip/_vendor/requests/utils.py +6 -16
- pip/_vendor/resolvelib/__init__.py +3 -3
- pip/_vendor/resolvelib/reporters.py +1 -1
- pip/_vendor/resolvelib/resolvers/__init__.py +4 -4
- pip/_vendor/resolvelib/resolvers/resolution.py +91 -10
- pip/_vendor/rich/__main__.py +12 -40
- pip/_vendor/rich/_inspect.py +1 -1
- pip/_vendor/rich/_ratio.py +1 -7
- pip/_vendor/rich/align.py +1 -7
- pip/_vendor/rich/box.py +1 -7
- pip/_vendor/rich/console.py +25 -20
- pip/_vendor/rich/control.py +1 -7
- pip/_vendor/rich/diagnose.py +1 -0
- pip/_vendor/rich/emoji.py +1 -6
- pip/_vendor/rich/live.py +32 -7
- pip/_vendor/rich/live_render.py +1 -7
- pip/_vendor/rich/logging.py +1 -1
- pip/_vendor/rich/panel.py +3 -4
- pip/_vendor/rich/progress.py +15 -15
- pip/_vendor/rich/spinner.py +7 -13
- pip/_vendor/rich/syntax.py +24 -5
- pip/_vendor/rich/traceback.py +32 -17
- pip/_vendor/truststore/_api.py +1 -1
- pip/_vendor/vendor.txt +9 -10
- {pip-25.1.1.dist-info → pip-25.2.dist-info}/METADATA +26 -4
- {pip-25.1.1.dist-info → pip-25.2.dist-info}/RECORD +193 -180
- {pip-25.1.1.dist-info → pip-25.2.dist-info}/WHEEL +1 -1
- {pip-25.1.1.dist-info → pip-25.2.dist-info}/licenses/AUTHORS.txt +12 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt +13 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/certifi/LICENSE +20 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/dependency_groups/LICENSE.txt +9 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/distlib/LICENSE.txt +284 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/distro/LICENSE +202 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/idna/LICENSE.md +31 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/msgpack/COPYING +14 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/packaging/LICENSE +3 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.APACHE +177 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.BSD +23 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/pkg_resources/LICENSE +17 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/platformdirs/LICENSE +21 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/pygments/LICENSE +25 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/pyproject_hooks/LICENSE +21 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/requests/LICENSE +175 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/resolvelib/LICENSE +13 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/rich/LICENSE +19 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/tomli/LICENSE +21 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/tomli/LICENSE-HEADER +3 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/tomli_w/LICENSE +21 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/truststore/LICENSE +21 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/urllib3/LICENSE.txt +21 -0
- pip/_vendor/distlib/database.py +0 -1329
- pip/_vendor/distlib/index.py +0 -508
- pip/_vendor/distlib/locators.py +0 -1295
- pip/_vendor/distlib/manifest.py +0 -384
- pip/_vendor/distlib/markers.py +0 -162
- pip/_vendor/distlib/metadata.py +0 -1031
- pip/_vendor/distlib/version.py +0 -750
- pip/_vendor/distlib/wheel.py +0 -1100
- pip/_vendor/typing_extensions.py +0 -4584
- {pip-25.1.1.dist-info → pip-25.2.dist-info}/entry_points.txt +0 -0
- {pip-25.1.1.dist-info → pip-25.2.dist-info}/licenses/LICENSE.txt +0 -0
- {pip-25.1.1.dist-info → pip-25.2.dist-info}/top_level.txt +0 -0
|
@@ -8,12 +8,14 @@ These are meant to be used elsewhere within pip to create instances of
|
|
|
8
8
|
InstallRequirement.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
11
13
|
import copy
|
|
12
14
|
import logging
|
|
13
15
|
import os
|
|
14
16
|
import re
|
|
17
|
+
from collections.abc import Collection
|
|
15
18
|
from dataclasses import dataclass
|
|
16
|
-
from typing import Collection, Dict, List, Optional, Set, Tuple, Union
|
|
17
19
|
|
|
18
20
|
from pip._vendor.packaging.markers import Marker
|
|
19
21
|
from pip._vendor.packaging.requirements import InvalidRequirement, Requirement
|
|
@@ -41,7 +43,7 @@ logger = logging.getLogger(__name__)
|
|
|
41
43
|
operators = Specifier._operators.keys()
|
|
42
44
|
|
|
43
45
|
|
|
44
|
-
def _strip_extras(path: str) ->
|
|
46
|
+
def _strip_extras(path: str) -> tuple[str, str | None]:
|
|
45
47
|
m = re.match(r"^(.+)(\[[^\]]+\])$", path)
|
|
46
48
|
extras = None
|
|
47
49
|
if m:
|
|
@@ -53,19 +55,19 @@ def _strip_extras(path: str) -> Tuple[str, Optional[str]]:
|
|
|
53
55
|
return path_no_extras, extras
|
|
54
56
|
|
|
55
57
|
|
|
56
|
-
def convert_extras(extras:
|
|
58
|
+
def convert_extras(extras: str | None) -> set[str]:
|
|
57
59
|
if not extras:
|
|
58
60
|
return set()
|
|
59
61
|
return get_requirement("placeholder" + extras.lower()).extras
|
|
60
62
|
|
|
61
63
|
|
|
62
|
-
def _set_requirement_extras(req: Requirement, new_extras:
|
|
64
|
+
def _set_requirement_extras(req: Requirement, new_extras: set[str]) -> Requirement:
|
|
63
65
|
"""
|
|
64
66
|
Returns a new requirement based on the given one, with the supplied extras. If the
|
|
65
67
|
given requirement already has extras those are replaced (or dropped if no new extras
|
|
66
68
|
are given).
|
|
67
69
|
"""
|
|
68
|
-
match:
|
|
70
|
+
match: re.Match[str] | None = re.fullmatch(
|
|
69
71
|
# see https://peps.python.org/pep-0508/#complete-grammar
|
|
70
72
|
r"([\w\t .-]+)(\[[^\]]*\])?(.*)",
|
|
71
73
|
str(req),
|
|
@@ -75,8 +77,8 @@ def _set_requirement_extras(req: Requirement, new_extras: Set[str]) -> Requireme
|
|
|
75
77
|
assert (
|
|
76
78
|
match is not None
|
|
77
79
|
), f"regex match on requirement {req} failed, this should never happen"
|
|
78
|
-
pre:
|
|
79
|
-
post:
|
|
80
|
+
pre: str | None = match.group(1)
|
|
81
|
+
post: str | None = match.group(3)
|
|
80
82
|
assert (
|
|
81
83
|
pre is not None and post is not None
|
|
82
84
|
), f"regex group selection for requirement {req} failed, this should never happen"
|
|
@@ -84,7 +86,7 @@ def _set_requirement_extras(req: Requirement, new_extras: Set[str]) -> Requireme
|
|
|
84
86
|
return get_requirement(f"{pre}{extras}{post}")
|
|
85
87
|
|
|
86
88
|
|
|
87
|
-
def parse_editable(editable_req: str) ->
|
|
89
|
+
def parse_editable(editable_req: str) -> tuple[str | None, str, set[str]]:
|
|
88
90
|
"""Parses an editable requirement into:
|
|
89
91
|
- a requirement name
|
|
90
92
|
- an URL
|
|
@@ -194,10 +196,10 @@ def deduce_helpful_msg(req: str) -> str:
|
|
|
194
196
|
|
|
195
197
|
@dataclass(frozen=True)
|
|
196
198
|
class RequirementParts:
|
|
197
|
-
requirement:
|
|
198
|
-
link:
|
|
199
|
-
markers:
|
|
200
|
-
extras:
|
|
199
|
+
requirement: Requirement | None
|
|
200
|
+
link: Link | None
|
|
201
|
+
markers: Marker | None
|
|
202
|
+
extras: set[str]
|
|
201
203
|
|
|
202
204
|
|
|
203
205
|
def parse_req_from_editable(editable_req: str) -> RequirementParts:
|
|
@@ -205,7 +207,7 @@ def parse_req_from_editable(editable_req: str) -> RequirementParts:
|
|
|
205
207
|
|
|
206
208
|
if name is not None:
|
|
207
209
|
try:
|
|
208
|
-
req:
|
|
210
|
+
req: Requirement | None = get_requirement(name)
|
|
209
211
|
except InvalidRequirement as exc:
|
|
210
212
|
raise InstallationError(f"Invalid requirement: {name!r}: {exc}")
|
|
211
213
|
else:
|
|
@@ -221,16 +223,16 @@ def parse_req_from_editable(editable_req: str) -> RequirementParts:
|
|
|
221
223
|
|
|
222
224
|
def install_req_from_editable(
|
|
223
225
|
editable_req: str,
|
|
224
|
-
comes_from:
|
|
226
|
+
comes_from: InstallRequirement | str | None = None,
|
|
225
227
|
*,
|
|
226
|
-
use_pep517:
|
|
228
|
+
use_pep517: bool | None = None,
|
|
227
229
|
isolated: bool = False,
|
|
228
|
-
global_options:
|
|
229
|
-
hash_options:
|
|
230
|
+
global_options: list[str] | None = None,
|
|
231
|
+
hash_options: dict[str, list[str]] | None = None,
|
|
230
232
|
constraint: bool = False,
|
|
231
233
|
user_supplied: bool = False,
|
|
232
234
|
permit_editable_wheels: bool = False,
|
|
233
|
-
config_settings:
|
|
235
|
+
config_settings: dict[str, str | list[str]] | None = None,
|
|
234
236
|
) -> InstallRequirement:
|
|
235
237
|
parts = parse_req_from_editable(editable_req)
|
|
236
238
|
|
|
@@ -270,7 +272,7 @@ def _looks_like_path(name: str) -> bool:
|
|
|
270
272
|
return False
|
|
271
273
|
|
|
272
274
|
|
|
273
|
-
def _get_url_from_path(path: str, name: str) ->
|
|
275
|
+
def _get_url_from_path(path: str, name: str) -> str | None:
|
|
274
276
|
"""
|
|
275
277
|
First, it checks whether a provided path is an installable directory. If it
|
|
276
278
|
is, returns the path.
|
|
@@ -304,7 +306,7 @@ def _get_url_from_path(path: str, name: str) -> Optional[str]:
|
|
|
304
306
|
return path_to_url(path)
|
|
305
307
|
|
|
306
308
|
|
|
307
|
-
def parse_req_from_line(name: str, line_source:
|
|
309
|
+
def parse_req_from_line(name: str, line_source: str | None) -> RequirementParts:
|
|
308
310
|
if is_url(name):
|
|
309
311
|
marker_sep = "; "
|
|
310
312
|
else:
|
|
@@ -376,7 +378,7 @@ def parse_req_from_line(name: str, line_source: Optional[str]) -> RequirementPar
|
|
|
376
378
|
raise InstallationError(msg)
|
|
377
379
|
|
|
378
380
|
if req_as_string is not None:
|
|
379
|
-
req:
|
|
381
|
+
req: Requirement | None = _parse_req_string(req_as_string)
|
|
380
382
|
else:
|
|
381
383
|
req = None
|
|
382
384
|
|
|
@@ -385,16 +387,16 @@ def parse_req_from_line(name: str, line_source: Optional[str]) -> RequirementPar
|
|
|
385
387
|
|
|
386
388
|
def install_req_from_line(
|
|
387
389
|
name: str,
|
|
388
|
-
comes_from:
|
|
390
|
+
comes_from: str | InstallRequirement | None = None,
|
|
389
391
|
*,
|
|
390
|
-
use_pep517:
|
|
392
|
+
use_pep517: bool | None = None,
|
|
391
393
|
isolated: bool = False,
|
|
392
|
-
global_options:
|
|
393
|
-
hash_options:
|
|
394
|
+
global_options: list[str] | None = None,
|
|
395
|
+
hash_options: dict[str, list[str]] | None = None,
|
|
394
396
|
constraint: bool = False,
|
|
395
|
-
line_source:
|
|
397
|
+
line_source: str | None = None,
|
|
396
398
|
user_supplied: bool = False,
|
|
397
|
-
config_settings:
|
|
399
|
+
config_settings: dict[str, str | list[str]] | None = None,
|
|
398
400
|
) -> InstallRequirement:
|
|
399
401
|
"""Creates an InstallRequirement from a name, which might be a
|
|
400
402
|
requirement, directory containing 'setup.py', filename, or URL.
|
|
@@ -422,9 +424,9 @@ def install_req_from_line(
|
|
|
422
424
|
|
|
423
425
|
def install_req_from_req_string(
|
|
424
426
|
req_string: str,
|
|
425
|
-
comes_from:
|
|
427
|
+
comes_from: InstallRequirement | None = None,
|
|
426
428
|
isolated: bool = False,
|
|
427
|
-
use_pep517:
|
|
429
|
+
use_pep517: bool | None = None,
|
|
428
430
|
user_supplied: bool = False,
|
|
429
431
|
) -> InstallRequirement:
|
|
430
432
|
try:
|
|
@@ -461,9 +463,9 @@ def install_req_from_req_string(
|
|
|
461
463
|
def install_req_from_parsed_requirement(
|
|
462
464
|
parsed_req: ParsedRequirement,
|
|
463
465
|
isolated: bool = False,
|
|
464
|
-
use_pep517:
|
|
466
|
+
use_pep517: bool | None = None,
|
|
465
467
|
user_supplied: bool = False,
|
|
466
|
-
config_settings:
|
|
468
|
+
config_settings: dict[str, str | list[str]] | None = None,
|
|
467
469
|
) -> InstallRequirement:
|
|
468
470
|
if parsed_req.is_editable:
|
|
469
471
|
req = install_req_from_editable(
|
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
if sys.version_info >= (3, 11):
|
|
5
|
-
import tomllib
|
|
6
|
-
else:
|
|
7
|
-
from pip._vendor import tomli as tomllib
|
|
1
|
+
from collections.abc import Iterable, Iterator
|
|
2
|
+
from typing import Any
|
|
8
3
|
|
|
9
4
|
from pip._vendor.dependency_groups import DependencyGroupResolver
|
|
10
5
|
|
|
11
6
|
from pip._internal.exceptions import InstallationError
|
|
7
|
+
from pip._internal.utils.compat import tomllib
|
|
12
8
|
|
|
13
9
|
|
|
14
|
-
def parse_dependency_groups(groups:
|
|
10
|
+
def parse_dependency_groups(groups: list[tuple[str, str]]) -> list[str]:
|
|
15
11
|
"""
|
|
16
12
|
Parse dependency groups data as provided via the CLI, in a `[path:]group` syntax.
|
|
17
13
|
|
|
@@ -22,7 +18,7 @@ def parse_dependency_groups(groups: List[Tuple[str, str]]) -> List[str]:
|
|
|
22
18
|
|
|
23
19
|
|
|
24
20
|
def _resolve_all_groups(
|
|
25
|
-
resolvers:
|
|
21
|
+
resolvers: dict[str, DependencyGroupResolver], groups: list[tuple[str, str]]
|
|
26
22
|
) -> Iterator[str]:
|
|
27
23
|
"""
|
|
28
24
|
Run all resolution, converting any error from `DependencyGroupResolver` into
|
|
@@ -39,7 +35,7 @@ def _resolve_all_groups(
|
|
|
39
35
|
) from e
|
|
40
36
|
|
|
41
37
|
|
|
42
|
-
def _build_resolvers(paths: Iterable[str]) ->
|
|
38
|
+
def _build_resolvers(paths: Iterable[str]) -> dict[str, Any]:
|
|
43
39
|
resolvers = {}
|
|
44
40
|
for path in paths:
|
|
45
41
|
if path in resolvers:
|
|
@@ -62,7 +58,7 @@ def _build_resolvers(paths: Iterable[str]) -> Dict[str, Any]:
|
|
|
62
58
|
return resolvers
|
|
63
59
|
|
|
64
60
|
|
|
65
|
-
def _load_pyproject(path: str) ->
|
|
61
|
+
def _load_pyproject(path: str) -> dict[str, Any]:
|
|
66
62
|
"""
|
|
67
63
|
This helper loads a pyproject.toml as TOML.
|
|
68
64
|
|
pip/_internal/req/req_file.py
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Requirements file parsing
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
5
7
|
import codecs
|
|
6
8
|
import locale
|
|
7
9
|
import logging
|
|
@@ -11,19 +13,14 @@ import re
|
|
|
11
13
|
import shlex
|
|
12
14
|
import sys
|
|
13
15
|
import urllib.parse
|
|
16
|
+
from collections.abc import Generator, Iterable
|
|
14
17
|
from dataclasses import dataclass
|
|
15
18
|
from optparse import Values
|
|
16
19
|
from typing import (
|
|
17
20
|
TYPE_CHECKING,
|
|
18
21
|
Any,
|
|
19
22
|
Callable,
|
|
20
|
-
Dict,
|
|
21
|
-
Generator,
|
|
22
|
-
Iterable,
|
|
23
|
-
List,
|
|
24
23
|
NoReturn,
|
|
25
|
-
Optional,
|
|
26
|
-
Tuple,
|
|
27
24
|
)
|
|
28
25
|
|
|
29
26
|
from pip._internal.cli import cmdoptions
|
|
@@ -36,9 +33,9 @@ if TYPE_CHECKING:
|
|
|
36
33
|
|
|
37
34
|
__all__ = ["parse_requirements"]
|
|
38
35
|
|
|
39
|
-
ReqFileLines = Iterable[
|
|
36
|
+
ReqFileLines = Iterable[tuple[int, str]]
|
|
40
37
|
|
|
41
|
-
LineParser = Callable[[str],
|
|
38
|
+
LineParser = Callable[[str], tuple[str, Values]]
|
|
42
39
|
|
|
43
40
|
SCHEME_RE = re.compile(r"^(http|https|file):", re.I)
|
|
44
41
|
COMMENT_RE = re.compile(r"(^|\s+)#.*$")
|
|
@@ -49,7 +46,7 @@ COMMENT_RE = re.compile(r"(^|\s+)#.*$")
|
|
|
49
46
|
# 2013 Edition.
|
|
50
47
|
ENV_VAR_RE = re.compile(r"(?P<var>\$\{(?P<name>[A-Z0-9_]+)\})")
|
|
51
48
|
|
|
52
|
-
SUPPORTED_OPTIONS:
|
|
49
|
+
SUPPORTED_OPTIONS: list[Callable[..., optparse.Option]] = [
|
|
53
50
|
cmdoptions.index_url,
|
|
54
51
|
cmdoptions.extra_index_url,
|
|
55
52
|
cmdoptions.no_index,
|
|
@@ -67,13 +64,13 @@ SUPPORTED_OPTIONS: List[Callable[..., optparse.Option]] = [
|
|
|
67
64
|
]
|
|
68
65
|
|
|
69
66
|
# options to be passed to requirements
|
|
70
|
-
SUPPORTED_OPTIONS_REQ:
|
|
67
|
+
SUPPORTED_OPTIONS_REQ: list[Callable[..., optparse.Option]] = [
|
|
71
68
|
cmdoptions.global_options,
|
|
72
69
|
cmdoptions.hash,
|
|
73
70
|
cmdoptions.config_settings,
|
|
74
71
|
]
|
|
75
72
|
|
|
76
|
-
SUPPORTED_OPTIONS_EDITABLE_REQ:
|
|
73
|
+
SUPPORTED_OPTIONS_EDITABLE_REQ: list[Callable[..., optparse.Option]] = [
|
|
77
74
|
cmdoptions.config_settings,
|
|
78
75
|
]
|
|
79
76
|
|
|
@@ -86,7 +83,7 @@ SUPPORTED_OPTIONS_EDITABLE_REQ_DEST = [
|
|
|
86
83
|
|
|
87
84
|
# order of BOMS is important: codecs.BOM_UTF16_LE is a prefix of codecs.BOM_UTF32_LE
|
|
88
85
|
# so data.startswith(BOM_UTF16_LE) would be true for UTF32_LE data
|
|
89
|
-
BOMS:
|
|
86
|
+
BOMS: list[tuple[bytes, str]] = [
|
|
90
87
|
(codecs.BOM_UTF8, "utf-8"),
|
|
91
88
|
(codecs.BOM_UTF32, "utf-32"),
|
|
92
89
|
(codecs.BOM_UTF32_BE, "utf-32-be"),
|
|
@@ -118,8 +115,8 @@ class ParsedRequirement:
|
|
|
118
115
|
is_editable: bool
|
|
119
116
|
comes_from: str
|
|
120
117
|
constraint: bool
|
|
121
|
-
options:
|
|
122
|
-
line_source:
|
|
118
|
+
options: dict[str, Any] | None
|
|
119
|
+
line_source: str | None
|
|
123
120
|
|
|
124
121
|
|
|
125
122
|
@dataclass(frozen=True)
|
|
@@ -137,7 +134,7 @@ class ParsedLine:
|
|
|
137
134
|
return bool(self.opts.editables)
|
|
138
135
|
|
|
139
136
|
@property
|
|
140
|
-
def requirement(self) ->
|
|
137
|
+
def requirement(self) -> str | None:
|
|
141
138
|
if self.args:
|
|
142
139
|
return self.args
|
|
143
140
|
elif self.is_editable:
|
|
@@ -148,9 +145,9 @@ class ParsedLine:
|
|
|
148
145
|
|
|
149
146
|
def parse_requirements(
|
|
150
147
|
filename: str,
|
|
151
|
-
session:
|
|
152
|
-
finder:
|
|
153
|
-
options:
|
|
148
|
+
session: PipSession,
|
|
149
|
+
finder: PackageFinder | None = None,
|
|
150
|
+
options: optparse.Values | None = None,
|
|
154
151
|
constraint: bool = False,
|
|
155
152
|
) -> Generator[ParsedRequirement, None, None]:
|
|
156
153
|
"""Parse a requirements file and yield ParsedRequirement instances.
|
|
@@ -187,7 +184,7 @@ def preprocess(content: str) -> ReqFileLines:
|
|
|
187
184
|
|
|
188
185
|
def handle_requirement_line(
|
|
189
186
|
line: ParsedLine,
|
|
190
|
-
options:
|
|
187
|
+
options: optparse.Values | None = None,
|
|
191
188
|
) -> ParsedRequirement:
|
|
192
189
|
# preserve for the nested code path
|
|
193
190
|
line_comes_from = "{} {} (line {})".format(
|
|
@@ -223,9 +220,9 @@ def handle_option_line(
|
|
|
223
220
|
opts: Values,
|
|
224
221
|
filename: str,
|
|
225
222
|
lineno: int,
|
|
226
|
-
finder:
|
|
227
|
-
options:
|
|
228
|
-
session:
|
|
223
|
+
finder: PackageFinder | None = None,
|
|
224
|
+
options: optparse.Values | None = None,
|
|
225
|
+
session: PipSession | None = None,
|
|
229
226
|
) -> None:
|
|
230
227
|
if opts.hashes:
|
|
231
228
|
logger.warning(
|
|
@@ -291,10 +288,10 @@ def handle_option_line(
|
|
|
291
288
|
|
|
292
289
|
def handle_line(
|
|
293
290
|
line: ParsedLine,
|
|
294
|
-
options:
|
|
295
|
-
finder:
|
|
296
|
-
session:
|
|
297
|
-
) ->
|
|
291
|
+
options: optparse.Values | None = None,
|
|
292
|
+
finder: PackageFinder | None = None,
|
|
293
|
+
session: PipSession | None = None,
|
|
294
|
+
) -> ParsedRequirement | None:
|
|
298
295
|
"""Handle a single parsed requirements line; This can result in
|
|
299
296
|
creating/yielding requirements, or updating the finder.
|
|
300
297
|
|
|
@@ -336,7 +333,7 @@ def handle_line(
|
|
|
336
333
|
class RequirementsFileParser:
|
|
337
334
|
def __init__(
|
|
338
335
|
self,
|
|
339
|
-
session:
|
|
336
|
+
session: PipSession,
|
|
340
337
|
line_parser: LineParser,
|
|
341
338
|
) -> None:
|
|
342
339
|
self._session = session
|
|
@@ -354,7 +351,7 @@ class RequirementsFileParser:
|
|
|
354
351
|
self,
|
|
355
352
|
filename: str,
|
|
356
353
|
constraint: bool,
|
|
357
|
-
parsed_files_stack:
|
|
354
|
+
parsed_files_stack: list[dict[str, str | None]],
|
|
358
355
|
) -> Generator[ParsedLine, None, None]:
|
|
359
356
|
for line in self._parse_file(filename, constraint):
|
|
360
357
|
if line.requirement is None and (
|
|
@@ -426,8 +423,8 @@ class RequirementsFileParser:
|
|
|
426
423
|
)
|
|
427
424
|
|
|
428
425
|
|
|
429
|
-
def get_line_parser(finder:
|
|
430
|
-
def parse_line(line: str) ->
|
|
426
|
+
def get_line_parser(finder: PackageFinder | None) -> LineParser:
|
|
427
|
+
def parse_line(line: str) -> tuple[str, Values]:
|
|
431
428
|
# Build new parser for each line since it accumulates appendable
|
|
432
429
|
# options.
|
|
433
430
|
parser = build_parser()
|
|
@@ -450,7 +447,7 @@ def get_line_parser(finder: Optional["PackageFinder"]) -> LineParser:
|
|
|
450
447
|
return parse_line
|
|
451
448
|
|
|
452
449
|
|
|
453
|
-
def break_args_options(line: str) ->
|
|
450
|
+
def break_args_options(line: str) -> tuple[str, str]:
|
|
454
451
|
"""Break up the line into an args and options string. We only want to shlex
|
|
455
452
|
(and then optparse) the options, not the args. args can contain markers
|
|
456
453
|
which are corrupted by shlex.
|
|
@@ -459,7 +456,7 @@ def break_args_options(line: str) -> Tuple[str, str]:
|
|
|
459
456
|
args = []
|
|
460
457
|
options = tokens[:]
|
|
461
458
|
for token in tokens:
|
|
462
|
-
if token.startswith("-"
|
|
459
|
+
if token.startswith(("-", "--")):
|
|
463
460
|
break
|
|
464
461
|
else:
|
|
465
462
|
args.append(token)
|
|
@@ -485,7 +482,7 @@ def build_parser() -> optparse.OptionParser:
|
|
|
485
482
|
|
|
486
483
|
# By default optparse sys.exits on parsing errors. We want to wrap
|
|
487
484
|
# that in our own exception.
|
|
488
|
-
def parser_exit(self: Any, msg: str) ->
|
|
485
|
+
def parser_exit(self: Any, msg: str) -> NoReturn:
|
|
489
486
|
raise OptionParsingError(msg)
|
|
490
487
|
|
|
491
488
|
# NOTE: mypy disallows assigning to a method
|
|
@@ -500,7 +497,7 @@ def join_lines(lines_enum: ReqFileLines) -> ReqFileLines:
|
|
|
500
497
|
comments). The joined line takes on the index of the first line.
|
|
501
498
|
"""
|
|
502
499
|
primary_line_number = None
|
|
503
|
-
new_line:
|
|
500
|
+
new_line: list[str] = []
|
|
504
501
|
for line_number, line in lines_enum:
|
|
505
502
|
if not line.endswith("\\") or COMMENT_RE.match(line):
|
|
506
503
|
if COMMENT_RE.match(line):
|
|
@@ -564,7 +561,7 @@ def expand_env_variables(lines_enum: ReqFileLines) -> ReqFileLines:
|
|
|
564
561
|
yield line_number, line
|
|
565
562
|
|
|
566
563
|
|
|
567
|
-
def get_file_content(url: str, session:
|
|
564
|
+
def get_file_content(url: str, session: PipSession) -> tuple[str, str]:
|
|
568
565
|
"""Gets the content of a file; it may be a filename, file: URL, or
|
|
569
566
|
http: URL. Returns (location, content). Content is unicode.
|
|
570
567
|
Respects # -*- coding: declarations on the retrieved files.
|
pip/_internal/req/req_install.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import functools
|
|
2
4
|
import logging
|
|
3
5
|
import os
|
|
@@ -5,9 +7,10 @@ import shutil
|
|
|
5
7
|
import sys
|
|
6
8
|
import uuid
|
|
7
9
|
import zipfile
|
|
10
|
+
from collections.abc import Collection, Iterable, Sequence
|
|
8
11
|
from optparse import Values
|
|
9
12
|
from pathlib import Path
|
|
10
|
-
from typing import Any
|
|
13
|
+
from typing import Any
|
|
11
14
|
|
|
12
15
|
from pip._vendor.packaging.markers import Marker
|
|
13
16
|
from pip._vendor.packaging.requirements import Requirement
|
|
@@ -71,17 +74,17 @@ class InstallRequirement:
|
|
|
71
74
|
|
|
72
75
|
def __init__(
|
|
73
76
|
self,
|
|
74
|
-
req:
|
|
75
|
-
comes_from:
|
|
77
|
+
req: Requirement | None,
|
|
78
|
+
comes_from: str | InstallRequirement | None,
|
|
76
79
|
editable: bool = False,
|
|
77
|
-
link:
|
|
78
|
-
markers:
|
|
79
|
-
use_pep517:
|
|
80
|
+
link: Link | None = None,
|
|
81
|
+
markers: Marker | None = None,
|
|
82
|
+
use_pep517: bool | None = None,
|
|
80
83
|
isolated: bool = False,
|
|
81
84
|
*,
|
|
82
|
-
global_options:
|
|
83
|
-
hash_options:
|
|
84
|
-
config_settings:
|
|
85
|
+
global_options: list[str] | None = None,
|
|
86
|
+
hash_options: dict[str, list[str]] | None = None,
|
|
87
|
+
config_settings: dict[str, str | list[str]] | None = None,
|
|
85
88
|
constraint: bool = False,
|
|
86
89
|
extras: Collection[str] = (),
|
|
87
90
|
user_supplied: bool = False,
|
|
@@ -99,7 +102,7 @@ class InstallRequirement:
|
|
|
99
102
|
# populating source_dir is done by the RequirementPreparer. Note this
|
|
100
103
|
# is not necessarily the directory where pyproject.toml or setup.py is
|
|
101
104
|
# located - that one is obtained via unpacked_source_directory.
|
|
102
|
-
self.source_dir:
|
|
105
|
+
self.source_dir: str | None = None
|
|
103
106
|
if self.editable:
|
|
104
107
|
assert link
|
|
105
108
|
if link.is_file:
|
|
@@ -115,14 +118,14 @@ class InstallRequirement:
|
|
|
115
118
|
# When this InstallRequirement is a wheel obtained from the cache of locally
|
|
116
119
|
# built wheels, this is the source link corresponding to the cache entry, which
|
|
117
120
|
# was used to download and build the cached wheel.
|
|
118
|
-
self.cached_wheel_source_link:
|
|
121
|
+
self.cached_wheel_source_link: Link | None = None
|
|
119
122
|
|
|
120
123
|
# Information about the location of the artifact that was downloaded . This
|
|
121
124
|
# property is guaranteed to be set in resolver results.
|
|
122
|
-
self.download_info:
|
|
125
|
+
self.download_info: DirectUrl | None = None
|
|
123
126
|
|
|
124
127
|
# Path to any downloaded or already-existing package.
|
|
125
|
-
self.local_file_path:
|
|
128
|
+
self.local_file_path: str | None = None
|
|
126
129
|
if self.link and self.link.is_file:
|
|
127
130
|
self.local_file_path = self.link.file_path
|
|
128
131
|
|
|
@@ -137,14 +140,14 @@ class InstallRequirement:
|
|
|
137
140
|
self.markers = markers
|
|
138
141
|
|
|
139
142
|
# This holds the Distribution object if this requirement is already installed.
|
|
140
|
-
self.satisfied_by:
|
|
143
|
+
self.satisfied_by: BaseDistribution | None = None
|
|
141
144
|
# Whether the installation process should try to uninstall an existing
|
|
142
145
|
# distribution before installing this requirement.
|
|
143
146
|
self.should_reinstall = False
|
|
144
147
|
# Temporary build location
|
|
145
|
-
self._temp_build_dir:
|
|
148
|
+
self._temp_build_dir: TempDirectory | None = None
|
|
146
149
|
# Set to True after successful installation
|
|
147
|
-
self.install_succeeded:
|
|
150
|
+
self.install_succeeded: bool | None = None
|
|
148
151
|
# Supplied options
|
|
149
152
|
self.global_options = global_options if global_options else []
|
|
150
153
|
self.hash_options = hash_options if hash_options else {}
|
|
@@ -163,16 +166,16 @@ class InstallRequirement:
|
|
|
163
166
|
# gets stored. We need this to pass to build_wheel, so the backend
|
|
164
167
|
# can ensure that the wheel matches the metadata (see the PEP for
|
|
165
168
|
# details).
|
|
166
|
-
self.metadata_directory:
|
|
169
|
+
self.metadata_directory: str | None = None
|
|
167
170
|
|
|
168
171
|
# The static build requirements (from pyproject.toml)
|
|
169
|
-
self.pyproject_requires:
|
|
172
|
+
self.pyproject_requires: list[str] | None = None
|
|
170
173
|
|
|
171
174
|
# Build requirements that we will check are available
|
|
172
|
-
self.requirements_to_check:
|
|
175
|
+
self.requirements_to_check: list[str] = []
|
|
173
176
|
|
|
174
177
|
# The PEP 517 backend we should use to build the project
|
|
175
|
-
self.pep517_backend:
|
|
178
|
+
self.pep517_backend: BuildBackendHookCaller | None = None
|
|
176
179
|
|
|
177
180
|
# Are we using PEP 517 for this requirement?
|
|
178
181
|
# After pyproject.toml has been loaded, the only valid values are True
|
|
@@ -195,7 +198,7 @@ class InstallRequirement:
|
|
|
195
198
|
self.needs_more_preparation = False
|
|
196
199
|
|
|
197
200
|
# This requirement needs to be unpacked before it can be installed.
|
|
198
|
-
self._archive_source:
|
|
201
|
+
self._archive_source: Path | None = None
|
|
199
202
|
|
|
200
203
|
def __str__(self) -> str:
|
|
201
204
|
if self.req:
|
|
@@ -214,7 +217,7 @@ class InstallRequirement:
|
|
|
214
217
|
s += f" in {location}"
|
|
215
218
|
if self.comes_from:
|
|
216
219
|
if isinstance(self.comes_from, str):
|
|
217
|
-
comes_from:
|
|
220
|
+
comes_from: str | None = self.comes_from
|
|
218
221
|
else:
|
|
219
222
|
comes_from = self.comes_from.from_path()
|
|
220
223
|
if comes_from:
|
|
@@ -240,7 +243,7 @@ class InstallRequirement:
|
|
|
240
243
|
|
|
241
244
|
# Things that are valid for all kinds of requirements?
|
|
242
245
|
@property
|
|
243
|
-
def name(self) ->
|
|
246
|
+
def name(self) -> str | None:
|
|
244
247
|
if self.req is None:
|
|
245
248
|
return None
|
|
246
249
|
return self.req.name
|
|
@@ -277,7 +280,7 @@ class InstallRequirement:
|
|
|
277
280
|
specifiers = self.req.specifier
|
|
278
281
|
return len(specifiers) == 1 and next(iter(specifiers)).operator in {"==", "==="}
|
|
279
282
|
|
|
280
|
-
def match_markers(self, extras_requested:
|
|
283
|
+
def match_markers(self, extras_requested: Iterable[str] | None = None) -> bool:
|
|
281
284
|
if not extras_requested:
|
|
282
285
|
# Provide an extra to safely evaluate the markers
|
|
283
286
|
# without matching any extra
|
|
@@ -326,13 +329,13 @@ class InstallRequirement:
|
|
|
326
329
|
good_hashes.setdefault(link.hash_name, []).append(link.hash)
|
|
327
330
|
return Hashes(good_hashes)
|
|
328
331
|
|
|
329
|
-
def from_path(self) ->
|
|
332
|
+
def from_path(self) -> str | None:
|
|
330
333
|
"""Format a nice indicator to show where this "comes from" """
|
|
331
334
|
if self.req is None:
|
|
332
335
|
return None
|
|
333
336
|
s = str(self.req)
|
|
334
337
|
if self.comes_from:
|
|
335
|
-
comes_from:
|
|
338
|
+
comes_from: str | None
|
|
336
339
|
if isinstance(self.comes_from, str):
|
|
337
340
|
comes_from = self.comes_from
|
|
338
341
|
else:
|
|
@@ -699,7 +702,7 @@ class InstallRequirement:
|
|
|
699
702
|
# Top-level Actions
|
|
700
703
|
def uninstall(
|
|
701
704
|
self, auto_confirm: bool = False, verbose: bool = False
|
|
702
|
-
) ->
|
|
705
|
+
) -> UninstallPathSet | None:
|
|
703
706
|
"""
|
|
704
707
|
Uninstall the distribution currently satisfying this requirement.
|
|
705
708
|
|
|
@@ -737,7 +740,7 @@ class InstallRequirement:
|
|
|
737
740
|
name = _clean_zip_name(path, rootdir)
|
|
738
741
|
return self.req.name + "/" + name
|
|
739
742
|
|
|
740
|
-
def archive(self, build_dir:
|
|
743
|
+
def archive(self, build_dir: str | None) -> None:
|
|
741
744
|
"""Saves archive to provided build_dir.
|
|
742
745
|
|
|
743
746
|
Used for saving downloaded VCS requirements as part of `pip download`.
|
|
@@ -806,10 +809,10 @@ class InstallRequirement:
|
|
|
806
809
|
|
|
807
810
|
def install(
|
|
808
811
|
self,
|
|
809
|
-
global_options:
|
|
810
|
-
root:
|
|
811
|
-
home:
|
|
812
|
-
prefix:
|
|
812
|
+
global_options: Sequence[str] | None = None,
|
|
813
|
+
root: str | None = None,
|
|
814
|
+
home: str | None = None,
|
|
815
|
+
prefix: str | None = None,
|
|
813
816
|
warn_script_location: bool = True,
|
|
814
817
|
use_user_site: bool = False,
|
|
815
818
|
pycompile: bool = True,
|
|
@@ -905,7 +908,7 @@ def check_invalid_constraint_type(req: InstallRequirement) -> str:
|
|
|
905
908
|
return problem
|
|
906
909
|
|
|
907
910
|
|
|
908
|
-
def _has_option(options: Values, reqs:
|
|
911
|
+
def _has_option(options: Values, reqs: list[InstallRequirement], option: str) -> bool:
|
|
909
912
|
if getattr(options, option, None):
|
|
910
913
|
return True
|
|
911
914
|
for req in reqs:
|
|
@@ -916,7 +919,7 @@ def _has_option(options: Values, reqs: List[InstallRequirement], option: str) ->
|
|
|
916
919
|
|
|
917
920
|
def check_legacy_setup_py_options(
|
|
918
921
|
options: Values,
|
|
919
|
-
reqs:
|
|
922
|
+
reqs: list[InstallRequirement],
|
|
920
923
|
) -> None:
|
|
921
924
|
has_build_options = _has_option(options, reqs, "build_options")
|
|
922
925
|
has_global_options = _has_option(options, reqs, "global_options")
|