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.
This commit is contained in:
q0w 2022-02-18 17:58:40 +03:00 committed by GitHub
parent feb5fb4636
commit 0c6d20f8c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 3 deletions

1
news/9794.feature.rst Normal file
View File

@ -0,0 +1 @@
Validate build dependencies when using ``--no-build-isolation``.

View File

@ -20,7 +20,7 @@ from pip._vendor.packaging.version import Version
from pip import __file__ as pip_location
from pip._internal.cli.spinners import open_spinner
from pip._internal.locations import get_platlib, get_prefixed_libs, get_purelib
from pip._internal.metadata import get_environment
from pip._internal.metadata import get_default_environment, get_environment
from pip._internal.utils.subprocess import call_subprocess
from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds
@ -168,7 +168,11 @@ class BuildEnvironment:
missing = set()
conflicting = set()
if reqs:
env = get_environment(self._lib_dirs)
env = (
get_environment(self._lib_dirs)
if hasattr(self, "_lib_dirs")
else get_default_environment()
)
for req_str in reqs:
req = Requirement(req_str)
dist = env.get_distribution(req.name)

View File

@ -43,7 +43,16 @@ class SourceDistribution(AbstractDistribution):
self.req.isolated_editable_sanity_check()
# Install the dynamic build requirements.
self._install_build_reqs(finder)
elif self.req.use_pep517:
pyproject_requires = self.req.pyproject_requires
assert pyproject_requires is not None
conflicting, missing = self.req.build_env.check_requirements(
pyproject_requires
)
if conflicting:
self._raise_conflicts("the backend dependencies", conflicting)
if missing:
self._raise_missing_reqs(missing)
self.req.prepare_metadata()
def _prepare_build_backend(self, finder: PackageFinder) -> None:
@ -125,3 +134,12 @@ class SourceDistribution(AbstractDistribution):
),
)
raise InstallationError(error_message)
def _raise_missing_reqs(self, missing: Set[str]) -> None:
format_string = (
"Some build dependencies for {requirement} are missing: {missing}."
)
error_message = format_string.format(
requirement=self.req, missing=", ".join(map(repr, sorted(missing)))
)
raise InstallationError(error_message)

View File

@ -160,6 +160,56 @@ def test_conflicting_pep517_backend_requirements(
assert result.returncode != 0 and msg in result.stderr, str(result)
def test_validate_missing_pep517_backend_requirements(
script: PipTestEnvironment, tmpdir: Path, data: TestData
) -> None:
project_dir = make_project(
tmpdir, requires=["test_backend", "simplewheel==1.0"], backend="test_backend"
)
result = script.pip(
"install",
"--no-index",
"-f",
data.backends,
"-f",
data.packages,
"--no-build-isolation",
project_dir,
expect_error=True,
)
msg = (
"Some build dependencies for {url} are missing: "
"'simplewheel==1.0', 'test_backend'.".format(url=path_to_url(project_dir))
)
assert result.returncode != 0 and msg in result.stderr, str(result)
def test_validate_conflicting_pep517_backend_requirements(
script: PipTestEnvironment, tmpdir: Path, data: TestData
) -> None:
project_dir = make_project(
tmpdir, requires=["simplewheel==1.0"], backend="test_backend"
)
script.pip("install", "simplewheel==2.0", "--no-index", "-f", data.packages)
result = script.pip(
"install",
"--no-index",
"-f",
data.backends,
"-f",
data.packages,
"--no-build-isolation",
project_dir,
expect_error=True,
)
msg = (
"Some build dependencies for {url} conflict with the backend "
"dependencies: simplewheel==2.0 is incompatible with "
"simplewheel==1.0.".format(url=path_to_url(project_dir))
)
assert result.returncode != 0 and msg in result.stderr, str(result)
def test_pep517_backend_requirements_already_satisfied(
script: PipTestEnvironment, tmpdir: Path, data: TestData
) -> None: