diff --git a/src/poetry/utils/pip.py b/src/poetry/utils/pip.py index 5e6d5835bc6..6367f647507 100644 --- a/src/poetry/utils/pip.py +++ b/src/poetry/utils/pip.py @@ -31,7 +31,7 @@ def pip_install( # lot of packages. args = ["install", "--disable-pip-version-check", "--prefix", str(environment.path)] - if not is_wheel: + if not is_wheel and not editable: args.insert(1, "--use-pep517") if upgrade: diff --git a/tests/conftest.py b/tests/conftest.py index 6dee1e1b032..5515651419a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -34,6 +34,7 @@ from tests.helpers import TestLocker from tests.helpers import TestRepository from tests.helpers import get_package +from tests.helpers import isolated_environment from tests.helpers import mock_clone from tests.helpers import mock_download @@ -246,27 +247,19 @@ def _pep517_metadata(cls: PackageInfo, path: Path) -> PackageInfo: @pytest.fixture def environ() -> Iterator[None]: - original_environ = dict(os.environ) - - yield - - os.environ.clear() - os.environ.update(original_environ) + with isolated_environment(): + yield @pytest.fixture(autouse=True) def isolate_environ() -> Iterator[None]: """Ensure the environment is isolated from user configuration.""" - original_environ = dict(os.environ) - - for var in os.environ: - if var.startswith("POETRY_"): - del os.environ[var] - - yield + with isolated_environment(): + for var in os.environ: + if var.startswith("POETRY_") or var in {"PYTHONPATH", "VIRTUAL_ENV"}: + del os.environ[var] - os.environ.clear() - os.environ.update(original_environ) + yield @pytest.fixture(autouse=True) diff --git a/tests/fixtures/extended_project/build.py b/tests/fixtures/extended_project/build.py index e69de29bb2d..7a12c342719 100644 --- a/tests/fixtures/extended_project/build.py +++ b/tests/fixtures/extended_project/build.py @@ -0,0 +1,12 @@ +from __future__ import annotations + +from pathlib import Path +from typing import Any + + +def build(setup_kwargs: dict[str, Any]): + assert setup_kwargs["name"] == "extended-project" + assert setup_kwargs["version"] == "1.2.3" + + dynamic_module = Path(__file__).parent / "extended_project" / "built.py" + dynamic_module.write_text("# Generated by build.py") diff --git a/tests/fixtures/extended_project/pyproject.toml b/tests/fixtures/extended_project/pyproject.toml index ecb7deb9107..15b72917b0f 100644 --- a/tests/fixtures/extended_project/pyproject.toml +++ b/tests/fixtures/extended_project/pyproject.toml @@ -20,8 +20,10 @@ classifiers = [ "Topic :: Software Development :: Libraries :: Python Modules" ] -build = "build.py" +[tool.poetry.build] +script = "build.py" +generate-setup-file = true # Requirements [tool.poetry.dependencies] -python = "~2.7 || ^3.4" +python = "^3.7" diff --git a/tests/helpers.py b/tests/helpers.py index 9992c0e83dc..1969873263b 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -1,5 +1,6 @@ from __future__ import annotations +import contextlib import os import re import shutil @@ -9,6 +10,7 @@ from pathlib import Path from typing import TYPE_CHECKING from typing import Any +from typing import Iterator from poetry.core.masonry.utils.helpers import escape_name from poetry.core.masonry.utils.helpers import escape_version @@ -230,3 +232,21 @@ def find_links_for_package(self, package: Package) -> list[Link]: f"-{escape_version(package.version.text)}-py2.py3-none-any.whl" ) ] + + +@contextlib.contextmanager +def isolated_environment( + environ: dict[str, Any] | None = None, clear: bool = False +) -> Iterator[None]: + original_environ = dict(os.environ) + + if clear: + os.environ.clear() + + if environ: + os.environ.update(environ) + + yield + + os.environ.clear() + os.environ.update(original_environ) diff --git a/tests/masonry/builders/test_editable_builder.py b/tests/masonry/builders/test_editable_builder.py index cbd91f4dcdd..aa34a6b7808 100644 --- a/tests/masonry/builders/test_editable_builder.py +++ b/tests/masonry/builders/test_editable_builder.py @@ -12,9 +12,12 @@ from poetry.factory import Factory from poetry.masonry.builders.editable import EditableBuilder +from poetry.repositories.installed_repository import InstalledRepository +from poetry.utils.env import EnvCommandError from poetry.utils.env import EnvManager from poetry.utils.env import MockEnv from poetry.utils.env import VirtualEnv +from poetry.utils.env import ephemeral_environment if TYPE_CHECKING: @@ -203,6 +206,41 @@ def test_builder_falls_back_on_setup_and_pip_for_packages_with_build_scripts( assert [] == env.executed +def test_builder_setup_generation_runs_with_pip_editable(tmp_dir: str): + # create an isolated copy of the project + fixture = Path(__file__).parent.parent.parent / "fixtures" / "extended_project" + extended_project = Path(tmp_dir) / "extended_project" + + shutil.copytree(fixture, extended_project) + assert extended_project.exists() + + poetry = Factory().create_poetry(extended_project) + + # we need a venv with setuptools since we are verifying setup.py builds + with ephemeral_environment(flags={"no-setuptools": False}) as venv: + builder = EditableBuilder(poetry, venv, NullIO()) + builder.build() + + # is the package installed? + repository = InstalledRepository.load(venv) + assert repository.package("extended-project", "1.2.3") + + # check for the module built by build.py + try: + output = venv.run_python_script( + "from extended_project import built; print(built.__file__)" + ).strip() + except EnvCommandError: + pytest.fail("Unable to import built module") + else: + built_py = Path(output).resolve() + + expected = extended_project / "extended_project" / "built.py" + + # ensure the package was installed as editable + assert built_py == expected.resolve() + + def test_builder_installs_proper_files_when_packages_configured( project_with_include: Poetry, tmp_venv: VirtualEnv ):