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.
- pip/__init__.py +3 -3
- pip/_internal/__init__.py +2 -2
- pip/_internal/build_env.py +186 -94
- pip/_internal/cache.py +17 -15
- pip/_internal/cli/autocompletion.py +13 -4
- pip/_internal/cli/base_command.py +18 -7
- pip/_internal/cli/cmdoptions.py +57 -80
- pip/_internal/cli/command_context.py +4 -3
- pip/_internal/cli/index_command.py +11 -9
- pip/_internal/cli/main.py +3 -2
- pip/_internal/cli/main_parser.py +4 -3
- pip/_internal/cli/parser.py +24 -20
- pip/_internal/cli/progress_bars.py +19 -12
- pip/_internal/cli/req_command.py +57 -33
- pip/_internal/cli/spinners.py +81 -5
- pip/_internal/commands/__init__.py +5 -3
- pip/_internal/commands/cache.py +18 -15
- pip/_internal/commands/check.py +1 -2
- pip/_internal/commands/completion.py +1 -2
- pip/_internal/commands/configuration.py +26 -18
- pip/_internal/commands/debug.py +8 -6
- pip/_internal/commands/download.py +6 -10
- pip/_internal/commands/freeze.py +2 -3
- pip/_internal/commands/hash.py +1 -2
- pip/_internal/commands/help.py +1 -2
- pip/_internal/commands/index.py +15 -9
- pip/_internal/commands/inspect.py +4 -4
- pip/_internal/commands/install.py +63 -53
- pip/_internal/commands/list.py +35 -26
- pip/_internal/commands/lock.py +4 -8
- pip/_internal/commands/search.py +14 -12
- pip/_internal/commands/show.py +14 -11
- pip/_internal/commands/uninstall.py +1 -2
- pip/_internal/commands/wheel.py +7 -13
- pip/_internal/configuration.py +40 -27
- pip/_internal/distributions/base.py +6 -4
- pip/_internal/distributions/installed.py +8 -4
- pip/_internal/distributions/sdist.py +33 -27
- pip/_internal/distributions/wheel.py +6 -4
- pip/_internal/exceptions.py +78 -42
- pip/_internal/index/collector.py +24 -29
- pip/_internal/index/package_finder.py +73 -64
- pip/_internal/index/sources.py +17 -14
- pip/_internal/locations/__init__.py +18 -16
- pip/_internal/locations/_distutils.py +12 -11
- pip/_internal/locations/_sysconfig.py +5 -4
- pip/_internal/locations/base.py +4 -3
- pip/_internal/main.py +2 -2
- pip/_internal/metadata/__init__.py +14 -7
- pip/_internal/metadata/_json.py +5 -4
- pip/_internal/metadata/base.py +22 -27
- pip/_internal/metadata/importlib/_compat.py +6 -4
- pip/_internal/metadata/importlib/_dists.py +20 -19
- pip/_internal/metadata/importlib/_envs.py +9 -6
- pip/_internal/metadata/pkg_resources.py +11 -14
- pip/_internal/models/direct_url.py +24 -21
- pip/_internal/models/format_control.py +5 -5
- pip/_internal/models/installation_report.py +4 -3
- pip/_internal/models/link.py +39 -34
- pip/_internal/models/pylock.py +27 -22
- pip/_internal/models/search_scope.py +6 -7
- pip/_internal/models/selection_prefs.py +3 -3
- pip/_internal/models/target_python.py +10 -9
- pip/_internal/models/wheel.py +12 -71
- pip/_internal/network/auth.py +20 -22
- pip/_internal/network/cache.py +28 -17
- pip/_internal/network/download.py +169 -141
- pip/_internal/network/lazy_wheel.py +15 -10
- pip/_internal/network/session.py +32 -27
- pip/_internal/network/utils.py +2 -2
- pip/_internal/network/xmlrpc.py +2 -2
- pip/_internal/operations/build/build_tracker.py +10 -8
- pip/_internal/operations/build/wheel.py +7 -6
- pip/_internal/operations/build/wheel_editable.py +7 -6
- pip/_internal/operations/check.py +21 -26
- pip/_internal/operations/freeze.py +12 -9
- pip/_internal/operations/install/wheel.py +49 -41
- pip/_internal/operations/prepare.py +42 -31
- pip/_internal/pyproject.py +7 -69
- pip/_internal/req/__init__.py +12 -12
- pip/_internal/req/constructors.py +68 -62
- pip/_internal/req/req_dependency_group.py +7 -11
- pip/_internal/req/req_file.py +32 -36
- pip/_internal/req/req_install.py +64 -170
- pip/_internal/req/req_set.py +4 -5
- pip/_internal/req/req_uninstall.py +20 -17
- pip/_internal/resolution/base.py +3 -3
- pip/_internal/resolution/legacy/resolver.py +21 -20
- pip/_internal/resolution/resolvelib/base.py +16 -13
- pip/_internal/resolution/resolvelib/candidates.py +49 -37
- pip/_internal/resolution/resolvelib/factory.py +72 -50
- pip/_internal/resolution/resolvelib/found_candidates.py +11 -9
- pip/_internal/resolution/resolvelib/provider.py +24 -20
- pip/_internal/resolution/resolvelib/reporter.py +26 -11
- pip/_internal/resolution/resolvelib/requirements.py +8 -6
- pip/_internal/resolution/resolvelib/resolver.py +41 -29
- pip/_internal/self_outdated_check.py +19 -9
- pip/_internal/utils/appdirs.py +1 -2
- pip/_internal/utils/compat.py +7 -1
- pip/_internal/utils/compatibility_tags.py +17 -16
- pip/_internal/utils/deprecation.py +11 -9
- pip/_internal/utils/direct_url_helpers.py +2 -2
- pip/_internal/utils/egg_link.py +6 -5
- pip/_internal/utils/entrypoints.py +3 -2
- pip/_internal/utils/filesystem.py +20 -5
- pip/_internal/utils/filetypes.py +4 -6
- pip/_internal/utils/glibc.py +6 -5
- pip/_internal/utils/hashes.py +9 -6
- pip/_internal/utils/logging.py +8 -5
- pip/_internal/utils/misc.py +37 -45
- pip/_internal/utils/packaging.py +3 -2
- pip/_internal/utils/retry.py +7 -4
- pip/_internal/utils/subprocess.py +20 -17
- pip/_internal/utils/temp_dir.py +10 -12
- pip/_internal/utils/unpacking.py +31 -4
- pip/_internal/utils/urls.py +1 -1
- pip/_internal/utils/virtualenv.py +3 -2
- pip/_internal/utils/wheel.py +3 -4
- pip/_internal/vcs/bazaar.py +26 -8
- pip/_internal/vcs/git.py +59 -24
- pip/_internal/vcs/mercurial.py +34 -11
- pip/_internal/vcs/subversion.py +27 -16
- pip/_internal/vcs/versioncontrol.py +56 -51
- pip/_internal/wheel_builder.py +30 -101
- pip/_vendor/README.rst +180 -0
- pip/_vendor/cachecontrol/LICENSE.txt +13 -0
- pip/_vendor/cachecontrol/__init__.py +1 -1
- pip/_vendor/certifi/LICENSE +20 -0
- pip/_vendor/certifi/__init__.py +1 -1
- pip/_vendor/certifi/cacert.pem +164 -261
- pip/_vendor/certifi/core.py +1 -32
- pip/_vendor/dependency_groups/LICENSE.txt +9 -0
- pip/_vendor/distlib/LICENSE.txt +284 -0
- pip/_vendor/distlib/__init__.py +2 -2
- pip/_vendor/distlib/scripts.py +1 -1
- pip/_vendor/distro/LICENSE +202 -0
- pip/_vendor/idna/LICENSE.md +31 -0
- pip/_vendor/msgpack/COPYING +14 -0
- pip/_vendor/msgpack/__init__.py +2 -2
- pip/_vendor/packaging/LICENSE +3 -0
- pip/_vendor/packaging/LICENSE.APACHE +177 -0
- pip/_vendor/packaging/LICENSE.BSD +23 -0
- pip/_vendor/pkg_resources/LICENSE +17 -0
- pip/_vendor/pkg_resources/__init__.py +1 -1
- pip/_vendor/platformdirs/LICENSE +21 -0
- pip/_vendor/platformdirs/api.py +1 -1
- pip/_vendor/platformdirs/macos.py +10 -8
- pip/_vendor/platformdirs/version.py +16 -3
- pip/_vendor/pygments/LICENSE +25 -0
- pip/_vendor/pygments/__init__.py +1 -1
- pip/_vendor/pyproject_hooks/LICENSE +21 -0
- pip/_vendor/requests/LICENSE +175 -0
- pip/_vendor/requests/__version__.py +2 -2
- pip/_vendor/requests/adapters.py +17 -40
- pip/_vendor/requests/compat.py +12 -0
- pip/_vendor/requests/models.py +3 -1
- pip/_vendor/requests/sessions.py +1 -1
- pip/_vendor/requests/utils.py +6 -16
- pip/_vendor/resolvelib/LICENSE +13 -0
- pip/_vendor/resolvelib/__init__.py +3 -3
- pip/_vendor/resolvelib/reporters.py +1 -1
- pip/_vendor/resolvelib/resolvers/__init__.py +4 -4
- pip/_vendor/resolvelib/resolvers/abstract.py +3 -3
- pip/_vendor/resolvelib/resolvers/resolution.py +96 -10
- pip/_vendor/rich/LICENSE +19 -0
- pip/_vendor/rich/__main__.py +12 -40
- pip/_vendor/rich/_inspect.py +1 -1
- pip/_vendor/rich/_ratio.py +1 -7
- pip/_vendor/rich/align.py +1 -7
- pip/_vendor/rich/box.py +1 -7
- pip/_vendor/rich/console.py +25 -20
- pip/_vendor/rich/control.py +1 -7
- pip/_vendor/rich/diagnose.py +1 -0
- pip/_vendor/rich/emoji.py +1 -6
- pip/_vendor/rich/live.py +32 -7
- pip/_vendor/rich/live_render.py +1 -7
- pip/_vendor/rich/logging.py +1 -1
- pip/_vendor/rich/panel.py +3 -4
- pip/_vendor/rich/progress.py +15 -15
- pip/_vendor/rich/spinner.py +7 -13
- pip/_vendor/rich/style.py +7 -11
- pip/_vendor/rich/syntax.py +24 -5
- pip/_vendor/rich/traceback.py +32 -17
- pip/_vendor/tomli/LICENSE +21 -0
- pip/_vendor/tomli/__init__.py +1 -1
- pip/_vendor/tomli/_parser.py +28 -21
- pip/_vendor/tomli/_re.py +8 -5
- pip/_vendor/tomli_w/LICENSE +21 -0
- pip/_vendor/truststore/LICENSE +21 -0
- pip/_vendor/truststore/__init__.py +1 -1
- pip/_vendor/truststore/_api.py +15 -7
- pip/_vendor/truststore/_openssl.py +3 -1
- pip/_vendor/urllib3/LICENSE.txt +21 -0
- pip/_vendor/vendor.txt +11 -12
- {pip-25.1.1.dist-info → pip-25.3.dist-info}/METADATA +32 -11
- {pip-25.1.1.dist-info → pip-25.3.dist-info}/RECORD +221 -192
- {pip-25.1.1.dist-info → pip-25.3.dist-info}/WHEEL +1 -2
- pip-25.3.dist-info/entry_points.txt +4 -0
- {pip-25.1.1.dist-info → pip-25.3.dist-info}/licenses/AUTHORS.txt +21 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt +13 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/certifi/LICENSE +20 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/dependency_groups/LICENSE.txt +9 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/distlib/LICENSE.txt +284 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/distro/LICENSE +202 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/idna/LICENSE.md +31 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/msgpack/COPYING +14 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/packaging/LICENSE +3 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.APACHE +177 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.BSD +23 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/pkg_resources/LICENSE +17 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/platformdirs/LICENSE +21 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/pygments/LICENSE +25 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/pyproject_hooks/LICENSE +21 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/requests/LICENSE +175 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/resolvelib/LICENSE +13 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/rich/LICENSE +19 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/tomli/LICENSE +21 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/tomli_w/LICENSE +21 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/truststore/LICENSE +21 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/urllib3/LICENSE.txt +21 -0
- pip/_internal/operations/build/metadata_legacy.py +0 -73
- pip/_internal/operations/build/wheel_legacy.py +0 -118
- pip/_internal/operations/install/editable_legacy.py +0 -46
- pip/_internal/utils/setuptools_build.py +0 -147
- pip/_vendor/distlib/database.py +0 -1329
- pip/_vendor/distlib/index.py +0 -508
- pip/_vendor/distlib/locators.py +0 -1295
- pip/_vendor/distlib/manifest.py +0 -384
- pip/_vendor/distlib/markers.py +0 -162
- pip/_vendor/distlib/metadata.py +0 -1031
- pip/_vendor/distlib/version.py +0 -750
- pip/_vendor/distlib/wheel.py +0 -1100
- pip/_vendor/typing_extensions.py +0 -4584
- pip-25.1.1.dist-info/entry_points.txt +0 -3
- pip-25.1.1.dist-info/top_level.txt +0 -1
- {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 functools
|
|
2
4
|
import logging
|
|
3
5
|
import os
|
|
4
6
|
import pathlib
|
|
5
7
|
import sys
|
|
6
8
|
import sysconfig
|
|
7
|
-
from typing import Any
|
|
9
|
+
from typing import Any
|
|
8
10
|
|
|
9
11
|
from pip._internal.models.scheme import SCHEME_KEYS, Scheme
|
|
10
12
|
from pip._internal.utils.compat import WINDOWS
|
|
@@ -87,7 +89,7 @@ def _looks_like_bpo_44860() -> bool:
|
|
|
87
89
|
return unix_user_platlib == "$usersite"
|
|
88
90
|
|
|
89
91
|
|
|
90
|
-
def _looks_like_red_hat_patched_platlib_purelib(scheme:
|
|
92
|
+
def _looks_like_red_hat_patched_platlib_purelib(scheme: dict[str, str]) -> bool:
|
|
91
93
|
platlib = scheme["platlib"]
|
|
92
94
|
if "/$platlibdir/" in platlib:
|
|
93
95
|
platlib = platlib.replace("/$platlibdir/", f"/{_PLATLIBDIR}/")
|
|
@@ -97,7 +99,7 @@ def _looks_like_red_hat_patched_platlib_purelib(scheme: Dict[str, str]) -> bool:
|
|
|
97
99
|
return unpatched.replace("$platbase/", "$base/") == scheme["purelib"]
|
|
98
100
|
|
|
99
101
|
|
|
100
|
-
@functools.
|
|
102
|
+
@functools.cache
|
|
101
103
|
def _looks_like_red_hat_lib() -> bool:
|
|
102
104
|
"""Red Hat patches platlib in unix_prefix and unix_home, but not purelib.
|
|
103
105
|
|
|
@@ -112,7 +114,7 @@ def _looks_like_red_hat_lib() -> bool:
|
|
|
112
114
|
)
|
|
113
115
|
|
|
114
116
|
|
|
115
|
-
@functools.
|
|
117
|
+
@functools.cache
|
|
116
118
|
def _looks_like_debian_scheme() -> bool:
|
|
117
119
|
"""Debian adds two additional schemes."""
|
|
118
120
|
from distutils.command.install import INSTALL_SCHEMES
|
|
@@ -120,7 +122,7 @@ def _looks_like_debian_scheme() -> bool:
|
|
|
120
122
|
return "deb_system" in INSTALL_SCHEMES and "unix_local" in INSTALL_SCHEMES
|
|
121
123
|
|
|
122
124
|
|
|
123
|
-
@functools.
|
|
125
|
+
@functools.cache
|
|
124
126
|
def _looks_like_red_hat_scheme() -> bool:
|
|
125
127
|
"""Red Hat patches ``sys.prefix`` and ``sys.exec_prefix``.
|
|
126
128
|
|
|
@@ -140,7 +142,7 @@ def _looks_like_red_hat_scheme() -> bool:
|
|
|
140
142
|
)
|
|
141
143
|
|
|
142
144
|
|
|
143
|
-
@functools.
|
|
145
|
+
@functools.cache
|
|
144
146
|
def _looks_like_slackware_scheme() -> bool:
|
|
145
147
|
"""Slackware patches sysconfig but fails to patch distutils and site.
|
|
146
148
|
|
|
@@ -156,7 +158,7 @@ def _looks_like_slackware_scheme() -> bool:
|
|
|
156
158
|
return "/lib64/" in paths["purelib"] and "/lib64/" not in user_site
|
|
157
159
|
|
|
158
160
|
|
|
159
|
-
@functools.
|
|
161
|
+
@functools.cache
|
|
160
162
|
def _looks_like_msys2_mingw_scheme() -> bool:
|
|
161
163
|
"""MSYS2 patches distutils and sysconfig to use a UNIX-like scheme.
|
|
162
164
|
|
|
@@ -174,7 +176,7 @@ def _looks_like_msys2_mingw_scheme() -> bool:
|
|
|
174
176
|
)
|
|
175
177
|
|
|
176
178
|
|
|
177
|
-
@functools.
|
|
179
|
+
@functools.cache
|
|
178
180
|
def _warn_mismatched(old: pathlib.Path, new: pathlib.Path, *, key: str) -> None:
|
|
179
181
|
issue_url = "https://github.com/pypa/pip/issues/10151"
|
|
180
182
|
message = (
|
|
@@ -192,13 +194,13 @@ def _warn_if_mismatch(old: pathlib.Path, new: pathlib.Path, *, key: str) -> bool
|
|
|
192
194
|
return True
|
|
193
195
|
|
|
194
196
|
|
|
195
|
-
@functools.
|
|
197
|
+
@functools.cache
|
|
196
198
|
def _log_context(
|
|
197
199
|
*,
|
|
198
200
|
user: bool = False,
|
|
199
|
-
home:
|
|
200
|
-
root:
|
|
201
|
-
prefix:
|
|
201
|
+
home: str | None = None,
|
|
202
|
+
root: str | None = None,
|
|
203
|
+
prefix: str | None = None,
|
|
202
204
|
) -> None:
|
|
203
205
|
parts = [
|
|
204
206
|
"Additional context:",
|
|
@@ -214,10 +216,10 @@ def _log_context(
|
|
|
214
216
|
def get_scheme(
|
|
215
217
|
dist_name: str,
|
|
216
218
|
user: bool = False,
|
|
217
|
-
home:
|
|
218
|
-
root:
|
|
219
|
+
home: str | None = None,
|
|
220
|
+
root: str | None = None,
|
|
219
221
|
isolated: bool = False,
|
|
220
|
-
prefix:
|
|
222
|
+
prefix: str | None = None,
|
|
221
223
|
) -> Scheme:
|
|
222
224
|
new = _sysconfig.get_scheme(
|
|
223
225
|
dist_name,
|
|
@@ -281,7 +283,7 @@ def get_scheme(
|
|
|
281
283
|
continue
|
|
282
284
|
|
|
283
285
|
# On Python 3.9+, sysconfig's posix_user scheme sets platlib against
|
|
284
|
-
# sys.platlibdir, but distutils's unix_user incorrectly
|
|
286
|
+
# sys.platlibdir, but distutils's unix_user incorrectly continues
|
|
285
287
|
# using the same $usersite for both platlib and purelib. This creates a
|
|
286
288
|
# mismatch when sys.platlibdir is not "lib".
|
|
287
289
|
skip_bpo_44860 = (
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
#
|
|
10
10
|
# See https://github.com/pypa/pip/issues/8761 for the original discussion and
|
|
11
11
|
# rationale for why this is done within pip.
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
12
14
|
try:
|
|
13
15
|
__import__("_distutils_hack").remove_shim()
|
|
14
16
|
except (ImportError, AttributeError):
|
|
@@ -21,7 +23,6 @@ from distutils.cmd import Command as DistutilsCommand
|
|
|
21
23
|
from distutils.command.install import SCHEME_KEYS
|
|
22
24
|
from distutils.command.install import install as distutils_install_command
|
|
23
25
|
from distutils.sysconfig import get_python_lib
|
|
24
|
-
from typing import Dict, List, Optional, Union
|
|
25
26
|
|
|
26
27
|
from pip._internal.models.scheme import Scheme
|
|
27
28
|
from pip._internal.utils.compat import WINDOWS
|
|
@@ -35,19 +36,19 @@ logger = logging.getLogger(__name__)
|
|
|
35
36
|
def distutils_scheme(
|
|
36
37
|
dist_name: str,
|
|
37
38
|
user: bool = False,
|
|
38
|
-
home:
|
|
39
|
-
root:
|
|
39
|
+
home: str | None = None,
|
|
40
|
+
root: str | None = None,
|
|
40
41
|
isolated: bool = False,
|
|
41
|
-
prefix:
|
|
42
|
+
prefix: str | None = None,
|
|
42
43
|
*,
|
|
43
44
|
ignore_config_files: bool = False,
|
|
44
|
-
) ->
|
|
45
|
+
) -> dict[str, str]:
|
|
45
46
|
"""
|
|
46
47
|
Return a distutils install scheme
|
|
47
48
|
"""
|
|
48
49
|
from distutils.dist import Distribution
|
|
49
50
|
|
|
50
|
-
dist_args:
|
|
51
|
+
dist_args: dict[str, str | list[str]] = {"name": dist_name}
|
|
51
52
|
if isolated:
|
|
52
53
|
dist_args["script_args"] = ["--no-user-cfg"]
|
|
53
54
|
|
|
@@ -61,7 +62,7 @@ def distutils_scheme(
|
|
|
61
62
|
"Ignore distutils configs in %s due to encoding errors.",
|
|
62
63
|
", ".join(os.path.basename(p) for p in paths),
|
|
63
64
|
)
|
|
64
|
-
obj:
|
|
65
|
+
obj: DistutilsCommand | None = None
|
|
65
66
|
obj = d.get_command_obj("install", create=True)
|
|
66
67
|
assert obj is not None
|
|
67
68
|
i: distutils_install_command = obj
|
|
@@ -78,7 +79,7 @@ def distutils_scheme(
|
|
|
78
79
|
i.root = root or i.root
|
|
79
80
|
i.finalize_options()
|
|
80
81
|
|
|
81
|
-
scheme:
|
|
82
|
+
scheme: dict[str, str] = {}
|
|
82
83
|
for key in SCHEME_KEYS:
|
|
83
84
|
scheme[key] = getattr(i, "install_" + key)
|
|
84
85
|
|
|
@@ -115,10 +116,10 @@ def distutils_scheme(
|
|
|
115
116
|
def get_scheme(
|
|
116
117
|
dist_name: str,
|
|
117
118
|
user: bool = False,
|
|
118
|
-
home:
|
|
119
|
-
root:
|
|
119
|
+
home: str | None = None,
|
|
120
|
+
root: str | None = None,
|
|
120
121
|
isolated: bool = False,
|
|
121
|
-
prefix:
|
|
122
|
+
prefix: str | None = None,
|
|
122
123
|
) -> Scheme:
|
|
123
124
|
"""
|
|
124
125
|
Get the "scheme" corresponding to the input parameters. The distutils
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import logging
|
|
2
4
|
import os
|
|
3
5
|
import sys
|
|
4
6
|
import sysconfig
|
|
5
|
-
import typing
|
|
6
7
|
|
|
7
8
|
from pip._internal.exceptions import InvalidSchemeCombination, UserInstallationInvalid
|
|
8
9
|
from pip._internal.models.scheme import SCHEME_KEYS, Scheme
|
|
@@ -124,10 +125,10 @@ if sysconfig.get_config_var("userbase") is not None:
|
|
|
124
125
|
def get_scheme(
|
|
125
126
|
dist_name: str,
|
|
126
127
|
user: bool = False,
|
|
127
|
-
home:
|
|
128
|
-
root:
|
|
128
|
+
home: str | None = None,
|
|
129
|
+
root: str | None = None,
|
|
129
130
|
isolated: bool = False,
|
|
130
|
-
prefix:
|
|
131
|
+
prefix: str | None = None,
|
|
131
132
|
) -> Scheme:
|
|
132
133
|
"""
|
|
133
134
|
Get the "scheme" corresponding to the input parameters.
|
pip/_internal/locations/base.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import functools
|
|
2
4
|
import os
|
|
3
5
|
import site
|
|
4
6
|
import sys
|
|
5
7
|
import sysconfig
|
|
6
|
-
import typing
|
|
7
8
|
|
|
8
9
|
from pip._internal.exceptions import InstallationError
|
|
9
10
|
from pip._internal.utils import appdirs
|
|
@@ -71,11 +72,11 @@ def get_src_prefix() -> str:
|
|
|
71
72
|
try:
|
|
72
73
|
# Use getusersitepackages if this is present, as it ensures that the
|
|
73
74
|
# value is initialised properly.
|
|
74
|
-
user_site:
|
|
75
|
+
user_site: str | None = site.getusersitepackages()
|
|
75
76
|
except AttributeError:
|
|
76
77
|
user_site = site.USER_SITE
|
|
77
78
|
|
|
78
79
|
|
|
79
|
-
@functools.
|
|
80
|
+
@functools.cache
|
|
80
81
|
def is_osx_framework() -> bool:
|
|
81
82
|
return bool(sysconfig.get_config_var("PYTHONFRAMEWORK"))
|
pip/_internal/main.py
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import contextlib
|
|
2
4
|
import functools
|
|
3
5
|
import os
|
|
4
6
|
import sys
|
|
5
|
-
from typing import
|
|
7
|
+
from typing import TYPE_CHECKING, Literal, Protocol, cast
|
|
6
8
|
|
|
7
9
|
from pip._internal.utils.deprecation import deprecated
|
|
8
10
|
from pip._internal.utils.misc import strtobool
|
|
9
11
|
|
|
10
12
|
from .base import BaseDistribution, BaseEnvironment, FilesystemWheel, MemoryWheel, Wheel
|
|
11
13
|
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from pip._vendor.packaging.utils import NormalizedName
|
|
16
|
+
|
|
12
17
|
__all__ = [
|
|
13
18
|
"BaseDistribution",
|
|
14
19
|
"BaseEnvironment",
|
|
@@ -81,12 +86,12 @@ def _emit_pkg_resources_deprecation_if_needed() -> None:
|
|
|
81
86
|
|
|
82
87
|
|
|
83
88
|
class Backend(Protocol):
|
|
84
|
-
NAME:
|
|
85
|
-
Distribution:
|
|
86
|
-
Environment:
|
|
89
|
+
NAME: Literal["importlib", "pkg_resources"]
|
|
90
|
+
Distribution: type[BaseDistribution]
|
|
91
|
+
Environment: type[BaseEnvironment]
|
|
87
92
|
|
|
88
93
|
|
|
89
|
-
@functools.
|
|
94
|
+
@functools.cache
|
|
90
95
|
def select_backend() -> Backend:
|
|
91
96
|
if _should_use_importlib_metadata():
|
|
92
97
|
from . import importlib
|
|
@@ -110,7 +115,7 @@ def get_default_environment() -> BaseEnvironment:
|
|
|
110
115
|
return select_backend().Environment.default()
|
|
111
116
|
|
|
112
117
|
|
|
113
|
-
def get_environment(paths:
|
|
118
|
+
def get_environment(paths: list[str] | None) -> BaseEnvironment:
|
|
114
119
|
"""Get a representation of the environment specified by ``paths``.
|
|
115
120
|
|
|
116
121
|
This returns an Environment instance from the chosen backend based on the
|
|
@@ -129,7 +134,9 @@ def get_directory_distribution(directory: str) -> BaseDistribution:
|
|
|
129
134
|
return select_backend().Distribution.from_directory(directory)
|
|
130
135
|
|
|
131
136
|
|
|
132
|
-
def get_wheel_distribution(
|
|
137
|
+
def get_wheel_distribution(
|
|
138
|
+
wheel: Wheel, canonical_name: NormalizedName
|
|
139
|
+
) -> BaseDistribution:
|
|
133
140
|
"""Get the representation of the specified wheel's distribution metadata.
|
|
134
141
|
|
|
135
142
|
This returns a Distribution instance from the chosen backend based on
|
pip/_internal/metadata/_json.py
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# Extracted from https://github.com/pfmoore/pkg_metadata
|
|
2
|
+
from __future__ import annotations
|
|
2
3
|
|
|
3
4
|
from email.header import Header, decode_header, make_header
|
|
4
5
|
from email.message import Message
|
|
5
|
-
from typing import Any,
|
|
6
|
+
from typing import Any, cast
|
|
6
7
|
|
|
7
8
|
METADATA_FIELDS = [
|
|
8
9
|
# Name, Multiple-Use
|
|
@@ -40,10 +41,10 @@ def json_name(field: str) -> str:
|
|
|
40
41
|
return field.lower().replace("-", "_")
|
|
41
42
|
|
|
42
43
|
|
|
43
|
-
def msg_to_json(msg: Message) ->
|
|
44
|
+
def msg_to_json(msg: Message) -> dict[str, Any]:
|
|
44
45
|
"""Convert a Message object into a JSON-compatible dictionary."""
|
|
45
46
|
|
|
46
|
-
def sanitise_header(h:
|
|
47
|
+
def sanitise_header(h: Header | str) -> str:
|
|
47
48
|
if isinstance(h, Header):
|
|
48
49
|
chunks = []
|
|
49
50
|
for bytes, encoding in decode_header(h):
|
|
@@ -65,7 +66,7 @@ def msg_to_json(msg: Message) -> Dict[str, Any]:
|
|
|
65
66
|
continue
|
|
66
67
|
key = json_name(field)
|
|
67
68
|
if multi:
|
|
68
|
-
value:
|
|
69
|
+
value: str | list[str] = [
|
|
69
70
|
sanitise_header(v) for v in msg.get_all(field) # type: ignore
|
|
70
71
|
]
|
|
71
72
|
else:
|
pip/_internal/metadata/base.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import csv
|
|
2
4
|
import email.message
|
|
3
5
|
import functools
|
|
@@ -6,19 +8,12 @@ import logging
|
|
|
6
8
|
import pathlib
|
|
7
9
|
import re
|
|
8
10
|
import zipfile
|
|
11
|
+
from collections.abc import Collection, Container, Iterable, Iterator
|
|
9
12
|
from typing import (
|
|
10
13
|
IO,
|
|
11
14
|
Any,
|
|
12
|
-
Collection,
|
|
13
|
-
Container,
|
|
14
|
-
Dict,
|
|
15
|
-
Iterable,
|
|
16
|
-
Iterator,
|
|
17
|
-
List,
|
|
18
15
|
NamedTuple,
|
|
19
|
-
Optional,
|
|
20
16
|
Protocol,
|
|
21
|
-
Tuple,
|
|
22
17
|
Union,
|
|
23
18
|
)
|
|
24
19
|
|
|
@@ -61,8 +56,8 @@ class BaseEntryPoint(Protocol):
|
|
|
61
56
|
|
|
62
57
|
|
|
63
58
|
def _convert_installed_files_path(
|
|
64
|
-
entry:
|
|
65
|
-
info:
|
|
59
|
+
entry: tuple[str, ...],
|
|
60
|
+
info: tuple[str, ...],
|
|
66
61
|
) -> str:
|
|
67
62
|
"""Convert a legacy installed-files.txt path into modern RECORD path.
|
|
68
63
|
|
|
@@ -98,7 +93,7 @@ class RequiresEntry(NamedTuple):
|
|
|
98
93
|
|
|
99
94
|
class BaseDistribution(Protocol):
|
|
100
95
|
@classmethod
|
|
101
|
-
def from_directory(cls, directory: str) ->
|
|
96
|
+
def from_directory(cls, directory: str) -> BaseDistribution:
|
|
102
97
|
"""Load the distribution from a metadata directory.
|
|
103
98
|
|
|
104
99
|
:param directory: Path to a metadata directory, e.g. ``.dist-info``.
|
|
@@ -111,7 +106,7 @@ class BaseDistribution(Protocol):
|
|
|
111
106
|
metadata_contents: bytes,
|
|
112
107
|
filename: str,
|
|
113
108
|
project_name: str,
|
|
114
|
-
) ->
|
|
109
|
+
) -> BaseDistribution:
|
|
115
110
|
"""Load the distribution from the contents of a METADATA file.
|
|
116
111
|
|
|
117
112
|
This is used to implement PEP 658 by generating a "shallow" dist object that can
|
|
@@ -124,7 +119,7 @@ class BaseDistribution(Protocol):
|
|
|
124
119
|
raise NotImplementedError()
|
|
125
120
|
|
|
126
121
|
@classmethod
|
|
127
|
-
def from_wheel(cls, wheel:
|
|
122
|
+
def from_wheel(cls, wheel: Wheel, name: str) -> BaseDistribution:
|
|
128
123
|
"""Load the distribution from a given wheel.
|
|
129
124
|
|
|
130
125
|
:param wheel: A concrete wheel definition.
|
|
@@ -144,7 +139,7 @@ class BaseDistribution(Protocol):
|
|
|
144
139
|
return f"{self.raw_name} {self.raw_version}"
|
|
145
140
|
|
|
146
141
|
@property
|
|
147
|
-
def location(self) ->
|
|
142
|
+
def location(self) -> str | None:
|
|
148
143
|
"""Where the distribution is loaded from.
|
|
149
144
|
|
|
150
145
|
A string value is not necessarily a filesystem path, since distributions
|
|
@@ -158,7 +153,7 @@ class BaseDistribution(Protocol):
|
|
|
158
153
|
raise NotImplementedError()
|
|
159
154
|
|
|
160
155
|
@property
|
|
161
|
-
def editable_project_location(self) ->
|
|
156
|
+
def editable_project_location(self) -> str | None:
|
|
162
157
|
"""The project location for editable distributions.
|
|
163
158
|
|
|
164
159
|
This is the directory where pyproject.toml or setup.py is located.
|
|
@@ -180,7 +175,7 @@ class BaseDistribution(Protocol):
|
|
|
180
175
|
return None
|
|
181
176
|
|
|
182
177
|
@property
|
|
183
|
-
def installed_location(self) ->
|
|
178
|
+
def installed_location(self) -> str | None:
|
|
184
179
|
"""The distribution's "installed" location.
|
|
185
180
|
|
|
186
181
|
This should generally be a ``site-packages`` directory. This is
|
|
@@ -193,7 +188,7 @@ class BaseDistribution(Protocol):
|
|
|
193
188
|
raise NotImplementedError()
|
|
194
189
|
|
|
195
190
|
@property
|
|
196
|
-
def info_location(self) ->
|
|
191
|
+
def info_location(self) -> str | None:
|
|
197
192
|
"""Location of the .[egg|dist]-info directory or file.
|
|
198
193
|
|
|
199
194
|
Similarly to ``location``, a string value is not necessarily a
|
|
@@ -290,7 +285,7 @@ class BaseDistribution(Protocol):
|
|
|
290
285
|
return self.raw_name.replace("-", "_")
|
|
291
286
|
|
|
292
287
|
@property
|
|
293
|
-
def direct_url(self) ->
|
|
288
|
+
def direct_url(self) -> DirectUrl | None:
|
|
294
289
|
"""Obtain a DirectUrl from this distribution.
|
|
295
290
|
|
|
296
291
|
Returns None if the distribution has no `direct_url.json` metadata,
|
|
@@ -398,7 +393,7 @@ class BaseDistribution(Protocol):
|
|
|
398
393
|
return metadata
|
|
399
394
|
|
|
400
395
|
@property
|
|
401
|
-
def metadata_dict(self) ->
|
|
396
|
+
def metadata_dict(self) -> dict[str, Any]:
|
|
402
397
|
"""PEP 566 compliant JSON-serializable representation of METADATA or PKG-INFO.
|
|
403
398
|
|
|
404
399
|
This should return an empty dict if the metadata file is unavailable.
|
|
@@ -409,7 +404,7 @@ class BaseDistribution(Protocol):
|
|
|
409
404
|
return msg_to_json(self.metadata)
|
|
410
405
|
|
|
411
406
|
@property
|
|
412
|
-
def metadata_version(self) ->
|
|
407
|
+
def metadata_version(self) -> str | None:
|
|
413
408
|
"""Value of "Metadata-Version:" in distribution metadata, if available."""
|
|
414
409
|
return self.metadata.get("Metadata-Version")
|
|
415
410
|
|
|
@@ -463,7 +458,7 @@ class BaseDistribution(Protocol):
|
|
|
463
458
|
"""
|
|
464
459
|
raise NotImplementedError()
|
|
465
460
|
|
|
466
|
-
def _iter_declared_entries_from_record(self) ->
|
|
461
|
+
def _iter_declared_entries_from_record(self) -> Iterator[str] | None:
|
|
467
462
|
try:
|
|
468
463
|
text = self.read_text("RECORD")
|
|
469
464
|
except FileNotFoundError:
|
|
@@ -471,7 +466,7 @@ class BaseDistribution(Protocol):
|
|
|
471
466
|
# This extra Path-str cast normalizes entries.
|
|
472
467
|
return (str(pathlib.Path(row[0])) for row in csv.reader(text.splitlines()))
|
|
473
468
|
|
|
474
|
-
def _iter_declared_entries_from_legacy(self) ->
|
|
469
|
+
def _iter_declared_entries_from_legacy(self) -> Iterator[str] | None:
|
|
475
470
|
try:
|
|
476
471
|
text = self.read_text("installed-files.txt")
|
|
477
472
|
except FileNotFoundError:
|
|
@@ -492,7 +487,7 @@ class BaseDistribution(Protocol):
|
|
|
492
487
|
for p in paths
|
|
493
488
|
)
|
|
494
489
|
|
|
495
|
-
def iter_declared_entries(self) ->
|
|
490
|
+
def iter_declared_entries(self) -> Iterator[str] | None:
|
|
496
491
|
"""Iterate through file entries declared in this distribution.
|
|
497
492
|
|
|
498
493
|
For modern .dist-info distributions, this is the files listed in the
|
|
@@ -585,14 +580,14 @@ class BaseEnvironment:
|
|
|
585
580
|
"""An environment containing distributions to introspect."""
|
|
586
581
|
|
|
587
582
|
@classmethod
|
|
588
|
-
def default(cls) ->
|
|
583
|
+
def default(cls) -> BaseEnvironment:
|
|
589
584
|
raise NotImplementedError()
|
|
590
585
|
|
|
591
586
|
@classmethod
|
|
592
|
-
def from_paths(cls, paths:
|
|
587
|
+
def from_paths(cls, paths: list[str] | None) -> BaseEnvironment:
|
|
593
588
|
raise NotImplementedError()
|
|
594
589
|
|
|
595
|
-
def get_distribution(self, name: str) ->
|
|
590
|
+
def get_distribution(self, name: str) -> BaseDistribution | None:
|
|
596
591
|
"""Given a requirement name, return the installed distributions.
|
|
597
592
|
|
|
598
593
|
The name may not be normalized. The implementation must canonicalize
|
|
@@ -600,7 +595,7 @@ class BaseEnvironment:
|
|
|
600
595
|
"""
|
|
601
596
|
raise NotImplementedError()
|
|
602
597
|
|
|
603
|
-
def _iter_distributions(self) -> Iterator[
|
|
598
|
+
def _iter_distributions(self) -> Iterator[BaseDistribution]:
|
|
604
599
|
"""Iterate through installed distributions.
|
|
605
600
|
|
|
606
601
|
This function should be implemented by subclass, but never called
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import importlib.metadata
|
|
2
4
|
import os
|
|
3
|
-
from typing import Any,
|
|
5
|
+
from typing import Any, Protocol, cast
|
|
4
6
|
|
|
5
7
|
from pip._vendor.packaging.utils import NormalizedName, canonicalize_name
|
|
6
8
|
|
|
@@ -30,11 +32,11 @@ class BasePath(Protocol):
|
|
|
30
32
|
raise NotImplementedError()
|
|
31
33
|
|
|
32
34
|
@property
|
|
33
|
-
def parent(self) ->
|
|
35
|
+
def parent(self) -> BasePath:
|
|
34
36
|
raise NotImplementedError()
|
|
35
37
|
|
|
36
38
|
|
|
37
|
-
def get_info_location(d: importlib.metadata.Distribution) ->
|
|
39
|
+
def get_info_location(d: importlib.metadata.Distribution) -> BasePath | None:
|
|
38
40
|
"""Find the path to the distribution's metadata directory.
|
|
39
41
|
|
|
40
42
|
HACK: This relies on importlib.metadata's private ``_path`` attribute. Not
|
|
@@ -48,7 +50,7 @@ def get_info_location(d: importlib.metadata.Distribution) -> Optional[BasePath]:
|
|
|
48
50
|
|
|
49
51
|
def parse_name_and_version_from_info_directory(
|
|
50
52
|
dist: importlib.metadata.Distribution,
|
|
51
|
-
) ->
|
|
53
|
+
) -> tuple[str | None, str | None]:
|
|
52
54
|
"""Get a name and version from the metadata directory name.
|
|
53
55
|
|
|
54
56
|
This is much faster than reading distribution metadata.
|
|
@@ -1,17 +1,12 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import email.message
|
|
2
4
|
import importlib.metadata
|
|
3
5
|
import pathlib
|
|
4
6
|
import zipfile
|
|
7
|
+
from collections.abc import Collection, Iterable, Iterator, Mapping, Sequence
|
|
5
8
|
from os import PathLike
|
|
6
9
|
from typing import (
|
|
7
|
-
Collection,
|
|
8
|
-
Dict,
|
|
9
|
-
Iterable,
|
|
10
|
-
Iterator,
|
|
11
|
-
Mapping,
|
|
12
|
-
Optional,
|
|
13
|
-
Sequence,
|
|
14
|
-
Union,
|
|
15
10
|
cast,
|
|
16
11
|
)
|
|
17
12
|
|
|
@@ -33,6 +28,7 @@ from pip._internal.utils.temp_dir import TempDirectory
|
|
|
33
28
|
from pip._internal.utils.wheel import parse_wheel, read_wheel_metadata_file
|
|
34
29
|
|
|
35
30
|
from ._compat import (
|
|
31
|
+
BadMetadata,
|
|
36
32
|
BasePath,
|
|
37
33
|
get_dist_canonical_name,
|
|
38
34
|
parse_name_and_version_from_info_directory,
|
|
@@ -64,7 +60,7 @@ class WheelDistribution(importlib.metadata.Distribution):
|
|
|
64
60
|
zf: zipfile.ZipFile,
|
|
65
61
|
name: str,
|
|
66
62
|
location: str,
|
|
67
|
-
) ->
|
|
63
|
+
) -> WheelDistribution:
|
|
68
64
|
info_dir, _ = parse_wheel(zf, name)
|
|
69
65
|
paths = (
|
|
70
66
|
(name, pathlib.PurePosixPath(name.split("/", 1)[-1]))
|
|
@@ -84,7 +80,7 @@ class WheelDistribution(importlib.metadata.Distribution):
|
|
|
84
80
|
return iter(self._files)
|
|
85
81
|
raise FileNotFoundError(path)
|
|
86
82
|
|
|
87
|
-
def read_text(self, filename: str) ->
|
|
83
|
+
def read_text(self, filename: str) -> str | None:
|
|
88
84
|
try:
|
|
89
85
|
data = self._files[pathlib.PurePosixPath(filename)]
|
|
90
86
|
except KeyError:
|
|
@@ -97,7 +93,7 @@ class WheelDistribution(importlib.metadata.Distribution):
|
|
|
97
93
|
raise UnsupportedWheel(error)
|
|
98
94
|
return text
|
|
99
95
|
|
|
100
|
-
def locate_file(self, path:
|
|
96
|
+
def locate_file(self, path: str | PathLike[str]) -> pathlib.Path:
|
|
101
97
|
# This method doesn't make sense for our in-memory wheel, but the API
|
|
102
98
|
# requires us to define it.
|
|
103
99
|
raise NotImplementedError
|
|
@@ -107,8 +103,8 @@ class Distribution(BaseDistribution):
|
|
|
107
103
|
def __init__(
|
|
108
104
|
self,
|
|
109
105
|
dist: importlib.metadata.Distribution,
|
|
110
|
-
info_location:
|
|
111
|
-
installed_location:
|
|
106
|
+
info_location: BasePath | None,
|
|
107
|
+
installed_location: BasePath | None,
|
|
112
108
|
) -> None:
|
|
113
109
|
self._dist = dist
|
|
114
110
|
self._info_location = info_location
|
|
@@ -147,19 +143,19 @@ class Distribution(BaseDistribution):
|
|
|
147
143
|
return cls(dist, dist.info_location, pathlib.PurePosixPath(wheel.location))
|
|
148
144
|
|
|
149
145
|
@property
|
|
150
|
-
def location(self) ->
|
|
146
|
+
def location(self) -> str | None:
|
|
151
147
|
if self._info_location is None:
|
|
152
148
|
return None
|
|
153
149
|
return str(self._info_location.parent)
|
|
154
150
|
|
|
155
151
|
@property
|
|
156
|
-
def info_location(self) ->
|
|
152
|
+
def info_location(self) -> str | None:
|
|
157
153
|
if self._info_location is None:
|
|
158
154
|
return None
|
|
159
155
|
return str(self._info_location)
|
|
160
156
|
|
|
161
157
|
@property
|
|
162
|
-
def installed_location(self) ->
|
|
158
|
+
def installed_location(self) -> str | None:
|
|
163
159
|
if self._installed_location is None:
|
|
164
160
|
return None
|
|
165
161
|
return normalize_path(str(self._installed_location))
|
|
@@ -170,9 +166,14 @@ class Distribution(BaseDistribution):
|
|
|
170
166
|
|
|
171
167
|
@property
|
|
172
168
|
def version(self) -> Version:
|
|
173
|
-
|
|
169
|
+
try:
|
|
170
|
+
version = (
|
|
171
|
+
parse_name_and_version_from_info_directory(self._dist)[1]
|
|
172
|
+
or self._dist.version
|
|
173
|
+
)
|
|
174
174
|
return parse_version(version)
|
|
175
|
-
|
|
175
|
+
except TypeError:
|
|
176
|
+
raise BadMetadata(self._dist, reason="invalid metadata entry `version`")
|
|
176
177
|
|
|
177
178
|
@property
|
|
178
179
|
def raw_version(self) -> str:
|
|
@@ -215,7 +216,7 @@ class Distribution(BaseDistribution):
|
|
|
215
216
|
]
|
|
216
217
|
|
|
217
218
|
def iter_dependencies(self, extras: Collection[str] = ()) -> Iterable[Requirement]:
|
|
218
|
-
contexts: Sequence[
|
|
219
|
+
contexts: Sequence[dict[str, str]] = [{"extra": e} for e in extras]
|
|
219
220
|
for req_string in self.metadata.get_all("Requires-Dist", []):
|
|
220
221
|
# strip() because email.message.Message.get_all() may return a leading \n
|
|
221
222
|
# in case a long header was wrapped.
|