pip 25.2__py3-none-any.whl → 26.0__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 +1 -1
- pip/_internal/__init__.py +0 -0
- pip/_internal/build_env.py +265 -8
- pip/_internal/cache.py +1 -1
- pip/_internal/cli/base_command.py +11 -0
- pip/_internal/cli/cmdoptions.py +200 -71
- pip/_internal/cli/index_command.py +20 -0
- pip/_internal/cli/main.py +11 -6
- pip/_internal/cli/main_parser.py +3 -1
- pip/_internal/cli/parser.py +96 -36
- pip/_internal/cli/progress_bars.py +4 -2
- pip/_internal/cli/req_command.py +126 -30
- pip/_internal/commands/cache.py +24 -0
- pip/_internal/commands/completion.py +2 -1
- pip/_internal/commands/download.py +12 -11
- pip/_internal/commands/index.py +13 -6
- pip/_internal/commands/install.py +55 -43
- pip/_internal/commands/list.py +14 -16
- pip/_internal/commands/lock.py +19 -14
- pip/_internal/commands/wheel.py +13 -23
- pip/_internal/configuration.py +1 -2
- pip/_internal/distributions/sdist.py +13 -14
- pip/_internal/exceptions.py +96 -6
- pip/_internal/index/collector.py +2 -3
- pip/_internal/index/package_finder.py +87 -21
- pip/_internal/locations/__init__.py +1 -2
- pip/_internal/locations/_sysconfig.py +4 -1
- pip/_internal/metadata/__init__.py +7 -2
- pip/_internal/metadata/importlib/_dists.py +8 -2
- pip/_internal/models/link.py +18 -14
- pip/_internal/models/release_control.py +92 -0
- pip/_internal/models/selection_prefs.py +6 -3
- pip/_internal/models/wheel.py +5 -66
- pip/_internal/network/auth.py +6 -2
- pip/_internal/network/cache.py +6 -11
- pip/_internal/network/download.py +4 -5
- pip/_internal/network/lazy_wheel.py +5 -3
- pip/_internal/network/session.py +14 -10
- pip/_internal/operations/build/wheel.py +4 -4
- pip/_internal/operations/build/wheel_editable.py +4 -4
- pip/_internal/operations/install/wheel.py +1 -2
- pip/_internal/operations/prepare.py +9 -4
- pip/_internal/pyproject.py +2 -61
- pip/_internal/req/__init__.py +1 -3
- pip/_internal/req/constructors.py +45 -39
- pip/_internal/req/pep723.py +41 -0
- pip/_internal/req/req_file.py +10 -2
- pip/_internal/req/req_install.py +32 -141
- pip/_internal/resolution/resolvelib/candidates.py +20 -11
- pip/_internal/resolution/resolvelib/factory.py +43 -1
- pip/_internal/resolution/resolvelib/provider.py +9 -0
- pip/_internal/resolution/resolvelib/reporter.py +21 -8
- pip/_internal/resolution/resolvelib/requirements.py +7 -3
- pip/_internal/resolution/resolvelib/resolver.py +2 -6
- pip/_internal/self_outdated_check.py +17 -16
- pip/_internal/utils/datetime.py +18 -0
- pip/_internal/utils/filesystem.py +52 -1
- pip/_internal/utils/logging.py +34 -2
- pip/_internal/utils/misc.py +18 -12
- pip/_internal/utils/pylock.py +116 -0
- pip/_internal/utils/unpacking.py +26 -1
- pip/_internal/vcs/versioncontrol.py +3 -1
- pip/_internal/wheel_builder.py +23 -96
- pip/_vendor/README.rst +180 -0
- pip/_vendor/cachecontrol/LICENSE.txt +13 -0
- pip/_vendor/cachecontrol/__init__.py +6 -3
- pip/_vendor/cachecontrol/adapter.py +0 -1
- pip/_vendor/cachecontrol/controller.py +1 -1
- pip/_vendor/cachecontrol/filewrapper.py +3 -1
- pip/_vendor/certifi/LICENSE +20 -0
- pip/_vendor/certifi/__init__.py +1 -1
- pip/_vendor/certifi/cacert.pem +62 -372
- pip/_vendor/dependency_groups/LICENSE.txt +9 -0
- pip/_vendor/distlib/LICENSE.txt +284 -0
- pip/_vendor/distro/LICENSE +202 -0
- pip/_vendor/idna/LICENSE.md +31 -0
- pip/_vendor/idna/codec.py +1 -1
- pip/_vendor/idna/core.py +1 -1
- pip/_vendor/idna/idnadata.py +72 -6
- pip/_vendor/idna/package_data.py +1 -1
- pip/_vendor/idna/uts46data.py +891 -731
- 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/packaging/__init__.py +1 -1
- pip/_vendor/packaging/_elffile.py +0 -1
- pip/_vendor/packaging/_manylinux.py +36 -36
- pip/_vendor/packaging/_musllinux.py +1 -1
- pip/_vendor/packaging/_parser.py +22 -10
- pip/_vendor/packaging/_structures.py +8 -0
- pip/_vendor/packaging/_tokenizer.py +23 -25
- pip/_vendor/packaging/licenses/__init__.py +13 -11
- pip/_vendor/packaging/licenses/_spdx.py +41 -1
- pip/_vendor/packaging/markers.py +64 -38
- pip/_vendor/packaging/metadata.py +143 -27
- pip/_vendor/packaging/pylock.py +635 -0
- pip/_vendor/packaging/requirements.py +5 -10
- pip/_vendor/packaging/specifiers.py +219 -170
- pip/_vendor/packaging/tags.py +15 -20
- pip/_vendor/packaging/utils.py +19 -24
- pip/_vendor/packaging/version.py +315 -105
- pip/_vendor/pkg_resources/LICENSE +17 -0
- 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/platformdirs/windows.py +7 -1
- pip/_vendor/pygments/LICENSE +25 -0
- 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/sessions.py +1 -1
- pip/_vendor/resolvelib/LICENSE +13 -0
- pip/_vendor/resolvelib/__init__.py +1 -1
- pip/_vendor/resolvelib/resolvers/abstract.py +3 -3
- pip/_vendor/resolvelib/resolvers/resolution.py +5 -0
- pip/_vendor/rich/LICENSE +19 -0
- pip/_vendor/rich/style.py +7 -11
- 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 +14 -6
- pip/_vendor/truststore/_openssl.py +3 -1
- pip/_vendor/urllib3/LICENSE.txt +21 -0
- pip/_vendor/vendor.txt +11 -11
- {pip-25.2.dist-info → pip-26.0.dist-info}/METADATA +10 -11
- {pip-25.2.dist-info → pip-26.0.dist-info}/RECORD +158 -139
- {pip-25.2.dist-info → pip-26.0.dist-info}/WHEEL +1 -2
- pip-26.0.dist-info/entry_points.txt +4 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/AUTHORS.txt +27 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/idna/LICENSE.md +1 -1
- pip/_internal/models/pylock.py +0 -188
- pip/_internal/operations/build/metadata_legacy.py +0 -73
- pip/_internal/operations/build/wheel_legacy.py +0 -119
- pip/_internal/operations/install/editable_legacy.py +0 -48
- pip/_internal/utils/setuptools_build.py +0 -149
- pip-25.2.dist-info/entry_points.txt +0 -3
- pip-25.2.dist-info/licenses/src/pip/_vendor/tomli/LICENSE-HEADER +0 -3
- pip-25.2.dist-info/top_level.txt +0 -1
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/LICENSE.txt +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/certifi/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/dependency_groups/LICENSE.txt +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/distlib/LICENSE.txt +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/distro/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/msgpack/COPYING +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE.APACHE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE.BSD +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/pkg_resources/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/platformdirs/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/pygments/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/pyproject_hooks/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/requests/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/resolvelib/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/rich/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/tomli/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/tomli_w/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/truststore/LICENSE +0 -0
- {pip-25.2.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/urllib3/LICENSE.txt +0 -0
pip/_internal/pyproject.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import importlib.util
|
|
4
3
|
import os
|
|
5
4
|
from collections import namedtuple
|
|
6
5
|
from typing import Any
|
|
@@ -30,13 +29,11 @@ BuildSystemDetails = namedtuple(
|
|
|
30
29
|
|
|
31
30
|
|
|
32
31
|
def load_pyproject_toml(
|
|
33
|
-
|
|
34
|
-
) -> BuildSystemDetails
|
|
32
|
+
pyproject_toml: str, setup_py: str, req_name: str
|
|
33
|
+
) -> BuildSystemDetails:
|
|
35
34
|
"""Load the pyproject.toml file.
|
|
36
35
|
|
|
37
36
|
Parameters:
|
|
38
|
-
use_pep517 - Has the user requested PEP 517 processing? None
|
|
39
|
-
means the user hasn't explicitly specified.
|
|
40
37
|
pyproject_toml - Location of the project's pyproject.toml file
|
|
41
38
|
setup_py - Location of the project's setup.py file
|
|
42
39
|
req_name - The name of the requirement we're processing (for
|
|
@@ -69,57 +66,7 @@ def load_pyproject_toml(
|
|
|
69
66
|
else:
|
|
70
67
|
build_system = None
|
|
71
68
|
|
|
72
|
-
# The following cases must use PEP 517
|
|
73
|
-
# We check for use_pep517 being non-None and falsy because that means
|
|
74
|
-
# the user explicitly requested --no-use-pep517. The value 0 as
|
|
75
|
-
# opposed to False can occur when the value is provided via an
|
|
76
|
-
# environment variable or config file option (due to the quirk of
|
|
77
|
-
# strtobool() returning an integer in pip's configuration code).
|
|
78
|
-
if has_pyproject and not has_setup:
|
|
79
|
-
if use_pep517 is not None and not use_pep517:
|
|
80
|
-
raise InstallationError(
|
|
81
|
-
"Disabling PEP 517 processing is invalid: "
|
|
82
|
-
"project does not have a setup.py"
|
|
83
|
-
)
|
|
84
|
-
use_pep517 = True
|
|
85
|
-
elif build_system and "build-backend" in build_system:
|
|
86
|
-
if use_pep517 is not None and not use_pep517:
|
|
87
|
-
raise InstallationError(
|
|
88
|
-
"Disabling PEP 517 processing is invalid: "
|
|
89
|
-
"project specifies a build backend of {} "
|
|
90
|
-
"in pyproject.toml".format(build_system["build-backend"])
|
|
91
|
-
)
|
|
92
|
-
use_pep517 = True
|
|
93
|
-
|
|
94
|
-
# If we haven't worked out whether to use PEP 517 yet,
|
|
95
|
-
# and the user hasn't explicitly stated a preference,
|
|
96
|
-
# we do so if the project has a pyproject.toml file
|
|
97
|
-
# or if we cannot import setuptools or wheels.
|
|
98
|
-
|
|
99
|
-
# We fallback to PEP 517 when without setuptools or without the wheel package,
|
|
100
|
-
# so setuptools can be installed as a default build backend.
|
|
101
|
-
# For more info see:
|
|
102
|
-
# https://discuss.python.org/t/pip-without-setuptools-could-the-experience-be-improved/11810/9
|
|
103
|
-
# https://github.com/pypa/pip/issues/8559
|
|
104
|
-
elif use_pep517 is None:
|
|
105
|
-
use_pep517 = (
|
|
106
|
-
has_pyproject
|
|
107
|
-
or not importlib.util.find_spec("setuptools")
|
|
108
|
-
or not importlib.util.find_spec("wheel")
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
# At this point, we know whether we're going to use PEP 517.
|
|
112
|
-
assert use_pep517 is not None
|
|
113
|
-
|
|
114
|
-
# If we're using the legacy code path, there is nothing further
|
|
115
|
-
# for us to do here.
|
|
116
|
-
if not use_pep517:
|
|
117
|
-
return None
|
|
118
|
-
|
|
119
69
|
if build_system is None:
|
|
120
|
-
# Either the user has a pyproject.toml with no build-system
|
|
121
|
-
# section, or the user has no pyproject.toml, but has opted in
|
|
122
|
-
# explicitly via --use-pep517.
|
|
123
70
|
# In the absence of any explicit backend specification, we
|
|
124
71
|
# assume the setuptools backend that most closely emulates the
|
|
125
72
|
# traditional direct setup.py execution, and require wheel and
|
|
@@ -130,12 +77,6 @@ def load_pyproject_toml(
|
|
|
130
77
|
"build-backend": "setuptools.build_meta:__legacy__",
|
|
131
78
|
}
|
|
132
79
|
|
|
133
|
-
# If we're using PEP 517, we have build system information (either
|
|
134
|
-
# from pyproject.toml, or defaulted by the code above).
|
|
135
|
-
# Note that at this point, we do not know if the user has actually
|
|
136
|
-
# specified a backend, though.
|
|
137
|
-
assert build_system is not None
|
|
138
|
-
|
|
139
80
|
# Ensure that the build-system section in pyproject.toml conforms
|
|
140
81
|
# to PEP 518.
|
|
141
82
|
|
pip/_internal/req/__init__.py
CHANGED
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import collections
|
|
4
4
|
import logging
|
|
5
|
-
from collections.abc import Generator
|
|
5
|
+
from collections.abc import Generator
|
|
6
6
|
from dataclasses import dataclass
|
|
7
7
|
|
|
8
8
|
from pip._internal.cli.progress_bars import BarType, get_install_progress_renderer
|
|
@@ -37,7 +37,6 @@ def _validate_requirements(
|
|
|
37
37
|
|
|
38
38
|
def install_given_reqs(
|
|
39
39
|
requirements: list[InstallRequirement],
|
|
40
|
-
global_options: Sequence[str],
|
|
41
40
|
root: str | None,
|
|
42
41
|
home: str | None,
|
|
43
42
|
prefix: str | None,
|
|
@@ -83,7 +82,6 @@ def install_given_reqs(
|
|
|
83
82
|
|
|
84
83
|
try:
|
|
85
84
|
requirement.install(
|
|
86
|
-
global_options,
|
|
87
85
|
root=root,
|
|
88
86
|
home=home,
|
|
89
87
|
prefix=prefix,
|
|
@@ -47,7 +47,7 @@ def _strip_extras(path: str) -> tuple[str, str | None]:
|
|
|
47
47
|
m = re.match(r"^(.+)(\[[^\]]+\])$", path)
|
|
48
48
|
extras = None
|
|
49
49
|
if m:
|
|
50
|
-
path_no_extras = m.group(1)
|
|
50
|
+
path_no_extras = m.group(1).rstrip()
|
|
51
51
|
extras = m.group(2)
|
|
52
52
|
else:
|
|
53
53
|
path_no_extras = path
|
|
@@ -86,17 +86,25 @@ def _set_requirement_extras(req: Requirement, new_extras: set[str]) -> Requireme
|
|
|
86
86
|
return get_requirement(f"{pre}{extras}{post}")
|
|
87
87
|
|
|
88
88
|
|
|
89
|
-
def
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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)
|
|
99
103
|
|
|
104
|
+
raise ValueError
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _parse_pip_syntax_editable(editable_req: str) -> tuple[str | None, str, set[str]]:
|
|
100
108
|
url = editable_req
|
|
101
109
|
|
|
102
110
|
# If a file path is specified with extras, strip off the extras.
|
|
@@ -122,9 +130,27 @@ def parse_editable(editable_req: str) -> tuple[str | None, str, set[str]]:
|
|
|
122
130
|
url = f"{version_control}+{url}"
|
|
123
131
|
break
|
|
124
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
|
+
|
|
125
151
|
link = Link(url)
|
|
126
152
|
|
|
127
|
-
if not link.is_vcs:
|
|
153
|
+
if not link.is_vcs and not link.url.startswith("file:"):
|
|
128
154
|
backends = ", ".join(vcs.all_schemes)
|
|
129
155
|
raise InstallationError(
|
|
130
156
|
f"{editable_req} is not a valid editable requirement. "
|
|
@@ -132,13 +158,13 @@ def parse_editable(editable_req: str) -> tuple[str | None, str, set[str]]:
|
|
|
132
158
|
f"(beginning with {backends})."
|
|
133
159
|
)
|
|
134
160
|
|
|
135
|
-
|
|
136
|
-
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:"):
|
|
137
163
|
raise InstallationError(
|
|
138
164
|
f"Could not detect requirement name for '{editable_req}', "
|
|
139
|
-
"please specify one with
|
|
165
|
+
"please specify one with your_package_name @ URL"
|
|
140
166
|
)
|
|
141
|
-
return package_name, url,
|
|
167
|
+
return package_name, url, extras
|
|
142
168
|
|
|
143
169
|
|
|
144
170
|
def check_first_requirement_in_file(filename: str) -> None:
|
|
@@ -225,17 +251,17 @@ def install_req_from_editable(
|
|
|
225
251
|
editable_req: str,
|
|
226
252
|
comes_from: InstallRequirement | str | None = None,
|
|
227
253
|
*,
|
|
228
|
-
use_pep517: bool | None = None,
|
|
229
254
|
isolated: bool = False,
|
|
230
|
-
global_options: list[str] | None = None,
|
|
231
255
|
hash_options: dict[str, list[str]] | None = None,
|
|
232
256
|
constraint: bool = False,
|
|
233
257
|
user_supplied: bool = False,
|
|
234
258
|
permit_editable_wheels: bool = False,
|
|
235
259
|
config_settings: dict[str, str | list[str]] | None = None,
|
|
236
260
|
) -> InstallRequirement:
|
|
237
|
-
|
|
261
|
+
if constraint:
|
|
262
|
+
raise InstallationError("Editable requirements are not allowed as constraints")
|
|
238
263
|
|
|
264
|
+
parts = parse_req_from_editable(editable_req)
|
|
239
265
|
return InstallRequirement(
|
|
240
266
|
parts.requirement,
|
|
241
267
|
comes_from=comes_from,
|
|
@@ -244,9 +270,7 @@ def install_req_from_editable(
|
|
|
244
270
|
permit_editable_wheels=permit_editable_wheels,
|
|
245
271
|
link=parts.link,
|
|
246
272
|
constraint=constraint,
|
|
247
|
-
use_pep517=use_pep517,
|
|
248
273
|
isolated=isolated,
|
|
249
|
-
global_options=global_options,
|
|
250
274
|
hash_options=hash_options,
|
|
251
275
|
config_settings=config_settings,
|
|
252
276
|
extras=parts.extras,
|
|
@@ -389,9 +413,7 @@ def install_req_from_line(
|
|
|
389
413
|
name: str,
|
|
390
414
|
comes_from: str | InstallRequirement | None = None,
|
|
391
415
|
*,
|
|
392
|
-
use_pep517: bool | None = None,
|
|
393
416
|
isolated: bool = False,
|
|
394
|
-
global_options: list[str] | None = None,
|
|
395
417
|
hash_options: dict[str, list[str]] | None = None,
|
|
396
418
|
constraint: bool = False,
|
|
397
419
|
line_source: str | None = None,
|
|
@@ -411,9 +433,7 @@ def install_req_from_line(
|
|
|
411
433
|
comes_from,
|
|
412
434
|
link=parts.link,
|
|
413
435
|
markers=parts.markers,
|
|
414
|
-
use_pep517=use_pep517,
|
|
415
436
|
isolated=isolated,
|
|
416
|
-
global_options=global_options,
|
|
417
437
|
hash_options=hash_options,
|
|
418
438
|
config_settings=config_settings,
|
|
419
439
|
constraint=constraint,
|
|
@@ -426,7 +446,6 @@ def install_req_from_req_string(
|
|
|
426
446
|
req_string: str,
|
|
427
447
|
comes_from: InstallRequirement | None = None,
|
|
428
448
|
isolated: bool = False,
|
|
429
|
-
use_pep517: bool | None = None,
|
|
430
449
|
user_supplied: bool = False,
|
|
431
450
|
) -> InstallRequirement:
|
|
432
451
|
try:
|
|
@@ -455,7 +474,6 @@ def install_req_from_req_string(
|
|
|
455
474
|
req,
|
|
456
475
|
comes_from,
|
|
457
476
|
isolated=isolated,
|
|
458
|
-
use_pep517=use_pep517,
|
|
459
477
|
user_supplied=user_supplied,
|
|
460
478
|
)
|
|
461
479
|
|
|
@@ -463,7 +481,6 @@ def install_req_from_req_string(
|
|
|
463
481
|
def install_req_from_parsed_requirement(
|
|
464
482
|
parsed_req: ParsedRequirement,
|
|
465
483
|
isolated: bool = False,
|
|
466
|
-
use_pep517: bool | None = None,
|
|
467
484
|
user_supplied: bool = False,
|
|
468
485
|
config_settings: dict[str, str | list[str]] | None = None,
|
|
469
486
|
) -> InstallRequirement:
|
|
@@ -471,7 +488,6 @@ def install_req_from_parsed_requirement(
|
|
|
471
488
|
req = install_req_from_editable(
|
|
472
489
|
parsed_req.requirement,
|
|
473
490
|
comes_from=parsed_req.comes_from,
|
|
474
|
-
use_pep517=use_pep517,
|
|
475
491
|
constraint=parsed_req.constraint,
|
|
476
492
|
isolated=isolated,
|
|
477
493
|
user_supplied=user_supplied,
|
|
@@ -482,13 +498,7 @@ def install_req_from_parsed_requirement(
|
|
|
482
498
|
req = install_req_from_line(
|
|
483
499
|
parsed_req.requirement,
|
|
484
500
|
comes_from=parsed_req.comes_from,
|
|
485
|
-
use_pep517=use_pep517,
|
|
486
501
|
isolated=isolated,
|
|
487
|
-
global_options=(
|
|
488
|
-
parsed_req.options.get("global_options", [])
|
|
489
|
-
if parsed_req.options
|
|
490
|
-
else []
|
|
491
|
-
),
|
|
492
502
|
hash_options=(
|
|
493
503
|
parsed_req.options.get("hashes", {}) if parsed_req.options else {}
|
|
494
504
|
),
|
|
@@ -509,9 +519,7 @@ def install_req_from_link_and_ireq(
|
|
|
509
519
|
editable=ireq.editable,
|
|
510
520
|
link=link,
|
|
511
521
|
markers=ireq.markers,
|
|
512
|
-
use_pep517=ireq.use_pep517,
|
|
513
522
|
isolated=ireq.isolated,
|
|
514
|
-
global_options=ireq.global_options,
|
|
515
523
|
hash_options=ireq.hash_options,
|
|
516
524
|
config_settings=ireq.config_settings,
|
|
517
525
|
user_supplied=ireq.user_supplied,
|
|
@@ -532,9 +540,7 @@ def install_req_drop_extras(ireq: InstallRequirement) -> InstallRequirement:
|
|
|
532
540
|
editable=ireq.editable,
|
|
533
541
|
link=ireq.link,
|
|
534
542
|
markers=ireq.markers,
|
|
535
|
-
use_pep517=ireq.use_pep517,
|
|
536
543
|
isolated=ireq.isolated,
|
|
537
|
-
global_options=ireq.global_options,
|
|
538
544
|
hash_options=ireq.hash_options,
|
|
539
545
|
constraint=ireq.constraint,
|
|
540
546
|
extras=[],
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from pip._internal.utils.compat import tomllib
|
|
5
|
+
|
|
6
|
+
REGEX = r"(?m)^# /// (?P<type>[a-zA-Z0-9-]+)$\s(?P<content>(^#(| .*)$\s)+)^# ///$"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class PEP723Exception(ValueError):
|
|
10
|
+
"""Raised to indicate a problem when parsing PEP 723 metadata from a script"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, msg: str) -> None:
|
|
13
|
+
self.msg = msg
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def pep723_metadata(scriptfile: str) -> dict[str, Any]:
|
|
17
|
+
with open(scriptfile) as f:
|
|
18
|
+
script = f.read()
|
|
19
|
+
|
|
20
|
+
name = "script"
|
|
21
|
+
matches = list(
|
|
22
|
+
filter(lambda m: m.group("type") == name, re.finditer(REGEX, script))
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
if len(matches) > 1:
|
|
26
|
+
raise PEP723Exception(f"Multiple {name!r} blocks found in {scriptfile!r}")
|
|
27
|
+
elif len(matches) == 1:
|
|
28
|
+
content = "".join(
|
|
29
|
+
line[2:] if line.startswith("# ") else line[1:]
|
|
30
|
+
for line in matches[0].group("content").splitlines(keepends=True)
|
|
31
|
+
)
|
|
32
|
+
try:
|
|
33
|
+
metadata = tomllib.loads(content)
|
|
34
|
+
except Exception as exc:
|
|
35
|
+
raise PEP723Exception(f"Failed to parse TOML in {scriptfile!r}") from exc
|
|
36
|
+
else:
|
|
37
|
+
raise PEP723Exception(
|
|
38
|
+
f"File does not contain {name!r} metadata: {scriptfile!r}"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
return metadata
|
pip/_internal/req/req_file.py
CHANGED
|
@@ -25,6 +25,7 @@ from typing import (
|
|
|
25
25
|
|
|
26
26
|
from pip._internal.cli import cmdoptions
|
|
27
27
|
from pip._internal.exceptions import InstallationError, RequirementsFileParseError
|
|
28
|
+
from pip._internal.models.release_control import ReleaseControl
|
|
28
29
|
from pip._internal.models.search_scope import SearchScope
|
|
29
30
|
|
|
30
31
|
if TYPE_CHECKING:
|
|
@@ -59,13 +60,14 @@ SUPPORTED_OPTIONS: list[Callable[..., optparse.Option]] = [
|
|
|
59
60
|
cmdoptions.prefer_binary,
|
|
60
61
|
cmdoptions.require_hashes,
|
|
61
62
|
cmdoptions.pre,
|
|
63
|
+
cmdoptions.all_releases,
|
|
64
|
+
cmdoptions.only_final,
|
|
62
65
|
cmdoptions.trusted_host,
|
|
63
66
|
cmdoptions.use_new_feature,
|
|
64
67
|
]
|
|
65
68
|
|
|
66
69
|
# options to be passed to requirements
|
|
67
70
|
SUPPORTED_OPTIONS_REQ: list[Callable[..., optparse.Option]] = [
|
|
68
|
-
cmdoptions.global_options,
|
|
69
71
|
cmdoptions.hash,
|
|
70
72
|
cmdoptions.config_settings,
|
|
71
73
|
]
|
|
@@ -274,8 +276,14 @@ def handle_option_line(
|
|
|
274
276
|
)
|
|
275
277
|
finder.search_scope = search_scope
|
|
276
278
|
|
|
279
|
+
# Transform --pre into --all-releases :all:
|
|
277
280
|
if opts.pre:
|
|
278
|
-
|
|
281
|
+
if not opts.release_control:
|
|
282
|
+
opts.release_control = ReleaseControl()
|
|
283
|
+
opts.release_control.all_releases.add(":all:")
|
|
284
|
+
|
|
285
|
+
if opts.release_control:
|
|
286
|
+
finder.set_release_control(opts.release_control)
|
|
279
287
|
|
|
280
288
|
if opts.prefer_binary:
|
|
281
289
|
finder.set_prefer_binary()
|
pip/_internal/req/req_install.py
CHANGED
|
@@ -7,7 +7,7 @@ import shutil
|
|
|
7
7
|
import sys
|
|
8
8
|
import uuid
|
|
9
9
|
import zipfile
|
|
10
|
-
from collections.abc import Collection, Iterable
|
|
10
|
+
from collections.abc import Collection, Iterable
|
|
11
11
|
from optparse import Values
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
from typing import Any
|
|
@@ -34,12 +34,6 @@ from pip._internal.models.direct_url import DirectUrl
|
|
|
34
34
|
from pip._internal.models.link import Link
|
|
35
35
|
from pip._internal.operations.build.metadata import generate_metadata
|
|
36
36
|
from pip._internal.operations.build.metadata_editable import generate_editable_metadata
|
|
37
|
-
from pip._internal.operations.build.metadata_legacy import (
|
|
38
|
-
generate_metadata as generate_metadata_legacy,
|
|
39
|
-
)
|
|
40
|
-
from pip._internal.operations.install.editable_legacy import (
|
|
41
|
-
install_editable as install_editable_legacy,
|
|
42
|
-
)
|
|
43
37
|
from pip._internal.operations.install.wheel import install_wheel
|
|
44
38
|
from pip._internal.pyproject import load_pyproject_toml, make_pyproject_path
|
|
45
39
|
from pip._internal.req.req_uninstall import UninstallPathSet
|
|
@@ -79,10 +73,8 @@ class InstallRequirement:
|
|
|
79
73
|
editable: bool = False,
|
|
80
74
|
link: Link | None = None,
|
|
81
75
|
markers: Marker | None = None,
|
|
82
|
-
use_pep517: bool | None = None,
|
|
83
76
|
isolated: bool = False,
|
|
84
77
|
*,
|
|
85
|
-
global_options: list[str] | None = None,
|
|
86
78
|
hash_options: dict[str, list[str]] | None = None,
|
|
87
79
|
config_settings: dict[str, str | list[str]] | None = None,
|
|
88
80
|
constraint: bool = False,
|
|
@@ -149,7 +141,6 @@ class InstallRequirement:
|
|
|
149
141
|
# Set to True after successful installation
|
|
150
142
|
self.install_succeeded: bool | None = None
|
|
151
143
|
# Supplied options
|
|
152
|
-
self.global_options = global_options if global_options else []
|
|
153
144
|
self.hash_options = hash_options if hash_options else {}
|
|
154
145
|
self.config_settings = config_settings
|
|
155
146
|
# Set to True after successful preparation of this requirement
|
|
@@ -168,6 +159,10 @@ class InstallRequirement:
|
|
|
168
159
|
# details).
|
|
169
160
|
self.metadata_directory: str | None = None
|
|
170
161
|
|
|
162
|
+
# The cached metadata distribution that this requirement represents.
|
|
163
|
+
# See get_dist / set_dist.
|
|
164
|
+
self._distribution: BaseDistribution | None = None
|
|
165
|
+
|
|
171
166
|
# The static build requirements (from pyproject.toml)
|
|
172
167
|
self.pyproject_requires: list[str] | None = None
|
|
173
168
|
|
|
@@ -177,23 +172,6 @@ class InstallRequirement:
|
|
|
177
172
|
# The PEP 517 backend we should use to build the project
|
|
178
173
|
self.pep517_backend: BuildBackendHookCaller | None = None
|
|
179
174
|
|
|
180
|
-
# Are we using PEP 517 for this requirement?
|
|
181
|
-
# After pyproject.toml has been loaded, the only valid values are True
|
|
182
|
-
# and False. Before loading, None is valid (meaning "use the default").
|
|
183
|
-
# Setting an explicit value before loading pyproject.toml is supported,
|
|
184
|
-
# but after loading this flag should be treated as read only.
|
|
185
|
-
self.use_pep517 = use_pep517
|
|
186
|
-
|
|
187
|
-
# If config settings are provided, enforce PEP 517.
|
|
188
|
-
if self.config_settings:
|
|
189
|
-
if self.use_pep517 is False:
|
|
190
|
-
logger.warning(
|
|
191
|
-
"--no-use-pep517 ignored for %s "
|
|
192
|
-
"because --config-settings are specified.",
|
|
193
|
-
self,
|
|
194
|
-
)
|
|
195
|
-
self.use_pep517 = True
|
|
196
|
-
|
|
197
175
|
# This requirement needs more preparation before it can be built
|
|
198
176
|
self.needs_more_preparation = False
|
|
199
177
|
|
|
@@ -250,8 +228,6 @@ class InstallRequirement:
|
|
|
250
228
|
|
|
251
229
|
@functools.cached_property
|
|
252
230
|
def supports_pyproject_editable(self) -> bool:
|
|
253
|
-
if not self.use_pep517:
|
|
254
|
-
return False
|
|
255
231
|
assert self.pep517_backend
|
|
256
232
|
with self.build_env:
|
|
257
233
|
runner = runner_with_spinner_message(
|
|
@@ -492,13 +468,6 @@ class InstallRequirement:
|
|
|
492
468
|
|
|
493
469
|
return setup_py
|
|
494
470
|
|
|
495
|
-
@property
|
|
496
|
-
def setup_cfg_path(self) -> str:
|
|
497
|
-
assert self.source_dir, f"No source dir for {self}"
|
|
498
|
-
setup_cfg = os.path.join(self.unpacked_source_directory, "setup.cfg")
|
|
499
|
-
|
|
500
|
-
return setup_cfg
|
|
501
|
-
|
|
502
471
|
@property
|
|
503
472
|
def pyproject_toml_path(self) -> str:
|
|
504
473
|
assert self.source_dir, f"No source dir for {self}"
|
|
@@ -508,20 +477,12 @@ class InstallRequirement:
|
|
|
508
477
|
"""Load the pyproject.toml file.
|
|
509
478
|
|
|
510
479
|
After calling this routine, all of the attributes related to PEP 517
|
|
511
|
-
processing for this requirement have been set.
|
|
512
|
-
use_pep517 attribute can be used to determine whether we should
|
|
513
|
-
follow the PEP 517 or legacy (setup.py) code path.
|
|
480
|
+
processing for this requirement have been set.
|
|
514
481
|
"""
|
|
515
482
|
pyproject_toml_data = load_pyproject_toml(
|
|
516
|
-
self.
|
|
483
|
+
self.pyproject_toml_path, self.setup_py_path, str(self)
|
|
517
484
|
)
|
|
518
|
-
|
|
519
|
-
if pyproject_toml_data is None:
|
|
520
|
-
assert not self.config_settings
|
|
521
|
-
self.use_pep517 = False
|
|
522
|
-
return
|
|
523
|
-
|
|
524
|
-
self.use_pep517 = True
|
|
485
|
+
assert pyproject_toml_data
|
|
525
486
|
requires, backend, check, backend_path = pyproject_toml_data
|
|
526
487
|
self.requirements_to_check = check
|
|
527
488
|
self.pyproject_requires = requires
|
|
@@ -532,23 +493,15 @@ class InstallRequirement:
|
|
|
532
493
|
backend_path=backend_path,
|
|
533
494
|
)
|
|
534
495
|
|
|
535
|
-
def
|
|
496
|
+
def editable_sanity_check(self) -> None:
|
|
536
497
|
"""Check that an editable requirement if valid for use with PEP 517/518.
|
|
537
498
|
|
|
538
|
-
This verifies that an editable
|
|
539
|
-
or as a setup.py or a setup.cfg
|
|
499
|
+
This verifies that an editable has a build backend that supports PEP 660.
|
|
540
500
|
"""
|
|
541
|
-
if
|
|
542
|
-
self.editable
|
|
543
|
-
and self.use_pep517
|
|
544
|
-
and not self.supports_pyproject_editable
|
|
545
|
-
and not os.path.isfile(self.setup_py_path)
|
|
546
|
-
and not os.path.isfile(self.setup_cfg_path)
|
|
547
|
-
):
|
|
501
|
+
if self.editable and not self.supports_pyproject_editable:
|
|
548
502
|
raise InstallationError(
|
|
549
|
-
f"Project {self}
|
|
550
|
-
f"
|
|
551
|
-
f"have a 'setup.py' nor a 'setup.cfg', "
|
|
503
|
+
f"Project {self} uses a build backend "
|
|
504
|
+
f"that is missing the 'build_editable' hook, so "
|
|
552
505
|
f"it cannot be installed in editable mode. "
|
|
553
506
|
f"Consider using a build backend that supports PEP 660."
|
|
554
507
|
)
|
|
@@ -562,30 +515,21 @@ class InstallRequirement:
|
|
|
562
515
|
assert self.source_dir, f"No source dir for {self}"
|
|
563
516
|
details = self.name or f"from {self.link}"
|
|
564
517
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
self.
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
)
|
|
577
|
-
else:
|
|
578
|
-
self.metadata_directory = generate_metadata(
|
|
579
|
-
build_env=self.build_env,
|
|
580
|
-
backend=self.pep517_backend,
|
|
581
|
-
details=details,
|
|
582
|
-
)
|
|
518
|
+
assert self.pep517_backend is not None
|
|
519
|
+
if (
|
|
520
|
+
self.editable
|
|
521
|
+
and self.permit_editable_wheels
|
|
522
|
+
and self.supports_pyproject_editable
|
|
523
|
+
):
|
|
524
|
+
self.metadata_directory = generate_editable_metadata(
|
|
525
|
+
build_env=self.build_env,
|
|
526
|
+
backend=self.pep517_backend,
|
|
527
|
+
details=details,
|
|
528
|
+
)
|
|
583
529
|
else:
|
|
584
|
-
self.metadata_directory =
|
|
530
|
+
self.metadata_directory = generate_metadata(
|
|
585
531
|
build_env=self.build_env,
|
|
586
|
-
|
|
587
|
-
source_dir=self.unpacked_source_directory,
|
|
588
|
-
isolated=self.isolated,
|
|
532
|
+
backend=self.pep517_backend,
|
|
589
533
|
details=details,
|
|
590
534
|
)
|
|
591
535
|
|
|
@@ -604,8 +548,13 @@ class InstallRequirement:
|
|
|
604
548
|
|
|
605
549
|
return self._metadata
|
|
606
550
|
|
|
551
|
+
def set_dist(self, distribution: BaseDistribution) -> None:
|
|
552
|
+
self._distribution = distribution
|
|
553
|
+
|
|
607
554
|
def get_dist(self) -> BaseDistribution:
|
|
608
|
-
if self.
|
|
555
|
+
if self._distribution is not None:
|
|
556
|
+
return self._distribution
|
|
557
|
+
elif self.metadata_directory:
|
|
609
558
|
return get_directory_distribution(self.metadata_directory)
|
|
610
559
|
elif self.local_file_path and self.is_wheel:
|
|
611
560
|
assert self.req is not None
|
|
@@ -809,7 +758,6 @@ class InstallRequirement:
|
|
|
809
758
|
|
|
810
759
|
def install(
|
|
811
760
|
self,
|
|
812
|
-
global_options: Sequence[str] | None = None,
|
|
813
761
|
root: str | None = None,
|
|
814
762
|
home: str | None = None,
|
|
815
763
|
prefix: str | None = None,
|
|
@@ -827,43 +775,6 @@ class InstallRequirement:
|
|
|
827
775
|
prefix=prefix,
|
|
828
776
|
)
|
|
829
777
|
|
|
830
|
-
if self.editable and not self.is_wheel:
|
|
831
|
-
deprecated(
|
|
832
|
-
reason=(
|
|
833
|
-
f"Legacy editable install of {self} (setup.py develop) "
|
|
834
|
-
"is deprecated."
|
|
835
|
-
),
|
|
836
|
-
replacement=(
|
|
837
|
-
"to add a pyproject.toml or enable --use-pep517, "
|
|
838
|
-
"and use setuptools >= 64. "
|
|
839
|
-
"If the resulting installation is not behaving as expected, "
|
|
840
|
-
"try using --config-settings editable_mode=compat. "
|
|
841
|
-
"Please consult the setuptools documentation for more information"
|
|
842
|
-
),
|
|
843
|
-
gone_in="25.3",
|
|
844
|
-
issue=11457,
|
|
845
|
-
)
|
|
846
|
-
if self.config_settings:
|
|
847
|
-
logger.warning(
|
|
848
|
-
"--config-settings ignored for legacy editable install of %s. "
|
|
849
|
-
"Consider upgrading to a version of setuptools "
|
|
850
|
-
"that supports PEP 660 (>= 64).",
|
|
851
|
-
self,
|
|
852
|
-
)
|
|
853
|
-
install_editable_legacy(
|
|
854
|
-
global_options=global_options if global_options is not None else [],
|
|
855
|
-
prefix=prefix,
|
|
856
|
-
home=home,
|
|
857
|
-
use_user_site=use_user_site,
|
|
858
|
-
name=self.req.name,
|
|
859
|
-
setup_py_path=self.setup_py_path,
|
|
860
|
-
isolated=self.isolated,
|
|
861
|
-
build_env=self.build_env,
|
|
862
|
-
unpacked_source_directory=self.unpacked_source_directory,
|
|
863
|
-
)
|
|
864
|
-
self.install_succeeded = True
|
|
865
|
-
return
|
|
866
|
-
|
|
867
778
|
assert self.is_wheel
|
|
868
779
|
assert self.local_file_path
|
|
869
780
|
|
|
@@ -915,23 +826,3 @@ def _has_option(options: Values, reqs: list[InstallRequirement], option: str) ->
|
|
|
915
826
|
if getattr(req, option, None):
|
|
916
827
|
return True
|
|
917
828
|
return False
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
def check_legacy_setup_py_options(
|
|
921
|
-
options: Values,
|
|
922
|
-
reqs: list[InstallRequirement],
|
|
923
|
-
) -> None:
|
|
924
|
-
has_build_options = _has_option(options, reqs, "build_options")
|
|
925
|
-
has_global_options = _has_option(options, reqs, "global_options")
|
|
926
|
-
if has_build_options or has_global_options:
|
|
927
|
-
deprecated(
|
|
928
|
-
reason="--build-option and --global-option are deprecated.",
|
|
929
|
-
issue=11859,
|
|
930
|
-
replacement="to use --config-settings",
|
|
931
|
-
gone_in="25.3",
|
|
932
|
-
)
|
|
933
|
-
logger.warning(
|
|
934
|
-
"Implying --no-binary=:all: due to the presence of "
|
|
935
|
-
"--build-option / --global-option. "
|
|
936
|
-
)
|
|
937
|
-
options.format_control.disallow_binaries()
|