Skip to content

Commit 0c6d20f

Browse files
authored
Validate build deps when --no-build-isolation is passed (#10886)
This can help catch issues in setting up the build environment, helping ensure that packages get built according to their declared metadata.
1 parent feb5fb4 commit 0c6d20f

File tree

4 files changed

+76
-3
lines changed

4 files changed

+76
-3
lines changed

news/9794.feature.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Validate build dependencies when using ``--no-build-isolation``.

src/pip/_internal/build_env.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from pip import __file__ as pip_location
2121
from pip._internal.cli.spinners import open_spinner
2222
from pip._internal.locations import get_platlib, get_prefixed_libs, get_purelib
23-
from pip._internal.metadata import get_environment
23+
from pip._internal.metadata import get_default_environment, get_environment
2424
from pip._internal.utils.subprocess import call_subprocess
2525
from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds
2626

@@ -168,7 +168,11 @@ def check_requirements(
168168
missing = set()
169169
conflicting = set()
170170
if reqs:
171-
env = get_environment(self._lib_dirs)
171+
env = (
172+
get_environment(self._lib_dirs)
173+
if hasattr(self, "_lib_dirs")
174+
else get_default_environment()
175+
)
172176
for req_str in reqs:
173177
req = Requirement(req_str)
174178
dist = env.get_distribution(req.name)

src/pip/_internal/distributions/sdist.py

+19-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,16 @@ def prepare_distribution_metadata(
4343
self.req.isolated_editable_sanity_check()
4444
# Install the dynamic build requirements.
4545
self._install_build_reqs(finder)
46-
46+
elif self.req.use_pep517:
47+
pyproject_requires = self.req.pyproject_requires
48+
assert pyproject_requires is not None
49+
conflicting, missing = self.req.build_env.check_requirements(
50+
pyproject_requires
51+
)
52+
if conflicting:
53+
self._raise_conflicts("the backend dependencies", conflicting)
54+
if missing:
55+
self._raise_missing_reqs(missing)
4756
self.req.prepare_metadata()
4857

4958
def _prepare_build_backend(self, finder: PackageFinder) -> None:
@@ -125,3 +134,12 @@ def _raise_conflicts(
125134
),
126135
)
127136
raise InstallationError(error_message)
137+
138+
def _raise_missing_reqs(self, missing: Set[str]) -> None:
139+
format_string = (
140+
"Some build dependencies for {requirement} are missing: {missing}."
141+
)
142+
error_message = format_string.format(
143+
requirement=self.req, missing=", ".join(map(repr, sorted(missing)))
144+
)
145+
raise InstallationError(error_message)

tests/functional/test_pep517.py

+50
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,56 @@ def test_conflicting_pep517_backend_requirements(
160160
assert result.returncode != 0 and msg in result.stderr, str(result)
161161

162162

163+
def test_validate_missing_pep517_backend_requirements(
164+
script: PipTestEnvironment, tmpdir: Path, data: TestData
165+
) -> None:
166+
project_dir = make_project(
167+
tmpdir, requires=["test_backend", "simplewheel==1.0"], backend="test_backend"
168+
)
169+
result = script.pip(
170+
"install",
171+
"--no-index",
172+
"-f",
173+
data.backends,
174+
"-f",
175+
data.packages,
176+
"--no-build-isolation",
177+
project_dir,
178+
expect_error=True,
179+
)
180+
msg = (
181+
"Some build dependencies for {url} are missing: "
182+
"'simplewheel==1.0', 'test_backend'.".format(url=path_to_url(project_dir))
183+
)
184+
assert result.returncode != 0 and msg in result.stderr, str(result)
185+
186+
187+
def test_validate_conflicting_pep517_backend_requirements(
188+
script: PipTestEnvironment, tmpdir: Path, data: TestData
189+
) -> None:
190+
project_dir = make_project(
191+
tmpdir, requires=["simplewheel==1.0"], backend="test_backend"
192+
)
193+
script.pip("install", "simplewheel==2.0", "--no-index", "-f", data.packages)
194+
result = script.pip(
195+
"install",
196+
"--no-index",
197+
"-f",
198+
data.backends,
199+
"-f",
200+
data.packages,
201+
"--no-build-isolation",
202+
project_dir,
203+
expect_error=True,
204+
)
205+
msg = (
206+
"Some build dependencies for {url} conflict with the backend "
207+
"dependencies: simplewheel==2.0 is incompatible with "
208+
"simplewheel==1.0.".format(url=path_to_url(project_dir))
209+
)
210+
assert result.returncode != 0 and msg in result.stderr, str(result)
211+
212+
163213
def test_pep517_backend_requirements_already_satisfied(
164214
script: PipTestEnvironment, tmpdir: Path, data: TestData
165215
) -> None:

0 commit comments

Comments
 (0)