pip/tests/functional/test_pep517.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

425 lines
13 KiB
Python
Raw Normal View History

import os
from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple
import pytest
import tomli_w
2018-08-01 17:45:08 +02:00
from pip._internal.build_env import BuildEnvironment
from pip._internal.req import InstallRequirement
from tests.lib import (
PipTestEnvironment,
TestData,
create_basic_wheel_for_package,
make_test_finder,
)
def make_project(
tmpdir: Path,
requires: Optional[List[str]] = None,
backend: Optional[str] = None,
backend_path: Optional[List[str]] = None,
) -> Path:
2020-06-04 23:11:08 +02:00
requires = requires or []
project_dir = tmpdir / "project"
project_dir.mkdir()
buildsys: Dict[str, Any] = {"requires": requires}
if backend:
buildsys["build-backend"] = backend
if backend_path:
buildsys["backend-path"] = backend_path
data = tomli_w.dumps({"build-system": buildsys})
project_dir.joinpath("pyproject.toml").write_text(data)
2018-10-10 12:25:26 +02:00
return project_dir
def test_backend(tmpdir: Path, data: TestData) -> None:
2018-10-10 12:25:26 +02:00
"""Check we can call a requirement's backend successfully"""
project_dir = make_project(tmpdir, backend="dummy_backend")
req = InstallRequirement(None, None)
req.source_dir = os.fspath(project_dir) # make req believe it has been unpacked
req.load_pyproject_toml()
env = BuildEnvironment()
finder = make_test_finder(find_links=[data.backends])
env.install_requirements(finder, ["dummy_backend"], "normal", kind="Installing")
conflicting, missing = env.check_requirements(["dummy_backend"])
assert not conflicting and not missing
assert hasattr(req.pep517_backend, "build_wheel")
with env:
assert req.pep517_backend is not None
assert req.pep517_backend.build_wheel("dir") == "Backend called"
dummy_backend_code = """\
def build_wheel(
wheel_directory,
config_settings=None,
metadata_directory=None
):
return "Backend called"
"""
def test_backend_path(tmpdir: Path, data: TestData) -> None:
"""Check we can call a backend inside the project"""
project_dir = make_project(tmpdir, backend="dummy_backend", backend_path=["."])
(project_dir / "dummy_backend.py").write_text(dummy_backend_code)
req = InstallRequirement(None, None)
req.source_dir = os.fspath(project_dir) # make req believe it has been unpacked
req.load_pyproject_toml()
env = BuildEnvironment()
assert hasattr(req.pep517_backend, "build_wheel")
with env:
assert req.pep517_backend is not None
assert req.pep517_backend.build_wheel("dir") == "Backend called"
def test_backend_path_and_dep(tmpdir: Path, data: TestData) -> None:
"""Check we can call a requirement's backend successfully"""
project_dir = make_project(
tmpdir, backend="dummy_internal_backend", backend_path=["."]
)
(project_dir / "dummy_internal_backend.py").write_text(
"from dummy_backend import build_wheel"
)
req = InstallRequirement(None, None)
req.source_dir = os.fspath(project_dir) # make req believe it has been unpacked
req.load_pyproject_toml()
env = BuildEnvironment()
finder = make_test_finder(find_links=[data.backends])
env.install_requirements(finder, ["dummy_backend"], "normal", kind="Installing")
assert hasattr(req.pep517_backend, "build_wheel")
with env:
assert req.pep517_backend is not None
assert req.pep517_backend.build_wheel("dir") == "Backend called"
2018-10-10 12:25:26 +02:00
def test_pep517_install(
script: PipTestEnvironment, tmpdir: Path, data: TestData
) -> None:
2018-10-10 12:25:26 +02:00
"""Check we can build with a custom backend"""
project_dir = make_project(
tmpdir, requires=["test_backend"], backend="test_backend"
)
result = script.pip("install", "--no-index", "-f", data.backends, project_dir)
result.assert_installed("project", editable=False)
def test_pep517_install_with_reqs(
script: PipTestEnvironment, tmpdir: Path, data: TestData
) -> None:
2018-10-10 12:25:26 +02:00
"""Backend generated requirements are installed in the build env"""
project_dir = make_project(
tmpdir, requires=["test_backend"], backend="test_backend"
)
project_dir.joinpath("backend_reqs.txt").write_text("simplewheel")
2018-10-10 12:25:26 +02:00
result = script.pip(
"install", "--no-index", "-f", data.backends, "-f", data.packages, project_dir
)
result.assert_installed("project", editable=False)
def test_no_use_pep517_without_setup_py(
script: PipTestEnvironment, tmpdir: Path, data: TestData
) -> None:
2018-10-10 12:25:26 +02:00
"""Using --no-use-pep517 requires setup.py"""
project_dir = make_project(
tmpdir, requires=["test_backend"], backend="test_backend"
)
result = script.pip(
"install",
"--no-index",
"--no-use-pep517",
"-f",
data.backends,
project_dir,
expect_error=True,
)
assert "project does not have a setup.py" in result.stderr
def test_conflicting_pep517_backend_requirements(
script: PipTestEnvironment, tmpdir: Path, data: TestData
) -> None:
project_dir = make_project(
tmpdir, requires=["test_backend", "simplewheel==1.0"], backend="test_backend"
)
project_dir.joinpath("backend_reqs.txt").write_text("simplewheel==2.0")
result = script.pip(
"install",
"--no-index",
"-f",
data.backends,
"-f",
data.packages,
project_dir,
expect_error=True,
)
msg = (
2023-11-07 10:14:56 +01:00
f"Some build dependencies for {project_dir.as_uri()} conflict with the backend "
"dependencies: simplewheel==1.0 is incompatible with "
2023-11-07 10:14:56 +01:00
"simplewheel==2.0."
2021-08-13 15:23:45 +02:00
)
assert result.returncode != 0 and msg in result.stderr, str(result)
2022-05-12 20:23:19 +02:00
def test_no_check_build_deps(
script: PipTestEnvironment, tmpdir: Path, data: TestData
) -> None:
project_dir = make_project(
tmpdir, requires=["simplewheel==2.0"], backend="test_backend"
)
script.pip(
"install",
"simplewheel==1.0",
"test_backend",
"--no-index",
"-f",
data.packages,
"-f",
data.backends,
)
result = script.pip("install", "--no-build-isolation", project_dir)
result.assert_installed("project", editable=False)
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",
2022-05-12 20:23:19 +02:00
"--check-build-dependencies",
project_dir,
expect_error=True,
)
msg = (
2023-11-07 10:14:56 +01:00
f"Some build dependencies for {project_dir.as_uri()} are missing: "
"'simplewheel==1.0', 'test_backend'."
)
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",
2022-05-12 20:23:19 +02:00
"--check-build-dependencies",
project_dir,
expect_error=True,
)
msg = (
2023-11-07 10:14:56 +01:00
f"Some build dependencies for {project_dir.as_uri()} conflict with the backend "
"dependencies: simplewheel==2.0 is incompatible with "
2023-11-07 10:14:56 +01:00
"simplewheel==1.0."
)
assert result.returncode != 0 and msg in result.stderr, str(result)
def test_pep517_backend_requirements_satisfied_by_prerelease(
script: PipTestEnvironment,
data: TestData,
) -> None:
create_basic_wheel_for_package(script, "myreq", "1.0a1")
script.pip("install", "myreq==1.0a1", "--no-index", "-f", script.scratch_path)
script.pip("install", "test_backend", "--no-index", "-f", data.backends)
project_dir = make_project(
script.temp_path,
requires=["test_backend", "myreq"],
backend="test_backend",
)
project_dir.joinpath("backend_reqs.txt").write_text("myreq")
result = script.pip("install", "--no-index", "--no-build-isolation", project_dir)
assert "Installing backend dependencies:" not in result.stdout
def test_pep517_backend_requirements_already_satisfied(
script: PipTestEnvironment, tmpdir: Path, data: TestData
) -> None:
project_dir = make_project(
tmpdir, requires=["test_backend", "simplewheel==1.0"], backend="test_backend"
)
project_dir.joinpath("backend_reqs.txt").write_text("simplewheel")
result = script.pip(
"install",
"--no-index",
"-f",
data.backends,
"-f",
data.packages,
project_dir,
)
assert "Installing backend dependencies:" not in result.stdout
2019-01-23 03:31:29 +01:00
def test_pep517_install_with_no_cache_dir(
script: PipTestEnvironment, tmpdir: Path, data: TestData
) -> None:
2019-01-23 03:31:29 +01:00
"""Check builds with a custom backends work, even with no cache."""
project_dir = make_project(
tmpdir, requires=["test_backend"], backend="test_backend"
)
result = script.pip(
"install",
"--no-cache-dir",
"--no-index",
"-f",
data.backends,
project_dir,
)
result.assert_installed("project", editable=False)
def make_pyproject_with_setup(
tmpdir: Path, build_system: bool = True, set_backend: bool = True
) -> Tuple[Path, str]:
project_dir = tmpdir / "project"
project_dir.mkdir()
setup_script = "from setuptools import setup\n"
expect_script_dir_on_path = True
if build_system:
buildsys: Dict[str, Any] = {
"requires": ["setuptools", "wheel"],
}
if set_backend:
buildsys["build-backend"] = "setuptools.build_meta"
expect_script_dir_on_path = False
project_data = tomli_w.dumps({"build-system": buildsys})
else:
project_data = ""
if expect_script_dir_on_path:
setup_script += "from pep517_test import __version__\n"
else:
setup_script += (
"try:\n"
" import pep517_test\n"
"except ImportError:\n"
" pass\n"
"else:\n"
' raise RuntimeError("Source dir incorrectly on sys.path")\n'
)
setup_script += 'setup(name="pep517_test", version="0.1", packages=["pep517_test"])'
project_dir.joinpath("pyproject.toml").write_text(project_data)
project_dir.joinpath("setup.py").write_text(setup_script)
package_dir = project_dir / "pep517_test"
package_dir.mkdir()
package_dir.joinpath("__init__.py").write_text('__version__ = "0.1"')
return project_dir, "pep517_test"
def test_no_build_system_section(
script: PipTestEnvironment, tmpdir: Path, data: TestData, common_wheels: Path
) -> None:
"""Check builds with setup.py, pyproject.toml, but no build-system section."""
project_dir, name = make_pyproject_with_setup(tmpdir, build_system=False)
result = script.pip(
"install",
"--no-cache-dir",
"--no-index",
"-f",
common_wheels,
project_dir,
)
result.assert_installed(name, editable=False)
def test_no_build_backend_entry(
script: PipTestEnvironment, tmpdir: Path, data: TestData, common_wheels: Path
) -> None:
"""Check builds with setup.py, pyproject.toml, but no build-backend entry."""
project_dir, name = make_pyproject_with_setup(tmpdir, set_backend=False)
result = script.pip(
"install",
"--no-cache-dir",
"--no-index",
"-f",
common_wheels,
project_dir,
)
result.assert_installed(name, editable=False)
def test_explicit_setuptools_backend(
script: PipTestEnvironment, tmpdir: Path, data: TestData, common_wheels: Path
) -> None:
"""Check builds with setup.py, pyproject.toml, and a build-backend entry."""
project_dir, name = make_pyproject_with_setup(tmpdir)
result = script.pip(
"install",
"--no-cache-dir",
"--no-index",
"-f",
common_wheels,
project_dir,
)
result.assert_installed(name, editable=False)
2019-02-27 19:04:50 +01:00
@pytest.mark.network
def test_pep517_and_build_options(
script: PipTestEnvironment, tmpdir: Path, data: TestData, common_wheels: Path
) -> None:
"""Backend generated requirements are installed in the build env"""
project_dir, name = make_pyproject_with_setup(tmpdir)
result = script.pip(
2019-02-27 18:50:42 +01:00
"wheel",
"--wheel-dir",
tmpdir,
"--build-option",
"foo",
"-f",
common_wheels,
project_dir,
allow_stderr_warning=True,
)
assert "Ignoring --build-option when building" in result.stderr
assert "using PEP 517" in result.stderr
@pytest.mark.network
def test_pep517_and_global_options(
script: PipTestEnvironment, tmpdir: Path, data: TestData, common_wheels: Path
) -> None:
"""Backend generated requirements are installed in the build env"""
project_dir, name = make_pyproject_with_setup(tmpdir)
result = script.pip(
"wheel",
"--wheel-dir",
tmpdir,
"--global-option",
"foo",
"-f",
common_wheels,
project_dir,
allow_stderr_warning=True,
)
assert "Ignoring --global-option when building" in result.stderr
assert "using PEP 517" in result.stderr