Skip to content

Commit e9d570e

Browse files
committed
fixup! ae0bda5
1 parent 134fa1d commit e9d570e

File tree

7 files changed

+157
-84
lines changed

7 files changed

+157
-84
lines changed

src/pip/_internal/distributions/sdist.py

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import logging
2-
from typing import Set, Tuple
2+
from typing import Iterable, Set, Tuple
33

44
from pip._internal.build_env import BuildEnvironment
55
from pip._internal.distributions.base import AbstractDistribution
@@ -37,23 +37,17 @@ def prepare_distribution_metadata(
3737
self.req.prepare_metadata()
3838

3939
def _setup_isolation(self, finder: PackageFinder) -> None:
40-
def _raise_conflicts(
41-
conflicting_with: str, conflicting_reqs: Set[Tuple[str, str]]
42-
) -> None:
43-
format_string = (
44-
"Some build dependencies for {requirement} "
45-
"conflict with {conflicting_with}: {description}."
46-
)
47-
error_message = format_string.format(
48-
requirement=self.req,
49-
conflicting_with=conflicting_with,
50-
description=", ".join(
51-
f"{installed} is incompatible with {wanted}"
52-
for installed, wanted in sorted(conflicting)
53-
),
54-
)
55-
raise InstallationError(error_message)
40+
self._prepare_build_backend(finder)
41+
# Install any extra build dependencies that the backend requests.
42+
# This must be done in a second pass, as the pyproject.toml
43+
# dependencies must be installed before we can call the backend.
44+
if self.req.editable and not self.req.no_build_editable:
45+
build_reqs = self._get_build_requires_editable()
46+
else:
47+
build_reqs = self._get_build_requires_wheel()
48+
self._install_build_reqs(finder, build_reqs)
5649

50+
def _prepare_build_backend(self, finder: PackageFinder) -> None:
5751
# Isolate in a BuildEnvironment and install the build-time
5852
# requirements.
5953
pyproject_requires = self.req.pyproject_requires
@@ -67,7 +61,7 @@ def _raise_conflicts(
6761
self.req.requirements_to_check
6862
)
6963
if conflicting:
70-
_raise_conflicts("PEP 517/518 supported requirements", conflicting)
64+
self._raise_conflicts("PEP 517/518 supported requirements", conflicting)
7165
if missing:
7266
logger.warning(
7367
"Missing build requirements in pyproject.toml for %s.",
@@ -78,26 +72,46 @@ def _raise_conflicts(
7872
"pip cannot fall back to setuptools without %s.",
7973
" and ".join(map(repr, sorted(missing))),
8074
)
81-
# Install any extra build dependencies that the backend requests.
82-
# This must be done in a second pass, as the pyproject.toml
83-
# dependencies must be installed before we can call the backend.
75+
76+
def _get_build_requires_wheel(self) -> Iterable[str]:
77+
with self.req.build_env:
78+
runner = runner_with_spinner_message("Getting requirements to build wheel")
79+
backend = self.req.pep517_backend
80+
assert backend is not None
81+
with backend.subprocess_runner(runner):
82+
return backend.get_requires_for_build_wheel()
83+
84+
def _get_build_requires_editable(self) -> Iterable[str]:
8485
with self.req.build_env:
8586
runner = runner_with_spinner_message(
86-
"Getting requirements to build {}".format(
87-
"editable" if self.req.editable else "wheel"
88-
)
87+
"Getting requirements to build editable"
8988
)
9089
backend = self.req.pep517_backend
9190
assert backend is not None
9291
with backend.subprocess_runner(runner):
93-
if self.req.editable and not self.req.no_build_editable:
94-
reqs = backend.get_requires_for_build_editable()
95-
else:
96-
reqs = backend.get_requires_for_build_wheel()
92+
return backend.get_requires_for_build_editable()
9793

94+
def _install_build_reqs(self, finder: PackageFinder, reqs: Iterable[str]) -> None:
9895
conflicting, missing = self.req.build_env.check_requirements(reqs)
9996
if conflicting:
100-
_raise_conflicts("the backend dependencies", conflicting)
97+
self._raise_conflicts("the backend dependencies", conflicting)
10198
self.req.build_env.install_requirements(
10299
finder, missing, "normal", "Installing backend dependencies"
103100
)
101+
102+
def _raise_conflicts(
103+
self, conflicting_with: str, conflicting_reqs: Set[Tuple[str, str]]
104+
) -> None:
105+
format_string = (
106+
"Some build dependencies for {requirement} "
107+
"conflict with {conflicting_with}: {description}."
108+
)
109+
error_message = format_string.format(
110+
requirement=self.req,
111+
conflicting_with=conflicting_with,
112+
description=", ".join(
113+
f"{installed} is incompatible with {wanted}"
114+
for installed, wanted in sorted(conflicting_reqs)
115+
),
116+
)
117+
raise InstallationError(error_message)

src/pip/_internal/operations/build/metadata.py

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,8 @@
1010
from pip._internal.utils.temp_dir import TempDirectory
1111

1212

13-
def generate_metadata(
14-
build_env: BuildEnvironment, backend: Pep517HookCaller, editable: bool
15-
) -> str:
16-
"""Generate metadata using mechanisms described in PEP 517 and PEP 660.
13+
def generate_metadata(build_env: BuildEnvironment, backend: Pep517HookCaller) -> str:
14+
"""Generate metadata using mechanisms described in PEP 517.
1715
1816
Returns the generated metadata directory.
1917
"""
@@ -23,15 +21,10 @@ def generate_metadata(
2321

2422
with build_env:
2523
# Note that Pep517HookCaller implements a fallback for
26-
# prepare_metadata_for_build_wheel/editable, so we don't have to
24+
# prepare_metadata_for_build_wheel, so we don't have to
2725
# consider the possibility that this hook doesn't exist.
28-
runner = runner_with_spinner_message(
29-
"Preparing {} metadata".format("editable" if editable else "wheel")
30-
)
26+
runner = runner_with_spinner_message("Preparing wheel metadata")
3127
with backend.subprocess_runner(runner):
32-
if editable:
33-
distinfo_dir = backend.prepare_metadata_for_build_editable(metadata_dir)
34-
else:
35-
distinfo_dir = backend.prepare_metadata_for_build_wheel(metadata_dir)
28+
distinfo_dir = backend.prepare_metadata_for_build_wheel(metadata_dir)
3629

3730
return os.path.join(metadata_dir, distinfo_dir)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"""Metadata generation logic for source distributions.
2+
"""
3+
4+
import os
5+
6+
from pip._vendor.pep517.wrappers import Pep517HookCaller
7+
8+
from pip._internal.build_env import BuildEnvironment
9+
from pip._internal.utils.subprocess import runner_with_spinner_message
10+
from pip._internal.utils.temp_dir import TempDirectory
11+
12+
13+
def generate_editable_metadata(
14+
build_env: BuildEnvironment, backend: Pep517HookCaller
15+
) -> str:
16+
"""Generate metadata using mechanisms described in PEP 517 and PEP 660.
17+
18+
Returns the generated metadata directory.
19+
"""
20+
metadata_tmpdir = TempDirectory(kind="modern-metadata", globally_managed=True)
21+
22+
metadata_dir = metadata_tmpdir.path
23+
24+
with build_env:
25+
# Note that Pep517HookCaller implements a fallback for
26+
# prepare_metadata_for_build_wheel/editable, so we don't have to
27+
# consider the possibility that this hook doesn't exist.
28+
runner = runner_with_spinner_message("Preparing editable metadata")
29+
with backend.subprocess_runner(runner):
30+
distinfo_dir = backend.prepare_metadata_for_build_editable(metadata_dir)
31+
32+
return os.path.join(metadata_dir, distinfo_dir)

src/pip/_internal/operations/build/wheel.py

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import os
33
from typing import Optional
44

5-
from pip._vendor.pep517.wrappers import HookMissing, Pep517HookCaller
5+
from pip._vendor.pep517.wrappers import Pep517HookCaller
66

77
from pip._internal.utils.subprocess import runner_with_spinner_message
88

@@ -14,7 +14,6 @@ def build_wheel_pep517(
1414
backend: Pep517HookCaller,
1515
metadata_directory: str,
1616
tempd: str,
17-
editable: bool,
1817
) -> Optional[str]:
1918
"""Build one InstallRequirement using the PEP 517 build process.
2019
@@ -24,33 +23,13 @@ def build_wheel_pep517(
2423
try:
2524
logger.debug("Destination directory: %s", tempd)
2625

27-
artifact = "editable" if editable else "wheel"
28-
pep = "660" if editable else "517"
29-
runner = runner_with_spinner_message(
30-
f"Building {artifact} for {name} (PEP {pep})"
31-
)
26+
runner = runner_with_spinner_message(f"Building wheel for {name} (PEP 517)")
3227
with backend.subprocess_runner(runner):
33-
if editable:
34-
try:
35-
wheel_name = backend.build_editable(
36-
tempd,
37-
metadata_directory=metadata_directory,
38-
)
39-
except HookMissing as e:
40-
logger.warning(
41-
"Cannot build %s %s because the build "
42-
"backend does not have the %s hook",
43-
artifact,
44-
name,
45-
e,
46-
)
47-
return None
48-
else:
49-
wheel_name = backend.build_wheel(
50-
tempd,
51-
metadata_directory=metadata_directory,
52-
)
28+
wheel_name = backend.build_wheel(
29+
tempd,
30+
metadata_directory=metadata_directory,
31+
)
5332
except Exception:
54-
logger.exception("Failed building %s for %s", artifact, name, exc_info=True)
33+
logger.error("Failed building wheel for %s", name)
5534
return None
5635
return os.path.join(tempd, wheel_name)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import logging
2+
import os
3+
from typing import Optional
4+
5+
from pip._vendor.pep517.wrappers import HookMissing, Pep517HookCaller
6+
7+
from pip._internal.utils.subprocess import runner_with_spinner_message
8+
9+
logger = logging.getLogger(__name__)
10+
11+
12+
def build_editable_pep660(
13+
name: str,
14+
backend: Pep517HookCaller,
15+
metadata_directory: str,
16+
tempd: str,
17+
) -> Optional[str]:
18+
"""Build one InstallRequirement using the PEP 660 build process.
19+
20+
Returns path to wheel if successfully built. Otherwise, returns None.
21+
"""
22+
assert metadata_directory is not None
23+
try:
24+
logger.debug("Destination directory: %s", tempd)
25+
26+
runner = runner_with_spinner_message(
27+
f"Building editable for {name} (pyproject.toml)"
28+
)
29+
with backend.subprocess_runner(runner):
30+
try:
31+
wheel_name = backend.build_editable(
32+
tempd,
33+
metadata_directory=metadata_directory,
34+
)
35+
except HookMissing as e:
36+
logger.warning(
37+
"Cannot build editable %s because the build "
38+
"backend does not have the %s hook",
39+
name,
40+
e,
41+
)
42+
return None
43+
except Exception:
44+
logger.error("Failed building editable for %s", name)
45+
return None
46+
return os.path.join(tempd, wheel_name)

src/pip/_internal/req/req_install.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from pip._internal.locations import get_scheme
2525
from pip._internal.models.link import Link
2626
from pip._internal.operations.build.metadata import generate_metadata
27+
from pip._internal.operations.build.metadata_editable import generate_editable_metadata
2728
from pip._internal.operations.build.metadata_legacy import (
2829
generate_metadata as generate_metadata_legacy,
2930
)
@@ -195,7 +196,8 @@ def __init__(
195196
# Setting an explicit value before loading pyproject.toml is supported,
196197
# but after loading this flag should be treated as read only.
197198
self.use_pep517 = use_pep517
198-
# Supports_pep660 will be set to True or False when we try to prepare
199+
200+
# supports_pep660 will be set to True or False when we try to prepare
199201
# editable metadata or build an editable wheel. None means "we don't know yet".
200202
self.supports_pep660: Optional[bool] = None
201203

@@ -501,18 +503,15 @@ def load_pyproject_toml(self) -> None:
501503
backend_path=backend_path,
502504
)
503505

504-
def _generate_metadata_for_editable(self) -> str:
506+
def _generate_editable_metadata(self) -> str:
505507
"""Invokes metadata generator functions, with the required arguments."""
506508
if self.use_pep517:
507509
assert self.pep517_backend is not None
508510
try:
509-
metadata_directory = generate_metadata(
511+
metadata_directory = generate_editable_metadata(
510512
build_env=self.build_env,
511513
backend=self.pep517_backend,
512-
editable=True,
513514
)
514-
self.supports_pep660 = True
515-
return metadata_directory
516515
except HookMissing as e:
517516
self.supports_pep660 = False
518517
if not os.path.exists(self.setup_py_path) and not os.path.exists(
@@ -528,6 +527,9 @@ def _generate_metadata_for_editable(self) -> str:
528527
# At this point we have determined that the build_editable hook
529528
# is missing, and there is a setup.py or setup.cfg
530529
# so we fallback to the legacy metadata generation
530+
else:
531+
self.supports_pep660 = True
532+
return metadata_directory
531533
else:
532534
if not os.path.exists(self.setup_py_path) and not os.path.exists(
533535
self.setup_cfg_path
@@ -554,7 +556,6 @@ def _generate_metadata(self) -> str:
554556
return generate_metadata(
555557
build_env=self.build_env,
556558
backend=self.pep517_backend,
557-
editable=False,
558559
)
559560
except HookMissing as e:
560561
raise InstallationError(
@@ -584,7 +585,7 @@ def prepare_metadata(self) -> None:
584585

585586
with indent_log():
586587
if self.editable and not self.no_build_editable:
587-
self.metadata_directory = self._generate_metadata_for_editable()
588+
self.metadata_directory = self._generate_editable_metadata()
588589
else:
589590
self.metadata_directory = self._generate_metadata()
590591

src/pip/_internal/wheel_builder.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from pip._internal.models.link import Link
1717
from pip._internal.models.wheel import Wheel
1818
from pip._internal.operations.build.wheel import build_wheel_pep517
19+
from pip._internal.operations.build.wheel_editable import build_editable_pep660
1920
from pip._internal.operations.build.wheel_legacy import build_wheel_legacy
2021
from pip._internal.req.req_install import InstallRequirement
2122
from pip._internal.utils.logging import indent_log
@@ -252,13 +253,20 @@ def _build_one_inside_env(
252253
logger.warning(
253254
"Ignoring --build-option when building %s using PEP 517", req.name
254255
)
255-
wheel_path = build_wheel_pep517(
256-
name=req.name,
257-
backend=req.pep517_backend,
258-
metadata_directory=req.metadata_directory,
259-
tempd=temp_dir.path,
260-
editable=editable,
261-
)
256+
if editable:
257+
wheel_path = build_editable_pep660(
258+
name=req.name,
259+
backend=req.pep517_backend,
260+
metadata_directory=req.metadata_directory,
261+
tempd=temp_dir.path,
262+
)
263+
else:
264+
wheel_path = build_wheel_pep517(
265+
name=req.name,
266+
backend=req.pep517_backend,
267+
metadata_directory=req.metadata_directory,
268+
tempd=temp_dir.path,
269+
)
262270
else:
263271
wheel_path = build_wheel_legacy(
264272
name=req.name,

0 commit comments

Comments
 (0)