From 0dcdbac4b60cbd2c7f78025d3e50ccc6b57ed2e9 Mon Sep 17 00:00:00 2001 From: Robert Taylor Date: Mon, 28 Nov 2022 22:43:33 +0000 Subject: [PATCH 1/3] Fix wheel data section to use normalised package name, and test --- src/poetry/core/masonry/builders/wheel.py | 3 ++- tests/masonry/builders/test_complete.py | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/poetry/core/masonry/builders/wheel.py b/src/poetry/core/masonry/builders/wheel.py index ba0f4ed69..9abf7f4d9 100644 --- a/src/poetry/core/masonry/builders/wheel.py +++ b/src/poetry/core/masonry/builders/wheel.py @@ -308,7 +308,8 @@ def dist_info(self) -> str: @property def wheel_data_folder(self) -> str: - return f"{self._package.name}-{self._meta.version}.data" + name = distribution_name(self._package.name) + return f"{name}-{self._meta.version}.data" @property def wheel_filename(self) -> str: diff --git a/tests/masonry/builders/test_complete.py b/tests/masonry/builders/test_complete.py index c93ec3801..9e4b27abc 100644 --- a/tests/masonry/builders/test_complete.py +++ b/tests/masonry/builders/test_complete.py @@ -223,10 +223,10 @@ def test_complete() -> None: try: assert "my_package/sub_pgk1/extra_file.xml" not in zip.namelist() - assert "my-package-1.2.3.data/scripts/script.sh" in zip.namelist() + assert "my_package-1.2.3.data/scripts/script.sh" in zip.namelist() assert ( "Hello World" - in zip.read("my-package-1.2.3.data/scripts/script.sh").decode() + in zip.read("my_package-1.2.3.data/scripts/script.sh").decode() ) entry_points = zip.read("my_package-1.2.3.dist-info/entry_points.txt") @@ -342,7 +342,7 @@ def test_complete_no_vcs() -> None: "my_package/sub_pkg1/__init__.py", "my_package/sub_pkg2/__init__.py", "my_package/sub_pkg2/data2/data.json", - "my-package-1.2.3.data/scripts/script.sh", + "my_package-1.2.3.data/scripts/script.sh", "my_package/sub_pkg3/foo.py", "my_package-1.2.3.dist-info/entry_points.txt", "my_package-1.2.3.dist-info/LICENSE", From 6146d5607e0a84cc9291a0ee2d687c1550f82f43 Mon Sep 17 00:00:00 2001 From: Robert Taylor Date: Mon, 28 Nov 2022 15:29:23 +0000 Subject: [PATCH 2/3] Capture any scripts generated by setup/build and include in wheel --- src/poetry/core/masonry/builders/wheel.py | 61 +++++++++++++++-------- tests/masonry/test_api.py | 1 - 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/poetry/core/masonry/builders/wheel.py b/src/poetry/core/masonry/builders/wheel.py index 9abf7f4d9..b384856b0 100644 --- a/src/poetry/core/masonry/builders/wheel.py +++ b/src/poetry/core/masonry/builders/wheel.py @@ -8,6 +8,7 @@ import shutil import stat import subprocess +import sys import tempfile import zipfile @@ -180,28 +181,48 @@ def _build(self, wheel: zipfile.ZipFile) -> None: finally: os.chdir(current_path) + python_version_major = sys.version_info[0] + python_version_minor = sys.version_info[1] build_dir = self._path / "build" libs: list[Path] = list(build_dir.glob("lib.*")) - if not libs: - # 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 lib.glob("**/*"): - if pkg.is_dir() or self.is_excluded(pkg): - continue - - rel_path = str(pkg.relative_to(lib)) - - if rel_path in wheel.namelist(): - continue - - logger.debug(f"Adding: {rel_path}") - - self._add_file(wheel, pkg, rel_path) + scripts: list[Path] = list( + build_dir.glob( + f"scripts-{python_version_major}.{python_version_minor}/*" + ) + ) + if libs: + lib = libs[0] + + for pkg in lib.glob("**/*"): + if pkg.is_dir() or self.is_excluded(pkg): + continue + + rel_path = str(pkg.relative_to(lib)) + + if rel_path in wheel.namelist(): + continue + + logger.debug(f"Adding: {rel_path}") + + self._add_file(wheel, pkg, rel_path) + + if scripts: + for abs_path in scripts: + logger.debug(f"Adding: scripts/{abs_path.name}") + self._add_file( + wheel, + abs_path, + Path.joinpath( + Path(self.wheel_data_folder), + "scripts", + abs_path.name, + ), + ) + + # The result of building the extensions + # does not exist, this may due to conditional + # builds, so we assume that it's okay + return def _copy_file_scripts(self, wheel: zipfile.ZipFile) -> None: file_scripts = self.convert_script_files() diff --git a/tests/masonry/test_api.py b/tests/masonry/test_api.py index dfc1699c3..6e6603cc3 100644 --- a/tests/masonry/test_api.py +++ b/tests/masonry/test_api.py @@ -93,7 +93,6 @@ def test_build_wheel_extended() -> None: assert whl.exists() validate_wheel_contents(name="extended", version="0.1", path=whl.as_posix()) - def test_build_sdist() -> None: with temporary_directory() as tmp_dir, cwd(os.path.join(fixtures, "complete")): filename = api.build_sdist(tmp_dir) From 182f66db4556d332e7ba6fcd7dd108c7988339ab Mon Sep 17 00:00:00 2001 From: Robert Taylor Date: Mon, 28 Nov 2022 22:41:33 +0000 Subject: [PATCH 3/3] Add test for scripts generated in build.py --- .../fixtures/script_generated/build.py | 21 ++++++++++++++++++ .../fixtures/script_generated/pyproject.toml | 16 ++++++++++++++ .../script_generated/__init__.py | 0 .../script_generated/generated/__init__.py | 0 tests/masonry/test_api.py | 22 +++++++++++++++++++ tests/testutils.py | 10 ++++++++- 6 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 tests/masonry/builders/fixtures/script_generated/build.py create mode 100644 tests/masonry/builders/fixtures/script_generated/pyproject.toml create mode 100644 tests/masonry/builders/fixtures/script_generated/script_generated/__init__.py create mode 100644 tests/masonry/builders/fixtures/script_generated/script_generated/generated/__init__.py diff --git a/tests/masonry/builders/fixtures/script_generated/build.py b/tests/masonry/builders/fixtures/script_generated/build.py new file mode 100644 index 000000000..10b7b4f9e --- /dev/null +++ b/tests/masonry/builders/fixtures/script_generated/build.py @@ -0,0 +1,21 @@ +from pathlib import Path +from setuptools.command.build_py import build_py + + +class BuildPyCommand(build_py): + def run(self): + with open('script_generated/generated/file.py', 'w') as out: + print("#!/bin/env python3\nprint('Success!')\n", file=out) + return super().run() + + +def build(setup_kwargs): + setup_kwargs.update( + { + "cmdclass": { + "build_py": BuildPyCommand, + }, + "scripts": ["script_generated/generated/file.py"] + } + + ) diff --git a/tests/masonry/builders/fixtures/script_generated/pyproject.toml b/tests/masonry/builders/fixtures/script_generated/pyproject.toml new file mode 100644 index 000000000..95f4a588f --- /dev/null +++ b/tests/masonry/builders/fixtures/script_generated/pyproject.toml @@ -0,0 +1,16 @@ +[tool.poetry] +name = "script_generated" +version = "0.1" +description = "" +authors = ["Evgenii Gorchakov ", "Rob Taylor "] + +[tool.poetry.dependencies] +python = "^3.8" + +[build-system] +requires = ["poetry-core", "setuptools"] +build-backend = "poetry.core.masonry.api" + +[tool.poetry.build] +generate-setup-file = true +script = "build.py" diff --git a/tests/masonry/builders/fixtures/script_generated/script_generated/__init__.py b/tests/masonry/builders/fixtures/script_generated/script_generated/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/masonry/builders/fixtures/script_generated/script_generated/generated/__init__.py b/tests/masonry/builders/fixtures/script_generated/script_generated/generated/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/masonry/test_api.py b/tests/masonry/test_api.py index 6e6603cc3..c32bdfc4f 100644 --- a/tests/masonry/test_api.py +++ b/tests/masonry/test_api.py @@ -93,6 +93,28 @@ def test_build_wheel_extended() -> None: assert whl.exists() validate_wheel_contents(name="extended", version="0.1", path=whl.as_posix()) + +@pytest.mark.skipif( + sys.platform == "win32" + and sys.version_info <= (3, 6) + or platform.python_implementation().lower() == "pypy", + reason="Disable test on Windows for Python <=3.6 and for PyPy", +) +def test_build_wheel_script_generated() -> None: + with temporary_directory() as tmp_dir, cwd( + os.path.join(fixtures, "script_generated") + ): + filename = api.build_wheel(tmp_dir) + whl = Path(tmp_dir) / filename + assert whl.exists() + validate_wheel_contents( + name="script_generated", + version="0.1", + path=whl.as_posix(), + data_files=["scripts/file.py"], + ) + + def test_build_sdist() -> None: with temporary_directory() as tmp_dir, cwd(os.path.join(fixtures, "complete")): filename = api.build_sdist(tmp_dir) diff --git a/tests/testutils.py b/tests/testutils.py index d43b4abf9..4e548579a 100644 --- a/tests/testutils.py +++ b/tests/testutils.py @@ -60,16 +60,24 @@ def subprocess_run(*args: str, **kwargs: Any) -> subprocess.CompletedProcess[str def validate_wheel_contents( - name: str, version: str, path: str, files: list[str] | None = None + name: str, + version: str, + path: str, + files: list[str] | None = None, + data_files: list[str] | None = None, ) -> None: dist_info = f"{name}-{version}.dist-info" + dist_data = f"{name}-{version}.data" files = files or [] + data_files = data_files or [] with zipfile.ZipFile(path) as z: namelist = z.namelist() # we use concatenation here for PY2 compat for filename in ["WHEEL", "METADATA", "RECORD"] + files: assert f"{dist_info}/{filename}" in namelist + for filename in data_files: + assert f"{dist_data}/{filename}" in namelist def validate_sdist_contents(