diff --git a/src/poetry/core/masonry/builders/wheel.py b/src/poetry/core/masonry/builders/wheel.py index 4a0b52dfd..b24a64610 100644 --- a/src/poetry/core/masonry/builders/wheel.py +++ b/src/poetry/core/masonry/builders/wheel.py @@ -9,6 +9,7 @@ import stat import subprocess import sys +import sysconfig import tempfile import zipfile @@ -187,16 +188,13 @@ def _build(self, wheel: zipfile.ZipFile) -> None: # in-place - so there's no need to copy them into the zip return - build_dir = self._path / "build" - libs: list[Path] = list(build_dir.glob("lib.*")) - if not libs: + lib = self._get_build_lib_dir() + if lib is None: # The result of building the extensions # does not exist, this may due to conditional # builds, so we assume that it's okay return - lib = libs[0] - for pkg in sorted(lib.glob("**/*")): if pkg.is_dir() or self.is_excluded(pkg): continue @@ -210,6 +208,25 @@ def _build(self, wheel: zipfile.ZipFile) -> None: self._add_file(wheel, pkg, rel_path) + def _get_build_purelib_dir(self) -> Path: + return self._path / "build/lib" + + def _get_build_platlib_dir(self) -> Path: + # Roughly equivalent to the naming convention in used by distutils, see: + # distutils.command.build.build.finalize_options + plat_specifier = f"{sysconfig.get_platform()}-{sys.implementation.cache_tag}" + return self._path / f"build/lib.{plat_specifier}" + + def _get_build_lib_dir(self) -> Path | None: + # Either the purelib or platlib path will have been used when building + build_platlib = self._get_build_platlib_dir() + build_purelib = self._get_build_purelib_dir() + if build_platlib.exists(): + return build_platlib + elif build_purelib.exists(): + return build_purelib + return None + def _copy_file_scripts(self, wheel: zipfile.ZipFile) -> None: file_scripts = self.convert_script_files() @@ -237,6 +254,10 @@ def _run_build_command(self, setup: Path) -> None: "build", "-b", str(self._path / "build"), + "--build-purelib", + str(self._get_build_purelib_dir()), + "--build-platlib", + str(self._get_build_platlib_dir()), ] ) diff --git a/tests/masonry/builders/fixtures/build_with_build_py_only/README.rst b/tests/masonry/builders/fixtures/build_with_build_py_only/README.rst new file mode 100644 index 000000000..a7508bd51 --- /dev/null +++ b/tests/masonry/builders/fixtures/build_with_build_py_only/README.rst @@ -0,0 +1,2 @@ +Module 1 +======== diff --git a/tests/masonry/builders/fixtures/build_with_build_py_only/build.py b/tests/masonry/builders/fixtures/build_with_build_py_only/build.py new file mode 100644 index 000000000..8a8e8a8fb --- /dev/null +++ b/tests/masonry/builders/fixtures/build_with_build_py_only/build.py @@ -0,0 +1,15 @@ +from pathlib import Path +from setuptools.command.build_py import build_py + + +class BuildPyCommand(build_py): + def run(self): + gen_file = Path("build_with_build_py_only/generated/file.py") + gen_file.touch() + ret = super().run() + gen_file.unlink() + return ret + + +def build(setup_kwargs): + setup_kwargs["cmdclass"] = {"build_py": BuildPyCommand} diff --git a/tests/masonry/builders/fixtures/build_with_build_py_only/build_with_build_py_only/__init__.py b/tests/masonry/builders/fixtures/build_with_build_py_only/build_with_build_py_only/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/masonry/builders/fixtures/build_with_build_py_only/build_with_build_py_only/generated/__init__.py b/tests/masonry/builders/fixtures/build_with_build_py_only/build_with_build_py_only/generated/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/masonry/builders/fixtures/build_with_build_py_only/pyproject.toml b/tests/masonry/builders/fixtures/build_with_build_py_only/pyproject.toml new file mode 100644 index 000000000..db8721715 --- /dev/null +++ b/tests/masonry/builders/fixtures/build_with_build_py_only/pyproject.toml @@ -0,0 +1,16 @@ +[tool.poetry] +name = "build_with_build_py_only" +version = "0.1" +description = "Some description." +authors = [ + "Robert Belter " +] +license = "MIT" + +readme = "README.rst" + +homepage = "https://python-poetry.org/" + +[tool.poetry.build] +script = "build.py" +generate-setup-file = true diff --git a/tests/masonry/builders/test_wheel.py b/tests/masonry/builders/test_wheel.py index 8f663d852..a93f9d206 100644 --- a/tests/masonry/builders/test_wheel.py +++ b/tests/masonry/builders/test_wheel.py @@ -417,3 +417,18 @@ def test_extended_editable_build_inplace() -> None: assert any( (root / "extended" / f"extended{ext}").exists() for ext in shared_lib_extensions ) + + +def test_build_py_only_included() -> None: + """Tests that a build.py that only defined the command build_py (which generates a + lib folder) will have its artifacts included. + """ + root = fixtures_dir / "build_with_build_py_only" + WheelBuilder.make(Factory().create_poetry(root)) + + whl = next((root / "dist").glob("build_with_build_py_only-0.1-*.whl")) + + assert whl.exists() + + with zipfile.ZipFile(str(whl)) as z: + assert "build_with_build_py_only/generated/file.py" in z.namelist()