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
@@ -1,10 +1,12 @@
1
+ from __future__ import annotations
2
+
1
3
  import locale
2
4
  import logging
3
5
  import os
4
6
  import sys
5
7
  from optparse import Values
6
8
  from types import ModuleType
7
- from typing import Any, Dict, List, Optional
9
+ from typing import Any
8
10
 
9
11
  import pip._vendor
10
12
  from pip._vendor.certifi import where
@@ -34,7 +36,7 @@ def show_sys_implementation() -> None:
34
36
  show_value("name", implementation_name)
35
37
 
36
38
 
37
- def create_vendor_txt_map() -> Dict[str, str]:
39
+ def create_vendor_txt_map() -> dict[str, str]:
38
40
  with open_text_resource("pip._vendor", "vendor.txt") as f:
39
41
  # Purge non version specifying lines.
40
42
  # Also, remove any space prefix or suffixes (including comments).
@@ -46,7 +48,7 @@ def create_vendor_txt_map() -> Dict[str, str]:
46
48
  return dict(line.split("==", 1) for line in lines)
47
49
 
48
50
 
49
- def get_module_from_module_name(module_name: str) -> Optional[ModuleType]:
51
+ def get_module_from_module_name(module_name: str) -> ModuleType | None:
50
52
  # Module name can be uppercase in vendor.txt for some reason...
51
53
  module_name = module_name.lower().replace("-", "_")
52
54
  # PATCH: setuptools is actually only pkg_resources.
@@ -64,7 +66,7 @@ def get_module_from_module_name(module_name: str) -> Optional[ModuleType]:
64
66
  raise
65
67
 
66
68
 
67
- def get_vendor_version_from_module(module_name: str) -> Optional[str]:
69
+ def get_vendor_version_from_module(module_name: str) -> str | None:
68
70
  module = get_module_from_module_name(module_name)
69
71
  version = getattr(module, "__version__", None)
70
72
 
@@ -79,7 +81,7 @@ def get_vendor_version_from_module(module_name: str) -> Optional[str]:
79
81
  return version
80
82
 
81
83
 
82
- def show_actual_vendor_versions(vendor_txt_versions: Dict[str, str]) -> None:
84
+ def show_actual_vendor_versions(vendor_txt_versions: dict[str, str]) -> None:
83
85
  """Log the actual version and print extra info if there is
84
86
  a conflict or if the actual version could not be imported.
85
87
  """
@@ -169,7 +171,7 @@ class DebugCommand(Command):
169
171
  self.parser.insert_option_group(0, self.cmd_opts)
170
172
  self.parser.config.load()
171
173
 
172
- def run(self, options: Values, args: List[str]) -> int:
174
+ def run(self, options: Values, args: list[str]) -> int:
173
175
  logger.warning(
174
176
  "This command is only meant for debugging. "
175
177
  "Do not use this with automation for parsing and getting these "
@@ -1,14 +1,12 @@
1
1
  import logging
2
2
  import os
3
3
  from optparse import Values
4
- from typing import List
5
4
 
6
5
  from pip._internal.cli import cmdoptions
7
6
  from pip._internal.cli.cmdoptions import make_target_python
8
7
  from pip._internal.cli.req_command import RequirementCommand, with_cleanup
9
8
  from pip._internal.cli.status_codes import SUCCESS
10
9
  from pip._internal.operations.build.build_tracker import get_build_tracker
11
- from pip._internal.req.req_install import check_legacy_setup_py_options
12
10
  from pip._internal.utils.misc import ensure_dir, normalize_path, write_output
13
11
  from pip._internal.utils.temp_dir import TempDirectory
14
12
 
@@ -37,9 +35,9 @@ class DownloadCommand(RequirementCommand):
37
35
 
38
36
  def add_options(self) -> None:
39
37
  self.cmd_opts.add_option(cmdoptions.constraints())
38
+ self.cmd_opts.add_option(cmdoptions.build_constraints())
40
39
  self.cmd_opts.add_option(cmdoptions.requirements())
41
40
  self.cmd_opts.add_option(cmdoptions.no_deps())
42
- self.cmd_opts.add_option(cmdoptions.global_options())
43
41
  self.cmd_opts.add_option(cmdoptions.no_binary())
44
42
  self.cmd_opts.add_option(cmdoptions.only_binary())
45
43
  self.cmd_opts.add_option(cmdoptions.prefer_binary())
@@ -49,7 +47,6 @@ class DownloadCommand(RequirementCommand):
49
47
  self.cmd_opts.add_option(cmdoptions.progress_bar())
50
48
  self.cmd_opts.add_option(cmdoptions.no_build_isolation())
51
49
  self.cmd_opts.add_option(cmdoptions.use_pep517())
52
- self.cmd_opts.add_option(cmdoptions.no_use_pep517())
53
50
  self.cmd_opts.add_option(cmdoptions.check_build_deps())
54
51
  self.cmd_opts.add_option(cmdoptions.ignore_requires_python())
55
52
 
@@ -75,13 +72,14 @@ class DownloadCommand(RequirementCommand):
75
72
  self.parser.insert_option_group(0, self.cmd_opts)
76
73
 
77
74
  @with_cleanup
78
- def run(self, options: Values, args: List[str]) -> int:
75
+ def run(self, options: Values, args: list[str]) -> int:
79
76
  options.ignore_installed = True
80
77
  # editable doesn't really make sense for `pip download`, but the bowels
81
78
  # of the RequirementSet code require that property.
82
79
  options.editables = []
83
80
 
84
81
  cmdoptions.check_dist_restriction(options)
82
+ cmdoptions.check_build_constraints(options)
85
83
 
86
84
  options.download_dir = normalize_path(options.download_dir)
87
85
  ensure_dir(options.download_dir)
@@ -105,7 +103,6 @@ class DownloadCommand(RequirementCommand):
105
103
  )
106
104
 
107
105
  reqs = self.get_requirements(args, options, finder, session)
108
- check_legacy_setup_py_options(options, reqs)
109
106
 
110
107
  preparer = self.make_requirement_preparer(
111
108
  temp_build_dir=directory,
@@ -123,7 +120,6 @@ class DownloadCommand(RequirementCommand):
123
120
  finder=finder,
124
121
  options=options,
125
122
  ignore_requires_python=options.ignore_requires_python,
126
- use_pep517=options.use_pep517,
127
123
  py_version_info=options.python_version,
128
124
  )
129
125
 
@@ -131,15 +127,15 @@ class DownloadCommand(RequirementCommand):
131
127
 
132
128
  requirement_set = resolver.resolve(reqs, check_supported_wheels=True)
133
129
 
134
- downloaded: List[str] = []
130
+ preparer.prepare_linked_requirements_more(requirement_set.requirements.values())
131
+
132
+ downloaded: list[str] = []
135
133
  for req in requirement_set.requirements.values():
136
134
  if req.satisfied_by is None:
137
135
  assert req.name is not None
138
136
  preparer.save_linked_requirement(req)
139
137
  downloaded.append(req.name)
140
138
 
141
- preparer.prepare_linked_requirements_more(requirement_set.requirements.values())
142
-
143
139
  if downloaded:
144
140
  write_output("Successfully downloaded %s", " ".join(downloaded))
145
141
 
@@ -1,6 +1,5 @@
1
1
  import sys
2
2
  from optparse import Values
3
- from typing import AbstractSet, List
4
3
 
5
4
  from pip._internal.cli import cmdoptions
6
5
  from pip._internal.cli.base_command import Command
@@ -13,7 +12,7 @@ def _should_suppress_build_backends() -> bool:
13
12
  return sys.version_info < (3, 12)
14
13
 
15
14
 
16
- def _dev_pkgs() -> AbstractSet[str]:
15
+ def _dev_pkgs() -> set[str]:
17
16
  pkgs = {"pip"}
18
17
 
19
18
  if _should_suppress_build_backends():
@@ -85,7 +84,7 @@ class FreezeCommand(Command):
85
84
 
86
85
  self.parser.insert_option_group(0, self.cmd_opts)
87
86
 
88
- def run(self, options: Values, args: List[str]) -> int:
87
+ def run(self, options: Values, args: list[str]) -> int:
89
88
  skip = set(stdlib_pkgs)
90
89
  if not options.freeze_all:
91
90
  skip.update(_dev_pkgs())
@@ -2,7 +2,6 @@ import hashlib
2
2
  import logging
3
3
  import sys
4
4
  from optparse import Values
5
- from typing import List
6
5
 
7
6
  from pip._internal.cli.base_command import Command
8
7
  from pip._internal.cli.status_codes import ERROR, SUCCESS
@@ -37,7 +36,7 @@ class HashCommand(Command):
37
36
  )
38
37
  self.parser.insert_option_group(0, self.cmd_opts)
39
38
 
40
- def run(self, options: Values, args: List[str]) -> int:
39
+ def run(self, options: Values, args: list[str]) -> int:
41
40
  if not args:
42
41
  self.parser.print_usage(sys.stderr)
43
42
  return ERROR
@@ -1,5 +1,4 @@
1
1
  from optparse import Values
2
- from typing import List
3
2
 
4
3
  from pip._internal.cli.base_command import Command
5
4
  from pip._internal.cli.status_codes import SUCCESS
@@ -13,7 +12,7 @@ class HelpCommand(Command):
13
12
  %prog <command>"""
14
13
  ignore_require_venv = True
15
14
 
16
- def run(self, options: Values, args: List[str]) -> int:
15
+ def run(self, options: Values, args: list[str]) -> int:
17
16
  from pip._internal.commands import (
18
17
  commands_dict,
19
18
  create_command,
@@ -1,7 +1,10 @@
1
+ from __future__ import annotations
2
+
1
3
  import json
2
4
  import logging
5
+ from collections.abc import Iterable
3
6
  from optparse import Values
4
- from typing import Any, Iterable, List, Optional
7
+ from typing import Any, Callable
5
8
 
6
9
  from pip._vendor.packaging.version import Version
7
10
 
@@ -50,16 +53,19 @@ class IndexCommand(IndexGroupCommand):
50
53
  self.parser.insert_option_group(0, index_opts)
51
54
  self.parser.insert_option_group(0, self.cmd_opts)
52
55
 
53
- def run(self, options: Values, args: List[str]) -> int:
54
- handlers = {
56
+ def handler_map(self) -> dict[str, Callable[[Values, list[str]], None]]:
57
+ return {
55
58
  "versions": self.get_available_package_versions,
56
59
  }
57
60
 
61
+ def run(self, options: Values, args: list[str]) -> int:
62
+ handler_map = self.handler_map()
63
+
58
64
  # Determine action
59
- if not args or args[0] not in handlers:
65
+ if not args or args[0] not in handler_map:
60
66
  logger.error(
61
67
  "Need an action (%s) to perform.",
62
- ", ".join(sorted(handlers)),
68
+ ", ".join(sorted(handler_map)),
63
69
  )
64
70
  return ERROR
65
71
 
@@ -67,7 +73,7 @@ class IndexCommand(IndexGroupCommand):
67
73
 
68
74
  # Error handling happens here, not in the action-handlers.
69
75
  try:
70
- handlers[action](options, args[1:])
76
+ handler_map[action](options, args[1:])
71
77
  except PipError as e:
72
78
  logger.error(e.args[0])
73
79
  return ERROR
@@ -78,8 +84,8 @@ class IndexCommand(IndexGroupCommand):
78
84
  self,
79
85
  options: Values,
80
86
  session: PipSession,
81
- target_python: Optional[TargetPython] = None,
82
- ignore_requires_python: Optional[bool] = None,
87
+ target_python: TargetPython | None = None,
88
+ ignore_requires_python: bool | None = None,
83
89
  ) -> PackageFinder:
84
90
  """
85
91
  Create a package finder appropriate to the index command.
@@ -99,7 +105,7 @@ class IndexCommand(IndexGroupCommand):
99
105
  target_python=target_python,
100
106
  )
101
107
 
102
- def get_available_package_versions(self, options: Values, args: List[Any]) -> None:
108
+ def get_available_package_versions(self, options: Values, args: list[Any]) -> None:
103
109
  if len(args) != 1:
104
110
  raise CommandError("You need to specify exactly one argument")
105
111
 
@@ -1,6 +1,6 @@
1
1
  import logging
2
2
  from optparse import Values
3
- from typing import Any, Dict, List
3
+ from typing import Any
4
4
 
5
5
  from pip._vendor.packaging.markers import default_environment
6
6
  from pip._vendor.rich import print_json
@@ -45,7 +45,7 @@ class InspectCommand(Command):
45
45
  self.cmd_opts.add_option(cmdoptions.list_path())
46
46
  self.parser.insert_option_group(0, self.cmd_opts)
47
47
 
48
- def run(self, options: Values, args: List[str]) -> int:
48
+ def run(self, options: Values, args: list[str]) -> int:
49
49
  cmdoptions.check_list_path_option(options)
50
50
  dists = get_environment(options.path).iter_installed_distributions(
51
51
  local_only=options.local,
@@ -62,8 +62,8 @@ class InspectCommand(Command):
62
62
  print_json(data=output)
63
63
  return SUCCESS
64
64
 
65
- def _dist_to_dict(self, dist: BaseDistribution) -> Dict[str, Any]:
66
- res: Dict[str, Any] = {
65
+ def _dist_to_dict(self, dist: BaseDistribution) -> dict[str, Any]:
66
+ res: dict[str, Any] = {
67
67
  "metadata": dist.metadata_dict,
68
68
  "metadata_location": dist.info_location,
69
69
  }
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import errno
2
4
  import json
3
5
  import operator
@@ -5,7 +7,7 @@ import os
5
7
  import shutil
6
8
  import site
7
9
  from optparse import SUPPRESS_HELP, Values
8
- from typing import List, Optional
10
+ from pathlib import Path
9
11
 
10
12
  from pip._vendor.packaging.utils import canonicalize_name
11
13
  from pip._vendor.requests.exceptions import InvalidProxyURL
@@ -26,7 +28,11 @@ from pip._internal.cli.req_command import (
26
28
  with_cleanup,
27
29
  )
28
30
  from pip._internal.cli.status_codes import ERROR, SUCCESS
29
- from pip._internal.exceptions import CommandError, InstallationError
31
+ from pip._internal.exceptions import (
32
+ CommandError,
33
+ InstallationError,
34
+ InstallWheelBuildError,
35
+ )
30
36
  from pip._internal.locations import get_scheme
31
37
  from pip._internal.metadata import get_environment
32
38
  from pip._internal.models.installation_report import InstallationReport
@@ -35,7 +41,6 @@ from pip._internal.operations.check import ConflictDetails, check_install_confli
35
41
  from pip._internal.req import install_given_reqs
36
42
  from pip._internal.req.req_install import (
37
43
  InstallRequirement,
38
- check_legacy_setup_py_options,
39
44
  )
40
45
  from pip._internal.utils.compat import WINDOWS
41
46
  from pip._internal.utils.filesystem import test_writable_dir
@@ -53,7 +58,7 @@ from pip._internal.utils.virtualenv import (
53
58
  running_under_virtualenv,
54
59
  virtualenv_no_global,
55
60
  )
56
- from pip._internal.wheel_builder import build, should_build_for_install_command
61
+ from pip._internal.wheel_builder import build
57
62
 
58
63
  logger = getLogger(__name__)
59
64
 
@@ -81,6 +86,7 @@ class InstallCommand(RequirementCommand):
81
86
  def add_options(self) -> None:
82
87
  self.cmd_opts.add_option(cmdoptions.requirements())
83
88
  self.cmd_opts.add_option(cmdoptions.constraints())
89
+ self.cmd_opts.add_option(cmdoptions.build_constraints())
84
90
  self.cmd_opts.add_option(cmdoptions.no_deps())
85
91
  self.cmd_opts.add_option(cmdoptions.pre())
86
92
 
@@ -204,12 +210,10 @@ class InstallCommand(RequirementCommand):
204
210
  self.cmd_opts.add_option(cmdoptions.ignore_requires_python())
205
211
  self.cmd_opts.add_option(cmdoptions.no_build_isolation())
206
212
  self.cmd_opts.add_option(cmdoptions.use_pep517())
207
- self.cmd_opts.add_option(cmdoptions.no_use_pep517())
208
213
  self.cmd_opts.add_option(cmdoptions.check_build_deps())
209
214
  self.cmd_opts.add_option(cmdoptions.override_externally_managed())
210
215
 
211
216
  self.cmd_opts.add_option(cmdoptions.config_settings())
212
- self.cmd_opts.add_option(cmdoptions.global_options())
213
217
 
214
218
  self.cmd_opts.add_option(
215
219
  "--compile",
@@ -272,7 +276,7 @@ class InstallCommand(RequirementCommand):
272
276
  )
273
277
 
274
278
  @with_cleanup
275
- def run(self, options: Values, args: List[str]) -> int:
279
+ def run(self, options: Values, args: list[str]) -> int:
276
280
  if options.use_user_site and options.target_dir is not None:
277
281
  raise CommandError("Can not combine '--user' and '--target'")
278
282
 
@@ -297,6 +301,7 @@ class InstallCommand(RequirementCommand):
297
301
  if options.upgrade:
298
302
  upgrade_strategy = options.upgrade_strategy
299
303
 
304
+ cmdoptions.check_build_constraints(options)
300
305
  cmdoptions.check_dist_restriction(options, check_target=True)
301
306
 
302
307
  logger.verbose("Using %s", get_pip_version())
@@ -308,8 +313,8 @@ class InstallCommand(RequirementCommand):
308
313
  isolated_mode=options.isolated_mode,
309
314
  )
310
315
 
311
- target_temp_dir: Optional[TempDirectory] = None
312
- target_temp_dir_path: Optional[str] = None
316
+ target_temp_dir: TempDirectory | None = None
317
+ target_temp_dir_path: str | None = None
313
318
  if options.target_dir:
314
319
  options.ignore_installed = True
315
320
  options.target_dir = os.path.abspath(options.target_dir)
@@ -328,8 +333,6 @@ class InstallCommand(RequirementCommand):
328
333
  target_temp_dir_path = target_temp_dir.path
329
334
  self.enter_context(target_temp_dir)
330
335
 
331
- global_options = options.global_options or []
332
-
333
336
  session = self.get_default_session(options)
334
337
 
335
338
  target_python = make_target_python(options)
@@ -349,7 +352,6 @@ class InstallCommand(RequirementCommand):
349
352
 
350
353
  try:
351
354
  reqs = self.get_requirements(args, options, finder, session)
352
- check_legacy_setup_py_options(options, reqs)
353
355
 
354
356
  wheel_cache = WheelCache(options.cache_dir)
355
357
 
@@ -378,7 +380,6 @@ class InstallCommand(RequirementCommand):
378
380
  ignore_requires_python=options.ignore_requires_python,
379
381
  force_reinstall=options.force_reinstall,
380
382
  upgrade_strategy=upgrade_strategy,
381
- use_pep517=options.use_pep517,
382
383
  py_version_info=options.python_version,
383
384
  )
384
385
 
@@ -408,6 +409,13 @@ class InstallCommand(RequirementCommand):
408
409
  )
409
410
  return SUCCESS
410
411
 
412
+ # If there is any more preparation to do for the actual installation, do
413
+ # so now. This includes actually downloading the files in the case that
414
+ # we have been using PEP-658 metadata so far.
415
+ preparer.prepare_linked_requirements_more(
416
+ requirement_set.requirements.values()
417
+ )
418
+
411
419
  try:
412
420
  pip_req = requirement_set.get_requirement("pip")
413
421
  except KeyError:
@@ -419,31 +427,22 @@ class InstallCommand(RequirementCommand):
419
427
  protect_pip_from_modification_on_windows(modifying_pip=modifying_pip)
420
428
 
421
429
  reqs_to_build = [
422
- r
423
- for r in requirement_set.requirements_to_install
424
- if should_build_for_install_command(r)
430
+ r for r in requirement_set.requirements_to_install if not r.is_wheel
425
431
  ]
426
432
 
427
433
  _, build_failures = build(
428
434
  reqs_to_build,
429
435
  wheel_cache=wheel_cache,
430
436
  verify=True,
431
- build_options=[],
432
- global_options=global_options,
433
437
  )
434
438
 
435
439
  if build_failures:
436
- raise InstallationError(
437
- "Failed to build installable wheels for some "
438
- "pyproject.toml based projects ({})".format(
439
- ", ".join(r.name for r in build_failures) # type: ignore
440
- )
441
- )
440
+ raise InstallWheelBuildError(build_failures)
442
441
 
443
442
  to_install = resolver.get_installation_order(requirement_set)
444
443
 
445
444
  # Check for conflicts in the package set we're installing.
446
- conflicts: Optional[ConflictDetails] = None
445
+ conflicts: ConflictDetails | None = None
447
446
  should_warn_about_conflicts = (
448
447
  not options.ignore_dependencies and options.warn_about_conflicts
449
448
  )
@@ -458,7 +457,6 @@ class InstallCommand(RequirementCommand):
458
457
 
459
458
  installed = install_given_reqs(
460
459
  to_install,
461
- global_options,
462
460
  root=options.root_path,
463
461
  home=target_temp_dir_path,
464
462
  prefix=options.prefix_path,
@@ -581,8 +579,8 @@ class InstallCommand(RequirementCommand):
581
579
  shutil.move(os.path.join(lib_dir, item), target_item_dir)
582
580
 
583
581
  def _determine_conflicts(
584
- self, to_install: List[InstallRequirement]
585
- ) -> Optional[ConflictDetails]:
582
+ self, to_install: list[InstallRequirement]
583
+ ) -> ConflictDetails | None:
586
584
  try:
587
585
  return check_install_conflicts(to_install)
588
586
  except Exception:
@@ -599,7 +597,7 @@ class InstallCommand(RequirementCommand):
599
597
  if not missing and not conflicting:
600
598
  return
601
599
 
602
- parts: List[str] = []
600
+ parts: list[str] = []
603
601
  if resolver_variant == "legacy":
604
602
  parts.append(
605
603
  "pip's legacy dependency resolver does not consider dependency "
@@ -645,11 +643,11 @@ class InstallCommand(RequirementCommand):
645
643
 
646
644
  def get_lib_location_guesses(
647
645
  user: bool = False,
648
- home: Optional[str] = None,
649
- root: Optional[str] = None,
646
+ home: str | None = None,
647
+ root: str | None = None,
650
648
  isolated: bool = False,
651
- prefix: Optional[str] = None,
652
- ) -> List[str]:
649
+ prefix: str | None = None,
650
+ ) -> list[str]:
653
651
  scheme = get_scheme(
654
652
  "",
655
653
  user=user,
@@ -661,7 +659,7 @@ def get_lib_location_guesses(
661
659
  return [scheme.purelib, scheme.platlib]
662
660
 
663
661
 
664
- def site_packages_writable(root: Optional[str], isolated: bool) -> bool:
662
+ def site_packages_writable(root: str | None, isolated: bool) -> bool:
665
663
  return all(
666
664
  test_writable_dir(d)
667
665
  for d in set(get_lib_location_guesses(root=root, isolated=isolated))
@@ -669,10 +667,10 @@ def site_packages_writable(root: Optional[str], isolated: bool) -> bool:
669
667
 
670
668
 
671
669
  def decide_user_install(
672
- use_user_site: Optional[bool],
673
- prefix_path: Optional[str] = None,
674
- target_dir: Optional[str] = None,
675
- root_path: Optional[str] = None,
670
+ use_user_site: bool | None,
671
+ prefix_path: str | None = None,
672
+ target_dir: str | None = None,
673
+ root_path: str | None = None,
676
674
  isolated_mode: bool = False,
677
675
  ) -> bool:
678
676
  """Determine whether to do a user install based on the input options.
@@ -689,6 +687,7 @@ def decide_user_install(
689
687
  logger.debug("Non-user install by explicit request")
690
688
  return False
691
689
 
690
+ # If we have been asked for a user install explicitly, check compatibility.
692
691
  if use_user_site:
693
692
  if prefix_path:
694
693
  raise CommandError(
@@ -700,6 +699,13 @@ def decide_user_install(
700
699
  "Can not perform a '--user' install. User site-packages "
701
700
  "are not visible in this virtualenv."
702
701
  )
702
+ # Catch all remaining cases which honour the site.ENABLE_USER_SITE
703
+ # value, such as a plain Python installation (e.g. no virtualenv).
704
+ if not site.ENABLE_USER_SITE:
705
+ raise InstallationError(
706
+ "Can not perform a '--user' install. User site-packages "
707
+ "are disabled for this Python."
708
+ )
703
709
  logger.debug("User install by explicit request")
704
710
  return True
705
711
 
@@ -774,20 +780,24 @@ def create_os_error_message(
774
780
  )
775
781
  parts.append(".\n")
776
782
 
777
- # Suggest the user to enable Long Paths if path length is
778
- # more than 260
779
- if (
780
- WINDOWS
781
- and error.errno == errno.ENOENT
782
- and error.filename
783
- and len(error.filename) > 260
784
- ):
785
- parts.append(
786
- "HINT: This error might have occurred since "
787
- "this system does not have Windows Long Path "
788
- "support enabled. You can find information on "
789
- "how to enable this at "
790
- "https://pip.pypa.io/warnings/enable-long-paths\n"
791
- )
783
+ # On Windows, errors like EINVAL or ENOENT may occur
784
+ # if a file or folder name exceeds 255 characters,
785
+ # or if the full path exceeds 260 characters and long path support isn't enabled.
786
+ # This condition checks for such cases and adds a hint to the error output.
792
787
 
788
+ if WINDOWS and error.errno in (errno.EINVAL, errno.ENOENT) and error.filename:
789
+ if any(len(part) > 255 for part in Path(error.filename).parts):
790
+ parts.append(
791
+ "HINT: This error might be caused by a file or folder name exceeding "
792
+ "255 characters, which is a Windows limitation even if long paths "
793
+ "are enabled.\n "
794
+ )
795
+ if len(error.filename) > 260:
796
+ parts.append(
797
+ "HINT: This error might have occurred since "
798
+ "this system does not have Windows Long Path "
799
+ "support enabled. You can find information on "
800
+ "how to enable this at "
801
+ "https://pip.pypa.io/warnings/enable-long-paths\n"
802
+ )
793
803
  return "".join(parts).strip() + "\n"