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,11 +1,14 @@
1
1
  """Lazy ZIP over HTTP"""
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  __all__ = ["HTTPRangeRequestUnsupported", "dist_from_wheel_url"]
4
6
 
5
7
  from bisect import bisect_left, bisect_right
8
+ from collections.abc import Generator
6
9
  from contextlib import contextmanager
7
10
  from tempfile import NamedTemporaryFile
8
- from typing import Any, Dict, Generator, List, Optional, Tuple
11
+ from typing import Any
9
12
  from zipfile import BadZipFile, ZipFile
10
13
 
11
14
  from pip._vendor.packaging.utils import canonicalize_name
@@ -56,8 +59,8 @@ class LazyZipOverHTTP:
56
59
  self._length = int(head.headers["Content-Length"])
57
60
  self._file = NamedTemporaryFile()
58
61
  self.truncate(self._length)
59
- self._left: List[int] = []
60
- self._right: List[int] = []
62
+ self._left: list[int] = []
63
+ self._right: list[int] = []
61
64
  if "bytes" not in head.headers.get("Accept-Ranges", "none"):
62
65
  raise HTTPRangeRequestUnsupported("range request is not supported")
63
66
  self._check_zip()
@@ -117,7 +120,7 @@ class LazyZipOverHTTP:
117
120
  """Return the current position."""
118
121
  return self._file.tell()
119
122
 
120
- def truncate(self, size: Optional[int] = None) -> int:
123
+ def truncate(self, size: int | None = None) -> int:
121
124
  """Resize the stream to the given size in bytes.
122
125
 
123
126
  If size is unspecified resize to the current position.
@@ -131,7 +134,7 @@ class LazyZipOverHTTP:
131
134
  """Return False."""
132
135
  return False
133
136
 
134
- def __enter__(self) -> "LazyZipOverHTTP":
137
+ def __enter__(self) -> LazyZipOverHTTP:
135
138
  self._file.__enter__()
136
139
  return self
137
140
 
@@ -166,7 +169,7 @@ class LazyZipOverHTTP:
166
169
  break
167
170
 
168
171
  def _stream_response(
169
- self, start: int, end: int, base_headers: Dict[str, str] = HEADERS
172
+ self, start: int, end: int, base_headers: dict[str, str] = HEADERS
170
173
  ) -> Response:
171
174
  """Return HTTP response to a range request from start to end."""
172
175
  headers = base_headers.copy()
@@ -177,7 +180,7 @@ class LazyZipOverHTTP:
177
180
 
178
181
  def _merge(
179
182
  self, start: int, end: int, left: int, right: int
180
- ) -> Generator[Tuple[int, int], None, None]:
183
+ ) -> Generator[tuple[int, int], None, None]:
181
184
  """Return a generator of intervals to be fetched.
182
185
 
183
186
  Args:
@@ -2,6 +2,8 @@
2
2
  network request configuration and behavior.
3
3
  """
4
4
 
5
+ from __future__ import annotations
6
+
5
7
  import email.utils
6
8
  import functools
7
9
  import io
@@ -16,16 +18,11 @@ import subprocess
16
18
  import sys
17
19
  import urllib.parse
18
20
  import warnings
21
+ from collections.abc import Generator, Mapping, Sequence
19
22
  from typing import (
20
23
  TYPE_CHECKING,
21
24
  Any,
22
- Dict,
23
- Generator,
24
- List,
25
- Mapping,
26
25
  Optional,
27
- Sequence,
28
- Tuple,
29
26
  Union,
30
27
  )
31
28
 
@@ -54,18 +51,19 @@ if TYPE_CHECKING:
54
51
  from ssl import SSLContext
55
52
 
56
53
  from pip._vendor.urllib3.poolmanager import PoolManager
54
+ from pip._vendor.urllib3.proxymanager import ProxyManager
57
55
 
58
56
 
59
57
  logger = logging.getLogger(__name__)
60
58
 
61
- SecureOrigin = Tuple[str, str, Optional[Union[int, str]]]
59
+ SecureOrigin = tuple[str, str, Optional[Union[int, str]]]
62
60
 
63
61
 
64
62
  # Ignore warning raised when using --trusted-host.
65
63
  warnings.filterwarnings("ignore", category=InsecureRequestWarning)
66
64
 
67
65
 
68
- SECURE_ORIGINS: List[SecureOrigin] = [
66
+ SECURE_ORIGINS: list[SecureOrigin] = [
69
67
  # protocol, hostname, port
70
68
  # Taken from Chrome's list of secure origins (See: http://bit.ly/1qrySKC)
71
69
  ("https", "*", "*"),
@@ -112,7 +110,7 @@ def user_agent() -> str:
112
110
  """
113
111
  Return a string representing the user agent.
114
112
  """
115
- data: Dict[str, Any] = {
113
+ data: dict[str, Any] = {
116
114
  "installer": {"name": "pip", "version": __version__},
117
115
  "python": platform.python_version(),
118
116
  "implementation": {
@@ -140,7 +138,7 @@ def user_agent() -> str:
140
138
  from pip._vendor import distro
141
139
 
142
140
  linux_distribution = distro.name(), distro.version(), distro.codename()
143
- distro_infos: Dict[str, Any] = dict(
141
+ distro_infos: dict[str, Any] = dict(
144
142
  filter(
145
143
  lambda x: x[1],
146
144
  zip(["name", "version", "id"], linux_distribution),
@@ -214,10 +212,10 @@ class LocalFSAdapter(BaseAdapter):
214
212
  self,
215
213
  request: PreparedRequest,
216
214
  stream: bool = False,
217
- timeout: Optional[Union[float, Tuple[float, float]]] = None,
218
- verify: Union[bool, str] = True,
219
- cert: Optional[Union[str, Tuple[str, str]]] = None,
220
- proxies: Optional[Mapping[str, str]] = None,
215
+ timeout: float | tuple[float, float] | None = None,
216
+ verify: bool | str = True,
217
+ cert: str | tuple[str, str] | None = None,
218
+ proxies: Mapping[str, str] | None = None,
221
219
  ) -> Response:
222
220
  pathname = url_to_path(request.url)
223
221
 
@@ -264,7 +262,7 @@ class _SSLContextAdapterMixin:
264
262
  def __init__(
265
263
  self,
266
264
  *,
267
- ssl_context: Optional["SSLContext"] = None,
265
+ ssl_context: SSLContext | None = None,
268
266
  **kwargs: Any,
269
267
  ) -> None:
270
268
  self._ssl_context = ssl_context
@@ -276,7 +274,7 @@ class _SSLContextAdapterMixin:
276
274
  maxsize: int,
277
275
  block: bool = DEFAULT_POOLBLOCK,
278
276
  **pool_kwargs: Any,
279
- ) -> "PoolManager":
277
+ ) -> PoolManager:
280
278
  if self._ssl_context is not None:
281
279
  pool_kwargs.setdefault("ssl_context", self._ssl_context)
282
280
  return super().init_poolmanager( # type: ignore[misc]
@@ -286,6 +284,13 @@ class _SSLContextAdapterMixin:
286
284
  **pool_kwargs,
287
285
  )
288
286
 
287
+ def proxy_manager_for(self, proxy: str, **proxy_kwargs: Any) -> ProxyManager:
288
+ # Proxy manager replaces the pool manager, so inject our SSL
289
+ # context here too. https://github.com/pypa/pip/issues/13288
290
+ if self._ssl_context is not None:
291
+ proxy_kwargs.setdefault("ssl_context", self._ssl_context)
292
+ return super().proxy_manager_for(proxy, **proxy_kwargs) # type: ignore[misc]
293
+
289
294
 
290
295
  class HTTPAdapter(_SSLContextAdapterMixin, _BaseHTTPAdapter):
291
296
  pass
@@ -300,8 +305,8 @@ class InsecureHTTPAdapter(HTTPAdapter):
300
305
  self,
301
306
  conn: ConnectionPool,
302
307
  url: str,
303
- verify: Union[bool, str],
304
- cert: Optional[Union[str, Tuple[str, str]]],
308
+ verify: bool | str,
309
+ cert: str | tuple[str, str] | None,
305
310
  ) -> None:
306
311
  super().cert_verify(conn=conn, url=url, verify=False, cert=cert)
307
312
 
@@ -311,23 +316,23 @@ class InsecureCacheControlAdapter(CacheControlAdapter):
311
316
  self,
312
317
  conn: ConnectionPool,
313
318
  url: str,
314
- verify: Union[bool, str],
315
- cert: Optional[Union[str, Tuple[str, str]]],
319
+ verify: bool | str,
320
+ cert: str | tuple[str, str] | None,
316
321
  ) -> None:
317
322
  super().cert_verify(conn=conn, url=url, verify=False, cert=cert)
318
323
 
319
324
 
320
325
  class PipSession(requests.Session):
321
- timeout: Optional[int] = None
326
+ timeout: int | None = None
322
327
 
323
328
  def __init__(
324
329
  self,
325
330
  *args: Any,
326
331
  retries: int = 0,
327
- cache: Optional[str] = None,
332
+ cache: str | None = None,
328
333
  trusted_hosts: Sequence[str] = (),
329
- index_urls: Optional[List[str]] = None,
330
- ssl_context: Optional["SSLContext"] = None,
334
+ index_urls: list[str] | None = None,
335
+ ssl_context: SSLContext | None = None,
331
336
  **kwargs: Any,
332
337
  ) -> None:
333
338
  """
@@ -338,7 +343,7 @@ class PipSession(requests.Session):
338
343
 
339
344
  # Namespace the attribute with "pip_" just in case to prevent
340
345
  # possible conflicts with the base class.
341
- self.pip_trusted_origins: List[Tuple[str, Optional[int]]] = []
346
+ self.pip_trusted_origins: list[tuple[str, int | None]] = []
342
347
  self.pip_proxy = None
343
348
 
344
349
  # Attach our User Agent to the request
@@ -401,7 +406,7 @@ class PipSession(requests.Session):
401
406
  for host in trusted_hosts:
402
407
  self.add_trusted_host(host, suppress_logging=True)
403
408
 
404
- def update_index_urls(self, new_index_urls: List[str]) -> None:
409
+ def update_index_urls(self, new_index_urls: list[str]) -> None:
405
410
  """
406
411
  :param new_index_urls: New index urls to update the authentication
407
412
  handler with.
@@ -409,7 +414,7 @@ class PipSession(requests.Session):
409
414
  self.auth.index_urls = new_index_urls
410
415
 
411
416
  def add_trusted_host(
412
- self, host: str, source: Optional[str] = None, suppress_logging: bool = False
417
+ self, host: str, source: str | None = None, suppress_logging: bool = False
413
418
  ) -> None:
414
419
  """
415
420
  :param host: It is okay to provide a host that has previously been
@@ -1,4 +1,4 @@
1
- from typing import Dict, Generator
1
+ from collections.abc import Generator
2
2
 
3
3
  from pip._vendor.requests.models import Response
4
4
 
@@ -23,7 +23,7 @@ from pip._internal.exceptions import NetworkConnectionError
23
23
  # you're not asking for a compressed file and will then decompress it
24
24
  # before sending because if that's the case I don't think it'll ever be
25
25
  # possible to make this work.
26
- HEADERS: Dict[str, str] = {"Accept-Encoding": "identity"}
26
+ HEADERS: dict[str, str] = {"Accept-Encoding": "identity"}
27
27
 
28
28
  DOWNLOAD_CHUNK_SIZE = 256 * 1024
29
29
 
@@ -3,7 +3,7 @@
3
3
  import logging
4
4
  import urllib.parse
5
5
  import xmlrpc.client
6
- from typing import TYPE_CHECKING, Tuple
6
+ from typing import TYPE_CHECKING
7
7
 
8
8
  from pip._internal.exceptions import NetworkConnectionError
9
9
  from pip._internal.network.session import PipSession
@@ -36,7 +36,7 @@ class PipXmlrpcTransport(xmlrpc.client.Transport):
36
36
  handler: str,
37
37
  request_body: "SizedBuffer",
38
38
  verbose: bool = False,
39
- ) -> Tuple["_Marshallable", ...]:
39
+ ) -> tuple["_Marshallable", ...]:
40
40
  assert isinstance(host, str)
41
41
  parts = (self._scheme, host, handler, None, None, None)
42
42
  url = urllib.parse.urlunparse(parts)
@@ -1,9 +1,11 @@
1
+ from __future__ import annotations
2
+
1
3
  import contextlib
2
4
  import hashlib
3
5
  import logging
4
6
  import os
7
+ from collections.abc import Generator
5
8
  from types import TracebackType
6
- from typing import Dict, Generator, Optional, Type, Union
7
9
 
8
10
  from pip._internal.req.req_install import InstallRequirement
9
11
  from pip._internal.utils.temp_dir import TempDirectory
@@ -17,7 +19,7 @@ def update_env_context_manager(**changes: str) -> Generator[None, None, None]:
17
19
 
18
20
  # Save values from the target and change them.
19
21
  non_existent_marker = object()
20
- saved_values: Dict[str, Union[object, str]] = {}
22
+ saved_values: dict[str, object | str] = {}
21
23
  for name, new_value in changes.items():
22
24
  try:
23
25
  saved_values[name] = target[name]
@@ -38,7 +40,7 @@ def update_env_context_manager(**changes: str) -> Generator[None, None, None]:
38
40
 
39
41
 
40
42
  @contextlib.contextmanager
41
- def get_build_tracker() -> Generator["BuildTracker", None, None]:
43
+ def get_build_tracker() -> Generator[BuildTracker, None, None]:
42
44
  root = os.environ.get("PIP_BUILD_TRACKER")
43
45
  with contextlib.ExitStack() as ctx:
44
46
  if root is None:
@@ -65,18 +67,18 @@ class BuildTracker:
65
67
 
66
68
  def __init__(self, root: str) -> None:
67
69
  self._root = root
68
- self._entries: Dict[TrackerId, InstallRequirement] = {}
70
+ self._entries: dict[TrackerId, InstallRequirement] = {}
69
71
  logger.debug("Created build tracker: %s", self._root)
70
72
 
71
- def __enter__(self) -> "BuildTracker":
73
+ def __enter__(self) -> BuildTracker:
72
74
  logger.debug("Entered build tracker: %s", self._root)
73
75
  return self
74
76
 
75
77
  def __exit__(
76
78
  self,
77
- exc_type: Optional[Type[BaseException]],
78
- exc_val: Optional[BaseException],
79
- exc_tb: Optional[TracebackType],
79
+ exc_type: type[BaseException] | None,
80
+ exc_val: BaseException | None,
81
+ exc_tb: TracebackType | None,
80
82
  ) -> None:
81
83
  self.cleanup()
82
84
 
@@ -1,6 +1,7 @@
1
+ from __future__ import annotations
2
+
1
3
  import logging
2
4
  import os
3
- from typing import Optional
4
5
 
5
6
  from pip._vendor.pyproject_hooks import BuildBackendHookCaller
6
7
 
@@ -14,7 +15,7 @@ def build_wheel_pep517(
14
15
  backend: BuildBackendHookCaller,
15
16
  metadata_directory: str,
16
17
  tempd: str,
17
- ) -> Optional[str]:
18
+ ) -> str | None:
18
19
  """Build one InstallRequirement using the PEP 517 build process.
19
20
 
20
21
  Returns path to wheel if successfully built. Otherwise, returns None.
@@ -1,6 +1,7 @@
1
+ from __future__ import annotations
2
+
1
3
  import logging
2
4
  import os
3
- from typing import Optional
4
5
 
5
6
  from pip._vendor.pyproject_hooks import BuildBackendHookCaller, HookMissing
6
7
 
@@ -14,7 +15,7 @@ def build_wheel_editable(
14
15
  backend: BuildBackendHookCaller,
15
16
  metadata_directory: str,
16
17
  tempd: str,
17
- ) -> Optional[str]:
18
+ ) -> str | None:
18
19
  """Build one InstallRequirement using the PEP 660 build process.
19
20
 
20
21
  Returns path to wheel if successfully built. Otherwise, returns None.
@@ -1,6 +1,7 @@
1
+ from __future__ import annotations
2
+
1
3
  import logging
2
4
  import os.path
3
- from typing import List, Optional
4
5
 
5
6
  from pip._internal.cli.spinners import open_spinner
6
7
  from pip._internal.utils.deprecation import deprecated
@@ -11,7 +12,7 @@ logger = logging.getLogger(__name__)
11
12
 
12
13
 
13
14
  def format_command_result(
14
- command_args: List[str],
15
+ command_args: list[str],
15
16
  command_output: str,
16
17
  ) -> str:
17
18
  """Format command information for logging."""
@@ -31,12 +32,12 @@ def format_command_result(
31
32
 
32
33
 
33
34
  def get_legacy_build_wheel_path(
34
- names: List[str],
35
+ names: list[str],
35
36
  temp_dir: str,
36
37
  name: str,
37
- command_args: List[str],
38
+ command_args: list[str],
38
39
  command_output: str,
39
- ) -> Optional[str]:
40
+ ) -> str | None:
40
41
  """Return the path to the wheel in the temporary build directory."""
41
42
  # Sort for determinism.
42
43
  names = sorted(names)
@@ -61,10 +62,10 @@ def build_wheel_legacy(
61
62
  name: str,
62
63
  setup_py_path: str,
63
64
  source_dir: str,
64
- global_options: List[str],
65
- build_options: List[str],
65
+ global_options: list[str],
66
+ build_options: list[str],
66
67
  tempd: str,
67
- ) -> Optional[str]:
68
+ ) -> str | None:
68
69
  """Build one unpacked package using the "legacy" build process.
69
70
 
70
71
  Returns path to wheel if successfully built. Otherwise, returns None.
@@ -1,20 +1,15 @@
1
1
  """Validation of dependencies of packages"""
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  import logging
6
+ from collections.abc import Generator, Iterable
4
7
  from contextlib import suppress
5
8
  from email.parser import Parser
6
9
  from functools import reduce
7
10
  from typing import (
8
11
  Callable,
9
- Dict,
10
- FrozenSet,
11
- Generator,
12
- Iterable,
13
- List,
14
12
  NamedTuple,
15
- Optional,
16
- Set,
17
- Tuple,
18
13
  )
19
14
 
20
15
  from pip._vendor.packaging.requirements import Requirement
@@ -32,21 +27,21 @@ logger = logging.getLogger(__name__)
32
27
 
33
28
  class PackageDetails(NamedTuple):
34
29
  version: Version
35
- dependencies: List[Requirement]
30
+ dependencies: list[Requirement]
36
31
 
37
32
 
38
33
  # Shorthands
39
- PackageSet = Dict[NormalizedName, PackageDetails]
40
- Missing = Tuple[NormalizedName, Requirement]
41
- Conflicting = Tuple[NormalizedName, Version, Requirement]
34
+ PackageSet = dict[NormalizedName, PackageDetails]
35
+ Missing = tuple[NormalizedName, Requirement]
36
+ Conflicting = tuple[NormalizedName, Version, Requirement]
42
37
 
43
- MissingDict = Dict[NormalizedName, List[Missing]]
44
- ConflictingDict = Dict[NormalizedName, List[Conflicting]]
45
- CheckResult = Tuple[MissingDict, ConflictingDict]
46
- ConflictDetails = Tuple[PackageSet, CheckResult]
38
+ MissingDict = dict[NormalizedName, list[Missing]]
39
+ ConflictingDict = dict[NormalizedName, list[Conflicting]]
40
+ CheckResult = tuple[MissingDict, ConflictingDict]
41
+ ConflictDetails = tuple[PackageSet, CheckResult]
47
42
 
48
43
 
49
- def create_package_set_from_installed() -> Tuple[PackageSet, bool]:
44
+ def create_package_set_from_installed() -> tuple[PackageSet, bool]:
50
45
  """Converts a list of distributions into a PackageSet."""
51
46
  package_set = {}
52
47
  problems = False
@@ -64,7 +59,7 @@ def create_package_set_from_installed() -> Tuple[PackageSet, bool]:
64
59
 
65
60
 
66
61
  def check_package_set(
67
- package_set: PackageSet, should_ignore: Optional[Callable[[str], bool]] = None
62
+ package_set: PackageSet, should_ignore: Callable[[str], bool] | None = None
68
63
  ) -> CheckResult:
69
64
  """Check if a package set is consistent
70
65
 
@@ -77,8 +72,8 @@ def check_package_set(
77
72
 
78
73
  for package_name, package_detail in package_set.items():
79
74
  # Info about dependencies of package_name
80
- missing_deps: Set[Missing] = set()
81
- conflicting_deps: Set[Conflicting] = set()
75
+ missing_deps: set[Missing] = set()
76
+ conflicting_deps: set[Conflicting] = set()
82
77
 
83
78
  if should_ignore and should_ignore(package_name):
84
79
  continue
@@ -108,7 +103,7 @@ def check_package_set(
108
103
  return missing, conflicting
109
104
 
110
105
 
111
- def check_install_conflicts(to_install: List[InstallRequirement]) -> ConflictDetails:
106
+ def check_install_conflicts(to_install: list[InstallRequirement]) -> ConflictDetails:
112
107
  """For checking if the dependency graph would be consistent after \
113
108
  installing given requirements
114
109
  """
@@ -135,7 +130,7 @@ def check_unsupported(
135
130
  for p in packages:
136
131
  with suppress(FileNotFoundError):
137
132
  wheel_file = p.read_text("WHEEL")
138
- wheel_tags: FrozenSet[Tag] = reduce(
133
+ wheel_tags: frozenset[Tag] = reduce(
139
134
  frozenset.union,
140
135
  map(parse_tag, Parser().parsestr(wheel_file).get_all("Tag", [])),
141
136
  frozenset(),
@@ -145,8 +140,8 @@ def check_unsupported(
145
140
 
146
141
 
147
142
  def _simulate_installation_of(
148
- to_install: List[InstallRequirement], package_set: PackageSet
149
- ) -> Set[NormalizedName]:
143
+ to_install: list[InstallRequirement], package_set: PackageSet
144
+ ) -> set[NormalizedName]:
150
145
  """Computes the version of packages after installing to_install."""
151
146
  # Keep track of packages that were installed
152
147
  installed = set()
@@ -164,8 +159,8 @@ def _simulate_installation_of(
164
159
 
165
160
 
166
161
  def _create_whitelist(
167
- would_be_installed: Set[NormalizedName], package_set: PackageSet
168
- ) -> Set[NormalizedName]:
162
+ would_be_installed: set[NormalizedName], package_set: PackageSet
163
+ ) -> set[NormalizedName]:
169
164
  packages_affected = set(would_be_installed)
170
165
 
171
166
  for package_name in package_set:
@@ -1,8 +1,11 @@
1
+ from __future__ import annotations
2
+
1
3
  import collections
2
4
  import logging
3
5
  import os
6
+ from collections.abc import Container, Generator, Iterable
4
7
  from dataclasses import dataclass, field
5
- from typing import Container, Dict, Generator, Iterable, List, NamedTuple, Optional, Set
8
+ from typing import NamedTuple
6
9
 
7
10
  from pip._vendor.packaging.utils import NormalizedName, canonicalize_name
8
11
  from pip._vendor.packaging.version import InvalidVersion
@@ -21,19 +24,19 @@ logger = logging.getLogger(__name__)
21
24
 
22
25
  class _EditableInfo(NamedTuple):
23
26
  requirement: str
24
- comments: List[str]
27
+ comments: list[str]
25
28
 
26
29
 
27
30
  def freeze(
28
- requirement: Optional[List[str]] = None,
31
+ requirement: list[str] | None = None,
29
32
  local_only: bool = False,
30
33
  user_only: bool = False,
31
- paths: Optional[List[str]] = None,
34
+ paths: list[str] | None = None,
32
35
  isolated: bool = False,
33
36
  exclude_editable: bool = False,
34
37
  skip: Container[str] = (),
35
38
  ) -> Generator[str, None, None]:
36
- installations: Dict[str, FrozenRequirement] = {}
39
+ installations: dict[str, FrozenRequirement] = {}
37
40
 
38
41
  dists = get_environment(paths).iter_installed_distributions(
39
42
  local_only=local_only,
@@ -51,10 +54,10 @@ def freeze(
51
54
  # should only be emitted once, even if the same option is in multiple
52
55
  # requirements files, so we need to keep track of what has been emitted
53
56
  # so that we don't emit it again if it's seen again
54
- emitted_options: Set[str] = set()
57
+ emitted_options: set[str] = set()
55
58
  # keep track of which files a requirement is in so that we can
56
59
  # give an accurate warning if a requirement appears multiple times.
57
- req_files: Dict[str, List[str]] = collections.defaultdict(list)
60
+ req_files: dict[str, list[str]] = collections.defaultdict(list)
58
61
  for req_file_path in requirement:
59
62
  with open(req_file_path) as req_file:
60
63
  for line in req_file:
@@ -83,7 +86,7 @@ def freeze(
83
86
  yield line
84
87
  continue
85
88
 
86
- if line.startswith("-e") or line.startswith("--editable"):
89
+ if line.startswith(("-e", "--editable")):
87
90
  if line.startswith("-e"):
88
91
  line = line[2:].strip()
89
92
  else:
@@ -233,7 +236,7 @@ class FrozenRequirement:
233
236
  return canonicalize_name(self.name)
234
237
 
235
238
  @classmethod
236
- def from_dist(cls, dist: BaseDistribution) -> "FrozenRequirement":
239
+ def from_dist(cls, dist: BaseDistribution) -> FrozenRequirement:
237
240
  editable = dist.editable
238
241
  if editable:
239
242
  req, comments = _get_editable_info(dist)
@@ -1,7 +1,9 @@
1
1
  """Legacy editable installation process, i.e. `setup.py develop`."""
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  import logging
4
- from typing import Optional, Sequence
6
+ from collections.abc import Sequence
5
7
 
6
8
  from pip._internal.build_env import BuildEnvironment
7
9
  from pip._internal.utils.logging import indent_log
@@ -14,8 +16,8 @@ logger = logging.getLogger(__name__)
14
16
  def install_editable(
15
17
  *,
16
18
  global_options: Sequence[str],
17
- prefix: Optional[str],
18
- home: Optional[str],
19
+ prefix: str | None,
20
+ home: str | None,
19
21
  use_user_site: bool,
20
22
  name: str,
21
23
  setup_py_path: str,