pip 25.1.1__py3-none-any.whl → 25.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. pip/__init__.py +3 -3
  2. pip/_internal/__init__.py +2 -2
  3. pip/_internal/build_env.py +118 -94
  4. pip/_internal/cache.py +16 -14
  5. pip/_internal/cli/autocompletion.py +13 -4
  6. pip/_internal/cli/base_command.py +18 -7
  7. pip/_internal/cli/cmdoptions.py +14 -9
  8. pip/_internal/cli/command_context.py +4 -3
  9. pip/_internal/cli/index_command.py +11 -9
  10. pip/_internal/cli/main.py +3 -2
  11. pip/_internal/cli/main_parser.py +4 -3
  12. pip/_internal/cli/parser.py +26 -22
  13. pip/_internal/cli/progress_bars.py +19 -12
  14. pip/_internal/cli/req_command.py +16 -12
  15. pip/_internal/cli/spinners.py +81 -5
  16. pip/_internal/commands/__init__.py +5 -3
  17. pip/_internal/commands/cache.py +18 -15
  18. pip/_internal/commands/check.py +1 -2
  19. pip/_internal/commands/completion.py +1 -2
  20. pip/_internal/commands/configuration.py +26 -18
  21. pip/_internal/commands/debug.py +8 -6
  22. pip/_internal/commands/download.py +2 -3
  23. pip/_internal/commands/freeze.py +2 -3
  24. pip/_internal/commands/hash.py +1 -2
  25. pip/_internal/commands/help.py +1 -2
  26. pip/_internal/commands/index.py +15 -9
  27. pip/_internal/commands/inspect.py +4 -4
  28. pip/_internal/commands/install.py +44 -39
  29. pip/_internal/commands/list.py +35 -26
  30. pip/_internal/commands/lock.py +1 -2
  31. pip/_internal/commands/search.py +14 -12
  32. pip/_internal/commands/show.py +14 -11
  33. pip/_internal/commands/uninstall.py +1 -2
  34. pip/_internal/commands/wheel.py +2 -3
  35. pip/_internal/configuration.py +39 -25
  36. pip/_internal/distributions/base.py +6 -4
  37. pip/_internal/distributions/installed.py +8 -4
  38. pip/_internal/distributions/sdist.py +20 -13
  39. pip/_internal/distributions/wheel.py +6 -4
  40. pip/_internal/exceptions.py +58 -39
  41. pip/_internal/index/collector.py +24 -29
  42. pip/_internal/index/package_finder.py +70 -61
  43. pip/_internal/index/sources.py +17 -14
  44. pip/_internal/locations/__init__.py +18 -16
  45. pip/_internal/locations/_distutils.py +12 -11
  46. pip/_internal/locations/_sysconfig.py +5 -4
  47. pip/_internal/locations/base.py +4 -3
  48. pip/_internal/main.py +2 -2
  49. pip/_internal/metadata/__init__.py +8 -6
  50. pip/_internal/metadata/_json.py +5 -4
  51. pip/_internal/metadata/base.py +22 -27
  52. pip/_internal/metadata/importlib/_compat.py +6 -4
  53. pip/_internal/metadata/importlib/_dists.py +12 -17
  54. pip/_internal/metadata/importlib/_envs.py +9 -6
  55. pip/_internal/metadata/pkg_resources.py +11 -14
  56. pip/_internal/models/direct_url.py +24 -21
  57. pip/_internal/models/format_control.py +5 -5
  58. pip/_internal/models/installation_report.py +4 -3
  59. pip/_internal/models/link.py +39 -34
  60. pip/_internal/models/pylock.py +27 -22
  61. pip/_internal/models/search_scope.py +6 -7
  62. pip/_internal/models/selection_prefs.py +3 -3
  63. pip/_internal/models/target_python.py +10 -9
  64. pip/_internal/models/wheel.py +7 -5
  65. pip/_internal/network/auth.py +20 -22
  66. pip/_internal/network/cache.py +22 -6
  67. pip/_internal/network/download.py +169 -141
  68. pip/_internal/network/lazy_wheel.py +10 -7
  69. pip/_internal/network/session.py +32 -27
  70. pip/_internal/network/utils.py +2 -2
  71. pip/_internal/network/xmlrpc.py +2 -2
  72. pip/_internal/operations/build/build_tracker.py +10 -8
  73. pip/_internal/operations/build/wheel.py +3 -2
  74. pip/_internal/operations/build/wheel_editable.py +3 -2
  75. pip/_internal/operations/build/wheel_legacy.py +9 -8
  76. pip/_internal/operations/check.py +21 -26
  77. pip/_internal/operations/freeze.py +12 -9
  78. pip/_internal/operations/install/editable_legacy.py +5 -3
  79. pip/_internal/operations/install/wheel.py +49 -41
  80. pip/_internal/operations/prepare.py +35 -30
  81. pip/_internal/pyproject.py +7 -10
  82. pip/_internal/req/__init__.py +12 -10
  83. pip/_internal/req/constructors.py +33 -31
  84. pip/_internal/req/req_dependency_group.py +7 -11
  85. pip/_internal/req/req_file.py +32 -35
  86. pip/_internal/req/req_install.py +37 -34
  87. pip/_internal/req/req_set.py +4 -5
  88. pip/_internal/req/req_uninstall.py +20 -17
  89. pip/_internal/resolution/base.py +3 -3
  90. pip/_internal/resolution/legacy/resolver.py +21 -20
  91. pip/_internal/resolution/resolvelib/base.py +16 -13
  92. pip/_internal/resolution/resolvelib/candidates.py +29 -26
  93. pip/_internal/resolution/resolvelib/factory.py +41 -50
  94. pip/_internal/resolution/resolvelib/found_candidates.py +11 -9
  95. pip/_internal/resolution/resolvelib/provider.py +15 -20
  96. pip/_internal/resolution/resolvelib/reporter.py +5 -3
  97. pip/_internal/resolution/resolvelib/requirements.py +8 -6
  98. pip/_internal/resolution/resolvelib/resolver.py +39 -23
  99. pip/_internal/self_outdated_check.py +8 -6
  100. pip/_internal/utils/appdirs.py +1 -2
  101. pip/_internal/utils/compat.py +7 -1
  102. pip/_internal/utils/compatibility_tags.py +17 -16
  103. pip/_internal/utils/deprecation.py +11 -9
  104. pip/_internal/utils/direct_url_helpers.py +2 -2
  105. pip/_internal/utils/egg_link.py +6 -5
  106. pip/_internal/utils/entrypoints.py +3 -2
  107. pip/_internal/utils/filesystem.py +8 -5
  108. pip/_internal/utils/filetypes.py +4 -6
  109. pip/_internal/utils/glibc.py +6 -5
  110. pip/_internal/utils/hashes.py +9 -6
  111. pip/_internal/utils/logging.py +8 -5
  112. pip/_internal/utils/misc.py +37 -45
  113. pip/_internal/utils/packaging.py +3 -2
  114. pip/_internal/utils/retry.py +7 -4
  115. pip/_internal/utils/setuptools_build.py +12 -10
  116. pip/_internal/utils/subprocess.py +20 -17
  117. pip/_internal/utils/temp_dir.py +10 -12
  118. pip/_internal/utils/unpacking.py +6 -4
  119. pip/_internal/utils/urls.py +1 -1
  120. pip/_internal/utils/virtualenv.py +3 -2
  121. pip/_internal/utils/wheel.py +3 -4
  122. pip/_internal/vcs/bazaar.py +26 -8
  123. pip/_internal/vcs/git.py +59 -24
  124. pip/_internal/vcs/mercurial.py +34 -11
  125. pip/_internal/vcs/subversion.py +27 -16
  126. pip/_internal/vcs/versioncontrol.py +56 -51
  127. pip/_internal/wheel_builder.py +14 -12
  128. pip/_vendor/cachecontrol/__init__.py +1 -1
  129. pip/_vendor/certifi/__init__.py +1 -1
  130. pip/_vendor/certifi/cacert.pem +102 -221
  131. pip/_vendor/certifi/core.py +1 -32
  132. pip/_vendor/distlib/__init__.py +2 -2
  133. pip/_vendor/distlib/scripts.py +1 -1
  134. pip/_vendor/msgpack/__init__.py +2 -2
  135. pip/_vendor/pkg_resources/__init__.py +1 -1
  136. pip/_vendor/platformdirs/version.py +2 -2
  137. pip/_vendor/pygments/__init__.py +1 -1
  138. pip/_vendor/requests/__version__.py +2 -2
  139. pip/_vendor/requests/compat.py +12 -0
  140. pip/_vendor/requests/models.py +3 -1
  141. pip/_vendor/requests/utils.py +6 -16
  142. pip/_vendor/resolvelib/__init__.py +3 -3
  143. pip/_vendor/resolvelib/reporters.py +1 -1
  144. pip/_vendor/resolvelib/resolvers/__init__.py +4 -4
  145. pip/_vendor/resolvelib/resolvers/resolution.py +91 -10
  146. pip/_vendor/rich/__main__.py +12 -40
  147. pip/_vendor/rich/_inspect.py +1 -1
  148. pip/_vendor/rich/_ratio.py +1 -7
  149. pip/_vendor/rich/align.py +1 -7
  150. pip/_vendor/rich/box.py +1 -7
  151. pip/_vendor/rich/console.py +25 -20
  152. pip/_vendor/rich/control.py +1 -7
  153. pip/_vendor/rich/diagnose.py +1 -0
  154. pip/_vendor/rich/emoji.py +1 -6
  155. pip/_vendor/rich/live.py +32 -7
  156. pip/_vendor/rich/live_render.py +1 -7
  157. pip/_vendor/rich/logging.py +1 -1
  158. pip/_vendor/rich/panel.py +3 -4
  159. pip/_vendor/rich/progress.py +15 -15
  160. pip/_vendor/rich/spinner.py +7 -13
  161. pip/_vendor/rich/syntax.py +24 -5
  162. pip/_vendor/rich/traceback.py +32 -17
  163. pip/_vendor/truststore/_api.py +1 -1
  164. pip/_vendor/vendor.txt +9 -10
  165. {pip-25.1.1.dist-info → pip-25.2.dist-info}/METADATA +26 -4
  166. {pip-25.1.1.dist-info → pip-25.2.dist-info}/RECORD +193 -180
  167. {pip-25.1.1.dist-info → pip-25.2.dist-info}/WHEEL +1 -1
  168. {pip-25.1.1.dist-info → pip-25.2.dist-info}/licenses/AUTHORS.txt +12 -0
  169. pip-25.2.dist-info/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt +13 -0
  170. pip-25.2.dist-info/licenses/src/pip/_vendor/certifi/LICENSE +20 -0
  171. pip-25.2.dist-info/licenses/src/pip/_vendor/dependency_groups/LICENSE.txt +9 -0
  172. pip-25.2.dist-info/licenses/src/pip/_vendor/distlib/LICENSE.txt +284 -0
  173. pip-25.2.dist-info/licenses/src/pip/_vendor/distro/LICENSE +202 -0
  174. pip-25.2.dist-info/licenses/src/pip/_vendor/idna/LICENSE.md +31 -0
  175. pip-25.2.dist-info/licenses/src/pip/_vendor/msgpack/COPYING +14 -0
  176. pip-25.2.dist-info/licenses/src/pip/_vendor/packaging/LICENSE +3 -0
  177. pip-25.2.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.APACHE +177 -0
  178. pip-25.2.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.BSD +23 -0
  179. pip-25.2.dist-info/licenses/src/pip/_vendor/pkg_resources/LICENSE +17 -0
  180. pip-25.2.dist-info/licenses/src/pip/_vendor/platformdirs/LICENSE +21 -0
  181. pip-25.2.dist-info/licenses/src/pip/_vendor/pygments/LICENSE +25 -0
  182. pip-25.2.dist-info/licenses/src/pip/_vendor/pyproject_hooks/LICENSE +21 -0
  183. pip-25.2.dist-info/licenses/src/pip/_vendor/requests/LICENSE +175 -0
  184. pip-25.2.dist-info/licenses/src/pip/_vendor/resolvelib/LICENSE +13 -0
  185. pip-25.2.dist-info/licenses/src/pip/_vendor/rich/LICENSE +19 -0
  186. pip-25.2.dist-info/licenses/src/pip/_vendor/tomli/LICENSE +21 -0
  187. pip-25.2.dist-info/licenses/src/pip/_vendor/tomli/LICENSE-HEADER +3 -0
  188. pip-25.2.dist-info/licenses/src/pip/_vendor/tomli_w/LICENSE +21 -0
  189. pip-25.2.dist-info/licenses/src/pip/_vendor/truststore/LICENSE +21 -0
  190. pip-25.2.dist-info/licenses/src/pip/_vendor/urllib3/LICENSE.txt +21 -0
  191. pip/_vendor/distlib/database.py +0 -1329
  192. pip/_vendor/distlib/index.py +0 -508
  193. pip/_vendor/distlib/locators.py +0 -1295
  194. pip/_vendor/distlib/manifest.py +0 -384
  195. pip/_vendor/distlib/markers.py +0 -162
  196. pip/_vendor/distlib/metadata.py +0 -1031
  197. pip/_vendor/distlib/version.py +0 -750
  198. pip/_vendor/distlib/wheel.py +0 -1100
  199. pip/_vendor/typing_extensions.py +0 -4584
  200. {pip-25.1.1.dist-info → pip-25.2.dist-info}/entry_points.txt +0 -0
  201. {pip-25.1.1.dist-info → pip-25.2.dist-info}/licenses/LICENSE.txt +0 -0
  202. {pip-25.1.1.dist-info → pip-25.2.dist-info}/top_level.txt +0 -0
@@ -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: Dict[str, InstallRequirement] = OrderedDict()
15
+ self.requirements: dict[str, InstallRequirement] = OrderedDict()
17
16
  self.check_supported_wheels = check_supported_wheels
18
17
 
19
- self.unnamed_requirements: List[InstallRequirement] = []
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) -> List[InstallRequirement]:
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) -> List[InstallRequirement]:
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, Dict, Generator, Iterable, List, Optional, Set, Tuple
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: Set[Any] = set()
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]) -> Set[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: Set[str] = set()
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]) -> Set[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: Set[str] = set()
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: Set[str] = set()
127
- all_subdirs: Set[str] = set()
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]) -> Tuple[Set[str], Set[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: Dict[str, TempDirectory] = {}
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: List[Tuple[str, str]] = []
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: Set[str] = set()
301
- self._refuse: Set[str] = set()
302
- self._pth: Dict[str, UninstallPthEntries] = {}
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) -> "UninstallPathSet":
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: Set[str] = set()
585
- self._saved_lines: Optional[List[bytes]] = None
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)
@@ -1,4 +1,4 @@
1
- from typing import Callable, List, Optional
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: List[InstallRequirement], check_supported_wheels: bool
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
- ) -> List[InstallRequirement]:
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 DefaultDict, Iterable, List, Optional, Set, Tuple
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 = DefaultDict[Optional[str], List[InstallRequirement]]
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: Tuple[int, int, int],
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: Optional[WheelCache],
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: Optional[Tuple[int, ...]] = None,
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: List[InstallRequirement], check_supported_wheels: bool
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: List[InstallRequirement] = []
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: Optional[str] = None,
196
- extras_requested: Optional[Iterable[str]] = None,
197
- ) -> Tuple[List[InstallRequirement], Optional[InstallRequirement]]:
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: Optional[InstallRequirement] = (
246
- requirement_set.get_requirement(install_req.name)
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) -> Optional[Link]:
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
- ) -> List[InstallRequirement]:
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: List[InstallRequirement] = []
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
- ) -> List[InstallRequirement]:
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: Set[InstallRequirement] = set()
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 FrozenSet, Iterable, Optional, Tuple
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 = Tuple[Optional["Candidate"], Optional[InstallRequirement]]
15
+ CandidateLookup = tuple[Optional["Candidate"], Optional[InstallRequirement]]
13
16
 
14
17
 
15
- def format_name(project: NormalizedName, extras: FrozenSet[NormalizedName]) -> str:
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: FrozenSet[Link]
29
+ links: frozenset[Link]
27
30
 
28
31
  @classmethod
29
- def empty(cls) -> "Constraint":
32
+ def empty(cls) -> Constraint:
30
33
  return Constraint(SpecifierSet(), Hashes(), frozenset())
31
34
 
32
35
  @classmethod
33
- def from_ireq(cls, ireq: InstallRequirement) -> "Constraint":
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) -> "Constraint":
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: "Candidate") -> bool:
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: "Candidate") -> bool:
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: "Candidate") -> bool:
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) -> Optional[Link]:
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[Optional[Requirement]]:
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) -> Optional[InstallRequirement]:
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 typing import TYPE_CHECKING, Any, FrozenSet, Iterable, Optional, Tuple, Union, cast
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) -> Optional[BaseCandidate]:
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: "Factory",
150
- name: Optional[NormalizedName] = None,
151
- version: Optional[Version] = None,
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: Optional[int] = None
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) -> Optional[Link]:
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[Optional[Requirement]]:
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) -> Optional[InstallRequirement]:
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: "Factory",
271
- name: Optional[NormalizedName] = None,
272
- version: Optional[Version] = None,
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: "Factory",
328
- name: Optional[NormalizedName] = None,
329
- version: Optional[Version] = None,
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: "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[Optional[Requirement]]:
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) -> Optional[InstallRequirement]:
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: FrozenSet[str],
446
+ extras: frozenset[str],
444
447
  *,
445
- comes_from: Optional[InstallRequirement] = None,
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) -> Optional[Link]:
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[Optional[Requirement]]:
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) -> Optional[InstallRequirement]:
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: Optional[Tuple[int, ...]]) -> None:
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[Optional[Requirement]]:
578
+ def iter_dependencies(self, with_requires: bool) -> Iterable[Requirement | None]:
576
579
  return ()
577
580
 
578
- def get_install_requirement(self) -> Optional[InstallRequirement]:
581
+ def get_install_requirement(self) -> InstallRequirement | None:
579
582
  return None