From de040209715568e524b8091a70cd2be30f096ed8 Mon Sep 17 00:00:00 2001 From: Arun Babu Neelicattu Date: Tue, 31 Mar 2020 17:44:16 +0200 Subject: [PATCH 1/4] Add a setup file context manager in sdist builder A temporary setup file is required for various scenarios at the moment. This change introduces a context manager such that generates a temporary setup.py file and handles cleanup on exiting the context. --- poetry/core/masonry/builders/sdist.py | 21 +++++++++++++++++++++ tests/masonry/builders/test_sdist.py | 26 ++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/poetry/core/masonry/builders/sdist.py b/poetry/core/masonry/builders/sdist.py index 0bf375498..b2ebd1373 100644 --- a/poetry/core/masonry/builders/sdist.py +++ b/poetry/core/masonry/builders/sdist.py @@ -6,13 +6,16 @@ import time from collections import defaultdict +from contextlib import contextmanager from copy import copy from gzip import GzipFile from io import BytesIO from posixpath import join as pjoin from pprint import pformat +from typing import Iterator from poetry.core.utils._compat import Path +from poetry.core.utils._compat import decode from poetry.core.utils._compat import encode from poetry.core.utils._compat import to_str @@ -198,6 +201,24 @@ def build_setup(self): # type: () -> bytes ) ) + @contextmanager + def setup_py(self): # type: () -> Iterator[Path] + setup = self._path / "setup.py" + has_setup = setup.exists() + + if has_setup: + logger.info( + " - A setup.py file already exists. Using it." + ) + else: + with setup.open("w", encoding="utf-8") as f: + f.write(decode(self.build_setup())) + + yield setup + + if not has_setup: + setup.unlink() + def build_pkg_info(self): return encode(self.get_metadata_content()) diff --git a/tests/masonry/builders/test_sdist.py b/tests/masonry/builders/test_sdist.py index a3cc7f519..8a182ac54 100644 --- a/tests/masonry/builders/test_sdist.py +++ b/tests/masonry/builders/test_sdist.py @@ -14,6 +14,7 @@ from poetry.core.packages.dependency import Dependency from poetry.core.packages.vcs_dependency import VCSDependency from poetry.core.utils._compat import Path +from poetry.core.utils._compat import encode from poetry.core.utils._compat import to_str @@ -247,6 +248,31 @@ def test_package(): assert "my-package-1.2.3/LICENSE" in tar.getnames() +def test_setup_py_context(): + poetry = Factory().create_poetry(project("complete")) + + builder = SdistBuilder(poetry) + + project_setup_py = poetry.file.parent / "setup.py" + + assert not project_setup_py.exists() + + try: + with builder.setup_py() as setup: + assert setup.exists() + assert project_setup_py == setup + + with open(str(setup), "rb") as f: + # we convert to string and replace line endings here for compatibility + data = to_str(encode(f.read())).replace("\r\n", "\n") + assert data == to_str(builder.build_setup()) + + assert not project_setup_py.exists() + finally: + if project_setup_py.exists(): + project_setup_py.unlink() + + def test_module(): poetry = Factory().create_poetry(project("module1")) From f5d92c4f50b07b829f6b634af422273482866b11 Mon Sep 17 00:00:00 2001 From: Arun Babu Neelicattu Date: Tue, 31 Mar 2020 18:01:42 +0200 Subject: [PATCH 2/4] Fix PEP-517 issues for projects using build scripts Resolves: python-poetry/poetry#1516 --- poetry/core/masonry/builders/wheel.py | 66 +++++++++++++-------------- tests/masonry/test_api.py | 25 ++++++++++ 2 files changed, 58 insertions(+), 33 deletions(-) diff --git a/poetry/core/masonry/builders/wheel.py b/poetry/core/masonry/builders/wheel.py index cb98dcdae..e7d11bacb 100644 --- a/poetry/core/masonry/builders/wheel.py +++ b/poetry/core/masonry/builders/wheel.py @@ -25,6 +25,7 @@ from ..utils.helpers import normalize_file_permissions from ..utils.package_include import PackageInclude from .builder import Builder +from .sdist import SdistBuilder wheel_file_template = """\ @@ -92,39 +93,38 @@ def build(self): def _build(self, wheel): if self._package.build: - setup = self._path / "setup.py" - - # We need to place ourselves in the temporary - # directory in order to build the package - current_path = os.getcwd() - try: - os.chdir(str(self._path)) - self._run_build_command(setup) - finally: - os.chdir(current_path) - - build_dir = self._path / "build" - lib = list(build_dir.glob("lib.*")) - if not lib: - # The result of building the extensions - # does not exist, this may due to conditional - # builds, so we assume that it's okay - return - - lib = lib[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(" - Adding: {}".format(rel_path)) - - self._add_file(wheel, pkg, rel_path) + with SdistBuilder(poetry=self._poetry).setup_py() as setup: + # We need to place ourselves in the temporary + # directory in order to build the package + current_path = os.getcwd() + try: + os.chdir(str(self._path)) + self._run_build_command(setup) + finally: + os.chdir(current_path) + + build_dir = self._path / "build" + lib = list(build_dir.glob("lib.*")) + if not lib: + # The result of building the extensions + # does not exist, this may due to conditional + # builds, so we assume that it's okay + return + + lib = lib[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(" - Adding: {}".format(rel_path)) + + self._add_file(wheel, pkg, rel_path) def _run_build_command(self, setup): subprocess.check_call( diff --git a/tests/masonry/test_api.py b/tests/masonry/test_api.py index a9c6796db..c95203ad3 100644 --- a/tests/masonry/test_api.py +++ b/tests/masonry/test_api.py @@ -2,11 +2,15 @@ from __future__ import unicode_literals import os +import platform +import sys import tarfile import zipfile from contextlib import contextmanager +import pytest + from poetry.core import __version__ from poetry.core.masonry import api from poetry.core.utils._compat import Path @@ -51,6 +55,27 @@ def test_build_wheel(): assert "my_package-1.2.3.dist-info/METADATA" in namelist +@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_extended(): + with temporary_directory() as tmp_dir, cwd(os.path.join(fixtures, "extended")): + filename = api.build_wheel(tmp_dir) + + whl = Path(tmp_dir) / filename + assert whl.exists() + + with zipfile.ZipFile(str(os.path.join(tmp_dir, filename))) as zip: + namelist = zip.namelist() + + assert "extended-0.1.dist-info/RECORD" in namelist + assert "extended-0.1.dist-info/WHEEL" in namelist + assert "extended-0.1.dist-info/METADATA" in namelist + + def test_build_sdist(): with temporary_directory() as tmp_dir, cwd(os.path.join(fixtures, "complete")): filename = api.build_sdist(tmp_dir) From a3a83cd689fb57cb701e7854747bb138702c84c2 Mon Sep 17 00:00:00 2001 From: Arun Babu Neelicattu Date: Thu, 9 Apr 2020 18:00:25 +0200 Subject: [PATCH 3/4] Remove tests from sdist Adding tests causes ci issues with the current preview release of poetry. For the interim, removing this until core release is stabilised. Related-to: python-poetry/poetry#2283 --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 5706550f4..7e2517ba6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,6 @@ classifiers = [ packages = [ {include = "poetry"}, - {include = "tests", format = "sdist"}, ] [tool.poetry.dependencies] From ad97e254cddcfee83d146569730190da388d764a Mon Sep 17 00:00:00 2001 From: Arun Babu Neelicattu Date: Thu, 9 Apr 2020 18:09:19 +0200 Subject: [PATCH 4/4] Update cache-id to fix github actions issue --- .github/workflows/tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3d8c82147..0bff2d25b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -43,7 +43,7 @@ jobs: uses: actions/cache@v1 with: path: .venv - key: venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} + key: venv-${{ runner.os }}-py${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} - name: Install dependencies run: | source $HOME/.poetry/env @@ -81,7 +81,7 @@ jobs: uses: actions/cache@v1 with: path: .venv - key: venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} + key: venv-${{ runner.os }}-py${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} - name: Install dependencies run: | source $HOME/.poetry/env @@ -118,7 +118,7 @@ jobs: uses: actions/cache@v1 with: path: .venv - key: venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} + key: venv-${{ runner.os }}-py${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} - name: Install dependencies run: | $env:Path += ";$env:Userprofile\.poetry\bin"