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.
Files changed (236) hide show
  1. pip/__init__.py +3 -3
  2. pip/_internal/__init__.py +2 -2
  3. pip/_internal/build_env.py +186 -94
  4. pip/_internal/cache.py +17 -15
  5. pip/_internal/cli/autocompletion.py +13 -4
  6. pip/_internal/cli/base_command.py +18 -7
  7. pip/_internal/cli/cmdoptions.py +57 -80
  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 +24 -20
  13. pip/_internal/cli/progress_bars.py +19 -12
  14. pip/_internal/cli/req_command.py +57 -33
  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 +6 -10
  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 +63 -53
  29. pip/_internal/commands/list.py +35 -26
  30. pip/_internal/commands/lock.py +4 -8
  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 +7 -13
  35. pip/_internal/configuration.py +40 -27
  36. pip/_internal/distributions/base.py +6 -4
  37. pip/_internal/distributions/installed.py +8 -4
  38. pip/_internal/distributions/sdist.py +33 -27
  39. pip/_internal/distributions/wheel.py +6 -4
  40. pip/_internal/exceptions.py +78 -42
  41. pip/_internal/index/collector.py +24 -29
  42. pip/_internal/index/package_finder.py +73 -64
  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 +14 -7
  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 +20 -19
  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 +12 -71
  65. pip/_internal/network/auth.py +20 -22
  66. pip/_internal/network/cache.py +28 -17
  67. pip/_internal/network/download.py +169 -141
  68. pip/_internal/network/lazy_wheel.py +15 -10
  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 +7 -6
  74. pip/_internal/operations/build/wheel_editable.py +7 -6
  75. pip/_internal/operations/check.py +21 -26
  76. pip/_internal/operations/freeze.py +12 -9
  77. pip/_internal/operations/install/wheel.py +49 -41
  78. pip/_internal/operations/prepare.py +42 -31
  79. pip/_internal/pyproject.py +7 -69
  80. pip/_internal/req/__init__.py +12 -12
  81. pip/_internal/req/constructors.py +68 -62
  82. pip/_internal/req/req_dependency_group.py +7 -11
  83. pip/_internal/req/req_file.py +32 -36
  84. pip/_internal/req/req_install.py +64 -170
  85. pip/_internal/req/req_set.py +4 -5
  86. pip/_internal/req/req_uninstall.py +20 -17
  87. pip/_internal/resolution/base.py +3 -3
  88. pip/_internal/resolution/legacy/resolver.py +21 -20
  89. pip/_internal/resolution/resolvelib/base.py +16 -13
  90. pip/_internal/resolution/resolvelib/candidates.py +49 -37
  91. pip/_internal/resolution/resolvelib/factory.py +72 -50
  92. pip/_internal/resolution/resolvelib/found_candidates.py +11 -9
  93. pip/_internal/resolution/resolvelib/provider.py +24 -20
  94. pip/_internal/resolution/resolvelib/reporter.py +26 -11
  95. pip/_internal/resolution/resolvelib/requirements.py +8 -6
  96. pip/_internal/resolution/resolvelib/resolver.py +41 -29
  97. pip/_internal/self_outdated_check.py +19 -9
  98. pip/_internal/utils/appdirs.py +1 -2
  99. pip/_internal/utils/compat.py +7 -1
  100. pip/_internal/utils/compatibility_tags.py +17 -16
  101. pip/_internal/utils/deprecation.py +11 -9
  102. pip/_internal/utils/direct_url_helpers.py +2 -2
  103. pip/_internal/utils/egg_link.py +6 -5
  104. pip/_internal/utils/entrypoints.py +3 -2
  105. pip/_internal/utils/filesystem.py +20 -5
  106. pip/_internal/utils/filetypes.py +4 -6
  107. pip/_internal/utils/glibc.py +6 -5
  108. pip/_internal/utils/hashes.py +9 -6
  109. pip/_internal/utils/logging.py +8 -5
  110. pip/_internal/utils/misc.py +37 -45
  111. pip/_internal/utils/packaging.py +3 -2
  112. pip/_internal/utils/retry.py +7 -4
  113. pip/_internal/utils/subprocess.py +20 -17
  114. pip/_internal/utils/temp_dir.py +10 -12
  115. pip/_internal/utils/unpacking.py +31 -4
  116. pip/_internal/utils/urls.py +1 -1
  117. pip/_internal/utils/virtualenv.py +3 -2
  118. pip/_internal/utils/wheel.py +3 -4
  119. pip/_internal/vcs/bazaar.py +26 -8
  120. pip/_internal/vcs/git.py +59 -24
  121. pip/_internal/vcs/mercurial.py +34 -11
  122. pip/_internal/vcs/subversion.py +27 -16
  123. pip/_internal/vcs/versioncontrol.py +56 -51
  124. pip/_internal/wheel_builder.py +30 -101
  125. pip/_vendor/README.rst +180 -0
  126. pip/_vendor/cachecontrol/LICENSE.txt +13 -0
  127. pip/_vendor/cachecontrol/__init__.py +1 -1
  128. pip/_vendor/certifi/LICENSE +20 -0
  129. pip/_vendor/certifi/__init__.py +1 -1
  130. pip/_vendor/certifi/cacert.pem +164 -261
  131. pip/_vendor/certifi/core.py +1 -32
  132. pip/_vendor/dependency_groups/LICENSE.txt +9 -0
  133. pip/_vendor/distlib/LICENSE.txt +284 -0
  134. pip/_vendor/distlib/__init__.py +2 -2
  135. pip/_vendor/distlib/scripts.py +1 -1
  136. pip/_vendor/distro/LICENSE +202 -0
  137. pip/_vendor/idna/LICENSE.md +31 -0
  138. pip/_vendor/msgpack/COPYING +14 -0
  139. pip/_vendor/msgpack/__init__.py +2 -2
  140. pip/_vendor/packaging/LICENSE +3 -0
  141. pip/_vendor/packaging/LICENSE.APACHE +177 -0
  142. pip/_vendor/packaging/LICENSE.BSD +23 -0
  143. pip/_vendor/pkg_resources/LICENSE +17 -0
  144. pip/_vendor/pkg_resources/__init__.py +1 -1
  145. pip/_vendor/platformdirs/LICENSE +21 -0
  146. pip/_vendor/platformdirs/api.py +1 -1
  147. pip/_vendor/platformdirs/macos.py +10 -8
  148. pip/_vendor/platformdirs/version.py +16 -3
  149. pip/_vendor/pygments/LICENSE +25 -0
  150. pip/_vendor/pygments/__init__.py +1 -1
  151. pip/_vendor/pyproject_hooks/LICENSE +21 -0
  152. pip/_vendor/requests/LICENSE +175 -0
  153. pip/_vendor/requests/__version__.py +2 -2
  154. pip/_vendor/requests/adapters.py +17 -40
  155. pip/_vendor/requests/compat.py +12 -0
  156. pip/_vendor/requests/models.py +3 -1
  157. pip/_vendor/requests/sessions.py +1 -1
  158. pip/_vendor/requests/utils.py +6 -16
  159. pip/_vendor/resolvelib/LICENSE +13 -0
  160. pip/_vendor/resolvelib/__init__.py +3 -3
  161. pip/_vendor/resolvelib/reporters.py +1 -1
  162. pip/_vendor/resolvelib/resolvers/__init__.py +4 -4
  163. pip/_vendor/resolvelib/resolvers/abstract.py +3 -3
  164. pip/_vendor/resolvelib/resolvers/resolution.py +96 -10
  165. pip/_vendor/rich/LICENSE +19 -0
  166. pip/_vendor/rich/__main__.py +12 -40
  167. pip/_vendor/rich/_inspect.py +1 -1
  168. pip/_vendor/rich/_ratio.py +1 -7
  169. pip/_vendor/rich/align.py +1 -7
  170. pip/_vendor/rich/box.py +1 -7
  171. pip/_vendor/rich/console.py +25 -20
  172. pip/_vendor/rich/control.py +1 -7
  173. pip/_vendor/rich/diagnose.py +1 -0
  174. pip/_vendor/rich/emoji.py +1 -6
  175. pip/_vendor/rich/live.py +32 -7
  176. pip/_vendor/rich/live_render.py +1 -7
  177. pip/_vendor/rich/logging.py +1 -1
  178. pip/_vendor/rich/panel.py +3 -4
  179. pip/_vendor/rich/progress.py +15 -15
  180. pip/_vendor/rich/spinner.py +7 -13
  181. pip/_vendor/rich/style.py +7 -11
  182. pip/_vendor/rich/syntax.py +24 -5
  183. pip/_vendor/rich/traceback.py +32 -17
  184. pip/_vendor/tomli/LICENSE +21 -0
  185. pip/_vendor/tomli/__init__.py +1 -1
  186. pip/_vendor/tomli/_parser.py +28 -21
  187. pip/_vendor/tomli/_re.py +8 -5
  188. pip/_vendor/tomli_w/LICENSE +21 -0
  189. pip/_vendor/truststore/LICENSE +21 -0
  190. pip/_vendor/truststore/__init__.py +1 -1
  191. pip/_vendor/truststore/_api.py +15 -7
  192. pip/_vendor/truststore/_openssl.py +3 -1
  193. pip/_vendor/urllib3/LICENSE.txt +21 -0
  194. pip/_vendor/vendor.txt +11 -12
  195. {pip-25.1.1.dist-info → pip-25.3.dist-info}/METADATA +32 -11
  196. {pip-25.1.1.dist-info → pip-25.3.dist-info}/RECORD +221 -192
  197. {pip-25.1.1.dist-info → pip-25.3.dist-info}/WHEEL +1 -2
  198. pip-25.3.dist-info/entry_points.txt +4 -0
  199. {pip-25.1.1.dist-info → pip-25.3.dist-info}/licenses/AUTHORS.txt +21 -0
  200. pip-25.3.dist-info/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt +13 -0
  201. pip-25.3.dist-info/licenses/src/pip/_vendor/certifi/LICENSE +20 -0
  202. pip-25.3.dist-info/licenses/src/pip/_vendor/dependency_groups/LICENSE.txt +9 -0
  203. pip-25.3.dist-info/licenses/src/pip/_vendor/distlib/LICENSE.txt +284 -0
  204. pip-25.3.dist-info/licenses/src/pip/_vendor/distro/LICENSE +202 -0
  205. pip-25.3.dist-info/licenses/src/pip/_vendor/idna/LICENSE.md +31 -0
  206. pip-25.3.dist-info/licenses/src/pip/_vendor/msgpack/COPYING +14 -0
  207. pip-25.3.dist-info/licenses/src/pip/_vendor/packaging/LICENSE +3 -0
  208. pip-25.3.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.APACHE +177 -0
  209. pip-25.3.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.BSD +23 -0
  210. pip-25.3.dist-info/licenses/src/pip/_vendor/pkg_resources/LICENSE +17 -0
  211. pip-25.3.dist-info/licenses/src/pip/_vendor/platformdirs/LICENSE +21 -0
  212. pip-25.3.dist-info/licenses/src/pip/_vendor/pygments/LICENSE +25 -0
  213. pip-25.3.dist-info/licenses/src/pip/_vendor/pyproject_hooks/LICENSE +21 -0
  214. pip-25.3.dist-info/licenses/src/pip/_vendor/requests/LICENSE +175 -0
  215. pip-25.3.dist-info/licenses/src/pip/_vendor/resolvelib/LICENSE +13 -0
  216. pip-25.3.dist-info/licenses/src/pip/_vendor/rich/LICENSE +19 -0
  217. pip-25.3.dist-info/licenses/src/pip/_vendor/tomli/LICENSE +21 -0
  218. pip-25.3.dist-info/licenses/src/pip/_vendor/tomli_w/LICENSE +21 -0
  219. pip-25.3.dist-info/licenses/src/pip/_vendor/truststore/LICENSE +21 -0
  220. pip-25.3.dist-info/licenses/src/pip/_vendor/urllib3/LICENSE.txt +21 -0
  221. pip/_internal/operations/build/metadata_legacy.py +0 -73
  222. pip/_internal/operations/build/wheel_legacy.py +0 -118
  223. pip/_internal/operations/install/editable_legacy.py +0 -46
  224. pip/_internal/utils/setuptools_build.py +0 -147
  225. pip/_vendor/distlib/database.py +0 -1329
  226. pip/_vendor/distlib/index.py +0 -508
  227. pip/_vendor/distlib/locators.py +0 -1295
  228. pip/_vendor/distlib/manifest.py +0 -384
  229. pip/_vendor/distlib/markers.py +0 -162
  230. pip/_vendor/distlib/metadata.py +0 -1031
  231. pip/_vendor/distlib/version.py +0 -750
  232. pip/_vendor/distlib/wheel.py +0 -1100
  233. pip/_vendor/typing_extensions.py +0 -4584
  234. pip-25.1.1.dist-info/entry_points.txt +0 -3
  235. pip-25.1.1.dist-info/top_level.txt +0 -1
  236. {pip-25.1.1.dist-info → pip-25.3.dist-info}/licenses/LICENSE.txt +0 -0
@@ -2,16 +2,19 @@
2
2
 
3
3
  # The following comment should be removed at some point in the future.
4
4
  # mypy: strict-optional=False
5
+ from __future__ import annotations
5
6
 
6
7
  import mimetypes
7
8
  import os
8
9
  import shutil
10
+ from collections.abc import Iterable
9
11
  from dataclasses import dataclass
10
12
  from pathlib import Path
11
- from typing import Dict, Iterable, List, Optional
13
+ from typing import TYPE_CHECKING
12
14
 
13
15
  from pip._vendor.packaging.utils import canonicalize_name
14
16
 
17
+ from pip._internal.build_env import BuildEnvironmentInstaller
15
18
  from pip._internal.distributions import make_distribution_for_install_requirement
16
19
  from pip._internal.distributions.installed import InstalledDistribution
17
20
  from pip._internal.exceptions import (
@@ -28,7 +31,7 @@ from pip._internal.metadata import BaseDistribution, get_metadata_distribution
28
31
  from pip._internal.models.direct_url import ArchiveInfo
29
32
  from pip._internal.models.link import Link
30
33
  from pip._internal.models.wheel import Wheel
31
- from pip._internal.network.download import BatchDownloader, Downloader
34
+ from pip._internal.network.download import Downloader
32
35
  from pip._internal.network.lazy_wheel import (
33
36
  HTTPRangeRequestUnsupported,
34
37
  dist_from_wheel_url,
@@ -53,13 +56,16 @@ from pip._internal.utils.temp_dir import TempDirectory
53
56
  from pip._internal.utils.unpacking import unpack_file
54
57
  from pip._internal.vcs import vcs
55
58
 
59
+ if TYPE_CHECKING:
60
+ from pip._internal.cli.progress_bars import BarType
61
+
56
62
  logger = getLogger(__name__)
57
63
 
58
64
 
59
65
  def _get_prepared_distribution(
60
66
  req: InstallRequirement,
61
67
  build_tracker: BuildTracker,
62
- finder: PackageFinder,
68
+ build_env_installer: BuildEnvironmentInstaller,
63
69
  build_isolation: bool,
64
70
  check_build_deps: bool,
65
71
  ) -> BaseDistribution:
@@ -69,7 +75,7 @@ def _get_prepared_distribution(
69
75
  if tracker_id is not None:
70
76
  with build_tracker.track(req, tracker_id):
71
77
  abstract_dist.prepare_distribution_metadata(
72
- finder, build_isolation, check_build_deps
78
+ build_env_installer, build_isolation, check_build_deps
73
79
  )
74
80
  return abstract_dist.get_metadata_distribution()
75
81
 
@@ -83,7 +89,7 @@ def unpack_vcs_link(link: Link, location: str, verbosity: int) -> None:
83
89
  @dataclass
84
90
  class File:
85
91
  path: str
86
- content_type: Optional[str] = None
92
+ content_type: str | None = None
87
93
 
88
94
  def __post_init__(self) -> None:
89
95
  if self.content_type is None:
@@ -98,8 +104,8 @@ class File:
98
104
  def get_http_url(
99
105
  link: Link,
100
106
  download: Downloader,
101
- download_dir: Optional[str] = None,
102
- hashes: Optional[Hashes] = None,
107
+ download_dir: str | None = None,
108
+ hashes: Hashes | None = None,
103
109
  ) -> File:
104
110
  temp_dir = TempDirectory(kind="unpack", globally_managed=True)
105
111
  # If a download dir is specified, is the file already downloaded there?
@@ -120,7 +126,7 @@ def get_http_url(
120
126
 
121
127
 
122
128
  def get_file_url(
123
- link: Link, download_dir: Optional[str] = None, hashes: Optional[Hashes] = None
129
+ link: Link, download_dir: str | None = None, hashes: Hashes | None = None
124
130
  ) -> File:
125
131
  """Get file and optionally check its hash."""
126
132
  # If a download dir is specified, is the file already there and valid?
@@ -148,9 +154,9 @@ def unpack_url(
148
154
  location: str,
149
155
  download: Downloader,
150
156
  verbosity: int,
151
- download_dir: Optional[str] = None,
152
- hashes: Optional[Hashes] = None,
153
- ) -> Optional[File]:
157
+ download_dir: str | None = None,
158
+ hashes: Hashes | None = None,
159
+ ) -> File | None:
154
160
  """Unpack link into location, downloading if required.
155
161
 
156
162
  :param hashes: A Hashes object, one of whose embedded hashes must match,
@@ -189,9 +195,9 @@ def unpack_url(
189
195
  def _check_download_dir(
190
196
  link: Link,
191
197
  download_dir: str,
192
- hashes: Optional[Hashes],
198
+ hashes: Hashes | None,
193
199
  warn_on_hash_mismatch: bool = True,
194
- ) -> Optional[str]:
200
+ ) -> str | None:
195
201
  """Check download_dir for previously downloaded file with correct hash
196
202
  If a correct file is found return its path else None
197
203
  """
@@ -219,16 +225,18 @@ def _check_download_dir(
219
225
  class RequirementPreparer:
220
226
  """Prepares a Requirement"""
221
227
 
222
- def __init__(
228
+ def __init__( # noqa: PLR0913 (too many parameters)
223
229
  self,
230
+ *,
224
231
  build_dir: str,
225
- download_dir: Optional[str],
232
+ download_dir: str | None,
226
233
  src_dir: str,
227
234
  build_isolation: bool,
235
+ build_isolation_installer: BuildEnvironmentInstaller,
228
236
  check_build_deps: bool,
229
237
  build_tracker: BuildTracker,
230
238
  session: PipSession,
231
- progress_bar: str,
239
+ progress_bar: BarType,
232
240
  finder: PackageFinder,
233
241
  require_hashes: bool,
234
242
  use_user_site: bool,
@@ -244,7 +252,6 @@ class RequirementPreparer:
244
252
  self.build_tracker = build_tracker
245
253
  self._session = session
246
254
  self._download = Downloader(session, progress_bar, resume_retries)
247
- self._batch_download = BatchDownloader(session, progress_bar, resume_retries)
248
255
  self.finder = finder
249
256
 
250
257
  # Where still-packed archives should be written to. If None, they are
@@ -253,6 +260,7 @@ class RequirementPreparer:
253
260
 
254
261
  # Is build isolation allowed?
255
262
  self.build_isolation = build_isolation
263
+ self.build_env_installer = build_isolation_installer
256
264
 
257
265
  # Should check build dependencies?
258
266
  self.check_build_deps = check_build_deps
@@ -273,7 +281,7 @@ class RequirementPreparer:
273
281
  self.legacy_resolver = legacy_resolver
274
282
 
275
283
  # Memoized downloaded files, as mapping of url: path.
276
- self._downloaded: Dict[str, str] = {}
284
+ self._downloaded: dict[str, str] = {}
277
285
 
278
286
  # Previous "header" printed for a link-based InstallRequirement
279
287
  self._previous_requirement_header = ("", "")
@@ -291,7 +299,7 @@ class RequirementPreparer:
291
299
  # would already be included if we used req directly)
292
300
  if req.req and req.comes_from:
293
301
  if isinstance(req.comes_from, str):
294
- comes_from: Optional[str] = req.comes_from
302
+ comes_from: str | None = req.comes_from
295
303
  else:
296
304
  comes_from = req.comes_from.from_path()
297
305
  if comes_from:
@@ -363,7 +371,7 @@ class RequirementPreparer:
363
371
  def _fetch_metadata_only(
364
372
  self,
365
373
  req: InstallRequirement,
366
- ) -> Optional[BaseDistribution]:
374
+ ) -> BaseDistribution | None:
367
375
  if self.legacy_resolver:
368
376
  logger.debug(
369
377
  "Metadata-only fetching is not used in the legacy resolver",
@@ -382,7 +390,7 @@ class RequirementPreparer:
382
390
  def _fetch_metadata_using_link_data_attr(
383
391
  self,
384
392
  req: InstallRequirement,
385
- ) -> Optional[BaseDistribution]:
393
+ ) -> BaseDistribution | None:
386
394
  """Fetch metadata from the data-dist-info-metadata attribute, if possible."""
387
395
  # (1) Get the link to the metadata file, if provided by the backend.
388
396
  metadata_link = req.link.metadata_link()
@@ -423,7 +431,7 @@ class RequirementPreparer:
423
431
  def _fetch_metadata_using_lazy_wheel(
424
432
  self,
425
433
  link: Link,
426
- ) -> Optional[BaseDistribution]:
434
+ ) -> BaseDistribution | None:
427
435
  """Fetch metadata using lazy wheel, if possible."""
428
436
  # --use-feature=fast-deps must be provided.
429
437
  if not self.use_lazy_wheel:
@@ -436,7 +444,7 @@ class RequirementPreparer:
436
444
  return None
437
445
 
438
446
  wheel = Wheel(link.filename)
439
- name = canonicalize_name(wheel.name)
447
+ name = wheel.name
440
448
  logger.info(
441
449
  "Obtaining dependency information from %s %s",
442
450
  name,
@@ -462,15 +470,12 @@ class RequirementPreparer:
462
470
  # Map each link to the requirement that owns it. This allows us to set
463
471
  # `req.local_file_path` on the appropriate requirement after passing
464
472
  # all the links at once into BatchDownloader.
465
- links_to_fully_download: Dict[Link, InstallRequirement] = {}
473
+ links_to_fully_download: dict[Link, InstallRequirement] = {}
466
474
  for req in partially_downloaded_reqs:
467
475
  assert req.link
468
476
  links_to_fully_download[req.link] = req
469
477
 
470
- batch_download = self._batch_download(
471
- links_to_fully_download.keys(),
472
- temp_dir,
473
- )
478
+ batch_download = self._download.batch(links_to_fully_download.keys(), temp_dir)
474
479
  for link, (filepath, _) in batch_download:
475
480
  logger.debug("Downloading link %s to %s", link, filepath)
476
481
  req = links_to_fully_download[link]
@@ -526,6 +531,12 @@ class RequirementPreparer:
526
531
  metadata_dist = self._fetch_metadata_only(req)
527
532
  if metadata_dist is not None:
528
533
  req.needs_more_preparation = True
534
+ req.set_dist(metadata_dist)
535
+ # Ensure download_info is available even in dry-run mode
536
+ if req.download_info is None:
537
+ req.download_info = direct_url_from_link(
538
+ req.link, req.source_dir
539
+ )
529
540
  return metadata_dist
530
541
 
531
542
  # None of the optimizations worked, fully prepare the requirement
@@ -547,7 +558,7 @@ class RequirementPreparer:
547
558
 
548
559
  # Prepare requirements we found were already downloaded for some
549
560
  # reason. The other downloads will be completed separately.
550
- partially_downloaded_reqs: List[InstallRequirement] = []
561
+ partially_downloaded_reqs: list[InstallRequirement] = []
551
562
  for req in reqs:
552
563
  if req.needs_more_preparation:
553
564
  partially_downloaded_reqs.append(req)
@@ -647,7 +658,7 @@ class RequirementPreparer:
647
658
  dist = _get_prepared_distribution(
648
659
  req,
649
660
  self.build_tracker,
650
- self.finder,
661
+ self.build_env_installer,
651
662
  self.build_isolation,
652
663
  self.check_build_deps,
653
664
  )
@@ -703,7 +714,7 @@ class RequirementPreparer:
703
714
  dist = _get_prepared_distribution(
704
715
  req,
705
716
  self.build_tracker,
706
- self.finder,
717
+ self.build_env_installer,
707
718
  self.build_isolation,
708
719
  self.check_build_deps,
709
720
  )
@@ -1,13 +1,8 @@
1
- import importlib.util
1
+ from __future__ import annotations
2
+
2
3
  import os
3
- import sys
4
4
  from collections import namedtuple
5
- from typing import Any, List, Optional
6
-
7
- if sys.version_info >= (3, 11):
8
- import tomllib
9
- else:
10
- from pip._vendor import tomli as tomllib
5
+ from typing import Any
11
6
 
12
7
  from pip._vendor.packaging.requirements import InvalidRequirement
13
8
 
@@ -16,6 +11,7 @@ from pip._internal.exceptions import (
16
11
  InvalidPyProjectBuildRequires,
17
12
  MissingPyProjectBuildRequires,
18
13
  )
14
+ from pip._internal.utils.compat import tomllib
19
15
  from pip._internal.utils.packaging import get_requirement
20
16
 
21
17
 
@@ -33,13 +29,11 @@ BuildSystemDetails = namedtuple(
33
29
 
34
30
 
35
31
  def load_pyproject_toml(
36
- use_pep517: Optional[bool], pyproject_toml: str, setup_py: str, req_name: str
37
- ) -> Optional[BuildSystemDetails]:
32
+ pyproject_toml: str, setup_py: str, req_name: str
33
+ ) -> BuildSystemDetails:
38
34
  """Load the pyproject.toml file.
39
35
 
40
36
  Parameters:
41
- use_pep517 - Has the user requested PEP 517 processing? None
42
- means the user hasn't explicitly specified.
43
37
  pyproject_toml - Location of the project's pyproject.toml file
44
38
  setup_py - Location of the project's setup.py file
45
39
  req_name - The name of the requirement we're processing (for
@@ -72,57 +66,7 @@ def load_pyproject_toml(
72
66
  else:
73
67
  build_system = None
74
68
 
75
- # The following cases must use PEP 517
76
- # We check for use_pep517 being non-None and falsy because that means
77
- # the user explicitly requested --no-use-pep517. The value 0 as
78
- # opposed to False can occur when the value is provided via an
79
- # environment variable or config file option (due to the quirk of
80
- # strtobool() returning an integer in pip's configuration code).
81
- if has_pyproject and not has_setup:
82
- if use_pep517 is not None and not use_pep517:
83
- raise InstallationError(
84
- "Disabling PEP 517 processing is invalid: "
85
- "project does not have a setup.py"
86
- )
87
- use_pep517 = True
88
- elif build_system and "build-backend" in build_system:
89
- if use_pep517 is not None and not use_pep517:
90
- raise InstallationError(
91
- "Disabling PEP 517 processing is invalid: "
92
- "project specifies a build backend of {} "
93
- "in pyproject.toml".format(build_system["build-backend"])
94
- )
95
- use_pep517 = True
96
-
97
- # If we haven't worked out whether to use PEP 517 yet,
98
- # and the user hasn't explicitly stated a preference,
99
- # we do so if the project has a pyproject.toml file
100
- # or if we cannot import setuptools or wheels.
101
-
102
- # We fallback to PEP 517 when without setuptools or without the wheel package,
103
- # so setuptools can be installed as a default build backend.
104
- # For more info see:
105
- # https://discuss.python.org/t/pip-without-setuptools-could-the-experience-be-improved/11810/9
106
- # https://github.com/pypa/pip/issues/8559
107
- elif use_pep517 is None:
108
- use_pep517 = (
109
- has_pyproject
110
- or not importlib.util.find_spec("setuptools")
111
- or not importlib.util.find_spec("wheel")
112
- )
113
-
114
- # At this point, we know whether we're going to use PEP 517.
115
- assert use_pep517 is not None
116
-
117
- # If we're using the legacy code path, there is nothing further
118
- # for us to do here.
119
- if not use_pep517:
120
- return None
121
-
122
69
  if build_system is None:
123
- # Either the user has a pyproject.toml with no build-system
124
- # section, or the user has no pyproject.toml, but has opted in
125
- # explicitly via --use-pep517.
126
70
  # In the absence of any explicit backend specification, we
127
71
  # assume the setuptools backend that most closely emulates the
128
72
  # traditional direct setup.py execution, and require wheel and
@@ -133,12 +77,6 @@ def load_pyproject_toml(
133
77
  "build-backend": "setuptools.build_meta:__legacy__",
134
78
  }
135
79
 
136
- # If we're using PEP 517, we have build system information (either
137
- # from pyproject.toml, or defaulted by the code above).
138
- # Note that at this point, we do not know if the user has actually
139
- # specified a backend, though.
140
- assert build_system is not None
141
-
142
80
  # Ensure that the build-system section in pyproject.toml conforms
143
81
  # to PEP 518.
144
82
 
@@ -166,7 +104,7 @@ def load_pyproject_toml(
166
104
 
167
105
  backend = build_system.get("build-backend")
168
106
  backend_path = build_system.get("backend-path", [])
169
- check: List[str] = []
107
+ check: list[str] = []
170
108
  if backend is None:
171
109
  # If the user didn't specify a backend, we assume they want to use
172
110
  # the setuptools backend. But we can't be sure they have included
@@ -1,9 +1,11 @@
1
+ from __future__ import annotations
2
+
1
3
  import collections
2
4
  import logging
5
+ from collections.abc import Generator
3
6
  from dataclasses import dataclass
4
- from typing import Generator, List, Optional, Sequence, Tuple
5
7
 
6
- from pip._internal.cli.progress_bars import get_install_progress_renderer
8
+ from pip._internal.cli.progress_bars import BarType, get_install_progress_renderer
7
9
  from pip._internal.utils.logging import indent_log
8
10
 
9
11
  from .req_file import parse_requirements
@@ -26,24 +28,23 @@ class InstallationResult:
26
28
 
27
29
 
28
30
  def _validate_requirements(
29
- requirements: List[InstallRequirement],
30
- ) -> Generator[Tuple[str, InstallRequirement], None, None]:
31
+ requirements: list[InstallRequirement],
32
+ ) -> Generator[tuple[str, InstallRequirement], None, None]:
31
33
  for req in requirements:
32
34
  assert req.name, f"invalid to-be-installed requirement: {req}"
33
35
  yield req.name, req
34
36
 
35
37
 
36
38
  def install_given_reqs(
37
- requirements: List[InstallRequirement],
38
- global_options: Sequence[str],
39
- root: Optional[str],
40
- home: Optional[str],
41
- prefix: Optional[str],
39
+ requirements: list[InstallRequirement],
40
+ root: str | None,
41
+ home: str | None,
42
+ prefix: str | None,
42
43
  warn_script_location: bool,
43
44
  use_user_site: bool,
44
45
  pycompile: bool,
45
- progress_bar: str,
46
- ) -> List[InstallationResult]:
46
+ progress_bar: BarType,
47
+ ) -> list[InstallationResult]:
47
48
  """
48
49
  Install everything in the given list.
49
50
 
@@ -81,7 +82,6 @@ def install_given_reqs(
81
82
 
82
83
  try:
83
84
  requirement.install(
84
- global_options,
85
85
  root=root,
86
86
  home=home,
87
87
  prefix=prefix,