From fb420d6a0c640ceedda35d54fe7329e1c84ffb35 Mon Sep 17 00:00:00 2001 From: finswimmer Date: Tue, 29 Jun 2021 15:21:31 +0200 Subject: [PATCH] wip: implement PEP 660 hooks --- poetry/core/masonry/api.py | 14 ++++++++++ poetry/core/masonry/builders/wheel.py | 39 +++++++++++++++++++++++---- tests/masonry/test_api.py | 21 +++++++++++++++ 3 files changed, 69 insertions(+), 5 deletions(-) diff --git a/poetry/core/masonry/api.py b/poetry/core/masonry/api.py index e0a9be858..37bd9098a 100644 --- a/poetry/core/masonry/api.py +++ b/poetry/core/masonry/api.py @@ -78,3 +78,17 @@ def build_sdist( path = SdistBuilder(poetry).build(Path(sdist_directory)) return path.name + + +def build_editable( + wheel_directory: str, + config_settings: Optional[Dict[str, Any]] = None, + metadata_directory: Optional[str] = None, +) -> str: + poetry = Factory().create_poetry(Path(".").resolve(), with_dev=False) + + return WheelBuilder.make_in(poetry, Path(wheel_directory), editable=True) + + +get_requires_for_build_editable = get_requires_for_build_wheel +prepare_metadata_for_build_editable = prepare_metadata_for_build_wheel diff --git a/poetry/core/masonry/builders/wheel.py b/poetry/core/masonry/builders/wheel.py index 29bff308c..f08dbe1e2 100644 --- a/poetry/core/masonry/builders/wheel.py +++ b/poetry/core/masonry/builders/wheel.py @@ -28,6 +28,7 @@ from ..utils.helpers import escape_name from ..utils.helpers import escape_version from ..utils.helpers import normalize_file_permissions +from ..utils.package_include import PackageInclude from .builder import Builder from .sdist import SdistBuilder @@ -54,6 +55,7 @@ def __init__( target_dir: Optional[Path] = None, original: Optional[Path] = None, executable: Optional[str] = None, + editable: bool = False, ) -> None: super(WheelBuilder, self).__init__(poetry, executable=executable) @@ -62,6 +64,7 @@ def __init__( self._target_dir = target_dir or (self._poetry.file.parent / "dist") if original: self._original_path = original.parent + self._editable = editable @classmethod def make_in( @@ -70,9 +73,14 @@ def make_in( directory: Optional[Path] = None, original: Optional[Path] = None, executable: Optional[str] = None, + editable: bool = False, ) -> str: wb = WheelBuilder( - poetry, target_dir=directory, original=original, executable=executable + poetry, + target_dir=directory, + original=original, + executable=executable, + editable=editable, ) wb.build() @@ -100,12 +108,16 @@ def build(self) -> None: with zipfile.ZipFile( fd_file, mode="w", compression=zipfile.ZIP_DEFLATED ) as zip_file: - if not self._poetry.package.build_should_generate_setup(): - self._build(zip_file) - self._copy_module(zip_file) + if not self._editable: + if not self._poetry.package.build_should_generate_setup(): + self._build(zip_file) + self._copy_module(zip_file) + else: + self._copy_module(zip_file) + self._build(zip_file) else: - self._copy_module(zip_file) self._build(zip_file) + self._add_pth(zip_file) self._copy_file_scripts(zip_file) self._write_metadata(zip_file) @@ -118,6 +130,23 @@ def build(self) -> None: logger.info("Built {}".format(self.wheel_filename)) + def _add_pth(self, wheel: zipfile.ZipFile) -> None: + paths = set() + for include in self._module.includes: + if isinstance(include, PackageInclude) and ( + include.is_module() or include.is_package() + ): + paths.add(include.base.resolve().as_posix()) + + content = "" + for path in paths: + content += path + os.linesep + + pth_file = Path(self._module.name).with_suffix(".pth") + + with self._write_to_zip(wheel, str(pth_file)) as f: + f.write(content) + def _build(self, wheel: zipfile.ZipFile) -> None: if self._package.build_script: if not self._poetry.package.build_should_generate_setup(): diff --git a/tests/masonry/test_api.py b/tests/masonry/test_api.py index e0c73ab4c..040a0a5e9 100644 --- a/tests/masonry/test_api.py +++ b/tests/masonry/test_api.py @@ -3,6 +3,7 @@ import os import platform import sys +import zipfile from contextlib import contextmanager from pathlib import Path @@ -214,3 +215,23 @@ def test_prepare_metadata_for_build_wheel_with_bad_path_dep_succeeds(): ): api.prepare_metadata_for_build_wheel(tmp_dir) assert "does not exist" in str(err.value) + + +def test_build_editable_wheel(): + pkg_dir = Path(fixtures) / "complete" + + with temporary_directory() as tmp_dir, cwd(pkg_dir): + filename = api.build_editable(tmp_dir) + wheel_pth = Path(tmp_dir) / filename + + validate_wheel_contents( + name="my_package", + version="1.2.3", + path=str(wheel_pth), + ) + + with zipfile.ZipFile(wheel_pth) as z: + namelist = z.namelist() + + assert "my_package.pth" in namelist + assert pkg_dir.as_posix() == z.read("my_package.pth").decode().strip()