pip 25.1.1__py3-none-any.whl → 25.3__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 +186 -94
- pip/_internal/cache.py +17 -15
- pip/_internal/cli/autocompletion.py +13 -4
- pip/_internal/cli/base_command.py +18 -7
- pip/_internal/cli/cmdoptions.py +57 -80
- 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 +24 -20
- pip/_internal/cli/progress_bars.py +19 -12
- pip/_internal/cli/req_command.py +57 -33
- 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 +6 -10
- 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 +63 -53
- pip/_internal/commands/list.py +35 -26
- pip/_internal/commands/lock.py +4 -8
- 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 +7 -13
- pip/_internal/configuration.py +40 -27
- pip/_internal/distributions/base.py +6 -4
- pip/_internal/distributions/installed.py +8 -4
- pip/_internal/distributions/sdist.py +33 -27
- pip/_internal/distributions/wheel.py +6 -4
- pip/_internal/exceptions.py +78 -42
- pip/_internal/index/collector.py +24 -29
- pip/_internal/index/package_finder.py +73 -64
- 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 +14 -7
- 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 +20 -19
- 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 +12 -71
- pip/_internal/network/auth.py +20 -22
- pip/_internal/network/cache.py +28 -17
- pip/_internal/network/download.py +169 -141
- pip/_internal/network/lazy_wheel.py +15 -10
- 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 +7 -6
- pip/_internal/operations/build/wheel_editable.py +7 -6
- pip/_internal/operations/check.py +21 -26
- pip/_internal/operations/freeze.py +12 -9
- pip/_internal/operations/install/wheel.py +49 -41
- pip/_internal/operations/prepare.py +42 -31
- pip/_internal/pyproject.py +7 -69
- pip/_internal/req/__init__.py +12 -12
- pip/_internal/req/constructors.py +68 -62
- pip/_internal/req/req_dependency_group.py +7 -11
- pip/_internal/req/req_file.py +32 -36
- pip/_internal/req/req_install.py +64 -170
- 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 +49 -37
- pip/_internal/resolution/resolvelib/factory.py +72 -50
- pip/_internal/resolution/resolvelib/found_candidates.py +11 -9
- pip/_internal/resolution/resolvelib/provider.py +24 -20
- pip/_internal/resolution/resolvelib/reporter.py +26 -11
- pip/_internal/resolution/resolvelib/requirements.py +8 -6
- pip/_internal/resolution/resolvelib/resolver.py +41 -29
- pip/_internal/self_outdated_check.py +19 -9
- 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 +20 -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/subprocess.py +20 -17
- pip/_internal/utils/temp_dir.py +10 -12
- pip/_internal/utils/unpacking.py +31 -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 +30 -101
- pip/_vendor/README.rst +180 -0
- pip/_vendor/cachecontrol/LICENSE.txt +13 -0
- pip/_vendor/cachecontrol/__init__.py +1 -1
- pip/_vendor/certifi/LICENSE +20 -0
- pip/_vendor/certifi/__init__.py +1 -1
- pip/_vendor/certifi/cacert.pem +164 -261
- pip/_vendor/certifi/core.py +1 -32
- pip/_vendor/dependency_groups/LICENSE.txt +9 -0
- pip/_vendor/distlib/LICENSE.txt +284 -0
- pip/_vendor/distlib/__init__.py +2 -2
- pip/_vendor/distlib/scripts.py +1 -1
- pip/_vendor/distro/LICENSE +202 -0
- pip/_vendor/idna/LICENSE.md +31 -0
- 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/pkg_resources/LICENSE +17 -0
- pip/_vendor/pkg_resources/__init__.py +1 -1
- 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/pygments/LICENSE +25 -0
- pip/_vendor/pygments/__init__.py +1 -1
- 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/compat.py +12 -0
- pip/_vendor/requests/models.py +3 -1
- pip/_vendor/requests/sessions.py +1 -1
- pip/_vendor/requests/utils.py +6 -16
- pip/_vendor/resolvelib/LICENSE +13 -0
- 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/abstract.py +3 -3
- pip/_vendor/resolvelib/resolvers/resolution.py +96 -10
- pip/_vendor/rich/LICENSE +19 -0
- 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/style.py +7 -11
- pip/_vendor/rich/syntax.py +24 -5
- pip/_vendor/rich/traceback.py +32 -17
- 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 +15 -7
- pip/_vendor/truststore/_openssl.py +3 -1
- pip/_vendor/urllib3/LICENSE.txt +21 -0
- pip/_vendor/vendor.txt +11 -12
- {pip-25.1.1.dist-info → pip-25.3.dist-info}/METADATA +32 -11
- {pip-25.1.1.dist-info → pip-25.3.dist-info}/RECORD +221 -192
- {pip-25.1.1.dist-info → pip-25.3.dist-info}/WHEEL +1 -2
- pip-25.3.dist-info/entry_points.txt +4 -0
- {pip-25.1.1.dist-info → pip-25.3.dist-info}/licenses/AUTHORS.txt +21 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt +13 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/certifi/LICENSE +20 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/dependency_groups/LICENSE.txt +9 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/distlib/LICENSE.txt +284 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/distro/LICENSE +202 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/idna/LICENSE.md +31 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/msgpack/COPYING +14 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/packaging/LICENSE +3 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.APACHE +177 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.BSD +23 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/pkg_resources/LICENSE +17 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/platformdirs/LICENSE +21 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/pygments/LICENSE +25 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/pyproject_hooks/LICENSE +21 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/requests/LICENSE +175 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/resolvelib/LICENSE +13 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/rich/LICENSE +19 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/tomli/LICENSE +21 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/tomli_w/LICENSE +21 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/truststore/LICENSE +21 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/urllib3/LICENSE.txt +21 -0
- pip/_internal/operations/build/metadata_legacy.py +0 -73
- pip/_internal/operations/build/wheel_legacy.py +0 -118
- pip/_internal/operations/install/editable_legacy.py +0 -46
- pip/_internal/utils/setuptools_build.py +0 -147
- 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/entry_points.txt +0 -3
- pip-25.1.1.dist-info/top_level.txt +0 -1
- {pip-25.1.1.dist-info → pip-25.3.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -1,21 +1,14 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import contextlib
|
|
2
4
|
import functools
|
|
3
5
|
import logging
|
|
6
|
+
from collections.abc import Iterable, Iterator, Mapping, Sequence
|
|
4
7
|
from typing import (
|
|
5
8
|
TYPE_CHECKING,
|
|
6
9
|
Callable,
|
|
7
|
-
Dict,
|
|
8
|
-
FrozenSet,
|
|
9
|
-
Iterable,
|
|
10
|
-
Iterator,
|
|
11
|
-
List,
|
|
12
|
-
Mapping,
|
|
13
10
|
NamedTuple,
|
|
14
|
-
Optional,
|
|
15
11
|
Protocol,
|
|
16
|
-
Sequence,
|
|
17
|
-
Set,
|
|
18
|
-
Tuple,
|
|
19
12
|
TypeVar,
|
|
20
13
|
cast,
|
|
21
14
|
)
|
|
@@ -84,13 +77,13 @@ if TYPE_CHECKING:
|
|
|
84
77
|
logger = logging.getLogger(__name__)
|
|
85
78
|
|
|
86
79
|
C = TypeVar("C")
|
|
87
|
-
Cache =
|
|
80
|
+
Cache = dict[Link, C]
|
|
88
81
|
|
|
89
82
|
|
|
90
83
|
class CollectedRootRequirements(NamedTuple):
|
|
91
|
-
requirements:
|
|
92
|
-
constraints:
|
|
93
|
-
user_requested:
|
|
84
|
+
requirements: list[Requirement]
|
|
85
|
+
constraints: dict[str, Constraint]
|
|
86
|
+
user_requested: dict[str, int]
|
|
94
87
|
|
|
95
88
|
|
|
96
89
|
class Factory:
|
|
@@ -99,12 +92,12 @@ class Factory:
|
|
|
99
92
|
finder: PackageFinder,
|
|
100
93
|
preparer: RequirementPreparer,
|
|
101
94
|
make_install_req: InstallRequirementProvider,
|
|
102
|
-
wheel_cache:
|
|
95
|
+
wheel_cache: WheelCache | None,
|
|
103
96
|
use_user_site: bool,
|
|
104
97
|
force_reinstall: bool,
|
|
105
98
|
ignore_installed: bool,
|
|
106
99
|
ignore_requires_python: bool,
|
|
107
|
-
py_version_info:
|
|
100
|
+
py_version_info: tuple[int, ...] | None = None,
|
|
108
101
|
) -> None:
|
|
109
102
|
self._finder = finder
|
|
110
103
|
self.preparer = preparer
|
|
@@ -118,9 +111,9 @@ class Factory:
|
|
|
118
111
|
self._build_failures: Cache[InstallationError] = {}
|
|
119
112
|
self._link_candidate_cache: Cache[LinkCandidate] = {}
|
|
120
113
|
self._editable_candidate_cache: Cache[EditableCandidate] = {}
|
|
121
|
-
self._installed_candidate_cache:
|
|
122
|
-
self._extras_candidate_cache:
|
|
123
|
-
|
|
114
|
+
self._installed_candidate_cache: dict[str, AlreadyInstalledCandidate] = {}
|
|
115
|
+
self._extras_candidate_cache: dict[
|
|
116
|
+
tuple[int, frozenset[NormalizedName]], ExtrasCandidate
|
|
124
117
|
] = {}
|
|
125
118
|
self._supported_tags_cache = get_supported()
|
|
126
119
|
|
|
@@ -149,9 +142,9 @@ class Factory:
|
|
|
149
142
|
def _make_extras_candidate(
|
|
150
143
|
self,
|
|
151
144
|
base: BaseCandidate,
|
|
152
|
-
extras:
|
|
145
|
+
extras: frozenset[str],
|
|
153
146
|
*,
|
|
154
|
-
comes_from:
|
|
147
|
+
comes_from: InstallRequirement | None = None,
|
|
155
148
|
) -> ExtrasCandidate:
|
|
156
149
|
cache_key = (id(base), frozenset(canonicalize_name(e) for e in extras))
|
|
157
150
|
try:
|
|
@@ -164,7 +157,7 @@ class Factory:
|
|
|
164
157
|
def _make_candidate_from_dist(
|
|
165
158
|
self,
|
|
166
159
|
dist: BaseDistribution,
|
|
167
|
-
extras:
|
|
160
|
+
extras: frozenset[str],
|
|
168
161
|
template: InstallRequirement,
|
|
169
162
|
) -> Candidate:
|
|
170
163
|
try:
|
|
@@ -179,12 +172,12 @@ class Factory:
|
|
|
179
172
|
def _make_candidate_from_link(
|
|
180
173
|
self,
|
|
181
174
|
link: Link,
|
|
182
|
-
extras:
|
|
175
|
+
extras: frozenset[str],
|
|
183
176
|
template: InstallRequirement,
|
|
184
|
-
name:
|
|
185
|
-
version:
|
|
186
|
-
) ->
|
|
187
|
-
base:
|
|
177
|
+
name: NormalizedName | None,
|
|
178
|
+
version: Version | None,
|
|
179
|
+
) -> Candidate | None:
|
|
180
|
+
base: BaseCandidate | None = self._make_base_candidate_from_link(
|
|
188
181
|
link, template, name, version
|
|
189
182
|
)
|
|
190
183
|
if not extras or base is None:
|
|
@@ -195,9 +188,9 @@ class Factory:
|
|
|
195
188
|
self,
|
|
196
189
|
link: Link,
|
|
197
190
|
template: InstallRequirement,
|
|
198
|
-
name:
|
|
199
|
-
version:
|
|
200
|
-
) ->
|
|
191
|
+
name: NormalizedName | None,
|
|
192
|
+
version: Version | None,
|
|
193
|
+
) -> BaseCandidate | None:
|
|
201
194
|
# TODO: Check already installed candidate, and use it if the link and
|
|
202
195
|
# editable flag match.
|
|
203
196
|
|
|
@@ -254,7 +247,7 @@ class Factory:
|
|
|
254
247
|
specifier: SpecifierSet,
|
|
255
248
|
hashes: Hashes,
|
|
256
249
|
prefers_installed: bool,
|
|
257
|
-
incompatible_ids:
|
|
250
|
+
incompatible_ids: set[int],
|
|
258
251
|
) -> Iterable[Candidate]:
|
|
259
252
|
if not ireqs:
|
|
260
253
|
return ()
|
|
@@ -267,14 +260,14 @@ class Factory:
|
|
|
267
260
|
assert template.req, "Candidates found on index must be PEP 508"
|
|
268
261
|
name = canonicalize_name(template.req.name)
|
|
269
262
|
|
|
270
|
-
extras:
|
|
263
|
+
extras: frozenset[str] = frozenset()
|
|
271
264
|
for ireq in ireqs:
|
|
272
265
|
assert ireq.req, "Candidates found on index must be PEP 508"
|
|
273
266
|
specifier &= ireq.req.specifier
|
|
274
267
|
hashes &= ireq.hashes(trust_internet=False)
|
|
275
268
|
extras |= frozenset(ireq.extras)
|
|
276
269
|
|
|
277
|
-
def _get_installed_candidate() ->
|
|
270
|
+
def _get_installed_candidate() -> Candidate | None:
|
|
278
271
|
"""Get the candidate for the currently-installed version."""
|
|
279
272
|
# If --force-reinstall is set, we want the version from the index
|
|
280
273
|
# instead, so we "pretend" there is nothing installed.
|
|
@@ -353,7 +346,7 @@ class Factory:
|
|
|
353
346
|
def _iter_explicit_candidates_from_base(
|
|
354
347
|
self,
|
|
355
348
|
base_requirements: Iterable[Requirement],
|
|
356
|
-
extras:
|
|
349
|
+
extras: frozenset[str],
|
|
357
350
|
) -> Iterator[Candidate]:
|
|
358
351
|
"""Produce explicit candidates from the base given an extra-ed package.
|
|
359
352
|
|
|
@@ -404,8 +397,8 @@ class Factory:
|
|
|
404
397
|
is_satisfied_by: Callable[[Requirement, Candidate], bool],
|
|
405
398
|
) -> Iterable[Candidate]:
|
|
406
399
|
# Collect basic lookup information from the requirements.
|
|
407
|
-
explicit_candidates:
|
|
408
|
-
ireqs:
|
|
400
|
+
explicit_candidates: set[Candidate] = set()
|
|
401
|
+
ireqs: list[InstallRequirement] = []
|
|
409
402
|
for req in requirements[identifier]:
|
|
410
403
|
cand, ireq = req.get_candidate_lookup()
|
|
411
404
|
if cand is not None:
|
|
@@ -524,7 +517,7 @@ class Factory:
|
|
|
524
517
|
)
|
|
525
518
|
|
|
526
519
|
def collect_root_requirements(
|
|
527
|
-
self, root_ireqs:
|
|
520
|
+
self, root_ireqs: list[InstallRequirement]
|
|
528
521
|
) -> CollectedRootRequirements:
|
|
529
522
|
collected = CollectedRootRequirements([], {}, {})
|
|
530
523
|
for i, ireq in enumerate(root_ireqs):
|
|
@@ -573,7 +566,7 @@ class Factory:
|
|
|
573
566
|
def make_requirements_from_spec(
|
|
574
567
|
self,
|
|
575
568
|
specifier: str,
|
|
576
|
-
comes_from:
|
|
569
|
+
comes_from: InstallRequirement | None,
|
|
577
570
|
requested_extras: Iterable[str] = (),
|
|
578
571
|
) -> Iterator[Requirement]:
|
|
579
572
|
"""
|
|
@@ -591,7 +584,7 @@ class Factory:
|
|
|
591
584
|
def make_requires_python_requirement(
|
|
592
585
|
self,
|
|
593
586
|
specifier: SpecifierSet,
|
|
594
|
-
) ->
|
|
587
|
+
) -> Requirement | None:
|
|
595
588
|
if self._ignore_requires_python:
|
|
596
589
|
return None
|
|
597
590
|
# Don't bother creating a dependency for an empty Requires-Python.
|
|
@@ -599,9 +592,7 @@ class Factory:
|
|
|
599
592
|
return None
|
|
600
593
|
return RequiresPythonRequirement(specifier, self._python_candidate)
|
|
601
594
|
|
|
602
|
-
def get_wheel_cache_entry(
|
|
603
|
-
self, link: Link, name: Optional[str]
|
|
604
|
-
) -> Optional[CacheEntry]:
|
|
595
|
+
def get_wheel_cache_entry(self, link: Link, name: str | None) -> CacheEntry | None:
|
|
605
596
|
"""Look up the link in the wheel cache.
|
|
606
597
|
|
|
607
598
|
If ``preparer.require_hashes`` is True, don't use the wheel cache,
|
|
@@ -618,7 +609,7 @@ class Factory:
|
|
|
618
609
|
supported_tags=self._supported_tags_cache,
|
|
619
610
|
)
|
|
620
611
|
|
|
621
|
-
def get_dist_to_uninstall(self, candidate: Candidate) ->
|
|
612
|
+
def get_dist_to_uninstall(self, candidate: Candidate) -> BaseDistribution | None:
|
|
622
613
|
# TODO: Are there more cases this needs to return True? Editable?
|
|
623
614
|
dist = self._installed_dists.get(candidate.project_name)
|
|
624
615
|
if dist is None: # Not installed, no uninstallation required.
|
|
@@ -647,7 +638,7 @@ class Factory:
|
|
|
647
638
|
return None
|
|
648
639
|
|
|
649
640
|
def _report_requires_python_error(
|
|
650
|
-
self, causes: Sequence[
|
|
641
|
+
self, causes: Sequence[ConflictCause]
|
|
651
642
|
) -> UnsupportedPythonVersion:
|
|
652
643
|
assert causes, "Requires-Python error reported with no cause"
|
|
653
644
|
|
|
@@ -669,7 +660,7 @@ class Factory:
|
|
|
669
660
|
return UnsupportedPythonVersion(message)
|
|
670
661
|
|
|
671
662
|
def _report_single_requirement_conflict(
|
|
672
|
-
self, req: Requirement, parent:
|
|
663
|
+
self, req: Requirement, parent: Candidate | None
|
|
673
664
|
) -> DistributionNotFound:
|
|
674
665
|
if parent is None:
|
|
675
666
|
req_disp = str(req)
|
|
@@ -679,8 +670,8 @@ class Factory:
|
|
|
679
670
|
cands = self._finder.find_all_candidates(req.project_name)
|
|
680
671
|
skipped_by_requires_python = self._finder.requires_python_skipped_reasons()
|
|
681
672
|
|
|
682
|
-
versions_set:
|
|
683
|
-
yanked_versions_set:
|
|
673
|
+
versions_set: set[Version] = set()
|
|
674
|
+
yanked_versions_set: set[Version] = set()
|
|
684
675
|
for c in cands:
|
|
685
676
|
is_yanked = c.link.is_yanked if c.link else False
|
|
686
677
|
if is_yanked:
|
|
@@ -720,10 +711,25 @@ class Factory:
|
|
|
720
711
|
|
|
721
712
|
return DistributionNotFound(f"No matching distribution found for {req}")
|
|
722
713
|
|
|
714
|
+
def _has_any_candidates(self, project_name: str) -> bool:
|
|
715
|
+
"""
|
|
716
|
+
Check if there are any candidates available for the project name.
|
|
717
|
+
"""
|
|
718
|
+
return any(
|
|
719
|
+
self.find_candidates(
|
|
720
|
+
project_name,
|
|
721
|
+
requirements={project_name: []},
|
|
722
|
+
incompatibilities={},
|
|
723
|
+
constraint=Constraint.empty(),
|
|
724
|
+
prefers_installed=True,
|
|
725
|
+
is_satisfied_by=lambda r, c: True,
|
|
726
|
+
)
|
|
727
|
+
)
|
|
728
|
+
|
|
723
729
|
def get_installation_error(
|
|
724
730
|
self,
|
|
725
|
-
e:
|
|
726
|
-
constraints:
|
|
731
|
+
e: ResolutionImpossible[Requirement, Candidate],
|
|
732
|
+
constraints: dict[str, Constraint],
|
|
727
733
|
) -> InstallationError:
|
|
728
734
|
assert e.causes, "Installation error reported with no cause"
|
|
729
735
|
|
|
@@ -756,7 +762,7 @@ class Factory:
|
|
|
756
762
|
# satisfied at once.
|
|
757
763
|
|
|
758
764
|
# A couple of formatting helpers
|
|
759
|
-
def text_join(parts:
|
|
765
|
+
def text_join(parts: list[str]) -> str:
|
|
760
766
|
if len(parts) == 1:
|
|
761
767
|
return parts[0]
|
|
762
768
|
|
|
@@ -805,6 +811,22 @@ class Factory:
|
|
|
805
811
|
spec = constraints[key].specifier
|
|
806
812
|
msg += f"\n The user requested (constraint) {key}{spec}"
|
|
807
813
|
|
|
814
|
+
# Check for causes that had no candidates
|
|
815
|
+
causes = set()
|
|
816
|
+
for req, _ in e.causes:
|
|
817
|
+
causes.add(req.name)
|
|
818
|
+
|
|
819
|
+
no_candidates = {c for c in causes if not self._has_any_candidates(c)}
|
|
820
|
+
if no_candidates:
|
|
821
|
+
msg = (
|
|
822
|
+
msg
|
|
823
|
+
+ "\n\n"
|
|
824
|
+
+ "Additionally, some packages in these conflicts have no "
|
|
825
|
+
+ "matching distributions available for your environment:"
|
|
826
|
+
+ "\n "
|
|
827
|
+
+ "\n ".join(sorted(no_candidates))
|
|
828
|
+
)
|
|
829
|
+
|
|
808
830
|
msg = (
|
|
809
831
|
msg
|
|
810
832
|
+ "\n\n"
|
|
@@ -8,9 +8,11 @@ absolutely need, and not "download the world" when we only need one version of
|
|
|
8
8
|
something.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
11
13
|
import logging
|
|
12
|
-
from collections.abc import Sequence
|
|
13
|
-
from typing import Any, Callable,
|
|
14
|
+
from collections.abc import Iterator, Sequence
|
|
15
|
+
from typing import Any, Callable, Optional
|
|
14
16
|
|
|
15
17
|
from pip._vendor.packaging.version import _BaseVersion
|
|
16
18
|
|
|
@@ -20,7 +22,7 @@ from .base import Candidate
|
|
|
20
22
|
|
|
21
23
|
logger = logging.getLogger(__name__)
|
|
22
24
|
|
|
23
|
-
IndexCandidateInfo =
|
|
25
|
+
IndexCandidateInfo = tuple[_BaseVersion, Callable[[], Optional[Candidate]]]
|
|
24
26
|
|
|
25
27
|
|
|
26
28
|
def _iter_built(infos: Iterator[IndexCandidateInfo]) -> Iterator[Candidate]:
|
|
@@ -29,7 +31,7 @@ def _iter_built(infos: Iterator[IndexCandidateInfo]) -> Iterator[Candidate]:
|
|
|
29
31
|
This iterator is used when the package is not already installed. Candidates
|
|
30
32
|
from index come later in their normal ordering.
|
|
31
33
|
"""
|
|
32
|
-
versions_found:
|
|
34
|
+
versions_found: set[_BaseVersion] = set()
|
|
33
35
|
for version, func in infos:
|
|
34
36
|
if version in versions_found:
|
|
35
37
|
continue
|
|
@@ -65,7 +67,7 @@ def _iter_built_with_prepended(
|
|
|
65
67
|
normal ordering, except skipped when the version is already installed.
|
|
66
68
|
"""
|
|
67
69
|
yield installed
|
|
68
|
-
versions_found:
|
|
70
|
+
versions_found: set[_BaseVersion] = {installed.version}
|
|
69
71
|
for version, func in infos:
|
|
70
72
|
if version in versions_found:
|
|
71
73
|
continue
|
|
@@ -89,7 +91,7 @@ def _iter_built_with_inserted(
|
|
|
89
91
|
the installed candidate exactly once before we start yielding older or
|
|
90
92
|
equivalent candidates, or after all other candidates if they are all newer.
|
|
91
93
|
"""
|
|
92
|
-
versions_found:
|
|
94
|
+
versions_found: set[_BaseVersion] = set()
|
|
93
95
|
for version, func in infos:
|
|
94
96
|
if version in versions_found:
|
|
95
97
|
continue
|
|
@@ -120,15 +122,15 @@ class FoundCandidates(Sequence[Candidate]):
|
|
|
120
122
|
def __init__(
|
|
121
123
|
self,
|
|
122
124
|
get_infos: Callable[[], Iterator[IndexCandidateInfo]],
|
|
123
|
-
installed:
|
|
125
|
+
installed: Candidate | None,
|
|
124
126
|
prefers_installed: bool,
|
|
125
|
-
incompatible_ids:
|
|
127
|
+
incompatible_ids: set[int],
|
|
126
128
|
):
|
|
127
129
|
self._get_infos = get_infos
|
|
128
130
|
self._installed = installed
|
|
129
131
|
self._prefers_installed = prefers_installed
|
|
130
132
|
self._incompatible_ids = incompatible_ids
|
|
131
|
-
self._bool:
|
|
133
|
+
self._bool: bool | None = None
|
|
132
134
|
|
|
133
135
|
def __getitem__(self, index: Any) -> Any:
|
|
134
136
|
# Implemented to satisfy the ABC check. This is not needed by the
|
|
@@ -1,16 +1,11 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import math
|
|
2
|
-
from
|
|
4
|
+
from collections.abc import Iterable, Iterator, Mapping, Sequence
|
|
5
|
+
from functools import cache
|
|
3
6
|
from typing import (
|
|
4
7
|
TYPE_CHECKING,
|
|
5
|
-
Dict,
|
|
6
|
-
Iterable,
|
|
7
|
-
Iterator,
|
|
8
|
-
Mapping,
|
|
9
|
-
Optional,
|
|
10
|
-
Sequence,
|
|
11
|
-
Tuple,
|
|
12
8
|
TypeVar,
|
|
13
|
-
Union,
|
|
14
9
|
)
|
|
15
10
|
|
|
16
11
|
from pip._vendor.resolvelib.providers import AbstractProvider
|
|
@@ -59,7 +54,7 @@ def _get_with_identifier(
|
|
|
59
54
|
mapping: Mapping[str, V],
|
|
60
55
|
identifier: str,
|
|
61
56
|
default: D,
|
|
62
|
-
) ->
|
|
57
|
+
) -> D | V:
|
|
63
58
|
"""Get item from a package name lookup mapping with a resolver identifier.
|
|
64
59
|
|
|
65
60
|
This extra logic is needed when the target mapping is keyed by package
|
|
@@ -94,10 +89,10 @@ class PipProvider(_ProviderBase):
|
|
|
94
89
|
def __init__(
|
|
95
90
|
self,
|
|
96
91
|
factory: Factory,
|
|
97
|
-
constraints:
|
|
92
|
+
constraints: dict[str, Constraint],
|
|
98
93
|
ignore_dependencies: bool,
|
|
99
94
|
upgrade_strategy: str,
|
|
100
|
-
user_requested:
|
|
95
|
+
user_requested: dict[str, int],
|
|
101
96
|
) -> None:
|
|
102
97
|
self._factory = factory
|
|
103
98
|
self._constraints = constraints
|
|
@@ -105,7 +100,16 @@ class PipProvider(_ProviderBase):
|
|
|
105
100
|
self._upgrade_strategy = upgrade_strategy
|
|
106
101
|
self._user_requested = user_requested
|
|
107
102
|
|
|
108
|
-
|
|
103
|
+
@property
|
|
104
|
+
def constraints(self) -> dict[str, Constraint]:
|
|
105
|
+
"""Public view of user-specified constraints.
|
|
106
|
+
|
|
107
|
+
Exposes the provider's constraints mapping without encouraging
|
|
108
|
+
external callers to reach into private attributes.
|
|
109
|
+
"""
|
|
110
|
+
return self._constraints
|
|
111
|
+
|
|
112
|
+
def identify(self, requirement_or_candidate: Requirement | Candidate) -> str:
|
|
109
113
|
return requirement_or_candidate.name
|
|
110
114
|
|
|
111
115
|
def narrow_requirement_selection(
|
|
@@ -113,8 +117,8 @@ class PipProvider(_ProviderBase):
|
|
|
113
117
|
identifiers: Iterable[str],
|
|
114
118
|
resolutions: Mapping[str, Candidate],
|
|
115
119
|
candidates: Mapping[str, Iterator[Candidate]],
|
|
116
|
-
information: Mapping[str, Iterator[
|
|
117
|
-
backtrack_causes: Sequence[
|
|
120
|
+
information: Mapping[str, Iterator[PreferenceInformation]],
|
|
121
|
+
backtrack_causes: Sequence[PreferenceInformation],
|
|
118
122
|
) -> Iterable[str]:
|
|
119
123
|
"""Produce a subset of identifiers that should be considered before others.
|
|
120
124
|
|
|
@@ -156,9 +160,9 @@ class PipProvider(_ProviderBase):
|
|
|
156
160
|
identifier: str,
|
|
157
161
|
resolutions: Mapping[str, Candidate],
|
|
158
162
|
candidates: Mapping[str, Iterator[Candidate]],
|
|
159
|
-
information: Mapping[str, Iterable[
|
|
160
|
-
backtrack_causes: Sequence[
|
|
161
|
-
) ->
|
|
163
|
+
information: Mapping[str, Iterable[PreferenceInformation]],
|
|
164
|
+
backtrack_causes: Sequence[PreferenceInformation],
|
|
165
|
+
) -> Preference:
|
|
162
166
|
"""Produce a sort key for given requirement based on preference.
|
|
163
167
|
|
|
164
168
|
The lower the return value is, the more preferred this group of
|
|
@@ -192,7 +196,7 @@ class PipProvider(_ProviderBase):
|
|
|
192
196
|
|
|
193
197
|
if not has_information:
|
|
194
198
|
direct = False
|
|
195
|
-
ireqs:
|
|
199
|
+
ireqs: tuple[InstallRequirement | None, ...] = ()
|
|
196
200
|
else:
|
|
197
201
|
# Go through the information and for each requirement,
|
|
198
202
|
# check if it's explicit (e.g., a direct link) and get the
|
|
@@ -271,7 +275,7 @@ class PipProvider(_ProviderBase):
|
|
|
271
275
|
)
|
|
272
276
|
|
|
273
277
|
@staticmethod
|
|
274
|
-
@
|
|
278
|
+
@cache
|
|
275
279
|
def is_satisfied_by(requirement: Requirement, candidate: Candidate) -> bool:
|
|
276
280
|
return requirement.is_satisfied_by(candidate)
|
|
277
281
|
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from collections import defaultdict
|
|
4
|
+
from collections.abc import Mapping
|
|
2
5
|
from logging import getLogger
|
|
3
|
-
from typing import Any
|
|
6
|
+
from typing import Any
|
|
4
7
|
|
|
5
8
|
from pip._vendor.resolvelib.reporters import BaseReporter
|
|
6
9
|
|
|
7
|
-
from .base import Candidate, Requirement
|
|
10
|
+
from .base import Candidate, Constraint, Requirement
|
|
8
11
|
|
|
9
12
|
logger = getLogger(__name__)
|
|
10
13
|
|
|
11
14
|
|
|
12
15
|
class PipReporter(BaseReporter[Requirement, Candidate, str]):
|
|
13
|
-
def __init__(self) -> None:
|
|
14
|
-
self.reject_count_by_package:
|
|
16
|
+
def __init__(self, constraints: Mapping[str, Constraint] | None = None) -> None:
|
|
17
|
+
self.reject_count_by_package: defaultdict[str, int] = defaultdict(int)
|
|
18
|
+
self._constraints = constraints or {}
|
|
15
19
|
|
|
16
20
|
self._messages_at_reject_count = {
|
|
17
21
|
1: (
|
|
@@ -33,25 +37,36 @@ class PipReporter(BaseReporter[Requirement, Candidate, str]):
|
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
def rejecting_candidate(self, criterion: Any, candidate: Candidate) -> None:
|
|
40
|
+
"""Report a candidate being rejected.
|
|
41
|
+
|
|
42
|
+
Logs both the rejection count message (if applicable) and details about
|
|
43
|
+
the requirements and constraints that caused the rejection.
|
|
44
|
+
"""
|
|
36
45
|
self.reject_count_by_package[candidate.name] += 1
|
|
37
46
|
|
|
38
47
|
count = self.reject_count_by_package[candidate.name]
|
|
39
|
-
if count
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
message = self._messages_at_reject_count[count]
|
|
43
|
-
logger.info("INFO: %s", message.format(package_name=candidate.name))
|
|
48
|
+
if count in self._messages_at_reject_count:
|
|
49
|
+
message = self._messages_at_reject_count[count]
|
|
50
|
+
logger.info("INFO: %s", message.format(package_name=candidate.name))
|
|
44
51
|
|
|
45
52
|
msg = "Will try a different candidate, due to conflict:"
|
|
46
53
|
for req_info in criterion.information:
|
|
47
54
|
req, parent = req_info.requirement, req_info.parent
|
|
48
|
-
# Inspired by Factory.get_installation_error
|
|
49
55
|
msg += "\n "
|
|
50
56
|
if parent:
|
|
51
57
|
msg += f"{parent.name} {parent.version} depends on "
|
|
52
58
|
else:
|
|
53
59
|
msg += "The user requested "
|
|
54
60
|
msg += req.format_for_error()
|
|
61
|
+
|
|
62
|
+
# Add any relevant constraints
|
|
63
|
+
if self._constraints:
|
|
64
|
+
name = candidate.name
|
|
65
|
+
constraint = self._constraints.get(name)
|
|
66
|
+
if constraint and constraint.specifier:
|
|
67
|
+
constraint_text = f"{name}{constraint.specifier}"
|
|
68
|
+
msg += f"\n The user requested (constraint) {constraint_text}"
|
|
69
|
+
|
|
55
70
|
logger.debug(msg)
|
|
56
71
|
|
|
57
72
|
|
|
@@ -72,7 +87,7 @@ class PipDebuggingReporter(BaseReporter[Requirement, Candidate, str]):
|
|
|
72
87
|
logger.info("Reporter.ending(%r)", state)
|
|
73
88
|
|
|
74
89
|
def adding_requirement(
|
|
75
|
-
self, requirement: Requirement, parent:
|
|
90
|
+
self, requirement: Requirement, parent: Candidate | None
|
|
76
91
|
) -> None:
|
|
77
92
|
logger.info("Reporter.adding_requirement(%r, %r)", requirement, parent)
|
|
78
93
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
from
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
2
4
|
|
|
3
5
|
from pip._vendor.packaging.specifiers import SpecifierSet
|
|
4
6
|
from pip._vendor.packaging.utils import NormalizedName, canonicalize_name
|
|
@@ -51,8 +53,8 @@ class SpecifierRequirement(Requirement):
|
|
|
51
53
|
def __init__(self, ireq: InstallRequirement) -> None:
|
|
52
54
|
assert ireq.link is None, "This is a link, not a specifier"
|
|
53
55
|
self._ireq = ireq
|
|
54
|
-
self._equal_cache:
|
|
55
|
-
self._hash:
|
|
56
|
+
self._equal_cache: str | None = None
|
|
57
|
+
self._hash: int | None = None
|
|
56
58
|
self._extras = frozenset(canonicalize_name(e) for e in self._ireq.extras)
|
|
57
59
|
|
|
58
60
|
@property
|
|
@@ -128,8 +130,8 @@ class SpecifierWithoutExtrasRequirement(SpecifierRequirement):
|
|
|
128
130
|
def __init__(self, ireq: InstallRequirement) -> None:
|
|
129
131
|
assert ireq.link is None, "This is a link, not a specifier"
|
|
130
132
|
self._ireq = install_req_drop_extras(ireq)
|
|
131
|
-
self._equal_cache:
|
|
132
|
-
self._hash:
|
|
133
|
+
self._equal_cache: str | None = None
|
|
134
|
+
self._hash: int | None = None
|
|
133
135
|
self._extras = frozenset(canonicalize_name(e) for e in self._ireq.extras)
|
|
134
136
|
|
|
135
137
|
@property
|
|
@@ -159,7 +161,7 @@ class RequiresPythonRequirement(Requirement):
|
|
|
159
161
|
def __init__(self, specifier: SpecifierSet, match: Candidate) -> None:
|
|
160
162
|
self.specifier = specifier
|
|
161
163
|
self._specifier_string = str(specifier) # for faster __eq__
|
|
162
|
-
self._hash:
|
|
164
|
+
self._hash: int | None = None
|
|
163
165
|
self._candidate = match
|
|
164
166
|
|
|
165
167
|
def __str__(self) -> str:
|