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
pip/_internal/req/req_set.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from collections import OrderedDict
|
|
3
|
-
from typing import Dict, List
|
|
4
3
|
|
|
5
4
|
from pip._vendor.packaging.utils import canonicalize_name
|
|
6
5
|
|
|
@@ -13,10 +12,10 @@ class RequirementSet:
|
|
|
13
12
|
def __init__(self, check_supported_wheels: bool = True) -> None:
|
|
14
13
|
"""Create a RequirementSet."""
|
|
15
14
|
|
|
16
|
-
self.requirements:
|
|
15
|
+
self.requirements: dict[str, InstallRequirement] = OrderedDict()
|
|
17
16
|
self.check_supported_wheels = check_supported_wheels
|
|
18
17
|
|
|
19
|
-
self.unnamed_requirements:
|
|
18
|
+
self.unnamed_requirements: list[InstallRequirement] = []
|
|
20
19
|
|
|
21
20
|
def __str__(self) -> str:
|
|
22
21
|
requirements = sorted(
|
|
@@ -65,11 +64,11 @@ class RequirementSet:
|
|
|
65
64
|
raise KeyError(f"No project with the name {name!r}")
|
|
66
65
|
|
|
67
66
|
@property
|
|
68
|
-
def all_requirements(self) ->
|
|
67
|
+
def all_requirements(self) -> list[InstallRequirement]:
|
|
69
68
|
return self.unnamed_requirements + list(self.requirements.values())
|
|
70
69
|
|
|
71
70
|
@property
|
|
72
|
-
def requirements_to_install(self) ->
|
|
71
|
+
def requirements_to_install(self) -> list[InstallRequirement]:
|
|
73
72
|
"""Return the list of requirements that need to be installed.
|
|
74
73
|
|
|
75
74
|
TODO remove this property together with the legacy resolver, since the new
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import functools
|
|
2
4
|
import os
|
|
3
5
|
import sys
|
|
4
6
|
import sysconfig
|
|
7
|
+
from collections.abc import Generator, Iterable
|
|
5
8
|
from importlib.util import cache_from_source
|
|
6
|
-
from typing import Any, Callable
|
|
9
|
+
from typing import Any, Callable
|
|
7
10
|
|
|
8
11
|
from pip._internal.exceptions import LegacyDistutilsInstall, UninstallMissingRecord
|
|
9
12
|
from pip._internal.locations import get_bin_prefix, get_bin_user
|
|
@@ -42,7 +45,7 @@ def _unique(
|
|
|
42
45
|
) -> Callable[..., Generator[Any, None, None]]:
|
|
43
46
|
@functools.wraps(fn)
|
|
44
47
|
def unique(*args: Any, **kw: Any) -> Generator[Any, None, None]:
|
|
45
|
-
seen:
|
|
48
|
+
seen: set[Any] = set()
|
|
46
49
|
for item in fn(*args, **kw):
|
|
47
50
|
if item not in seen:
|
|
48
51
|
seen.add(item)
|
|
@@ -85,14 +88,14 @@ def uninstallation_paths(dist: BaseDistribution) -> Generator[str, None, None]:
|
|
|
85
88
|
yield path
|
|
86
89
|
|
|
87
90
|
|
|
88
|
-
def compact(paths: Iterable[str]) ->
|
|
91
|
+
def compact(paths: Iterable[str]) -> set[str]:
|
|
89
92
|
"""Compact a path set to contain the minimal number of paths
|
|
90
93
|
necessary to contain all paths in the set. If /a/path/ and
|
|
91
94
|
/a/path/to/a/file.txt are both in the set, leave only the
|
|
92
95
|
shorter path."""
|
|
93
96
|
|
|
94
97
|
sep = os.path.sep
|
|
95
|
-
short_paths:
|
|
98
|
+
short_paths: set[str] = set()
|
|
96
99
|
for path in sorted(paths, key=len):
|
|
97
100
|
should_skip = any(
|
|
98
101
|
path.startswith(shortpath.rstrip("*"))
|
|
@@ -104,7 +107,7 @@ def compact(paths: Iterable[str]) -> Set[str]:
|
|
|
104
107
|
return short_paths
|
|
105
108
|
|
|
106
109
|
|
|
107
|
-
def compress_for_rename(paths: Iterable[str]) ->
|
|
110
|
+
def compress_for_rename(paths: Iterable[str]) -> set[str]:
|
|
108
111
|
"""Returns a set containing the paths that need to be renamed.
|
|
109
112
|
|
|
110
113
|
This set may include directories when the original sequence of paths
|
|
@@ -113,7 +116,7 @@ def compress_for_rename(paths: Iterable[str]) -> Set[str]:
|
|
|
113
116
|
case_map = {os.path.normcase(p): p for p in paths}
|
|
114
117
|
remaining = set(case_map)
|
|
115
118
|
unchecked = sorted({os.path.split(p)[0] for p in case_map.values()}, key=len)
|
|
116
|
-
wildcards:
|
|
119
|
+
wildcards: set[str] = set()
|
|
117
120
|
|
|
118
121
|
def norm_join(*a: str) -> str:
|
|
119
122
|
return os.path.normcase(os.path.join(*a))
|
|
@@ -123,8 +126,8 @@ def compress_for_rename(paths: Iterable[str]) -> Set[str]:
|
|
|
123
126
|
# This directory has already been handled.
|
|
124
127
|
continue
|
|
125
128
|
|
|
126
|
-
all_files:
|
|
127
|
-
all_subdirs:
|
|
129
|
+
all_files: set[str] = set()
|
|
130
|
+
all_subdirs: set[str] = set()
|
|
128
131
|
for dirname, subdirs, files in os.walk(root):
|
|
129
132
|
all_subdirs.update(norm_join(root, dirname, d) for d in subdirs)
|
|
130
133
|
all_files.update(norm_join(root, dirname, f) for f in files)
|
|
@@ -138,7 +141,7 @@ def compress_for_rename(paths: Iterable[str]) -> Set[str]:
|
|
|
138
141
|
return set(map(case_map.__getitem__, remaining)) | wildcards
|
|
139
142
|
|
|
140
143
|
|
|
141
|
-
def compress_for_output_listing(paths: Iterable[str]) ->
|
|
144
|
+
def compress_for_output_listing(paths: Iterable[str]) -> tuple[set[str], set[str]]:
|
|
142
145
|
"""Returns a tuple of 2 sets of which paths to display to user
|
|
143
146
|
|
|
144
147
|
The first set contains paths that would be deleted. Files of a package
|
|
@@ -194,10 +197,10 @@ class StashedUninstallPathSet:
|
|
|
194
197
|
def __init__(self) -> None:
|
|
195
198
|
# Mapping from source file root to [Adjacent]TempDirectory
|
|
196
199
|
# for files under that directory.
|
|
197
|
-
self._save_dirs:
|
|
200
|
+
self._save_dirs: dict[str, TempDirectory] = {}
|
|
198
201
|
# (old path, new path) tuples for each move that may need
|
|
199
202
|
# to be undone.
|
|
200
|
-
self._moves:
|
|
203
|
+
self._moves: list[tuple[str, str]] = []
|
|
201
204
|
|
|
202
205
|
def _get_directory_stash(self, path: str) -> str:
|
|
203
206
|
"""Stashes a directory.
|
|
@@ -297,9 +300,9 @@ class UninstallPathSet:
|
|
|
297
300
|
requirement."""
|
|
298
301
|
|
|
299
302
|
def __init__(self, dist: BaseDistribution) -> None:
|
|
300
|
-
self._paths:
|
|
301
|
-
self._refuse:
|
|
302
|
-
self._pth:
|
|
303
|
+
self._paths: set[str] = set()
|
|
304
|
+
self._refuse: set[str] = set()
|
|
305
|
+
self._pth: dict[str, UninstallPthEntries] = {}
|
|
303
306
|
self._dist = dist
|
|
304
307
|
self._moved_paths = StashedUninstallPathSet()
|
|
305
308
|
# Create local cache of normalize_path results. Creating an UninstallPathSet
|
|
@@ -421,7 +424,7 @@ class UninstallPathSet:
|
|
|
421
424
|
self._moved_paths.commit()
|
|
422
425
|
|
|
423
426
|
@classmethod
|
|
424
|
-
def from_dist(cls, dist: BaseDistribution) ->
|
|
427
|
+
def from_dist(cls, dist: BaseDistribution) -> UninstallPathSet:
|
|
425
428
|
dist_location = dist.location
|
|
426
429
|
info_location = dist.info_location
|
|
427
430
|
if dist_location is None:
|
|
@@ -581,8 +584,8 @@ class UninstallPathSet:
|
|
|
581
584
|
class UninstallPthEntries:
|
|
582
585
|
def __init__(self, pth_file: str) -> None:
|
|
583
586
|
self.file = pth_file
|
|
584
|
-
self.entries:
|
|
585
|
-
self._saved_lines:
|
|
587
|
+
self.entries: set[str] = set()
|
|
588
|
+
self._saved_lines: list[bytes] | None = None
|
|
586
589
|
|
|
587
590
|
def add(self, entry: str) -> None:
|
|
588
591
|
entry = os.path.normcase(entry)
|
pip/_internal/resolution/base.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Callable,
|
|
1
|
+
from typing import Callable, Optional
|
|
2
2
|
|
|
3
3
|
from pip._internal.req.req_install import InstallRequirement
|
|
4
4
|
from pip._internal.req.req_set import RequirementSet
|
|
@@ -10,11 +10,11 @@ InstallRequirementProvider = Callable[
|
|
|
10
10
|
|
|
11
11
|
class BaseResolver:
|
|
12
12
|
def resolve(
|
|
13
|
-
self, root_reqs:
|
|
13
|
+
self, root_reqs: list[InstallRequirement], check_supported_wheels: bool
|
|
14
14
|
) -> RequirementSet:
|
|
15
15
|
raise NotImplementedError()
|
|
16
16
|
|
|
17
17
|
def get_installation_order(
|
|
18
18
|
self, req_set: RequirementSet
|
|
19
|
-
) ->
|
|
19
|
+
) -> list[InstallRequirement]:
|
|
20
20
|
raise NotImplementedError()
|
|
@@ -10,11 +10,14 @@ for sub-dependencies
|
|
|
10
10
|
a. "first found, wins" (where the order is breadth first)
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
13
15
|
import logging
|
|
14
16
|
import sys
|
|
15
17
|
from collections import defaultdict
|
|
18
|
+
from collections.abc import Iterable
|
|
16
19
|
from itertools import chain
|
|
17
|
-
from typing import
|
|
20
|
+
from typing import Optional
|
|
18
21
|
|
|
19
22
|
from pip._vendor.packaging import specifiers
|
|
20
23
|
from pip._vendor.packaging.requirements import Requirement
|
|
@@ -49,12 +52,12 @@ from pip._internal.utils.packaging import check_requires_python
|
|
|
49
52
|
|
|
50
53
|
logger = logging.getLogger(__name__)
|
|
51
54
|
|
|
52
|
-
DiscoveredDependencies =
|
|
55
|
+
DiscoveredDependencies = defaultdict[Optional[str], list[InstallRequirement]]
|
|
53
56
|
|
|
54
57
|
|
|
55
58
|
def _check_dist_requires_python(
|
|
56
59
|
dist: BaseDistribution,
|
|
57
|
-
version_info:
|
|
60
|
+
version_info: tuple[int, int, int],
|
|
58
61
|
ignore_requires_python: bool = False,
|
|
59
62
|
) -> None:
|
|
60
63
|
"""
|
|
@@ -117,7 +120,7 @@ class Resolver(BaseResolver):
|
|
|
117
120
|
self,
|
|
118
121
|
preparer: RequirementPreparer,
|
|
119
122
|
finder: PackageFinder,
|
|
120
|
-
wheel_cache:
|
|
123
|
+
wheel_cache: WheelCache | None,
|
|
121
124
|
make_install_req: InstallRequirementProvider,
|
|
122
125
|
use_user_site: bool,
|
|
123
126
|
ignore_dependencies: bool,
|
|
@@ -125,7 +128,7 @@ class Resolver(BaseResolver):
|
|
|
125
128
|
ignore_requires_python: bool,
|
|
126
129
|
force_reinstall: bool,
|
|
127
130
|
upgrade_strategy: str,
|
|
128
|
-
py_version_info:
|
|
131
|
+
py_version_info: tuple[int, ...] | None = None,
|
|
129
132
|
) -> None:
|
|
130
133
|
super().__init__()
|
|
131
134
|
assert upgrade_strategy in self._allowed_strategies
|
|
@@ -152,7 +155,7 @@ class Resolver(BaseResolver):
|
|
|
152
155
|
self._discovered_dependencies: DiscoveredDependencies = defaultdict(list)
|
|
153
156
|
|
|
154
157
|
def resolve(
|
|
155
|
-
self, root_reqs:
|
|
158
|
+
self, root_reqs: list[InstallRequirement], check_supported_wheels: bool
|
|
156
159
|
) -> RequirementSet:
|
|
157
160
|
"""Resolve what operations need to be done
|
|
158
161
|
|
|
@@ -174,7 +177,7 @@ class Resolver(BaseResolver):
|
|
|
174
177
|
# exceptions cannot be checked ahead of time, because
|
|
175
178
|
# _populate_link() needs to be called before we can make decisions
|
|
176
179
|
# based on link type.
|
|
177
|
-
discovered_reqs:
|
|
180
|
+
discovered_reqs: list[InstallRequirement] = []
|
|
178
181
|
hash_errors = HashErrors()
|
|
179
182
|
for req in chain(requirement_set.all_requirements, discovered_reqs):
|
|
180
183
|
try:
|
|
@@ -192,9 +195,9 @@ class Resolver(BaseResolver):
|
|
|
192
195
|
self,
|
|
193
196
|
requirement_set: RequirementSet,
|
|
194
197
|
install_req: InstallRequirement,
|
|
195
|
-
parent_req_name:
|
|
196
|
-
extras_requested:
|
|
197
|
-
) ->
|
|
198
|
+
parent_req_name: str | None = None,
|
|
199
|
+
extras_requested: Iterable[str] | None = None,
|
|
200
|
+
) -> tuple[list[InstallRequirement], InstallRequirement | None]:
|
|
198
201
|
"""Add install_req as a requirement to install.
|
|
199
202
|
|
|
200
203
|
:param parent_req_name: The name of the requirement that needed this
|
|
@@ -242,8 +245,8 @@ class Resolver(BaseResolver):
|
|
|
242
245
|
return [install_req], None
|
|
243
246
|
|
|
244
247
|
try:
|
|
245
|
-
existing_req:
|
|
246
|
-
|
|
248
|
+
existing_req: InstallRequirement | None = requirement_set.get_requirement(
|
|
249
|
+
install_req.name
|
|
247
250
|
)
|
|
248
251
|
except KeyError:
|
|
249
252
|
existing_req = None
|
|
@@ -323,9 +326,7 @@ class Resolver(BaseResolver):
|
|
|
323
326
|
req.should_reinstall = True
|
|
324
327
|
req.satisfied_by = None
|
|
325
328
|
|
|
326
|
-
def _check_skip_installed(
|
|
327
|
-
self, req_to_install: InstallRequirement
|
|
328
|
-
) -> Optional[str]:
|
|
329
|
+
def _check_skip_installed(self, req_to_install: InstallRequirement) -> str | None:
|
|
329
330
|
"""Check if req_to_install should be skipped.
|
|
330
331
|
|
|
331
332
|
This will check if the req is installed, and whether we should upgrade
|
|
@@ -377,7 +378,7 @@ class Resolver(BaseResolver):
|
|
|
377
378
|
self._set_req_to_reinstall(req_to_install)
|
|
378
379
|
return None
|
|
379
380
|
|
|
380
|
-
def _find_requirement_link(self, req: InstallRequirement) ->
|
|
381
|
+
def _find_requirement_link(self, req: InstallRequirement) -> Link | None:
|
|
381
382
|
upgrade = self._is_upgrade_allowed(req)
|
|
382
383
|
best_candidate = self.finder.find_requirement(req, upgrade)
|
|
383
384
|
if not best_candidate:
|
|
@@ -488,7 +489,7 @@ class Resolver(BaseResolver):
|
|
|
488
489
|
self,
|
|
489
490
|
requirement_set: RequirementSet,
|
|
490
491
|
req_to_install: InstallRequirement,
|
|
491
|
-
) ->
|
|
492
|
+
) -> list[InstallRequirement]:
|
|
492
493
|
"""Prepare a single requirements file.
|
|
493
494
|
|
|
494
495
|
:return: A list of additional InstallRequirements to also install.
|
|
@@ -511,7 +512,7 @@ class Resolver(BaseResolver):
|
|
|
511
512
|
ignore_requires_python=self.ignore_requires_python,
|
|
512
513
|
)
|
|
513
514
|
|
|
514
|
-
more_reqs:
|
|
515
|
+
more_reqs: list[InstallRequirement] = []
|
|
515
516
|
|
|
516
517
|
def add_req(subreq: Requirement, extras_requested: Iterable[str]) -> None:
|
|
517
518
|
# This idiosyncratically converts the Requirement to str and let
|
|
@@ -569,7 +570,7 @@ class Resolver(BaseResolver):
|
|
|
569
570
|
|
|
570
571
|
def get_installation_order(
|
|
571
572
|
self, req_set: RequirementSet
|
|
572
|
-
) ->
|
|
573
|
+
) -> list[InstallRequirement]:
|
|
573
574
|
"""Create the installation order.
|
|
574
575
|
|
|
575
576
|
The installation order is topological - requirements are installed
|
|
@@ -580,7 +581,7 @@ class Resolver(BaseResolver):
|
|
|
580
581
|
# installs the user specified things in the order given, except when
|
|
581
582
|
# dependencies must come earlier to achieve topological order.
|
|
582
583
|
order = []
|
|
583
|
-
ordered_reqs:
|
|
584
|
+
ordered_reqs: set[InstallRequirement] = set()
|
|
584
585
|
|
|
585
586
|
def schedule(req: InstallRequirement) -> None:
|
|
586
587
|
if req.satisfied_by or req in ordered_reqs:
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Iterable
|
|
1
4
|
from dataclasses import dataclass
|
|
2
|
-
from typing import
|
|
5
|
+
from typing import Optional
|
|
3
6
|
|
|
4
7
|
from pip._vendor.packaging.specifiers import SpecifierSet
|
|
5
8
|
from pip._vendor.packaging.utils import NormalizedName
|
|
@@ -9,10 +12,10 @@ from pip._internal.models.link import Link, links_equivalent
|
|
|
9
12
|
from pip._internal.req.req_install import InstallRequirement
|
|
10
13
|
from pip._internal.utils.hashes import Hashes
|
|
11
14
|
|
|
12
|
-
CandidateLookup =
|
|
15
|
+
CandidateLookup = tuple[Optional["Candidate"], Optional[InstallRequirement]]
|
|
13
16
|
|
|
14
17
|
|
|
15
|
-
def format_name(project: NormalizedName, extras:
|
|
18
|
+
def format_name(project: NormalizedName, extras: frozenset[NormalizedName]) -> str:
|
|
16
19
|
if not extras:
|
|
17
20
|
return project
|
|
18
21
|
extras_expr = ",".join(sorted(extras))
|
|
@@ -23,21 +26,21 @@ def format_name(project: NormalizedName, extras: FrozenSet[NormalizedName]) -> s
|
|
|
23
26
|
class Constraint:
|
|
24
27
|
specifier: SpecifierSet
|
|
25
28
|
hashes: Hashes
|
|
26
|
-
links:
|
|
29
|
+
links: frozenset[Link]
|
|
27
30
|
|
|
28
31
|
@classmethod
|
|
29
|
-
def empty(cls) ->
|
|
32
|
+
def empty(cls) -> Constraint:
|
|
30
33
|
return Constraint(SpecifierSet(), Hashes(), frozenset())
|
|
31
34
|
|
|
32
35
|
@classmethod
|
|
33
|
-
def from_ireq(cls, ireq: InstallRequirement) ->
|
|
36
|
+
def from_ireq(cls, ireq: InstallRequirement) -> Constraint:
|
|
34
37
|
links = frozenset([ireq.link]) if ireq.link else frozenset()
|
|
35
38
|
return Constraint(ireq.specifier, ireq.hashes(trust_internet=False), links)
|
|
36
39
|
|
|
37
40
|
def __bool__(self) -> bool:
|
|
38
41
|
return bool(self.specifier) or bool(self.hashes) or bool(self.links)
|
|
39
42
|
|
|
40
|
-
def __and__(self, other: InstallRequirement) ->
|
|
43
|
+
def __and__(self, other: InstallRequirement) -> Constraint:
|
|
41
44
|
if not isinstance(other, InstallRequirement):
|
|
42
45
|
return NotImplemented
|
|
43
46
|
specifier = self.specifier & other.specifier
|
|
@@ -47,7 +50,7 @@ class Constraint:
|
|
|
47
50
|
links = links.union([other.link])
|
|
48
51
|
return Constraint(specifier, hashes, links)
|
|
49
52
|
|
|
50
|
-
def is_satisfied_by(self, candidate:
|
|
53
|
+
def is_satisfied_by(self, candidate: Candidate) -> bool:
|
|
51
54
|
# Reject if there are any mismatched URL constraints on this package.
|
|
52
55
|
if self.links and not all(_match_link(link, candidate) for link in self.links):
|
|
53
56
|
return False
|
|
@@ -77,7 +80,7 @@ class Requirement:
|
|
|
77
80
|
"""
|
|
78
81
|
raise NotImplementedError("Subclass should override")
|
|
79
82
|
|
|
80
|
-
def is_satisfied_by(self, candidate:
|
|
83
|
+
def is_satisfied_by(self, candidate: Candidate) -> bool:
|
|
81
84
|
return False
|
|
82
85
|
|
|
83
86
|
def get_candidate_lookup(self) -> CandidateLookup:
|
|
@@ -87,7 +90,7 @@ class Requirement:
|
|
|
87
90
|
raise NotImplementedError("Subclass should override")
|
|
88
91
|
|
|
89
92
|
|
|
90
|
-
def _match_link(link: Link, candidate:
|
|
93
|
+
def _match_link(link: Link, candidate: Candidate) -> bool:
|
|
91
94
|
if candidate.source_link:
|
|
92
95
|
return links_equivalent(link, candidate.source_link)
|
|
93
96
|
return False
|
|
@@ -126,13 +129,13 @@ class Candidate:
|
|
|
126
129
|
raise NotImplementedError("Override in subclass")
|
|
127
130
|
|
|
128
131
|
@property
|
|
129
|
-
def source_link(self) ->
|
|
132
|
+
def source_link(self) -> Link | None:
|
|
130
133
|
raise NotImplementedError("Override in subclass")
|
|
131
134
|
|
|
132
|
-
def iter_dependencies(self, with_requires: bool) -> Iterable[
|
|
135
|
+
def iter_dependencies(self, with_requires: bool) -> Iterable[Requirement | None]:
|
|
133
136
|
raise NotImplementedError("Override in subclass")
|
|
134
137
|
|
|
135
|
-
def get_install_requirement(self) ->
|
|
138
|
+
def get_install_requirement(self) -> InstallRequirement | None:
|
|
136
139
|
raise NotImplementedError("Override in subclass")
|
|
137
140
|
|
|
138
141
|
def format_for_error(self) -> str:
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import logging
|
|
2
4
|
import sys
|
|
3
|
-
from
|
|
5
|
+
from collections.abc import Iterable
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Union, cast
|
|
4
7
|
|
|
5
8
|
from pip._vendor.packaging.requirements import InvalidRequirement
|
|
6
9
|
from pip._vendor.packaging.utils import NormalizedName, canonicalize_name
|
|
@@ -41,7 +44,7 @@ BaseCandidate = Union[
|
|
|
41
44
|
REQUIRES_PYTHON_IDENTIFIER = cast(NormalizedName, "<Python from Requires-Python>")
|
|
42
45
|
|
|
43
46
|
|
|
44
|
-
def as_base_candidate(candidate: Candidate) ->
|
|
47
|
+
def as_base_candidate(candidate: Candidate) -> BaseCandidate | None:
|
|
45
48
|
"""The runtime version of BaseCandidate."""
|
|
46
49
|
base_candidate_classes = (
|
|
47
50
|
AlreadyInstalledCandidate,
|
|
@@ -146,9 +149,9 @@ class _InstallRequirementBackedCandidate(Candidate):
|
|
|
146
149
|
link: Link,
|
|
147
150
|
source_link: Link,
|
|
148
151
|
ireq: InstallRequirement,
|
|
149
|
-
factory:
|
|
150
|
-
name:
|
|
151
|
-
version:
|
|
152
|
+
factory: Factory,
|
|
153
|
+
name: NormalizedName | None = None,
|
|
154
|
+
version: Version | None = None,
|
|
152
155
|
) -> None:
|
|
153
156
|
self._link = link
|
|
154
157
|
self._source_link = source_link
|
|
@@ -157,7 +160,7 @@ class _InstallRequirementBackedCandidate(Candidate):
|
|
|
157
160
|
self._name = name
|
|
158
161
|
self._version = version
|
|
159
162
|
self.dist = self._prepare()
|
|
160
|
-
self._hash:
|
|
163
|
+
self._hash: int | None = None
|
|
161
164
|
|
|
162
165
|
def __str__(self) -> str:
|
|
163
166
|
return f"{self.name} {self.version}"
|
|
@@ -178,7 +181,7 @@ class _InstallRequirementBackedCandidate(Candidate):
|
|
|
178
181
|
return False
|
|
179
182
|
|
|
180
183
|
@property
|
|
181
|
-
def source_link(self) ->
|
|
184
|
+
def source_link(self) -> Link | None:
|
|
182
185
|
return self._source_link
|
|
183
186
|
|
|
184
187
|
@property
|
|
@@ -248,7 +251,7 @@ class _InstallRequirementBackedCandidate(Candidate):
|
|
|
248
251
|
self._check_metadata_consistency(dist)
|
|
249
252
|
return dist
|
|
250
253
|
|
|
251
|
-
def iter_dependencies(self, with_requires: bool) -> Iterable[
|
|
254
|
+
def iter_dependencies(self, with_requires: bool) -> Iterable[Requirement | None]:
|
|
252
255
|
# Emit the Requires-Python requirement first to fail fast on
|
|
253
256
|
# unsupported candidates and avoid pointless downloads/preparation.
|
|
254
257
|
yield self._factory.make_requires_python_requirement(self.dist.requires_python)
|
|
@@ -256,7 +259,7 @@ class _InstallRequirementBackedCandidate(Candidate):
|
|
|
256
259
|
for r in requires:
|
|
257
260
|
yield from self._factory.make_requirements_from_spec(str(r), self._ireq)
|
|
258
261
|
|
|
259
|
-
def get_install_requirement(self) ->
|
|
262
|
+
def get_install_requirement(self) -> InstallRequirement | None:
|
|
260
263
|
return self._ireq
|
|
261
264
|
|
|
262
265
|
|
|
@@ -267,9 +270,9 @@ class LinkCandidate(_InstallRequirementBackedCandidate):
|
|
|
267
270
|
self,
|
|
268
271
|
link: Link,
|
|
269
272
|
template: InstallRequirement,
|
|
270
|
-
factory:
|
|
271
|
-
name:
|
|
272
|
-
version:
|
|
273
|
+
factory: Factory,
|
|
274
|
+
name: NormalizedName | None = None,
|
|
275
|
+
version: Version | None = None,
|
|
273
276
|
) -> None:
|
|
274
277
|
source_link = link
|
|
275
278
|
cache_entry = factory.get_wheel_cache_entry(source_link, name)
|
|
@@ -324,9 +327,9 @@ class EditableCandidate(_InstallRequirementBackedCandidate):
|
|
|
324
327
|
self,
|
|
325
328
|
link: Link,
|
|
326
329
|
template: InstallRequirement,
|
|
327
|
-
factory:
|
|
328
|
-
name:
|
|
329
|
-
version:
|
|
330
|
+
factory: Factory,
|
|
331
|
+
name: NormalizedName | None = None,
|
|
332
|
+
version: Version | None = None,
|
|
330
333
|
) -> None:
|
|
331
334
|
super().__init__(
|
|
332
335
|
link=link,
|
|
@@ -349,7 +352,7 @@ class AlreadyInstalledCandidate(Candidate):
|
|
|
349
352
|
self,
|
|
350
353
|
dist: BaseDistribution,
|
|
351
354
|
template: InstallRequirement,
|
|
352
|
-
factory:
|
|
355
|
+
factory: Factory,
|
|
353
356
|
) -> None:
|
|
354
357
|
self.dist = dist
|
|
355
358
|
self._ireq = _make_install_req_from_dist(dist, template)
|
|
@@ -398,7 +401,7 @@ class AlreadyInstalledCandidate(Candidate):
|
|
|
398
401
|
def format_for_error(self) -> str:
|
|
399
402
|
return f"{self.name} {self.version} (Installed)"
|
|
400
403
|
|
|
401
|
-
def iter_dependencies(self, with_requires: bool) -> Iterable[
|
|
404
|
+
def iter_dependencies(self, with_requires: bool) -> Iterable[Requirement | None]:
|
|
402
405
|
if not with_requires:
|
|
403
406
|
return
|
|
404
407
|
|
|
@@ -408,7 +411,7 @@ class AlreadyInstalledCandidate(Candidate):
|
|
|
408
411
|
except InvalidRequirement as exc:
|
|
409
412
|
raise InvalidInstalledPackage(dist=self.dist, invalid_exc=exc) from None
|
|
410
413
|
|
|
411
|
-
def get_install_requirement(self) ->
|
|
414
|
+
def get_install_requirement(self) -> InstallRequirement | None:
|
|
412
415
|
return None
|
|
413
416
|
|
|
414
417
|
|
|
@@ -440,9 +443,9 @@ class ExtrasCandidate(Candidate):
|
|
|
440
443
|
def __init__(
|
|
441
444
|
self,
|
|
442
445
|
base: BaseCandidate,
|
|
443
|
-
extras:
|
|
446
|
+
extras: frozenset[str],
|
|
444
447
|
*,
|
|
445
|
-
comes_from:
|
|
448
|
+
comes_from: InstallRequirement | None = None,
|
|
446
449
|
) -> None:
|
|
447
450
|
"""
|
|
448
451
|
:param comes_from: the InstallRequirement that led to this candidate if it
|
|
@@ -498,10 +501,10 @@ class ExtrasCandidate(Candidate):
|
|
|
498
501
|
return self.base.is_editable
|
|
499
502
|
|
|
500
503
|
@property
|
|
501
|
-
def source_link(self) ->
|
|
504
|
+
def source_link(self) -> Link | None:
|
|
502
505
|
return self.base.source_link
|
|
503
506
|
|
|
504
|
-
def iter_dependencies(self, with_requires: bool) -> Iterable[
|
|
507
|
+
def iter_dependencies(self, with_requires: bool) -> Iterable[Requirement | None]:
|
|
505
508
|
factory = self.base._factory
|
|
506
509
|
|
|
507
510
|
# Add a dependency on the exact base
|
|
@@ -529,7 +532,7 @@ class ExtrasCandidate(Candidate):
|
|
|
529
532
|
valid_extras,
|
|
530
533
|
)
|
|
531
534
|
|
|
532
|
-
def get_install_requirement(self) ->
|
|
535
|
+
def get_install_requirement(self) -> InstallRequirement | None:
|
|
533
536
|
# We don't return anything here, because we always
|
|
534
537
|
# depend on the base candidate, and we'll get the
|
|
535
538
|
# install requirement from that.
|
|
@@ -540,7 +543,7 @@ class RequiresPythonCandidate(Candidate):
|
|
|
540
543
|
is_installed = False
|
|
541
544
|
source_link = None
|
|
542
545
|
|
|
543
|
-
def __init__(self, py_version_info:
|
|
546
|
+
def __init__(self, py_version_info: tuple[int, ...] | None) -> None:
|
|
544
547
|
if py_version_info is not None:
|
|
545
548
|
version_info = normalize_version_info(py_version_info)
|
|
546
549
|
else:
|
|
@@ -572,8 +575,8 @@ class RequiresPythonCandidate(Candidate):
|
|
|
572
575
|
def format_for_error(self) -> str:
|
|
573
576
|
return f"Python {self.version}"
|
|
574
577
|
|
|
575
|
-
def iter_dependencies(self, with_requires: bool) -> Iterable[
|
|
578
|
+
def iter_dependencies(self, with_requires: bool) -> Iterable[Requirement | None]:
|
|
576
579
|
return ()
|
|
577
580
|
|
|
578
|
-
def get_install_requirement(self) ->
|
|
581
|
+
def get_install_requirement(self) -> InstallRequirement | None:
|
|
579
582
|
return None
|