mirror of
https://github.com/pypa/pip
synced 2023-12-13 21:30:23 +01:00
233 lines
8 KiB
Python
233 lines
8 KiB
Python
import os
|
|
from typing import Any, Dict
|
|
|
|
import pytest
|
|
import tomli_w
|
|
|
|
from pip._internal.utils.urls import path_to_url
|
|
from tests.lib import PipTestEnvironment
|
|
from tests.lib.path import Path
|
|
|
|
SETUP_PY = """
|
|
from setuptools import setup
|
|
|
|
setup()
|
|
"""
|
|
|
|
SETUP_CFG = """
|
|
[metadata]
|
|
name = project
|
|
version = 1.0.0
|
|
"""
|
|
|
|
BACKEND_WITHOUT_PEP660 = """
|
|
from setuptools.build_meta import (
|
|
build_wheel as _build_wheel,
|
|
prepare_metadata_for_build_wheel as _prepare_metadata_for_build_wheel,
|
|
get_requires_for_build_wheel as _get_requires_for_build_wheel,
|
|
)
|
|
|
|
def get_requires_for_build_wheel(config_settings=None):
|
|
with open("log.txt", "a") as f:
|
|
print(":get_requires_for_build_wheel called", file=f)
|
|
return _get_requires_for_build_wheel(config_settings)
|
|
|
|
def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None):
|
|
with open("log.txt", "a") as f:
|
|
print(":prepare_metadata_for_build_wheel called", file=f)
|
|
return _prepare_metadata_for_build_wheel(metadata_directory, config_settings)
|
|
|
|
def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
|
|
with open("log.txt", "a") as f:
|
|
print(":build_wheel called", file=f)
|
|
return _build_wheel(wheel_directory, config_settings, metadata_directory)
|
|
"""
|
|
|
|
# fmt: off
|
|
BACKEND_WITH_PEP660 = BACKEND_WITHOUT_PEP660 + """
|
|
def get_requires_for_build_editable(config_settings=None):
|
|
with open("log.txt", "a") as f:
|
|
print(":get_requires_for_build_editable called", file=f)
|
|
return _get_requires_for_build_wheel(config_settings)
|
|
|
|
def prepare_metadata_for_build_editable(metadata_directory, config_settings=None):
|
|
with open("log.txt", "a") as f:
|
|
print(":prepare_metadata_for_build_editable called", file=f)
|
|
return _prepare_metadata_for_build_wheel(metadata_directory, config_settings)
|
|
|
|
def build_editable(wheel_directory, config_settings=None, metadata_directory=None):
|
|
with open("log.txt", "a") as f:
|
|
print(":build_editable called", file=f)
|
|
return _build_wheel(wheel_directory, config_settings, metadata_directory)
|
|
"""
|
|
# fmt: on
|
|
|
|
|
|
def _make_project(
|
|
tmpdir: Path, backend_code: str, with_setup_py: bool, with_pyproject: bool = True
|
|
) -> Path:
|
|
project_dir = tmpdir / "project"
|
|
project_dir.mkdir()
|
|
project_dir.joinpath("setup.cfg").write_text(SETUP_CFG)
|
|
if with_setup_py:
|
|
project_dir.joinpath("setup.py").write_text(SETUP_PY)
|
|
if backend_code:
|
|
assert with_pyproject
|
|
buildsys: Dict[str, Any] = {"requires": ["setuptools", "wheel"]}
|
|
buildsys["build-backend"] = "test_backend"
|
|
buildsys["backend-path"] = ["."]
|
|
data = tomli_w.dumps({"build-system": buildsys})
|
|
project_dir.joinpath("pyproject.toml").write_text(data)
|
|
project_dir.joinpath("test_backend.py").write_text(backend_code)
|
|
elif with_pyproject:
|
|
project_dir.joinpath("pyproject.toml").touch()
|
|
project_dir.joinpath("log.txt").touch()
|
|
return project_dir
|
|
|
|
|
|
def _assert_hook_called(project_dir: Path, hook: str) -> None:
|
|
log = project_dir.joinpath("log.txt").read_text()
|
|
assert f":{hook} called" in log, f"{hook} has not been called"
|
|
|
|
|
|
def _assert_hook_not_called(project_dir: Path, hook: str) -> None:
|
|
log = project_dir.joinpath("log.txt").read_text()
|
|
assert f":{hook} called" not in log, f"{hook} should not have been called"
|
|
|
|
|
|
@pytest.mark.usefixtures("with_wheel")
|
|
def test_install_pep517_basic(tmpdir: Path, script: PipTestEnvironment) -> None:
|
|
"""
|
|
Check that the test harness we have in this file is sane.
|
|
"""
|
|
project_dir = _make_project(tmpdir, BACKEND_WITHOUT_PEP660, with_setup_py=False)
|
|
script.pip(
|
|
"install",
|
|
"--no-index",
|
|
"--no-build-isolation",
|
|
project_dir,
|
|
)
|
|
_assert_hook_called(project_dir, "prepare_metadata_for_build_wheel")
|
|
_assert_hook_called(project_dir, "build_wheel")
|
|
|
|
|
|
@pytest.mark.usefixtures("with_wheel")
|
|
def test_install_pep660_basic(tmpdir: Path, script: PipTestEnvironment) -> None:
|
|
"""
|
|
Test with backend that supports build_editable.
|
|
"""
|
|
project_dir = _make_project(tmpdir, BACKEND_WITH_PEP660, with_setup_py=False)
|
|
result = script.pip(
|
|
"install",
|
|
"--no-index",
|
|
"--no-build-isolation",
|
|
"--editable",
|
|
project_dir,
|
|
)
|
|
_assert_hook_called(project_dir, "prepare_metadata_for_build_editable")
|
|
_assert_hook_called(project_dir, "build_editable")
|
|
assert (
|
|
result.test_env.site_packages.joinpath("project.egg-link")
|
|
not in result.files_created
|
|
), "a .egg-link file should not have been created"
|
|
|
|
|
|
@pytest.mark.usefixtures("with_wheel")
|
|
def test_install_no_pep660_setup_py_fallback(
|
|
tmpdir: Path, script: PipTestEnvironment
|
|
) -> None:
|
|
"""
|
|
Test that we fall back to setuptools develop when using a backend that
|
|
does not support build_editable. Since there is a pyproject.toml,
|
|
the prepare_metadata_for_build_wheel hook is called.
|
|
"""
|
|
project_dir = _make_project(tmpdir, BACKEND_WITHOUT_PEP660, with_setup_py=True)
|
|
result = script.pip(
|
|
"install",
|
|
"--no-index",
|
|
"--no-build-isolation",
|
|
"--editable",
|
|
project_dir,
|
|
allow_stderr_warning=False,
|
|
)
|
|
_assert_hook_called(project_dir, "prepare_metadata_for_build_wheel")
|
|
assert (
|
|
result.test_env.site_packages.joinpath("project.egg-link")
|
|
in result.files_created
|
|
), "a .egg-link file should have been created"
|
|
|
|
|
|
@pytest.mark.usefixtures("with_wheel")
|
|
def test_install_no_pep660_setup_cfg_fallback(
|
|
tmpdir: Path, script: PipTestEnvironment
|
|
) -> None:
|
|
"""
|
|
Test that we fall back to setuptools develop when using a backend that
|
|
does not support build_editable. Since there is a pyproject.toml,
|
|
the prepare_metadata_for_build_wheel hook is called.
|
|
"""
|
|
project_dir = _make_project(tmpdir, BACKEND_WITHOUT_PEP660, with_setup_py=False)
|
|
result = script.pip(
|
|
"install",
|
|
"--no-index",
|
|
"--no-build-isolation",
|
|
"--editable",
|
|
project_dir,
|
|
allow_stderr_warning=False,
|
|
)
|
|
print(result.stdout, result.stderr)
|
|
_assert_hook_called(project_dir, "prepare_metadata_for_build_wheel")
|
|
assert (
|
|
result.test_env.site_packages.joinpath("project.egg-link")
|
|
in result.files_created
|
|
), ".egg-link file should have been created"
|
|
|
|
|
|
@pytest.mark.usefixtures("with_wheel")
|
|
def test_wheel_editable_pep660_basic(tmpdir: Path, script: PipTestEnvironment) -> None:
|
|
"""
|
|
Test 'pip wheel' of an editable pep 660 project.
|
|
It must *not* call prepare_metadata_for_build_editable.
|
|
"""
|
|
project_dir = _make_project(tmpdir, BACKEND_WITH_PEP660, with_setup_py=False)
|
|
wheel_dir = tmpdir / "dist"
|
|
script.pip(
|
|
"wheel",
|
|
"--no-index",
|
|
"--no-build-isolation",
|
|
"--editable",
|
|
project_dir,
|
|
"-w",
|
|
wheel_dir,
|
|
)
|
|
_assert_hook_not_called(project_dir, "prepare_metadata_for_build_editable")
|
|
_assert_hook_not_called(project_dir, "build_editable")
|
|
_assert_hook_called(project_dir, "prepare_metadata_for_build_wheel")
|
|
_assert_hook_called(project_dir, "build_wheel")
|
|
assert len(os.listdir(str(wheel_dir))) == 1, "a wheel should have been created"
|
|
|
|
|
|
@pytest.mark.usefixtures("with_wheel")
|
|
def test_download_editable_pep660_basic(
|
|
tmpdir: Path, script: PipTestEnvironment
|
|
) -> None:
|
|
"""
|
|
Test 'pip download' of an editable pep 660 project.
|
|
It must *not* call prepare_metadata_for_build_editable.
|
|
"""
|
|
project_dir = _make_project(tmpdir, BACKEND_WITH_PEP660, with_setup_py=False)
|
|
reqs_file = tmpdir / "requirements.txt"
|
|
reqs_file.write_text(f"-e {path_to_url(project_dir)}\n")
|
|
download_dir = tmpdir / "download"
|
|
script.pip(
|
|
"download",
|
|
"--no-index",
|
|
"--no-build-isolation",
|
|
"-r",
|
|
reqs_file,
|
|
"-d",
|
|
download_dir,
|
|
)
|
|
_assert_hook_not_called(project_dir, "prepare_metadata_for_build_editable")
|
|
_assert_hook_called(project_dir, "prepare_metadata_for_build_wheel")
|
|
assert len(os.listdir(str(download_dir))) == 1, "a zip should have been created"
|