pip 25.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 +45 -40
- 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 +53 -44
- 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 +9 -8
- 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 +54 -44
- 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/dependency_groups/_implementation.py +7 -11
- 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 +10 -11
- {pip-25.1.dist-info → pip-25.2.dist-info}/METADATA +26 -4
- {pip-25.1.dist-info → pip-25.2.dist-info}/RECORD +194 -181
- {pip-25.1.dist-info → pip-25.2.dist-info}/WHEEL +1 -1
- {pip-25.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.dist-info → pip-25.2.dist-info}/entry_points.txt +0 -0
- {pip-25.1.dist-info → pip-25.2.dist-info}/licenses/LICENSE.txt +0 -0
- {pip-25.1.dist-info → pip-25.2.dist-info}/top_level.txt +0 -0
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import logging
|
|
2
|
-
from
|
|
4
|
+
from collections.abc import Iterable
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
3
6
|
|
|
4
7
|
from pip._internal.build_env import BuildEnvironment
|
|
5
8
|
from pip._internal.distributions.base import AbstractDistribution
|
|
@@ -8,7 +11,7 @@ from pip._internal.metadata import BaseDistribution
|
|
|
8
11
|
from pip._internal.utils.subprocess import runner_with_spinner_message
|
|
9
12
|
|
|
10
13
|
if TYPE_CHECKING:
|
|
11
|
-
from pip._internal.
|
|
14
|
+
from pip._internal.build_env import BuildEnvironmentInstaller
|
|
12
15
|
|
|
13
16
|
logger = logging.getLogger(__name__)
|
|
14
17
|
|
|
@@ -21,7 +24,7 @@ class SourceDistribution(AbstractDistribution):
|
|
|
21
24
|
"""
|
|
22
25
|
|
|
23
26
|
@property
|
|
24
|
-
def build_tracker_id(self) ->
|
|
27
|
+
def build_tracker_id(self) -> str | None:
|
|
25
28
|
"""Identify this requirement uniquely by its link."""
|
|
26
29
|
assert self.req.link
|
|
27
30
|
return self.req.link.url_without_fragment
|
|
@@ -31,7 +34,7 @@ class SourceDistribution(AbstractDistribution):
|
|
|
31
34
|
|
|
32
35
|
def prepare_distribution_metadata(
|
|
33
36
|
self,
|
|
34
|
-
|
|
37
|
+
build_env_installer: BuildEnvironmentInstaller,
|
|
35
38
|
build_isolation: bool,
|
|
36
39
|
check_build_deps: bool,
|
|
37
40
|
) -> None:
|
|
@@ -43,7 +46,7 @@ class SourceDistribution(AbstractDistribution):
|
|
|
43
46
|
if should_isolate:
|
|
44
47
|
# Setup an isolated environment and install the build backend static
|
|
45
48
|
# requirements in it.
|
|
46
|
-
self._prepare_build_backend(
|
|
49
|
+
self._prepare_build_backend(build_env_installer)
|
|
47
50
|
# Check that if the requirement is editable, it either supports PEP 660 or
|
|
48
51
|
# has a setup.py or a setup.cfg. This cannot be done earlier because we need
|
|
49
52
|
# to setup the build backend to verify it supports build_editable, nor can
|
|
@@ -53,7 +56,7 @@ class SourceDistribution(AbstractDistribution):
|
|
|
53
56
|
# without setup.py nor setup.cfg.
|
|
54
57
|
self.req.isolated_editable_sanity_check()
|
|
55
58
|
# Install the dynamic build requirements.
|
|
56
|
-
self._install_build_reqs(
|
|
59
|
+
self._install_build_reqs(build_env_installer)
|
|
57
60
|
# Check if the current environment provides build dependencies
|
|
58
61
|
should_check_deps = self.req.use_pep517 and check_build_deps
|
|
59
62
|
if should_check_deps:
|
|
@@ -68,15 +71,17 @@ class SourceDistribution(AbstractDistribution):
|
|
|
68
71
|
self._raise_missing_reqs(missing)
|
|
69
72
|
self.req.prepare_metadata()
|
|
70
73
|
|
|
71
|
-
def _prepare_build_backend(
|
|
74
|
+
def _prepare_build_backend(
|
|
75
|
+
self, build_env_installer: BuildEnvironmentInstaller
|
|
76
|
+
) -> None:
|
|
72
77
|
# Isolate in a BuildEnvironment and install the build-time
|
|
73
78
|
# requirements.
|
|
74
79
|
pyproject_requires = self.req.pyproject_requires
|
|
75
80
|
assert pyproject_requires is not None
|
|
76
81
|
|
|
77
|
-
self.req.build_env = BuildEnvironment()
|
|
82
|
+
self.req.build_env = BuildEnvironment(build_env_installer)
|
|
78
83
|
self.req.build_env.install_requirements(
|
|
79
|
-
|
|
84
|
+
pyproject_requires, "overlay", kind="build dependencies", for_req=self.req
|
|
80
85
|
)
|
|
81
86
|
conflicting, missing = self.req.build_env.check_requirements(
|
|
82
87
|
self.req.requirements_to_check
|
|
@@ -112,7 +117,9 @@ class SourceDistribution(AbstractDistribution):
|
|
|
112
117
|
with backend.subprocess_runner(runner):
|
|
113
118
|
return backend.get_requires_for_build_editable()
|
|
114
119
|
|
|
115
|
-
def _install_build_reqs(
|
|
120
|
+
def _install_build_reqs(
|
|
121
|
+
self, build_env_installer: BuildEnvironmentInstaller
|
|
122
|
+
) -> None:
|
|
116
123
|
# Install any extra build dependencies that the backend requests.
|
|
117
124
|
# This must be done in a second pass, as the pyproject.toml
|
|
118
125
|
# dependencies must be installed before we can call the backend.
|
|
@@ -128,11 +135,11 @@ class SourceDistribution(AbstractDistribution):
|
|
|
128
135
|
if conflicting:
|
|
129
136
|
self._raise_conflicts("the backend dependencies", conflicting)
|
|
130
137
|
self.req.build_env.install_requirements(
|
|
131
|
-
|
|
138
|
+
missing, "normal", kind="backend dependencies", for_req=self.req
|
|
132
139
|
)
|
|
133
140
|
|
|
134
141
|
def _raise_conflicts(
|
|
135
|
-
self, conflicting_with: str, conflicting_reqs:
|
|
142
|
+
self, conflicting_with: str, conflicting_reqs: set[tuple[str, str]]
|
|
136
143
|
) -> None:
|
|
137
144
|
format_string = (
|
|
138
145
|
"Some build dependencies for {requirement} "
|
|
@@ -148,7 +155,7 @@ class SourceDistribution(AbstractDistribution):
|
|
|
148
155
|
)
|
|
149
156
|
raise InstallationError(error_message)
|
|
150
157
|
|
|
151
|
-
def _raise_missing_reqs(self, missing:
|
|
158
|
+
def _raise_missing_reqs(self, missing: set[str]) -> None:
|
|
152
159
|
format_string = (
|
|
153
160
|
"Some build dependencies for {requirement} are missing: {missing}."
|
|
154
161
|
)
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
from
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
2
4
|
|
|
3
5
|
from pip._vendor.packaging.utils import canonicalize_name
|
|
4
6
|
|
|
@@ -10,7 +12,7 @@ from pip._internal.metadata import (
|
|
|
10
12
|
)
|
|
11
13
|
|
|
12
14
|
if TYPE_CHECKING:
|
|
13
|
-
from pip._internal.
|
|
15
|
+
from pip._internal.build_env import BuildEnvironmentInstaller
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
class WheelDistribution(AbstractDistribution):
|
|
@@ -20,7 +22,7 @@ class WheelDistribution(AbstractDistribution):
|
|
|
20
22
|
"""
|
|
21
23
|
|
|
22
24
|
@property
|
|
23
|
-
def build_tracker_id(self) ->
|
|
25
|
+
def build_tracker_id(self) -> str | None:
|
|
24
26
|
return None
|
|
25
27
|
|
|
26
28
|
def get_metadata_distribution(self) -> BaseDistribution:
|
|
@@ -35,7 +37,7 @@ class WheelDistribution(AbstractDistribution):
|
|
|
35
37
|
|
|
36
38
|
def prepare_distribution_metadata(
|
|
37
39
|
self,
|
|
38
|
-
|
|
40
|
+
build_env_installer: BuildEnvironmentInstaller,
|
|
39
41
|
build_isolation: bool,
|
|
40
42
|
check_build_deps: bool,
|
|
41
43
|
) -> None:
|
pip/_internal/exceptions.py
CHANGED
|
@@ -5,6 +5,8 @@ operate. This is expected to be importable from any/all files within the
|
|
|
5
5
|
subpackage and, thus, should not depend on them.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
8
10
|
import configparser
|
|
9
11
|
import contextlib
|
|
10
12
|
import locale
|
|
@@ -12,8 +14,9 @@ import logging
|
|
|
12
14
|
import pathlib
|
|
13
15
|
import re
|
|
14
16
|
import sys
|
|
17
|
+
from collections.abc import Iterator
|
|
15
18
|
from itertools import chain, groupby, repeat
|
|
16
|
-
from typing import TYPE_CHECKING,
|
|
19
|
+
from typing import TYPE_CHECKING, Literal
|
|
17
20
|
|
|
18
21
|
from pip._vendor.packaging.requirements import InvalidRequirement
|
|
19
22
|
from pip._vendor.packaging.version import InvalidVersion
|
|
@@ -27,7 +30,7 @@ if TYPE_CHECKING:
|
|
|
27
30
|
from pip._vendor.requests.models import Request, Response
|
|
28
31
|
|
|
29
32
|
from pip._internal.metadata import BaseDistribution
|
|
30
|
-
from pip._internal.
|
|
33
|
+
from pip._internal.network.download import _FileDownload
|
|
31
34
|
from pip._internal.req.req_install import InstallRequirement
|
|
32
35
|
|
|
33
36
|
logger = logging.getLogger(__name__)
|
|
@@ -41,7 +44,7 @@ def _is_kebab_case(s: str) -> bool:
|
|
|
41
44
|
|
|
42
45
|
|
|
43
46
|
def _prefix_with_indent(
|
|
44
|
-
s:
|
|
47
|
+
s: Text | str,
|
|
45
48
|
console: Console,
|
|
46
49
|
*,
|
|
47
50
|
prefix: str,
|
|
@@ -77,13 +80,13 @@ class DiagnosticPipError(PipError):
|
|
|
77
80
|
def __init__(
|
|
78
81
|
self,
|
|
79
82
|
*,
|
|
80
|
-
kind:
|
|
81
|
-
reference:
|
|
82
|
-
message:
|
|
83
|
-
context:
|
|
84
|
-
hint_stmt:
|
|
85
|
-
note_stmt:
|
|
86
|
-
link:
|
|
83
|
+
kind: Literal["error", "warning"] = "error",
|
|
84
|
+
reference: str | None = None,
|
|
85
|
+
message: str | Text,
|
|
86
|
+
context: str | Text | None,
|
|
87
|
+
hint_stmt: str | Text | None,
|
|
88
|
+
note_stmt: str | Text | None = None,
|
|
89
|
+
link: str | None = None,
|
|
87
90
|
) -> None:
|
|
88
91
|
# Ensure a proper reference is provided.
|
|
89
92
|
if reference is None:
|
|
@@ -232,7 +235,7 @@ class NoneMetadataError(PipError):
|
|
|
232
235
|
|
|
233
236
|
def __init__(
|
|
234
237
|
self,
|
|
235
|
-
dist:
|
|
238
|
+
dist: BaseDistribution,
|
|
236
239
|
metadata_name: str,
|
|
237
240
|
) -> None:
|
|
238
241
|
"""
|
|
@@ -293,8 +296,8 @@ class NetworkConnectionError(PipError):
|
|
|
293
296
|
def __init__(
|
|
294
297
|
self,
|
|
295
298
|
error_msg: str,
|
|
296
|
-
response:
|
|
297
|
-
request:
|
|
299
|
+
response: Response | None = None,
|
|
300
|
+
request: Request | None = None,
|
|
298
301
|
) -> None:
|
|
299
302
|
"""
|
|
300
303
|
Initialize NetworkConnectionError with `request` and `response`
|
|
@@ -343,7 +346,7 @@ class MetadataInconsistent(InstallationError):
|
|
|
343
346
|
"""
|
|
344
347
|
|
|
345
348
|
def __init__(
|
|
346
|
-
self, ireq:
|
|
349
|
+
self, ireq: InstallRequirement, field: str, f_val: str, m_val: str
|
|
347
350
|
) -> None:
|
|
348
351
|
self.ireq = ireq
|
|
349
352
|
self.field = field
|
|
@@ -360,7 +363,7 @@ class MetadataInconsistent(InstallationError):
|
|
|
360
363
|
class MetadataInvalid(InstallationError):
|
|
361
364
|
"""Metadata is invalid."""
|
|
362
365
|
|
|
363
|
-
def __init__(self, ireq:
|
|
366
|
+
def __init__(self, ireq: InstallRequirement, error: str) -> None:
|
|
364
367
|
self.ireq = ireq
|
|
365
368
|
self.error = error
|
|
366
369
|
|
|
@@ -378,7 +381,7 @@ class InstallationSubprocessError(DiagnosticPipError, InstallationError):
|
|
|
378
381
|
*,
|
|
379
382
|
command_description: str,
|
|
380
383
|
exit_code: int,
|
|
381
|
-
output_lines:
|
|
384
|
+
output_lines: list[str] | None,
|
|
382
385
|
) -> None:
|
|
383
386
|
if output_lines is None:
|
|
384
387
|
output_prompt = Text("See above for output.")
|
|
@@ -432,9 +435,9 @@ class HashErrors(InstallationError):
|
|
|
432
435
|
"""Multiple HashError instances rolled into one for reporting"""
|
|
433
436
|
|
|
434
437
|
def __init__(self) -> None:
|
|
435
|
-
self.errors:
|
|
438
|
+
self.errors: list[HashError] = []
|
|
436
439
|
|
|
437
|
-
def append(self, error:
|
|
440
|
+
def append(self, error: HashError) -> None:
|
|
438
441
|
self.errors.append(error)
|
|
439
442
|
|
|
440
443
|
def __str__(self) -> str:
|
|
@@ -468,7 +471,7 @@ class HashError(InstallationError):
|
|
|
468
471
|
|
|
469
472
|
"""
|
|
470
473
|
|
|
471
|
-
req:
|
|
474
|
+
req: InstallRequirement | None = None
|
|
472
475
|
head = ""
|
|
473
476
|
order: int = -1
|
|
474
477
|
|
|
@@ -590,7 +593,7 @@ class HashMismatch(HashError):
|
|
|
590
593
|
"someone may have tampered with them."
|
|
591
594
|
)
|
|
592
595
|
|
|
593
|
-
def __init__(self, allowed:
|
|
596
|
+
def __init__(self, allowed: dict[str, list[str]], gots: dict[str, _Hash]) -> None:
|
|
594
597
|
"""
|
|
595
598
|
:param allowed: A dict of algorithm names pointing to lists of allowed
|
|
596
599
|
hex digests
|
|
@@ -615,12 +618,12 @@ class HashMismatch(HashError):
|
|
|
615
618
|
|
|
616
619
|
"""
|
|
617
620
|
|
|
618
|
-
def hash_then_or(hash_name: str) ->
|
|
621
|
+
def hash_then_or(hash_name: str) -> chain[str]:
|
|
619
622
|
# For now, all the decent hashes have 6-char names, so we can get
|
|
620
623
|
# away with hard-coding space literals.
|
|
621
624
|
return chain([hash_name], repeat(" or"))
|
|
622
625
|
|
|
623
|
-
lines:
|
|
626
|
+
lines: list[str] = []
|
|
624
627
|
for hash_name, expecteds in self.allowed.items():
|
|
625
628
|
prefix = hash_then_or(hash_name)
|
|
626
629
|
lines.extend((f" Expected {next(prefix)} {e}") for e in expecteds)
|
|
@@ -641,8 +644,8 @@ class ConfigurationFileCouldNotBeLoaded(ConfigurationError):
|
|
|
641
644
|
def __init__(
|
|
642
645
|
self,
|
|
643
646
|
reason: str = "could not be loaded",
|
|
644
|
-
fname:
|
|
645
|
-
error:
|
|
647
|
+
fname: str | None = None,
|
|
648
|
+
error: configparser.Error | None = None,
|
|
646
649
|
) -> None:
|
|
647
650
|
super().__init__(error)
|
|
648
651
|
self.reason = reason
|
|
@@ -677,7 +680,7 @@ class ExternallyManagedEnvironment(DiagnosticPipError):
|
|
|
677
680
|
|
|
678
681
|
reference = "externally-managed-environment"
|
|
679
682
|
|
|
680
|
-
def __init__(self, error:
|
|
683
|
+
def __init__(self, error: str | None) -> None:
|
|
681
684
|
if error is None:
|
|
682
685
|
context = Text(_DEFAULT_EXTERNALLY_MANAGED_ERROR)
|
|
683
686
|
else:
|
|
@@ -704,7 +707,7 @@ class ExternallyManagedEnvironment(DiagnosticPipError):
|
|
|
704
707
|
try:
|
|
705
708
|
category = locale.LC_MESSAGES
|
|
706
709
|
except AttributeError:
|
|
707
|
-
lang:
|
|
710
|
+
lang: str | None = None
|
|
708
711
|
else:
|
|
709
712
|
lang, _ = locale.getlocale(category)
|
|
710
713
|
if lang is not None:
|
|
@@ -719,8 +722,8 @@ class ExternallyManagedEnvironment(DiagnosticPipError):
|
|
|
719
722
|
@classmethod
|
|
720
723
|
def from_config(
|
|
721
724
|
cls,
|
|
722
|
-
config:
|
|
723
|
-
) ->
|
|
725
|
+
config: pathlib.Path | str,
|
|
726
|
+
) -> ExternallyManagedEnvironment:
|
|
724
727
|
parser = configparser.ConfigParser(interpolation=None)
|
|
725
728
|
try:
|
|
726
729
|
parser.read(config, encoding="utf-8")
|
|
@@ -741,7 +744,7 @@ class ExternallyManagedEnvironment(DiagnosticPipError):
|
|
|
741
744
|
class UninstallMissingRecord(DiagnosticPipError):
|
|
742
745
|
reference = "uninstall-no-record-file"
|
|
743
746
|
|
|
744
|
-
def __init__(self, *, distribution:
|
|
747
|
+
def __init__(self, *, distribution: BaseDistribution) -> None:
|
|
745
748
|
installer = distribution.installer
|
|
746
749
|
if not installer or installer == "pip":
|
|
747
750
|
dep = f"{distribution.raw_name}=={distribution.version}"
|
|
@@ -768,7 +771,7 @@ class UninstallMissingRecord(DiagnosticPipError):
|
|
|
768
771
|
class LegacyDistutilsInstall(DiagnosticPipError):
|
|
769
772
|
reference = "uninstall-distutils-installed-package"
|
|
770
773
|
|
|
771
|
-
def __init__(self, *, distribution:
|
|
774
|
+
def __init__(self, *, distribution: BaseDistribution) -> None:
|
|
772
775
|
super().__init__(
|
|
773
776
|
message=Text(f"Cannot uninstall {distribution}"),
|
|
774
777
|
context=(
|
|
@@ -786,8 +789,8 @@ class InvalidInstalledPackage(DiagnosticPipError):
|
|
|
786
789
|
def __init__(
|
|
787
790
|
self,
|
|
788
791
|
*,
|
|
789
|
-
dist:
|
|
790
|
-
invalid_exc:
|
|
792
|
+
dist: BaseDistribution,
|
|
793
|
+
invalid_exc: InvalidRequirement | InvalidVersion,
|
|
791
794
|
) -> None:
|
|
792
795
|
installed_location = dist.installed_location
|
|
793
796
|
|
|
@@ -816,17 +819,19 @@ class IncompleteDownloadError(DiagnosticPipError):
|
|
|
816
819
|
|
|
817
820
|
reference = "incomplete-download"
|
|
818
821
|
|
|
819
|
-
def __init__(
|
|
820
|
-
self, link: "Link", received: int, expected: int, *, retries: int
|
|
821
|
-
) -> None:
|
|
822
|
+
def __init__(self, download: _FileDownload) -> None:
|
|
822
823
|
# Dodge circular import.
|
|
823
824
|
from pip._internal.utils.misc import format_size
|
|
824
825
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
826
|
+
assert download.size is not None
|
|
827
|
+
download_status = (
|
|
828
|
+
f"{format_size(download.bytes_received)}/{format_size(download.size)}"
|
|
829
|
+
)
|
|
830
|
+
if download.reattempts:
|
|
831
|
+
retry_status = f"after {download.reattempts + 1} attempts "
|
|
828
832
|
hint = "Use --resume-retries to configure resume attempt limit."
|
|
829
833
|
else:
|
|
834
|
+
# Download retrying is not enabled.
|
|
830
835
|
retry_status = ""
|
|
831
836
|
hint = "Consider using --resume-retries to enable download resumption."
|
|
832
837
|
message = Text(
|
|
@@ -836,7 +841,7 @@ class IncompleteDownloadError(DiagnosticPipError):
|
|
|
836
841
|
|
|
837
842
|
super().__init__(
|
|
838
843
|
message=message,
|
|
839
|
-
context=f"URL: {link.redacted_url}",
|
|
844
|
+
context=f"URL: {download.link.redacted_url}",
|
|
840
845
|
hint_stmt=hint,
|
|
841
846
|
note_stmt="This is an issue with network connectivity, not pip.",
|
|
842
847
|
)
|
|
@@ -860,3 +865,17 @@ class ResolutionTooDeepError(DiagnosticPipError):
|
|
|
860
865
|
),
|
|
861
866
|
link="https://pip.pypa.io/en/stable/topics/dependency-resolution/#handling-resolution-too-deep-errors",
|
|
862
867
|
)
|
|
868
|
+
|
|
869
|
+
|
|
870
|
+
class InstallWheelBuildError(DiagnosticPipError):
|
|
871
|
+
reference = "failed-wheel-build-for-install"
|
|
872
|
+
|
|
873
|
+
def __init__(self, failed: list[InstallRequirement]) -> None:
|
|
874
|
+
super().__init__(
|
|
875
|
+
message=(
|
|
876
|
+
"Failed to build installable wheels for some "
|
|
877
|
+
"pyproject.toml based projects"
|
|
878
|
+
),
|
|
879
|
+
context=", ".join(r.name for r in failed), # type: ignore
|
|
880
|
+
hint_stmt=None,
|
|
881
|
+
)
|
pip/_internal/index/collector.py
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
The main purpose of this module is to expose LinkCollector.collect_sources().
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
5
7
|
import collections
|
|
6
8
|
import email.message
|
|
7
9
|
import functools
|
|
@@ -11,21 +13,14 @@ import logging
|
|
|
11
13
|
import os
|
|
12
14
|
import urllib.parse
|
|
13
15
|
import urllib.request
|
|
16
|
+
from collections.abc import Iterable, MutableMapping, Sequence
|
|
14
17
|
from dataclasses import dataclass
|
|
15
18
|
from html.parser import HTMLParser
|
|
16
19
|
from optparse import Values
|
|
17
20
|
from typing import (
|
|
18
21
|
Callable,
|
|
19
|
-
Dict,
|
|
20
|
-
Iterable,
|
|
21
|
-
List,
|
|
22
|
-
MutableMapping,
|
|
23
22
|
NamedTuple,
|
|
24
|
-
Optional,
|
|
25
23
|
Protocol,
|
|
26
|
-
Sequence,
|
|
27
|
-
Tuple,
|
|
28
|
-
Union,
|
|
29
24
|
)
|
|
30
25
|
|
|
31
26
|
from pip._vendor import requests
|
|
@@ -48,7 +43,7 @@ logger = logging.getLogger(__name__)
|
|
|
48
43
|
ResponseHeaders = MutableMapping[str, str]
|
|
49
44
|
|
|
50
45
|
|
|
51
|
-
def _match_vcs_scheme(url: str) ->
|
|
46
|
+
def _match_vcs_scheme(url: str) -> str | None:
|
|
52
47
|
"""Look for VCS schemes in the URL.
|
|
53
48
|
|
|
54
49
|
Returns the matched VCS scheme, or None if there's no match.
|
|
@@ -173,7 +168,7 @@ def _get_simple_response(url: str, session: PipSession) -> Response:
|
|
|
173
168
|
return resp
|
|
174
169
|
|
|
175
170
|
|
|
176
|
-
def _get_encoding_from_headers(headers: ResponseHeaders) ->
|
|
171
|
+
def _get_encoding_from_headers(headers: ResponseHeaders) -> str | None:
|
|
177
172
|
"""Determine if we have any encoding information in our headers."""
|
|
178
173
|
if headers and "Content-Type" in headers:
|
|
179
174
|
m = email.message.Message()
|
|
@@ -185,7 +180,7 @@ def _get_encoding_from_headers(headers: ResponseHeaders) -> Optional[str]:
|
|
|
185
180
|
|
|
186
181
|
|
|
187
182
|
class CacheablePageContent:
|
|
188
|
-
def __init__(self, page:
|
|
183
|
+
def __init__(self, page: IndexContent) -> None:
|
|
189
184
|
assert page.cache_link_parsing
|
|
190
185
|
self.page = page
|
|
191
186
|
|
|
@@ -197,7 +192,7 @@ class CacheablePageContent:
|
|
|
197
192
|
|
|
198
193
|
|
|
199
194
|
class ParseLinks(Protocol):
|
|
200
|
-
def __call__(self, page:
|
|
195
|
+
def __call__(self, page: IndexContent) -> Iterable[Link]: ...
|
|
201
196
|
|
|
202
197
|
|
|
203
198
|
def with_cached_index_content(fn: ParseLinks) -> ParseLinks:
|
|
@@ -207,12 +202,12 @@ def with_cached_index_content(fn: ParseLinks) -> ParseLinks:
|
|
|
207
202
|
`page` has `page.cache_link_parsing == False`.
|
|
208
203
|
"""
|
|
209
204
|
|
|
210
|
-
@functools.
|
|
211
|
-
def wrapper(cacheable_page: CacheablePageContent) ->
|
|
205
|
+
@functools.cache
|
|
206
|
+
def wrapper(cacheable_page: CacheablePageContent) -> list[Link]:
|
|
212
207
|
return list(fn(cacheable_page.page))
|
|
213
208
|
|
|
214
209
|
@functools.wraps(fn)
|
|
215
|
-
def wrapper_wrapper(page:
|
|
210
|
+
def wrapper_wrapper(page: IndexContent) -> list[Link]:
|
|
216
211
|
if page.cache_link_parsing:
|
|
217
212
|
return wrapper(CacheablePageContent(page))
|
|
218
213
|
return list(fn(page))
|
|
@@ -221,7 +216,7 @@ def with_cached_index_content(fn: ParseLinks) -> ParseLinks:
|
|
|
221
216
|
|
|
222
217
|
|
|
223
218
|
@with_cached_index_content
|
|
224
|
-
def parse_links(page:
|
|
219
|
+
def parse_links(page: IndexContent) -> Iterable[Link]:
|
|
225
220
|
"""
|
|
226
221
|
Parse a Simple API's Index Content, and yield its anchor elements as Link objects.
|
|
227
222
|
"""
|
|
@@ -262,7 +257,7 @@ class IndexContent:
|
|
|
262
257
|
|
|
263
258
|
content: bytes
|
|
264
259
|
content_type: str
|
|
265
|
-
encoding:
|
|
260
|
+
encoding: str | None
|
|
266
261
|
url: str
|
|
267
262
|
cache_link_parsing: bool = True
|
|
268
263
|
|
|
@@ -280,10 +275,10 @@ class HTMLLinkParser(HTMLParser):
|
|
|
280
275
|
super().__init__(convert_charrefs=True)
|
|
281
276
|
|
|
282
277
|
self.url: str = url
|
|
283
|
-
self.base_url:
|
|
284
|
-
self.anchors:
|
|
278
|
+
self.base_url: str | None = None
|
|
279
|
+
self.anchors: list[dict[str, str | None]] = []
|
|
285
280
|
|
|
286
|
-
def handle_starttag(self, tag: str, attrs:
|
|
281
|
+
def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None:
|
|
287
282
|
if tag == "base" and self.base_url is None:
|
|
288
283
|
href = self.get_href(attrs)
|
|
289
284
|
if href is not None:
|
|
@@ -291,7 +286,7 @@ class HTMLLinkParser(HTMLParser):
|
|
|
291
286
|
elif tag == "a":
|
|
292
287
|
self.anchors.append(dict(attrs))
|
|
293
288
|
|
|
294
|
-
def get_href(self, attrs:
|
|
289
|
+
def get_href(self, attrs: list[tuple[str, str | None]]) -> str | None:
|
|
295
290
|
for name, value in attrs:
|
|
296
291
|
if name == "href":
|
|
297
292
|
return value
|
|
@@ -300,8 +295,8 @@ class HTMLLinkParser(HTMLParser):
|
|
|
300
295
|
|
|
301
296
|
def _handle_get_simple_fail(
|
|
302
297
|
link: Link,
|
|
303
|
-
reason:
|
|
304
|
-
meth:
|
|
298
|
+
reason: str | Exception,
|
|
299
|
+
meth: Callable[..., None] | None = None,
|
|
305
300
|
) -> None:
|
|
306
301
|
if meth is None:
|
|
307
302
|
meth = logger.debug
|
|
@@ -321,7 +316,7 @@ def _make_index_content(
|
|
|
321
316
|
)
|
|
322
317
|
|
|
323
318
|
|
|
324
|
-
def _get_index_content(link: Link, *, session: PipSession) ->
|
|
319
|
+
def _get_index_content(link: Link, *, session: PipSession) -> IndexContent | None:
|
|
325
320
|
url = link.url.split("#", 1)[0]
|
|
326
321
|
|
|
327
322
|
# Check for VCS schemes that do not support lookup as web pages.
|
|
@@ -383,8 +378,8 @@ def _get_index_content(link: Link, *, session: PipSession) -> Optional["IndexCon
|
|
|
383
378
|
|
|
384
379
|
|
|
385
380
|
class CollectedSources(NamedTuple):
|
|
386
|
-
find_links: Sequence[
|
|
387
|
-
index_urls: Sequence[
|
|
381
|
+
find_links: Sequence[LinkSource | None]
|
|
382
|
+
index_urls: Sequence[LinkSource | None]
|
|
388
383
|
|
|
389
384
|
|
|
390
385
|
class LinkCollector:
|
|
@@ -409,7 +404,7 @@ class LinkCollector:
|
|
|
409
404
|
session: PipSession,
|
|
410
405
|
options: Values,
|
|
411
406
|
suppress_no_index: bool = False,
|
|
412
|
-
) ->
|
|
407
|
+
) -> LinkCollector:
|
|
413
408
|
"""
|
|
414
409
|
:param session: The Session to use to make requests.
|
|
415
410
|
:param suppress_no_index: Whether to ignore the --no-index option
|
|
@@ -438,10 +433,10 @@ class LinkCollector:
|
|
|
438
433
|
return link_collector
|
|
439
434
|
|
|
440
435
|
@property
|
|
441
|
-
def find_links(self) ->
|
|
436
|
+
def find_links(self) -> list[str]:
|
|
442
437
|
return self.search_scope.find_links
|
|
443
438
|
|
|
444
|
-
def fetch_response(self, location: Link) ->
|
|
439
|
+
def fetch_response(self, location: Link) -> IndexContent | None:
|
|
445
440
|
"""
|
|
446
441
|
Fetch an HTML page containing package links.
|
|
447
442
|
"""
|