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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) 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 +45 -40
  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 +53 -44
  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 +9 -8
  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 +54 -44
  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/dependency_groups/_implementation.py +7 -11
  133. pip/_vendor/distlib/__init__.py +2 -2
  134. pip/_vendor/distlib/scripts.py +1 -1
  135. pip/_vendor/msgpack/__init__.py +2 -2
  136. pip/_vendor/pkg_resources/__init__.py +1 -1
  137. pip/_vendor/platformdirs/version.py +2 -2
  138. pip/_vendor/pygments/__init__.py +1 -1
  139. pip/_vendor/requests/__version__.py +2 -2
  140. pip/_vendor/requests/compat.py +12 -0
  141. pip/_vendor/requests/models.py +3 -1
  142. pip/_vendor/requests/utils.py +6 -16
  143. pip/_vendor/resolvelib/__init__.py +3 -3
  144. pip/_vendor/resolvelib/reporters.py +1 -1
  145. pip/_vendor/resolvelib/resolvers/__init__.py +4 -4
  146. pip/_vendor/resolvelib/resolvers/resolution.py +91 -10
  147. pip/_vendor/rich/__main__.py +12 -40
  148. pip/_vendor/rich/_inspect.py +1 -1
  149. pip/_vendor/rich/_ratio.py +1 -7
  150. pip/_vendor/rich/align.py +1 -7
  151. pip/_vendor/rich/box.py +1 -7
  152. pip/_vendor/rich/console.py +25 -20
  153. pip/_vendor/rich/control.py +1 -7
  154. pip/_vendor/rich/diagnose.py +1 -0
  155. pip/_vendor/rich/emoji.py +1 -6
  156. pip/_vendor/rich/live.py +32 -7
  157. pip/_vendor/rich/live_render.py +1 -7
  158. pip/_vendor/rich/logging.py +1 -1
  159. pip/_vendor/rich/panel.py +3 -4
  160. pip/_vendor/rich/progress.py +15 -15
  161. pip/_vendor/rich/spinner.py +7 -13
  162. pip/_vendor/rich/syntax.py +24 -5
  163. pip/_vendor/rich/traceback.py +32 -17
  164. pip/_vendor/truststore/_api.py +1 -1
  165. pip/_vendor/vendor.txt +10 -11
  166. {pip-25.1.dist-info → pip-25.2.dist-info}/METADATA +26 -4
  167. {pip-25.1.dist-info → pip-25.2.dist-info}/RECORD +194 -181
  168. {pip-25.1.dist-info → pip-25.2.dist-info}/WHEEL +1 -1
  169. {pip-25.1.dist-info → pip-25.2.dist-info}/licenses/AUTHORS.txt +12 -0
  170. pip-25.2.dist-info/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt +13 -0
  171. pip-25.2.dist-info/licenses/src/pip/_vendor/certifi/LICENSE +20 -0
  172. pip-25.2.dist-info/licenses/src/pip/_vendor/dependency_groups/LICENSE.txt +9 -0
  173. pip-25.2.dist-info/licenses/src/pip/_vendor/distlib/LICENSE.txt +284 -0
  174. pip-25.2.dist-info/licenses/src/pip/_vendor/distro/LICENSE +202 -0
  175. pip-25.2.dist-info/licenses/src/pip/_vendor/idna/LICENSE.md +31 -0
  176. pip-25.2.dist-info/licenses/src/pip/_vendor/msgpack/COPYING +14 -0
  177. pip-25.2.dist-info/licenses/src/pip/_vendor/packaging/LICENSE +3 -0
  178. pip-25.2.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.APACHE +177 -0
  179. pip-25.2.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.BSD +23 -0
  180. pip-25.2.dist-info/licenses/src/pip/_vendor/pkg_resources/LICENSE +17 -0
  181. pip-25.2.dist-info/licenses/src/pip/_vendor/platformdirs/LICENSE +21 -0
  182. pip-25.2.dist-info/licenses/src/pip/_vendor/pygments/LICENSE +25 -0
  183. pip-25.2.dist-info/licenses/src/pip/_vendor/pyproject_hooks/LICENSE +21 -0
  184. pip-25.2.dist-info/licenses/src/pip/_vendor/requests/LICENSE +175 -0
  185. pip-25.2.dist-info/licenses/src/pip/_vendor/resolvelib/LICENSE +13 -0
  186. pip-25.2.dist-info/licenses/src/pip/_vendor/rich/LICENSE +19 -0
  187. pip-25.2.dist-info/licenses/src/pip/_vendor/tomli/LICENSE +21 -0
  188. pip-25.2.dist-info/licenses/src/pip/_vendor/tomli/LICENSE-HEADER +3 -0
  189. pip-25.2.dist-info/licenses/src/pip/_vendor/tomli_w/LICENSE +21 -0
  190. pip-25.2.dist-info/licenses/src/pip/_vendor/truststore/LICENSE +21 -0
  191. pip-25.2.dist-info/licenses/src/pip/_vendor/urllib3/LICENSE.txt +21 -0
  192. pip/_vendor/distlib/database.py +0 -1329
  193. pip/_vendor/distlib/index.py +0 -508
  194. pip/_vendor/distlib/locators.py +0 -1295
  195. pip/_vendor/distlib/manifest.py +0 -384
  196. pip/_vendor/distlib/markers.py +0 -162
  197. pip/_vendor/distlib/metadata.py +0 -1031
  198. pip/_vendor/distlib/version.py +0 -750
  199. pip/_vendor/distlib/wheel.py +0 -1100
  200. pip/_vendor/typing_extensions.py +0 -4584
  201. {pip-25.1.dist-info → pip-25.2.dist-info}/entry_points.txt +0 -0
  202. {pip-25.1.dist-info → pip-25.2.dist-info}/licenses/LICENSE.txt +0 -0
  203. {pip-25.1.dist-info → pip-25.2.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,6 @@
1
1
  import sys
2
2
  import textwrap
3
3
  from optparse import Values
4
- from typing import List
5
4
 
6
5
  from pip._internal.cli.base_command import Command
7
6
  from pip._internal.cli.status_codes import SUCCESS
@@ -119,7 +118,7 @@ class CompletionCommand(Command):
119
118
 
120
119
  self.parser.insert_option_group(0, self.cmd_opts)
121
120
 
122
- def run(self, options: Values, args: List[str]) -> int:
121
+ def run(self, options: Values, args: list[str]) -> int:
123
122
  """Prints the completion code of the given shell"""
124
123
  shells = COMPLETION_SCRIPTS.keys()
125
124
  shell_options = ["--" + shell for shell in sorted(shells)]
@@ -1,8 +1,10 @@
1
+ from __future__ import annotations
2
+
1
3
  import logging
2
4
  import os
3
5
  import subprocess
4
6
  from optparse import Values
5
- from typing import Any, List, Optional
7
+ from typing import Any, Callable
6
8
 
7
9
  from pip._internal.cli.base_command import Command
8
10
  from pip._internal.cli.status_codes import ERROR, SUCCESS
@@ -93,8 +95,8 @@ class ConfigurationCommand(Command):
93
95
 
94
96
  self.parser.insert_option_group(0, self.cmd_opts)
95
97
 
96
- def run(self, options: Values, args: List[str]) -> int:
97
- handlers = {
98
+ def handler_map(self) -> dict[str, Callable[[Values, list[str]], None]]:
99
+ return {
98
100
  "list": self.list_values,
99
101
  "edit": self.open_in_editor,
100
102
  "get": self.get_name,
@@ -103,11 +105,14 @@ class ConfigurationCommand(Command):
103
105
  "debug": self.list_config_values,
104
106
  }
105
107
 
108
+ def run(self, options: Values, args: list[str]) -> int:
109
+ handler_map = self.handler_map()
110
+
106
111
  # Determine action
107
- if not args or args[0] not in handlers:
112
+ if not args or args[0] not in handler_map:
108
113
  logger.error(
109
114
  "Need an action (%s) to perform.",
110
- ", ".join(sorted(handlers)),
115
+ ", ".join(sorted(handler_map)),
111
116
  )
112
117
  return ERROR
113
118
 
@@ -131,14 +136,14 @@ class ConfigurationCommand(Command):
131
136
 
132
137
  # Error handling happens here, not in the action-handlers.
133
138
  try:
134
- handlers[action](options, args[1:])
139
+ handler_map[action](options, args[1:])
135
140
  except PipError as e:
136
141
  logger.error(e.args[0])
137
142
  return ERROR
138
143
 
139
144
  return SUCCESS
140
145
 
141
- def _determine_file(self, options: Values, need_value: bool) -> Optional[Kind]:
146
+ def _determine_file(self, options: Values, need_value: bool) -> Kind | None:
142
147
  file_options = [
143
148
  key
144
149
  for key, value in (
@@ -168,31 +173,32 @@ class ConfigurationCommand(Command):
168
173
  "(--user, --site, --global) to perform."
169
174
  )
170
175
 
171
- def list_values(self, options: Values, args: List[str]) -> None:
176
+ def list_values(self, options: Values, args: list[str]) -> None:
172
177
  self._get_n_args(args, "list", n=0)
173
178
 
174
179
  for key, value in sorted(self.configuration.items()):
175
- write_output("%s=%r", key, value)
180
+ for key, value in sorted(value.items()):
181
+ write_output("%s=%r", key, value)
176
182
 
177
- def get_name(self, options: Values, args: List[str]) -> None:
183
+ def get_name(self, options: Values, args: list[str]) -> None:
178
184
  key = self._get_n_args(args, "get [name]", n=1)
179
185
  value = self.configuration.get_value(key)
180
186
 
181
187
  write_output("%s", value)
182
188
 
183
- def set_name_value(self, options: Values, args: List[str]) -> None:
189
+ def set_name_value(self, options: Values, args: list[str]) -> None:
184
190
  key, value = self._get_n_args(args, "set [name] [value]", n=2)
185
191
  self.configuration.set_value(key, value)
186
192
 
187
193
  self._save_configuration()
188
194
 
189
- def unset_name(self, options: Values, args: List[str]) -> None:
195
+ def unset_name(self, options: Values, args: list[str]) -> None:
190
196
  key = self._get_n_args(args, "unset [name]", n=1)
191
197
  self.configuration.unset_value(key)
192
198
 
193
199
  self._save_configuration()
194
200
 
195
- def list_config_values(self, options: Values, args: List[str]) -> None:
201
+ def list_config_values(self, options: Values, args: list[str]) -> None:
196
202
  """List config key-value pairs across different config files"""
197
203
  self._get_n_args(args, "debug", n=0)
198
204
 
@@ -206,13 +212,15 @@ class ConfigurationCommand(Command):
206
212
  file_exists = os.path.exists(fname)
207
213
  write_output("%s, exists: %r", fname, file_exists)
208
214
  if file_exists:
209
- self.print_config_file_values(variant)
215
+ self.print_config_file_values(variant, fname)
210
216
 
211
- def print_config_file_values(self, variant: Kind) -> None:
217
+ def print_config_file_values(self, variant: Kind, fname: str) -> None:
212
218
  """Get key-value pairs from the file of a variant"""
213
219
  for name, value in self.configuration.get_values_in_config(variant).items():
214
220
  with indent_log():
215
- write_output("%s: %s", name, value)
221
+ if name == fname:
222
+ for confname, confvalue in value.items():
223
+ write_output("%s: %s", confname, confvalue)
216
224
 
217
225
  def print_env_var_values(self) -> None:
218
226
  """Get key-values pairs present as environment variables"""
@@ -222,7 +230,7 @@ class ConfigurationCommand(Command):
222
230
  env_var = f"PIP_{key.upper()}"
223
231
  write_output("%s=%r", env_var, value)
224
232
 
225
- def open_in_editor(self, options: Values, args: List[str]) -> None:
233
+ def open_in_editor(self, options: Values, args: list[str]) -> None:
226
234
  editor = self._determine_editor(options)
227
235
 
228
236
  fname = self.configuration.get_file_to_edit()
@@ -244,7 +252,7 @@ class ConfigurationCommand(Command):
244
252
  except subprocess.CalledProcessError as e:
245
253
  raise PipError(f"Editor Subprocess exited with exit code {e.returncode}")
246
254
 
247
- def _get_n_args(self, args: List[str], example: str, n: int) -> Any:
255
+ def _get_n_args(self, args: list[str], example: str, n: int) -> Any:
248
256
  """Helper to make sure the command got the right number of arguments"""
249
257
  if len(args) != n:
250
258
  msg = (
@@ -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,7 +1,6 @@
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
@@ -75,7 +74,7 @@ class DownloadCommand(RequirementCommand):
75
74
  self.parser.insert_option_group(0, self.cmd_opts)
76
75
 
77
76
  @with_cleanup
78
- def run(self, options: Values, args: List[str]) -> int:
77
+ def run(self, options: Values, args: list[str]) -> int:
79
78
  options.ignore_installed = True
80
79
  # editable doesn't really make sense for `pip download`, but the bowels
81
80
  # of the RequirementSet code require that property.
@@ -131,7 +130,7 @@ class DownloadCommand(RequirementCommand):
131
130
 
132
131
  requirement_set = resolver.resolve(reqs, check_supported_wheels=True)
133
132
 
134
- downloaded: List[str] = []
133
+ downloaded: list[str] = []
135
134
  for req in requirement_set.requirements.values():
136
135
  if req.satisfied_by is None:
137
136
  assert req.name is not None
@@ -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
@@ -272,7 +278,7 @@ class InstallCommand(RequirementCommand):
272
278
  )
273
279
 
274
280
  @with_cleanup
275
- def run(self, options: Values, args: List[str]) -> int:
281
+ def run(self, options: Values, args: list[str]) -> int:
276
282
  if options.use_user_site and options.target_dir is not None:
277
283
  raise CommandError("Can not combine '--user' and '--target'")
278
284
 
@@ -308,8 +314,8 @@ class InstallCommand(RequirementCommand):
308
314
  isolated_mode=options.isolated_mode,
309
315
  )
310
316
 
311
- target_temp_dir: Optional[TempDirectory] = None
312
- target_temp_dir_path: Optional[str] = None
317
+ target_temp_dir: TempDirectory | None = None
318
+ target_temp_dir_path: str | None = None
313
319
  if options.target_dir:
314
320
  options.ignore_installed = True
315
321
  options.target_dir = os.path.abspath(options.target_dir)
@@ -420,7 +426,7 @@ class InstallCommand(RequirementCommand):
420
426
 
421
427
  reqs_to_build = [
422
428
  r
423
- for r in requirement_set.requirements.values()
429
+ for r in requirement_set.requirements_to_install
424
430
  if should_build_for_install_command(r)
425
431
  ]
426
432
 
@@ -433,17 +439,12 @@ class InstallCommand(RequirementCommand):
433
439
  )
434
440
 
435
441
  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
- )
442
+ raise InstallWheelBuildError(build_failures)
442
443
 
443
444
  to_install = resolver.get_installation_order(requirement_set)
444
445
 
445
446
  # Check for conflicts in the package set we're installing.
446
- conflicts: Optional[ConflictDetails] = None
447
+ conflicts: ConflictDetails | None = None
447
448
  should_warn_about_conflicts = (
448
449
  not options.ignore_dependencies and options.warn_about_conflicts
449
450
  )
@@ -581,8 +582,8 @@ class InstallCommand(RequirementCommand):
581
582
  shutil.move(os.path.join(lib_dir, item), target_item_dir)
582
583
 
583
584
  def _determine_conflicts(
584
- self, to_install: List[InstallRequirement]
585
- ) -> Optional[ConflictDetails]:
585
+ self, to_install: list[InstallRequirement]
586
+ ) -> ConflictDetails | None:
586
587
  try:
587
588
  return check_install_conflicts(to_install)
588
589
  except Exception:
@@ -599,7 +600,7 @@ class InstallCommand(RequirementCommand):
599
600
  if not missing and not conflicting:
600
601
  return
601
602
 
602
- parts: List[str] = []
603
+ parts: list[str] = []
603
604
  if resolver_variant == "legacy":
604
605
  parts.append(
605
606
  "pip's legacy dependency resolver does not consider dependency "
@@ -645,11 +646,11 @@ class InstallCommand(RequirementCommand):
645
646
 
646
647
  def get_lib_location_guesses(
647
648
  user: bool = False,
648
- home: Optional[str] = None,
649
- root: Optional[str] = None,
649
+ home: str | None = None,
650
+ root: str | None = None,
650
651
  isolated: bool = False,
651
- prefix: Optional[str] = None,
652
- ) -> List[str]:
652
+ prefix: str | None = None,
653
+ ) -> list[str]:
653
654
  scheme = get_scheme(
654
655
  "",
655
656
  user=user,
@@ -661,7 +662,7 @@ def get_lib_location_guesses(
661
662
  return [scheme.purelib, scheme.platlib]
662
663
 
663
664
 
664
- def site_packages_writable(root: Optional[str], isolated: bool) -> bool:
665
+ def site_packages_writable(root: str | None, isolated: bool) -> bool:
665
666
  return all(
666
667
  test_writable_dir(d)
667
668
  for d in set(get_lib_location_guesses(root=root, isolated=isolated))
@@ -669,10 +670,10 @@ def site_packages_writable(root: Optional[str], isolated: bool) -> bool:
669
670
 
670
671
 
671
672
  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,
673
+ use_user_site: bool | None,
674
+ prefix_path: str | None = None,
675
+ target_dir: str | None = None,
676
+ root_path: str | None = None,
676
677
  isolated_mode: bool = False,
677
678
  ) -> bool:
678
679
  """Determine whether to do a user install based on the input options.
@@ -774,20 +775,24 @@ def create_os_error_message(
774
775
  )
775
776
  parts.append(".\n")
776
777
 
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
- )
778
+ # On Windows, errors like EINVAL or ENOENT may occur
779
+ # if a file or folder name exceeds 255 characters,
780
+ # or if the full path exceeds 260 characters and long path support isn't enabled.
781
+ # This condition checks for such cases and adds a hint to the error output.
792
782
 
783
+ if WINDOWS and error.errno in (errno.EINVAL, errno.ENOENT) and error.filename:
784
+ if any(len(part) > 255 for part in Path(error.filename).parts):
785
+ parts.append(
786
+ "HINT: This error might be caused by a file or folder name exceeding "
787
+ "255 characters, which is a Windows limitation even if long paths "
788
+ "are enabled.\n "
789
+ )
790
+ if len(error.filename) > 260:
791
+ parts.append(
792
+ "HINT: This error might have occurred since "
793
+ "this system does not have Windows Long Path "
794
+ "support enabled. You can find information on "
795
+ "how to enable this at "
796
+ "https://pip.pypa.io/warnings/enable-long-paths\n"
797
+ )
793
798
  return "".join(parts).strip() + "\n"