pip 25.2__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 +1 -1
- pip/_internal/__init__.py +0 -0
- pip/_internal/build_env.py +71 -3
- pip/_internal/cache.py +1 -1
- pip/_internal/cli/cmdoptions.py +43 -71
- pip/_internal/cli/parser.py +3 -3
- pip/_internal/cli/req_command.py +46 -26
- pip/_internal/commands/download.py +4 -7
- pip/_internal/commands/install.py +19 -14
- pip/_internal/commands/lock.py +3 -6
- pip/_internal/commands/wheel.py +5 -10
- pip/_internal/configuration.py +1 -2
- pip/_internal/distributions/sdist.py +13 -14
- pip/_internal/exceptions.py +20 -3
- pip/_internal/index/package_finder.py +3 -3
- pip/_internal/metadata/__init__.py +7 -2
- pip/_internal/metadata/importlib/_dists.py +8 -2
- pip/_internal/models/link.py +1 -1
- pip/_internal/models/wheel.py +5 -66
- pip/_internal/network/cache.py +6 -11
- pip/_internal/network/lazy_wheel.py +5 -3
- pip/_internal/operations/build/wheel.py +4 -4
- pip/_internal/operations/build/wheel_editable.py +4 -4
- pip/_internal/operations/prepare.py +7 -1
- pip/_internal/pyproject.py +2 -61
- pip/_internal/req/__init__.py +1 -3
- pip/_internal/req/constructors.py +42 -38
- pip/_internal/req/req_file.py +0 -1
- pip/_internal/req/req_install.py +32 -141
- pip/_internal/resolution/resolvelib/candidates.py +20 -11
- pip/_internal/resolution/resolvelib/factory.py +31 -0
- pip/_internal/resolution/resolvelib/provider.py +9 -0
- pip/_internal/resolution/resolvelib/reporter.py +21 -8
- pip/_internal/resolution/resolvelib/resolver.py +2 -6
- pip/_internal/self_outdated_check.py +11 -3
- pip/_internal/utils/filesystem.py +12 -0
- pip/_internal/utils/unpacking.py +25 -0
- pip/_internal/wheel_builder.py +23 -96
- pip/_vendor/README.rst +180 -0
- pip/_vendor/cachecontrol/LICENSE.txt +13 -0
- pip/_vendor/certifi/LICENSE +20 -0
- pip/_vendor/certifi/__init__.py +1 -1
- pip/_vendor/certifi/cacert.pem +62 -40
- 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/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/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/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 +8 -8
- {pip-25.2.dist-info → pip-25.3.dist-info}/METADATA +9 -10
- {pip-25.2.dist-info → pip-25.3.dist-info}/RECORD +106 -90
- {pip-25.2.dist-info → pip-25.3.dist-info}/WHEEL +1 -2
- pip-25.3.dist-info/entry_points.txt +4 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/AUTHORS.txt +9 -0
- 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-25.3.dist-info}/licenses/LICENSE.txt +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/certifi/LICENSE +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/dependency_groups/LICENSE.txt +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/distlib/LICENSE.txt +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/distro/LICENSE +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/idna/LICENSE.md +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/msgpack/COPYING +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE.APACHE +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE.BSD +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/pkg_resources/LICENSE +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/platformdirs/LICENSE +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/pygments/LICENSE +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/pyproject_hooks/LICENSE +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/requests/LICENSE +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/resolvelib/LICENSE +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/rich/LICENSE +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/tomli/LICENSE +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/tomli_w/LICENSE +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/truststore/LICENSE +0 -0
- {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/urllib3/LICENSE.txt +0 -0
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)
|
|
103
|
+
|
|
104
|
+
raise ValueError
|
|
105
|
+
|
|
99
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,9 +251,7 @@ 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,
|
|
@@ -244,9 +268,7 @@ def install_req_from_editable(
|
|
|
244
268
|
permit_editable_wheels=permit_editable_wheels,
|
|
245
269
|
link=parts.link,
|
|
246
270
|
constraint=constraint,
|
|
247
|
-
use_pep517=use_pep517,
|
|
248
271
|
isolated=isolated,
|
|
249
|
-
global_options=global_options,
|
|
250
272
|
hash_options=hash_options,
|
|
251
273
|
config_settings=config_settings,
|
|
252
274
|
extras=parts.extras,
|
|
@@ -389,9 +411,7 @@ def install_req_from_line(
|
|
|
389
411
|
name: str,
|
|
390
412
|
comes_from: str | InstallRequirement | None = None,
|
|
391
413
|
*,
|
|
392
|
-
use_pep517: bool | None = None,
|
|
393
414
|
isolated: bool = False,
|
|
394
|
-
global_options: list[str] | None = None,
|
|
395
415
|
hash_options: dict[str, list[str]] | None = None,
|
|
396
416
|
constraint: bool = False,
|
|
397
417
|
line_source: str | None = None,
|
|
@@ -411,9 +431,7 @@ def install_req_from_line(
|
|
|
411
431
|
comes_from,
|
|
412
432
|
link=parts.link,
|
|
413
433
|
markers=parts.markers,
|
|
414
|
-
use_pep517=use_pep517,
|
|
415
434
|
isolated=isolated,
|
|
416
|
-
global_options=global_options,
|
|
417
435
|
hash_options=hash_options,
|
|
418
436
|
config_settings=config_settings,
|
|
419
437
|
constraint=constraint,
|
|
@@ -426,7 +444,6 @@ def install_req_from_req_string(
|
|
|
426
444
|
req_string: str,
|
|
427
445
|
comes_from: InstallRequirement | None = None,
|
|
428
446
|
isolated: bool = False,
|
|
429
|
-
use_pep517: bool | None = None,
|
|
430
447
|
user_supplied: bool = False,
|
|
431
448
|
) -> InstallRequirement:
|
|
432
449
|
try:
|
|
@@ -455,7 +472,6 @@ def install_req_from_req_string(
|
|
|
455
472
|
req,
|
|
456
473
|
comes_from,
|
|
457
474
|
isolated=isolated,
|
|
458
|
-
use_pep517=use_pep517,
|
|
459
475
|
user_supplied=user_supplied,
|
|
460
476
|
)
|
|
461
477
|
|
|
@@ -463,7 +479,6 @@ def install_req_from_req_string(
|
|
|
463
479
|
def install_req_from_parsed_requirement(
|
|
464
480
|
parsed_req: ParsedRequirement,
|
|
465
481
|
isolated: bool = False,
|
|
466
|
-
use_pep517: bool | None = None,
|
|
467
482
|
user_supplied: bool = False,
|
|
468
483
|
config_settings: dict[str, str | list[str]] | None = None,
|
|
469
484
|
) -> InstallRequirement:
|
|
@@ -471,7 +486,6 @@ def install_req_from_parsed_requirement(
|
|
|
471
486
|
req = install_req_from_editable(
|
|
472
487
|
parsed_req.requirement,
|
|
473
488
|
comes_from=parsed_req.comes_from,
|
|
474
|
-
use_pep517=use_pep517,
|
|
475
489
|
constraint=parsed_req.constraint,
|
|
476
490
|
isolated=isolated,
|
|
477
491
|
user_supplied=user_supplied,
|
|
@@ -482,13 +496,7 @@ def install_req_from_parsed_requirement(
|
|
|
482
496
|
req = install_req_from_line(
|
|
483
497
|
parsed_req.requirement,
|
|
484
498
|
comes_from=parsed_req.comes_from,
|
|
485
|
-
use_pep517=use_pep517,
|
|
486
499
|
isolated=isolated,
|
|
487
|
-
global_options=(
|
|
488
|
-
parsed_req.options.get("global_options", [])
|
|
489
|
-
if parsed_req.options
|
|
490
|
-
else []
|
|
491
|
-
),
|
|
492
500
|
hash_options=(
|
|
493
501
|
parsed_req.options.get("hashes", {}) if parsed_req.options else {}
|
|
494
502
|
),
|
|
@@ -509,9 +517,7 @@ def install_req_from_link_and_ireq(
|
|
|
509
517
|
editable=ireq.editable,
|
|
510
518
|
link=link,
|
|
511
519
|
markers=ireq.markers,
|
|
512
|
-
use_pep517=ireq.use_pep517,
|
|
513
520
|
isolated=ireq.isolated,
|
|
514
|
-
global_options=ireq.global_options,
|
|
515
521
|
hash_options=ireq.hash_options,
|
|
516
522
|
config_settings=ireq.config_settings,
|
|
517
523
|
user_supplied=ireq.user_supplied,
|
|
@@ -532,9 +538,7 @@ def install_req_drop_extras(ireq: InstallRequirement) -> InstallRequirement:
|
|
|
532
538
|
editable=ireq.editable,
|
|
533
539
|
link=ireq.link,
|
|
534
540
|
markers=ireq.markers,
|
|
535
|
-
use_pep517=ireq.use_pep517,
|
|
536
541
|
isolated=ireq.isolated,
|
|
537
|
-
global_options=ireq.global_options,
|
|
538
542
|
hash_options=ireq.hash_options,
|
|
539
543
|
constraint=ireq.constraint,
|
|
540
544
|
extras=[],
|
pip/_internal/req/req_file.py
CHANGED
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()
|
|
@@ -10,6 +10,7 @@ from pip._vendor.packaging.utils import NormalizedName, canonicalize_name
|
|
|
10
10
|
from pip._vendor.packaging.version import Version
|
|
11
11
|
|
|
12
12
|
from pip._internal.exceptions import (
|
|
13
|
+
FailedToPrepareCandidate,
|
|
13
14
|
HashError,
|
|
14
15
|
InstallationSubprocessError,
|
|
15
16
|
InvalidInstalledPackage,
|
|
@@ -68,10 +69,8 @@ def make_install_req_from_link(
|
|
|
68
69
|
line,
|
|
69
70
|
user_supplied=template.user_supplied,
|
|
70
71
|
comes_from=template.comes_from,
|
|
71
|
-
use_pep517=template.use_pep517,
|
|
72
72
|
isolated=template.isolated,
|
|
73
73
|
constraint=template.constraint,
|
|
74
|
-
global_options=template.global_options,
|
|
75
74
|
hash_options=template.hash_options,
|
|
76
75
|
config_settings=template.config_settings,
|
|
77
76
|
)
|
|
@@ -85,15 +84,17 @@ def make_install_req_from_editable(
|
|
|
85
84
|
link: Link, template: InstallRequirement
|
|
86
85
|
) -> InstallRequirement:
|
|
87
86
|
assert template.editable, "template not editable"
|
|
87
|
+
if template.name:
|
|
88
|
+
req_string = f"{template.name} @ {link.url}"
|
|
89
|
+
else:
|
|
90
|
+
req_string = link.url
|
|
88
91
|
ireq = install_req_from_editable(
|
|
89
|
-
|
|
92
|
+
req_string,
|
|
90
93
|
user_supplied=template.user_supplied,
|
|
91
94
|
comes_from=template.comes_from,
|
|
92
|
-
use_pep517=template.use_pep517,
|
|
93
95
|
isolated=template.isolated,
|
|
94
96
|
constraint=template.constraint,
|
|
95
97
|
permit_editable_wheels=template.permit_editable_wheels,
|
|
96
|
-
global_options=template.global_options,
|
|
97
98
|
hash_options=template.hash_options,
|
|
98
99
|
config_settings=template.config_settings,
|
|
99
100
|
)
|
|
@@ -114,10 +115,8 @@ def _make_install_req_from_dist(
|
|
|
114
115
|
line,
|
|
115
116
|
user_supplied=template.user_supplied,
|
|
116
117
|
comes_from=template.comes_from,
|
|
117
|
-
use_pep517=template.use_pep517,
|
|
118
118
|
isolated=template.isolated,
|
|
119
119
|
constraint=template.constraint,
|
|
120
|
-
global_options=template.global_options,
|
|
121
120
|
hash_options=template.hash_options,
|
|
122
121
|
config_settings=template.config_settings,
|
|
123
122
|
)
|
|
@@ -244,9 +243,19 @@ class _InstallRequirementBackedCandidate(Candidate):
|
|
|
244
243
|
e.req = self._ireq
|
|
245
244
|
raise
|
|
246
245
|
except InstallationSubprocessError as exc:
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
246
|
+
if isinstance(self._ireq.comes_from, InstallRequirement):
|
|
247
|
+
request_chain = self._ireq.comes_from.from_path()
|
|
248
|
+
else:
|
|
249
|
+
request_chain = self._ireq.comes_from
|
|
250
|
+
|
|
251
|
+
if request_chain is None:
|
|
252
|
+
request_chain = "directly requested"
|
|
253
|
+
|
|
254
|
+
raise FailedToPrepareCandidate(
|
|
255
|
+
package_name=self._ireq.name or str(self._link),
|
|
256
|
+
requirement_chain=request_chain,
|
|
257
|
+
failed_step=exc.command_description,
|
|
258
|
+
)
|
|
250
259
|
|
|
251
260
|
self._check_metadata_consistency(dist)
|
|
252
261
|
return dist
|
|
@@ -283,7 +292,7 @@ class LinkCandidate(_InstallRequirementBackedCandidate):
|
|
|
283
292
|
assert ireq.link == link
|
|
284
293
|
if ireq.link.is_wheel and not ireq.link.is_file:
|
|
285
294
|
wheel = Wheel(ireq.link.filename)
|
|
286
|
-
wheel_name =
|
|
295
|
+
wheel_name = wheel.name
|
|
287
296
|
assert name == wheel_name, f"{name!r} != {wheel_name!r} for wheel"
|
|
288
297
|
# Version may not be present for PEP 508 direct URLs
|
|
289
298
|
if version is not None:
|
|
@@ -711,6 +711,21 @@ class Factory:
|
|
|
711
711
|
|
|
712
712
|
return DistributionNotFound(f"No matching distribution found for {req}")
|
|
713
713
|
|
|
714
|
+
def _has_any_candidates(self, project_name: str) -> bool:
|
|
715
|
+
"""
|
|
716
|
+
Check if there are any candidates available for the project name.
|
|
717
|
+
"""
|
|
718
|
+
return any(
|
|
719
|
+
self.find_candidates(
|
|
720
|
+
project_name,
|
|
721
|
+
requirements={project_name: []},
|
|
722
|
+
incompatibilities={},
|
|
723
|
+
constraint=Constraint.empty(),
|
|
724
|
+
prefers_installed=True,
|
|
725
|
+
is_satisfied_by=lambda r, c: True,
|
|
726
|
+
)
|
|
727
|
+
)
|
|
728
|
+
|
|
714
729
|
def get_installation_error(
|
|
715
730
|
self,
|
|
716
731
|
e: ResolutionImpossible[Requirement, Candidate],
|
|
@@ -796,6 +811,22 @@ class Factory:
|
|
|
796
811
|
spec = constraints[key].specifier
|
|
797
812
|
msg += f"\n The user requested (constraint) {key}{spec}"
|
|
798
813
|
|
|
814
|
+
# Check for causes that had no candidates
|
|
815
|
+
causes = set()
|
|
816
|
+
for req, _ in e.causes:
|
|
817
|
+
causes.add(req.name)
|
|
818
|
+
|
|
819
|
+
no_candidates = {c for c in causes if not self._has_any_candidates(c)}
|
|
820
|
+
if no_candidates:
|
|
821
|
+
msg = (
|
|
822
|
+
msg
|
|
823
|
+
+ "\n\n"
|
|
824
|
+
+ "Additionally, some packages in these conflicts have no "
|
|
825
|
+
+ "matching distributions available for your environment:"
|
|
826
|
+
+ "\n "
|
|
827
|
+
+ "\n ".join(sorted(no_candidates))
|
|
828
|
+
)
|
|
829
|
+
|
|
799
830
|
msg = (
|
|
800
831
|
msg
|
|
801
832
|
+ "\n\n"
|
|
@@ -100,6 +100,15 @@ class PipProvider(_ProviderBase):
|
|
|
100
100
|
self._upgrade_strategy = upgrade_strategy
|
|
101
101
|
self._user_requested = user_requested
|
|
102
102
|
|
|
103
|
+
@property
|
|
104
|
+
def constraints(self) -> dict[str, Constraint]:
|
|
105
|
+
"""Public view of user-specified constraints.
|
|
106
|
+
|
|
107
|
+
Exposes the provider's constraints mapping without encouraging
|
|
108
|
+
external callers to reach into private attributes.
|
|
109
|
+
"""
|
|
110
|
+
return self._constraints
|
|
111
|
+
|
|
103
112
|
def identify(self, requirement_or_candidate: Requirement | Candidate) -> str:
|
|
104
113
|
return requirement_or_candidate.name
|
|
105
114
|
|