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
|
@@ -8,12 +8,14 @@ These are meant to be used elsewhere within pip to create instances of
|
|
|
8
8
|
InstallRequirement.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
11
13
|
import copy
|
|
12
14
|
import logging
|
|
13
15
|
import os
|
|
14
16
|
import re
|
|
17
|
+
from collections.abc import Collection
|
|
15
18
|
from dataclasses import dataclass
|
|
16
|
-
from typing import Collection, Dict, List, Optional, Set, Tuple, Union
|
|
17
19
|
|
|
18
20
|
from pip._vendor.packaging.markers import Marker
|
|
19
21
|
from pip._vendor.packaging.requirements import InvalidRequirement, Requirement
|
|
@@ -41,11 +43,11 @@ logger = logging.getLogger(__name__)
|
|
|
41
43
|
operators = Specifier._operators.keys()
|
|
42
44
|
|
|
43
45
|
|
|
44
|
-
def _strip_extras(path: str) ->
|
|
46
|
+
def _strip_extras(path: str) -> tuple[str, str | None]:
|
|
45
47
|
m = re.match(r"^(.+)(\[[^\]]+\])$", path)
|
|
46
48
|
extras = None
|
|
47
49
|
if m:
|
|
48
|
-
path_no_extras = m.group(1)
|
|
50
|
+
path_no_extras = m.group(1).rstrip()
|
|
49
51
|
extras = m.group(2)
|
|
50
52
|
else:
|
|
51
53
|
path_no_extras = path
|
|
@@ -53,19 +55,19 @@ def _strip_extras(path: str) -> Tuple[str, Optional[str]]:
|
|
|
53
55
|
return path_no_extras, extras
|
|
54
56
|
|
|
55
57
|
|
|
56
|
-
def convert_extras(extras:
|
|
58
|
+
def convert_extras(extras: str | None) -> set[str]:
|
|
57
59
|
if not extras:
|
|
58
60
|
return set()
|
|
59
61
|
return get_requirement("placeholder" + extras.lower()).extras
|
|
60
62
|
|
|
61
63
|
|
|
62
|
-
def _set_requirement_extras(req: Requirement, new_extras:
|
|
64
|
+
def _set_requirement_extras(req: Requirement, new_extras: set[str]) -> Requirement:
|
|
63
65
|
"""
|
|
64
66
|
Returns a new requirement based on the given one, with the supplied extras. If the
|
|
65
67
|
given requirement already has extras those are replaced (or dropped if no new extras
|
|
66
68
|
are given).
|
|
67
69
|
"""
|
|
68
|
-
match:
|
|
70
|
+
match: re.Match[str] | None = re.fullmatch(
|
|
69
71
|
# see https://peps.python.org/pep-0508/#complete-grammar
|
|
70
72
|
r"([\w\t .-]+)(\[[^\]]*\])?(.*)",
|
|
71
73
|
str(req),
|
|
@@ -75,8 +77,8 @@ def _set_requirement_extras(req: Requirement, new_extras: Set[str]) -> Requireme
|
|
|
75
77
|
assert (
|
|
76
78
|
match is not None
|
|
77
79
|
), f"regex match on requirement {req} failed, this should never happen"
|
|
78
|
-
pre:
|
|
79
|
-
post:
|
|
80
|
+
pre: str | None = match.group(1)
|
|
81
|
+
post: str | None = match.group(3)
|
|
80
82
|
assert (
|
|
81
83
|
pre is not None and post is not None
|
|
82
84
|
), f"regex group selection for requirement {req} failed, this should never happen"
|
|
@@ -84,17 +86,25 @@ def _set_requirement_extras(req: Requirement, new_extras: Set[str]) -> Requireme
|
|
|
84
86
|
return get_requirement(f"{pre}{extras}{post}")
|
|
85
87
|
|
|
86
88
|
|
|
87
|
-
def
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
89
|
+
def _parse_direct_url_editable(editable_req: str) -> tuple[str | None, str, set[str]]:
|
|
90
|
+
try:
|
|
91
|
+
req = Requirement(editable_req)
|
|
92
|
+
except InvalidRequirement:
|
|
93
|
+
pass
|
|
94
|
+
else:
|
|
95
|
+
if req.url:
|
|
96
|
+
# Join the marker back into the name part. This will be parsed out
|
|
97
|
+
# later into a Requirement again.
|
|
98
|
+
if req.marker:
|
|
99
|
+
name = f"{req.name} ; {req.marker}"
|
|
100
|
+
else:
|
|
101
|
+
name = req.name
|
|
102
|
+
return (name, req.url, req.extras)
|
|
103
|
+
|
|
104
|
+
raise ValueError
|
|
97
105
|
|
|
106
|
+
|
|
107
|
+
def _parse_pip_syntax_editable(editable_req: str) -> tuple[str | None, str, set[str]]:
|
|
98
108
|
url = editable_req
|
|
99
109
|
|
|
100
110
|
# If a file path is specified with extras, strip off the extras.
|
|
@@ -120,9 +130,27 @@ def parse_editable(editable_req: str) -> Tuple[Optional[str], str, Set[str]]:
|
|
|
120
130
|
url = f"{version_control}+{url}"
|
|
121
131
|
break
|
|
122
132
|
|
|
133
|
+
return Link(url).egg_fragment, url, set()
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def parse_editable(editable_req: str) -> tuple[str | None, str, set[str]]:
|
|
137
|
+
"""Parses an editable requirement into:
|
|
138
|
+
- a requirement name with environment markers
|
|
139
|
+
- an URL
|
|
140
|
+
- extras
|
|
141
|
+
Accepted requirements:
|
|
142
|
+
- svn+http://blahblah@rev#egg=Foobar[baz]&subdirectory=version_subdir
|
|
143
|
+
- local_path[some_extra]
|
|
144
|
+
- Foobar[extra] @ svn+http://blahblah@rev#subdirectory=subdir ; markers
|
|
145
|
+
"""
|
|
146
|
+
try:
|
|
147
|
+
package_name, url, extras = _parse_direct_url_editable(editable_req)
|
|
148
|
+
except ValueError:
|
|
149
|
+
package_name, url, extras = _parse_pip_syntax_editable(editable_req)
|
|
150
|
+
|
|
123
151
|
link = Link(url)
|
|
124
152
|
|
|
125
|
-
if not link.is_vcs:
|
|
153
|
+
if not link.is_vcs and not link.url.startswith("file:"):
|
|
126
154
|
backends = ", ".join(vcs.all_schemes)
|
|
127
155
|
raise InstallationError(
|
|
128
156
|
f"{editable_req} is not a valid editable requirement. "
|
|
@@ -130,13 +158,13 @@ def parse_editable(editable_req: str) -> Tuple[Optional[str], str, Set[str]]:
|
|
|
130
158
|
f"(beginning with {backends})."
|
|
131
159
|
)
|
|
132
160
|
|
|
133
|
-
|
|
134
|
-
if not package_name:
|
|
161
|
+
# The project name can be inferred from local file URIs easily.
|
|
162
|
+
if not package_name and not link.url.startswith("file:"):
|
|
135
163
|
raise InstallationError(
|
|
136
164
|
f"Could not detect requirement name for '{editable_req}', "
|
|
137
|
-
"please specify one with
|
|
165
|
+
"please specify one with your_package_name @ URL"
|
|
138
166
|
)
|
|
139
|
-
return package_name, url,
|
|
167
|
+
return package_name, url, extras
|
|
140
168
|
|
|
141
169
|
|
|
142
170
|
def check_first_requirement_in_file(filename: str) -> None:
|
|
@@ -194,10 +222,10 @@ def deduce_helpful_msg(req: str) -> str:
|
|
|
194
222
|
|
|
195
223
|
@dataclass(frozen=True)
|
|
196
224
|
class RequirementParts:
|
|
197
|
-
requirement:
|
|
198
|
-
link:
|
|
199
|
-
markers:
|
|
200
|
-
extras:
|
|
225
|
+
requirement: Requirement | None
|
|
226
|
+
link: Link | None
|
|
227
|
+
markers: Marker | None
|
|
228
|
+
extras: set[str]
|
|
201
229
|
|
|
202
230
|
|
|
203
231
|
def parse_req_from_editable(editable_req: str) -> RequirementParts:
|
|
@@ -205,7 +233,7 @@ def parse_req_from_editable(editable_req: str) -> RequirementParts:
|
|
|
205
233
|
|
|
206
234
|
if name is not None:
|
|
207
235
|
try:
|
|
208
|
-
req:
|
|
236
|
+
req: Requirement | None = get_requirement(name)
|
|
209
237
|
except InvalidRequirement as exc:
|
|
210
238
|
raise InstallationError(f"Invalid requirement: {name!r}: {exc}")
|
|
211
239
|
else:
|
|
@@ -221,16 +249,14 @@ def parse_req_from_editable(editable_req: str) -> RequirementParts:
|
|
|
221
249
|
|
|
222
250
|
def install_req_from_editable(
|
|
223
251
|
editable_req: str,
|
|
224
|
-
comes_from:
|
|
252
|
+
comes_from: InstallRequirement | str | None = None,
|
|
225
253
|
*,
|
|
226
|
-
use_pep517: Optional[bool] = None,
|
|
227
254
|
isolated: bool = False,
|
|
228
|
-
|
|
229
|
-
hash_options: Optional[Dict[str, List[str]]] = None,
|
|
255
|
+
hash_options: dict[str, list[str]] | None = None,
|
|
230
256
|
constraint: bool = False,
|
|
231
257
|
user_supplied: bool = False,
|
|
232
258
|
permit_editable_wheels: bool = False,
|
|
233
|
-
config_settings:
|
|
259
|
+
config_settings: dict[str, str | list[str]] | None = None,
|
|
234
260
|
) -> InstallRequirement:
|
|
235
261
|
parts = parse_req_from_editable(editable_req)
|
|
236
262
|
|
|
@@ -242,9 +268,7 @@ def install_req_from_editable(
|
|
|
242
268
|
permit_editable_wheels=permit_editable_wheels,
|
|
243
269
|
link=parts.link,
|
|
244
270
|
constraint=constraint,
|
|
245
|
-
use_pep517=use_pep517,
|
|
246
271
|
isolated=isolated,
|
|
247
|
-
global_options=global_options,
|
|
248
272
|
hash_options=hash_options,
|
|
249
273
|
config_settings=config_settings,
|
|
250
274
|
extras=parts.extras,
|
|
@@ -270,7 +294,7 @@ def _looks_like_path(name: str) -> bool:
|
|
|
270
294
|
return False
|
|
271
295
|
|
|
272
296
|
|
|
273
|
-
def _get_url_from_path(path: str, name: str) ->
|
|
297
|
+
def _get_url_from_path(path: str, name: str) -> str | None:
|
|
274
298
|
"""
|
|
275
299
|
First, it checks whether a provided path is an installable directory. If it
|
|
276
300
|
is, returns the path.
|
|
@@ -304,7 +328,7 @@ def _get_url_from_path(path: str, name: str) -> Optional[str]:
|
|
|
304
328
|
return path_to_url(path)
|
|
305
329
|
|
|
306
330
|
|
|
307
|
-
def parse_req_from_line(name: str, line_source:
|
|
331
|
+
def parse_req_from_line(name: str, line_source: str | None) -> RequirementParts:
|
|
308
332
|
if is_url(name):
|
|
309
333
|
marker_sep = "; "
|
|
310
334
|
else:
|
|
@@ -376,7 +400,7 @@ def parse_req_from_line(name: str, line_source: Optional[str]) -> RequirementPar
|
|
|
376
400
|
raise InstallationError(msg)
|
|
377
401
|
|
|
378
402
|
if req_as_string is not None:
|
|
379
|
-
req:
|
|
403
|
+
req: Requirement | None = _parse_req_string(req_as_string)
|
|
380
404
|
else:
|
|
381
405
|
req = None
|
|
382
406
|
|
|
@@ -385,16 +409,14 @@ def parse_req_from_line(name: str, line_source: Optional[str]) -> RequirementPar
|
|
|
385
409
|
|
|
386
410
|
def install_req_from_line(
|
|
387
411
|
name: str,
|
|
388
|
-
comes_from:
|
|
412
|
+
comes_from: str | InstallRequirement | None = None,
|
|
389
413
|
*,
|
|
390
|
-
use_pep517: Optional[bool] = None,
|
|
391
414
|
isolated: bool = False,
|
|
392
|
-
|
|
393
|
-
hash_options: Optional[Dict[str, List[str]]] = None,
|
|
415
|
+
hash_options: dict[str, list[str]] | None = None,
|
|
394
416
|
constraint: bool = False,
|
|
395
|
-
line_source:
|
|
417
|
+
line_source: str | None = None,
|
|
396
418
|
user_supplied: bool = False,
|
|
397
|
-
config_settings:
|
|
419
|
+
config_settings: dict[str, str | list[str]] | None = None,
|
|
398
420
|
) -> InstallRequirement:
|
|
399
421
|
"""Creates an InstallRequirement from a name, which might be a
|
|
400
422
|
requirement, directory containing 'setup.py', filename, or URL.
|
|
@@ -409,9 +431,7 @@ def install_req_from_line(
|
|
|
409
431
|
comes_from,
|
|
410
432
|
link=parts.link,
|
|
411
433
|
markers=parts.markers,
|
|
412
|
-
use_pep517=use_pep517,
|
|
413
434
|
isolated=isolated,
|
|
414
|
-
global_options=global_options,
|
|
415
435
|
hash_options=hash_options,
|
|
416
436
|
config_settings=config_settings,
|
|
417
437
|
constraint=constraint,
|
|
@@ -422,9 +442,8 @@ def install_req_from_line(
|
|
|
422
442
|
|
|
423
443
|
def install_req_from_req_string(
|
|
424
444
|
req_string: str,
|
|
425
|
-
comes_from:
|
|
445
|
+
comes_from: InstallRequirement | None = None,
|
|
426
446
|
isolated: bool = False,
|
|
427
|
-
use_pep517: Optional[bool] = None,
|
|
428
447
|
user_supplied: bool = False,
|
|
429
448
|
) -> InstallRequirement:
|
|
430
449
|
try:
|
|
@@ -453,7 +472,6 @@ def install_req_from_req_string(
|
|
|
453
472
|
req,
|
|
454
473
|
comes_from,
|
|
455
474
|
isolated=isolated,
|
|
456
|
-
use_pep517=use_pep517,
|
|
457
475
|
user_supplied=user_supplied,
|
|
458
476
|
)
|
|
459
477
|
|
|
@@ -461,15 +479,13 @@ def install_req_from_req_string(
|
|
|
461
479
|
def install_req_from_parsed_requirement(
|
|
462
480
|
parsed_req: ParsedRequirement,
|
|
463
481
|
isolated: bool = False,
|
|
464
|
-
use_pep517: Optional[bool] = None,
|
|
465
482
|
user_supplied: bool = False,
|
|
466
|
-
config_settings:
|
|
483
|
+
config_settings: dict[str, str | list[str]] | None = None,
|
|
467
484
|
) -> InstallRequirement:
|
|
468
485
|
if parsed_req.is_editable:
|
|
469
486
|
req = install_req_from_editable(
|
|
470
487
|
parsed_req.requirement,
|
|
471
488
|
comes_from=parsed_req.comes_from,
|
|
472
|
-
use_pep517=use_pep517,
|
|
473
489
|
constraint=parsed_req.constraint,
|
|
474
490
|
isolated=isolated,
|
|
475
491
|
user_supplied=user_supplied,
|
|
@@ -480,13 +496,7 @@ def install_req_from_parsed_requirement(
|
|
|
480
496
|
req = install_req_from_line(
|
|
481
497
|
parsed_req.requirement,
|
|
482
498
|
comes_from=parsed_req.comes_from,
|
|
483
|
-
use_pep517=use_pep517,
|
|
484
499
|
isolated=isolated,
|
|
485
|
-
global_options=(
|
|
486
|
-
parsed_req.options.get("global_options", [])
|
|
487
|
-
if parsed_req.options
|
|
488
|
-
else []
|
|
489
|
-
),
|
|
490
500
|
hash_options=(
|
|
491
501
|
parsed_req.options.get("hashes", {}) if parsed_req.options else {}
|
|
492
502
|
),
|
|
@@ -507,9 +517,7 @@ def install_req_from_link_and_ireq(
|
|
|
507
517
|
editable=ireq.editable,
|
|
508
518
|
link=link,
|
|
509
519
|
markers=ireq.markers,
|
|
510
|
-
use_pep517=ireq.use_pep517,
|
|
511
520
|
isolated=ireq.isolated,
|
|
512
|
-
global_options=ireq.global_options,
|
|
513
521
|
hash_options=ireq.hash_options,
|
|
514
522
|
config_settings=ireq.config_settings,
|
|
515
523
|
user_supplied=ireq.user_supplied,
|
|
@@ -530,9 +538,7 @@ def install_req_drop_extras(ireq: InstallRequirement) -> InstallRequirement:
|
|
|
530
538
|
editable=ireq.editable,
|
|
531
539
|
link=ireq.link,
|
|
532
540
|
markers=ireq.markers,
|
|
533
|
-
use_pep517=ireq.use_pep517,
|
|
534
541
|
isolated=ireq.isolated,
|
|
535
|
-
global_options=ireq.global_options,
|
|
536
542
|
hash_options=ireq.hash_options,
|
|
537
543
|
constraint=ireq.constraint,
|
|
538
544
|
extras=[],
|
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
if sys.version_info >= (3, 11):
|
|
5
|
-
import tomllib
|
|
6
|
-
else:
|
|
7
|
-
from pip._vendor import tomli as tomllib
|
|
1
|
+
from collections.abc import Iterable, Iterator
|
|
2
|
+
from typing import Any
|
|
8
3
|
|
|
9
4
|
from pip._vendor.dependency_groups import DependencyGroupResolver
|
|
10
5
|
|
|
11
6
|
from pip._internal.exceptions import InstallationError
|
|
7
|
+
from pip._internal.utils.compat import tomllib
|
|
12
8
|
|
|
13
9
|
|
|
14
|
-
def parse_dependency_groups(groups:
|
|
10
|
+
def parse_dependency_groups(groups: list[tuple[str, str]]) -> list[str]:
|
|
15
11
|
"""
|
|
16
12
|
Parse dependency groups data as provided via the CLI, in a `[path:]group` syntax.
|
|
17
13
|
|
|
@@ -22,7 +18,7 @@ def parse_dependency_groups(groups: List[Tuple[str, str]]) -> List[str]:
|
|
|
22
18
|
|
|
23
19
|
|
|
24
20
|
def _resolve_all_groups(
|
|
25
|
-
resolvers:
|
|
21
|
+
resolvers: dict[str, DependencyGroupResolver], groups: list[tuple[str, str]]
|
|
26
22
|
) -> Iterator[str]:
|
|
27
23
|
"""
|
|
28
24
|
Run all resolution, converting any error from `DependencyGroupResolver` into
|
|
@@ -39,7 +35,7 @@ def _resolve_all_groups(
|
|
|
39
35
|
) from e
|
|
40
36
|
|
|
41
37
|
|
|
42
|
-
def _build_resolvers(paths: Iterable[str]) ->
|
|
38
|
+
def _build_resolvers(paths: Iterable[str]) -> dict[str, Any]:
|
|
43
39
|
resolvers = {}
|
|
44
40
|
for path in paths:
|
|
45
41
|
if path in resolvers:
|
|
@@ -62,7 +58,7 @@ def _build_resolvers(paths: Iterable[str]) -> Dict[str, Any]:
|
|
|
62
58
|
return resolvers
|
|
63
59
|
|
|
64
60
|
|
|
65
|
-
def _load_pyproject(path: str) ->
|
|
61
|
+
def _load_pyproject(path: str) -> dict[str, Any]:
|
|
66
62
|
"""
|
|
67
63
|
This helper loads a pyproject.toml as TOML.
|
|
68
64
|
|
pip/_internal/req/req_file.py
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Requirements file parsing
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
5
7
|
import codecs
|
|
6
8
|
import locale
|
|
7
9
|
import logging
|
|
@@ -11,19 +13,14 @@ import re
|
|
|
11
13
|
import shlex
|
|
12
14
|
import sys
|
|
13
15
|
import urllib.parse
|
|
16
|
+
from collections.abc import Generator, Iterable
|
|
14
17
|
from dataclasses import dataclass
|
|
15
18
|
from optparse import Values
|
|
16
19
|
from typing import (
|
|
17
20
|
TYPE_CHECKING,
|
|
18
21
|
Any,
|
|
19
22
|
Callable,
|
|
20
|
-
Dict,
|
|
21
|
-
Generator,
|
|
22
|
-
Iterable,
|
|
23
|
-
List,
|
|
24
23
|
NoReturn,
|
|
25
|
-
Optional,
|
|
26
|
-
Tuple,
|
|
27
24
|
)
|
|
28
25
|
|
|
29
26
|
from pip._internal.cli import cmdoptions
|
|
@@ -36,9 +33,9 @@ if TYPE_CHECKING:
|
|
|
36
33
|
|
|
37
34
|
__all__ = ["parse_requirements"]
|
|
38
35
|
|
|
39
|
-
ReqFileLines = Iterable[
|
|
36
|
+
ReqFileLines = Iterable[tuple[int, str]]
|
|
40
37
|
|
|
41
|
-
LineParser = Callable[[str],
|
|
38
|
+
LineParser = Callable[[str], tuple[str, Values]]
|
|
42
39
|
|
|
43
40
|
SCHEME_RE = re.compile(r"^(http|https|file):", re.I)
|
|
44
41
|
COMMENT_RE = re.compile(r"(^|\s+)#.*$")
|
|
@@ -49,7 +46,7 @@ COMMENT_RE = re.compile(r"(^|\s+)#.*$")
|
|
|
49
46
|
# 2013 Edition.
|
|
50
47
|
ENV_VAR_RE = re.compile(r"(?P<var>\$\{(?P<name>[A-Z0-9_]+)\})")
|
|
51
48
|
|
|
52
|
-
SUPPORTED_OPTIONS:
|
|
49
|
+
SUPPORTED_OPTIONS: list[Callable[..., optparse.Option]] = [
|
|
53
50
|
cmdoptions.index_url,
|
|
54
51
|
cmdoptions.extra_index_url,
|
|
55
52
|
cmdoptions.no_index,
|
|
@@ -67,13 +64,12 @@ SUPPORTED_OPTIONS: List[Callable[..., optparse.Option]] = [
|
|
|
67
64
|
]
|
|
68
65
|
|
|
69
66
|
# options to be passed to requirements
|
|
70
|
-
SUPPORTED_OPTIONS_REQ:
|
|
71
|
-
cmdoptions.global_options,
|
|
67
|
+
SUPPORTED_OPTIONS_REQ: list[Callable[..., optparse.Option]] = [
|
|
72
68
|
cmdoptions.hash,
|
|
73
69
|
cmdoptions.config_settings,
|
|
74
70
|
]
|
|
75
71
|
|
|
76
|
-
SUPPORTED_OPTIONS_EDITABLE_REQ:
|
|
72
|
+
SUPPORTED_OPTIONS_EDITABLE_REQ: list[Callable[..., optparse.Option]] = [
|
|
77
73
|
cmdoptions.config_settings,
|
|
78
74
|
]
|
|
79
75
|
|
|
@@ -86,7 +82,7 @@ SUPPORTED_OPTIONS_EDITABLE_REQ_DEST = [
|
|
|
86
82
|
|
|
87
83
|
# order of BOMS is important: codecs.BOM_UTF16_LE is a prefix of codecs.BOM_UTF32_LE
|
|
88
84
|
# so data.startswith(BOM_UTF16_LE) would be true for UTF32_LE data
|
|
89
|
-
BOMS:
|
|
85
|
+
BOMS: list[tuple[bytes, str]] = [
|
|
90
86
|
(codecs.BOM_UTF8, "utf-8"),
|
|
91
87
|
(codecs.BOM_UTF32, "utf-32"),
|
|
92
88
|
(codecs.BOM_UTF32_BE, "utf-32-be"),
|
|
@@ -118,8 +114,8 @@ class ParsedRequirement:
|
|
|
118
114
|
is_editable: bool
|
|
119
115
|
comes_from: str
|
|
120
116
|
constraint: bool
|
|
121
|
-
options:
|
|
122
|
-
line_source:
|
|
117
|
+
options: dict[str, Any] | None
|
|
118
|
+
line_source: str | None
|
|
123
119
|
|
|
124
120
|
|
|
125
121
|
@dataclass(frozen=True)
|
|
@@ -137,7 +133,7 @@ class ParsedLine:
|
|
|
137
133
|
return bool(self.opts.editables)
|
|
138
134
|
|
|
139
135
|
@property
|
|
140
|
-
def requirement(self) ->
|
|
136
|
+
def requirement(self) -> str | None:
|
|
141
137
|
if self.args:
|
|
142
138
|
return self.args
|
|
143
139
|
elif self.is_editable:
|
|
@@ -148,9 +144,9 @@ class ParsedLine:
|
|
|
148
144
|
|
|
149
145
|
def parse_requirements(
|
|
150
146
|
filename: str,
|
|
151
|
-
session:
|
|
152
|
-
finder:
|
|
153
|
-
options:
|
|
147
|
+
session: PipSession,
|
|
148
|
+
finder: PackageFinder | None = None,
|
|
149
|
+
options: optparse.Values | None = None,
|
|
154
150
|
constraint: bool = False,
|
|
155
151
|
) -> Generator[ParsedRequirement, None, None]:
|
|
156
152
|
"""Parse a requirements file and yield ParsedRequirement instances.
|
|
@@ -187,7 +183,7 @@ def preprocess(content: str) -> ReqFileLines:
|
|
|
187
183
|
|
|
188
184
|
def handle_requirement_line(
|
|
189
185
|
line: ParsedLine,
|
|
190
|
-
options:
|
|
186
|
+
options: optparse.Values | None = None,
|
|
191
187
|
) -> ParsedRequirement:
|
|
192
188
|
# preserve for the nested code path
|
|
193
189
|
line_comes_from = "{} {} (line {})".format(
|
|
@@ -223,9 +219,9 @@ def handle_option_line(
|
|
|
223
219
|
opts: Values,
|
|
224
220
|
filename: str,
|
|
225
221
|
lineno: int,
|
|
226
|
-
finder:
|
|
227
|
-
options:
|
|
228
|
-
session:
|
|
222
|
+
finder: PackageFinder | None = None,
|
|
223
|
+
options: optparse.Values | None = None,
|
|
224
|
+
session: PipSession | None = None,
|
|
229
225
|
) -> None:
|
|
230
226
|
if opts.hashes:
|
|
231
227
|
logger.warning(
|
|
@@ -291,10 +287,10 @@ def handle_option_line(
|
|
|
291
287
|
|
|
292
288
|
def handle_line(
|
|
293
289
|
line: ParsedLine,
|
|
294
|
-
options:
|
|
295
|
-
finder:
|
|
296
|
-
session:
|
|
297
|
-
) ->
|
|
290
|
+
options: optparse.Values | None = None,
|
|
291
|
+
finder: PackageFinder | None = None,
|
|
292
|
+
session: PipSession | None = None,
|
|
293
|
+
) -> ParsedRequirement | None:
|
|
298
294
|
"""Handle a single parsed requirements line; This can result in
|
|
299
295
|
creating/yielding requirements, or updating the finder.
|
|
300
296
|
|
|
@@ -336,7 +332,7 @@ def handle_line(
|
|
|
336
332
|
class RequirementsFileParser:
|
|
337
333
|
def __init__(
|
|
338
334
|
self,
|
|
339
|
-
session:
|
|
335
|
+
session: PipSession,
|
|
340
336
|
line_parser: LineParser,
|
|
341
337
|
) -> None:
|
|
342
338
|
self._session = session
|
|
@@ -354,7 +350,7 @@ class RequirementsFileParser:
|
|
|
354
350
|
self,
|
|
355
351
|
filename: str,
|
|
356
352
|
constraint: bool,
|
|
357
|
-
parsed_files_stack:
|
|
353
|
+
parsed_files_stack: list[dict[str, str | None]],
|
|
358
354
|
) -> Generator[ParsedLine, None, None]:
|
|
359
355
|
for line in self._parse_file(filename, constraint):
|
|
360
356
|
if line.requirement is None and (
|
|
@@ -426,8 +422,8 @@ class RequirementsFileParser:
|
|
|
426
422
|
)
|
|
427
423
|
|
|
428
424
|
|
|
429
|
-
def get_line_parser(finder:
|
|
430
|
-
def parse_line(line: str) ->
|
|
425
|
+
def get_line_parser(finder: PackageFinder | None) -> LineParser:
|
|
426
|
+
def parse_line(line: str) -> tuple[str, Values]:
|
|
431
427
|
# Build new parser for each line since it accumulates appendable
|
|
432
428
|
# options.
|
|
433
429
|
parser = build_parser()
|
|
@@ -450,7 +446,7 @@ def get_line_parser(finder: Optional["PackageFinder"]) -> LineParser:
|
|
|
450
446
|
return parse_line
|
|
451
447
|
|
|
452
448
|
|
|
453
|
-
def break_args_options(line: str) ->
|
|
449
|
+
def break_args_options(line: str) -> tuple[str, str]:
|
|
454
450
|
"""Break up the line into an args and options string. We only want to shlex
|
|
455
451
|
(and then optparse) the options, not the args. args can contain markers
|
|
456
452
|
which are corrupted by shlex.
|
|
@@ -459,7 +455,7 @@ def break_args_options(line: str) -> Tuple[str, str]:
|
|
|
459
455
|
args = []
|
|
460
456
|
options = tokens[:]
|
|
461
457
|
for token in tokens:
|
|
462
|
-
if token.startswith("-"
|
|
458
|
+
if token.startswith(("-", "--")):
|
|
463
459
|
break
|
|
464
460
|
else:
|
|
465
461
|
args.append(token)
|
|
@@ -485,7 +481,7 @@ def build_parser() -> optparse.OptionParser:
|
|
|
485
481
|
|
|
486
482
|
# By default optparse sys.exits on parsing errors. We want to wrap
|
|
487
483
|
# that in our own exception.
|
|
488
|
-
def parser_exit(self: Any, msg: str) ->
|
|
484
|
+
def parser_exit(self: Any, msg: str) -> NoReturn:
|
|
489
485
|
raise OptionParsingError(msg)
|
|
490
486
|
|
|
491
487
|
# NOTE: mypy disallows assigning to a method
|
|
@@ -500,7 +496,7 @@ def join_lines(lines_enum: ReqFileLines) -> ReqFileLines:
|
|
|
500
496
|
comments). The joined line takes on the index of the first line.
|
|
501
497
|
"""
|
|
502
498
|
primary_line_number = None
|
|
503
|
-
new_line:
|
|
499
|
+
new_line: list[str] = []
|
|
504
500
|
for line_number, line in lines_enum:
|
|
505
501
|
if not line.endswith("\\") or COMMENT_RE.match(line):
|
|
506
502
|
if COMMENT_RE.match(line):
|
|
@@ -564,7 +560,7 @@ def expand_env_variables(lines_enum: ReqFileLines) -> ReqFileLines:
|
|
|
564
560
|
yield line_number, line
|
|
565
561
|
|
|
566
562
|
|
|
567
|
-
def get_file_content(url: str, session:
|
|
563
|
+
def get_file_content(url: str, session: PipSession) -> tuple[str, str]:
|
|
568
564
|
"""Gets the content of a file; it may be a filename, file: URL, or
|
|
569
565
|
http: URL. Returns (location, content). Content is unicode.
|
|
570
566
|
Respects # -*- coding: declarations on the retrieved files.
|