From f8c97b6d439f01500d0c06b5b8781fcaa2c44a9f Mon Sep 17 00:00:00 2001 From: BrandonLWhite Date: Thu, 3 Oct 2024 13:03:00 -0500 Subject: [PATCH 01/18] Initial POC for platform filter --- src/poetry_plugin_bundle/bundlers/venv_bundler.py | 12 ++++++++++++ .../console/commands/bundle/venv.py | 8 ++++++++ 2 files changed, 20 insertions(+) diff --git a/src/poetry_plugin_bundle/bundlers/venv_bundler.py b/src/poetry_plugin_bundle/bundlers/venv_bundler.py index e3672ef..e412c83 100644 --- a/src/poetry_plugin_bundle/bundlers/venv_bundler.py +++ b/src/poetry_plugin_bundle/bundlers/venv_bundler.py @@ -23,6 +23,7 @@ def __init__(self) -> None: self._remove: bool = False self._activated_groups: set[str] | None = None self._compile: bool = False + self._platform: str | None = None def set_path(self, path: Path) -> VenvBundler: self._path = path @@ -49,6 +50,11 @@ def set_compile(self, compile: bool = False) -> VenvBundler: return self + def set_platform(self, platform: str | None) -> VenvBundler: + self._platform = platform + + return self + def bundle(self, poetry: Poetry, io: IO) -> bool: from pathlib import Path from tempfile import TemporaryDirectory @@ -142,6 +148,12 @@ def locked_repository(self) -> LockfileRepository: custom_locker = CustomLocker(poetry.locker.lock, poetry.local_config) + + if self._platform: + platforms_to_keep = set(["any", self._platform]) + new_supported_tags = [tag for tag in env.supported_tags if tag.platform in platforms_to_keep] + env._supported_tags = new_supported_tags + installer = Installer( NullIO() if not io.is_debug() else io, env, diff --git a/src/poetry_plugin_bundle/console/commands/bundle/venv.py b/src/poetry_plugin_bundle/console/commands/bundle/venv.py index 15fb9a4..96b6dc6 100644 --- a/src/poetry_plugin_bundle/console/commands/bundle/venv.py +++ b/src/poetry_plugin_bundle/console/commands/bundle/venv.py @@ -45,6 +45,13 @@ class BundleVenvCommand(BundleCommand): " because the old installer always compiles.)", flag=True, ), + option( + "platform", + None, + "TODO BW DOCME", + flag=False, + value_required=True, + ), ] bundler_name = "venv" @@ -54,4 +61,5 @@ def configure_bundler(self, bundler: VenvBundler) -> None: # type: ignore[overr bundler.set_executable(self.option("python")) bundler.set_remove(self.option("clear")) bundler.set_compile(self.option("compile")) + bundler.set_platform(self.option("platform")) bundler.set_activated_groups(self.activated_groups) From 78843af626d6bc63c4ec8c2d146089005af86df6 Mon Sep 17 00:00:00 2001 From: BrandonLWhite Date: Thu, 3 Oct 2024 15:56:48 -0500 Subject: [PATCH 02/18] Extract Method --- .../bundlers/venv_bundler.py | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/poetry_plugin_bundle/bundlers/venv_bundler.py b/src/poetry_plugin_bundle/bundlers/venv_bundler.py index e412c83..fe9b986 100644 --- a/src/poetry_plugin_bundle/bundlers/venv_bundler.py +++ b/src/poetry_plugin_bundle/bundlers/venv_bundler.py @@ -12,6 +12,7 @@ from cleo.io.outputs.section_output import SectionOutput from poetry.poetry import Poetry from poetry.repositories.lockfile_repository import LockfileRepository + from poetry.utils.env import Env class VenvBundler(Bundler): @@ -137,6 +138,9 @@ def create_venv_at_path( self._path, executable=executable, force=True ) + if self._platform: + self.constrain_env_platform(env) + self._write(io, f"{message}: Installing dependencies") class CustomLocker(Locker): @@ -148,12 +152,6 @@ def locked_repository(self) -> LockfileRepository: custom_locker = CustomLocker(poetry.locker.lock, poetry.local_config) - - if self._platform: - platforms_to_keep = set(["any", self._platform]) - new_supported_tags = [tag for tag in env.supported_tags if tag.platform in platforms_to_keep] - env._supported_tags = new_supported_tags - installer = Installer( NullIO() if not io.is_debug() else io, env, @@ -240,3 +238,17 @@ def _write(self, io: IO | SectionOutput, message: str) -> None: return io.overwrite(message) + + def constrain_env_platform(self, env: Env) -> None: + """ + TODO BW DOCME + """ + from packaging.tags import Tag + + replacement_tags: dict[Tag, Tag] = {} + for tag in env.supported_tags: + replacement_tag = tag if tag.platform == "any" else Tag(tag.interpreter, tag.abi, self._platform) + if replacement_tag not in replacement_tags: + replacement_tags[replacement_tag] = replacement_tag + + env._supported_tags = list(replacement_tags.values()) From 3f7114f6d4395632f66c3aed30b6eb6ab4db8105 Mon Sep 17 00:00:00 2001 From: BrandonLWhite Date: Wed, 9 Oct 2024 09:49:51 -0500 Subject: [PATCH 03/18] Add test coverage and rework supported Tag construction --- .../bundlers/venv_bundler.py | 95 +++++++++++- tests/bundlers/test_venv_bundler.py | 47 ++++++ .../project_with_binary_wheel/README.md | 0 .../project_with_binary_wheel/poetry.lock | 145 ++++++++++++++++++ .../project_with_binary_wheel/__init__.py | 0 .../project_with_binary_wheel/pyproject.toml | 15 ++ .../tests/__init__.py | 0 7 files changed, 294 insertions(+), 8 deletions(-) create mode 100644 tests/fixtures/project_with_binary_wheel/README.md create mode 100644 tests/fixtures/project_with_binary_wheel/poetry.lock create mode 100644 tests/fixtures/project_with_binary_wheel/project_with_binary_wheel/__init__.py create mode 100644 tests/fixtures/project_with_binary_wheel/pyproject.toml create mode 100644 tests/fixtures/project_with_binary_wheel/tests/__init__.py diff --git a/src/poetry_plugin_bundle/bundlers/venv_bundler.py b/src/poetry_plugin_bundle/bundlers/venv_bundler.py index fe9b986..1611aed 100644 --- a/src/poetry_plugin_bundle/bundlers/venv_bundler.py +++ b/src/poetry_plugin_bundle/bundlers/venv_bundler.py @@ -67,7 +67,6 @@ def bundle(self, poetry: Poetry, io: IO) -> bool: from poetry.installation.installer import Installer from poetry.installation.operations.install import Install from poetry.packages.locker import Locker - from poetry.utils.env import Env from poetry.utils.env import EnvManager from poetry.utils.env import InvalidCurrentPythonVersionError @@ -242,13 +241,93 @@ def _write(self, io: IO | SectionOutput, message: str) -> None: def constrain_env_platform(self, env: Env) -> None: """ TODO BW DOCME + This isn't quite achieving what I want. It is causing earlier but compatible platforms to be discarded. + I need to be able to somehow generate all of the earlier compatible platforms starting from the specified + platform. + The key is in .venv/lib/python3.11/site-packages/packaging/tags.py + It starts with sys_tags() + Is there a way I can query for compatibility? + + yield from _manylinux.platform_tags(archs) + + Idea: Use the poetry.lock file to build a list of all the tags and then filter down + based on the argument platform. Nah, that will break with the manylinux value wonkiness. + + See src/pip/_internal/utils/compatibility_tags.py + _custom_manylinux_platforms + _expand_allowed_platforms + + Wait, how does Poetry parse the wheel filenames to determine if it is compatible? + These involve ambiguous underscore values like "manylinux_2_28_x86_64" + Check out the poetry Wheel class. it might be helpful. """ - from packaging.tags import Tag - replacement_tags: dict[Tag, Tag] = {} - for tag in env.supported_tags: - replacement_tag = tag if tag.platform == "any" else Tag(tag.interpreter, tag.abi, self._platform) - if replacement_tag not in replacement_tags: - replacement_tags[replacement_tag] = replacement_tag + # TODO BW: Dynamically generate the interpreter and max python version. + env._supported_tags = create_supported_tags(platform=self._platform, interpreter="cp39", max_python_version=(3,9)) + +if TYPE_CHECKING: + from packaging.tags import Tag + + +def create_supported_tags(platform: str, interpreter: str, max_python_version: tuple[int]) -> list[Tag]: + """ + """ + from packaging.tags import cpython_tags, compatible_tags + + if platform.startswith("manylinux"): + supported_platforms = create_supported_manylinux_platforms(platform) + elif platform.startswith("musllinux"): + raise NotImplementedError(f"Platform {platform} not supported") + elif platform.startswith("macosx"): + raise NotImplementedError(f"Platform {platform} not supported") + else: + raise NotImplementedError(f"Platform {platform} not supported") + + tags = list(cpython_tags(python_version=max_python_version, platforms=supported_platforms)) + + tags.extend(compatible_tags(interpreter=interpreter, python_version=max_python_version, platforms=supported_platforms)) + + return tags + + +def create_supported_manylinux_platforms(platform: str) -> list[str]: + """ + https://peps.python.org/pep-0600/ + manylinux_${GLIBCMAJOR}_${GLIBCMINOR}_${ARCH} + + For now, only GLIBCMAJOR "2" is supported. It is unclear if there will be a need to support a future major + version like "3" and if specified, how generate the compatible 2.x version tags. + """ + import re + + # Implementation based on https://peps.python.org/pep-0600/#package-installers + + tag = normalize_legacy_manylinux_alias(platform) + match = re.match("manylinux_([0-9]+)_([0-9]+)_(.*)", tag) + if not match: + raise ValueError(f"Invalid manylinux tag: {tag}") + tag_major_str, tag_minor_str, tag_arch = match.groups() + tag_major_max = int(tag_major_str) + tag_minor_max = int(tag_minor_str) + + return [ + f"manylinux_{tag_major_max}_{tag_minor}_{tag_arch}" + for tag_minor in range(tag_minor_max, -1, -1) + ] + + +LEGACY_MANYLINUX_ALIASES = { + "manylinux1": "manylinux_2_5", + "manylinux2010": "manylinux_2_12", + "manylinux2014": "manylinux_2_17", +} + +def normalize_legacy_manylinux_alias(tag: str) -> str: + tag_os_index_end = tag.index("_") + tag_os = tag[:tag_os_index_end] + tag_arch_suffix = tag[tag_os_index_end:] + os_replacement = LEGACY_MANYLINUX_ALIASES.get(tag_os) + if not os_replacement: + return tag - env._supported_tags = list(replacement_tags.values()) + return os_replacement + tag_arch_suffix diff --git a/tests/bundlers/test_venv_bundler.py b/tests/bundlers/test_venv_bundler.py index 4cd2b27..b1de0e5 100644 --- a/tests/bundlers/test_venv_bundler.py +++ b/tests/bundlers/test_venv_bundler.py @@ -25,6 +25,7 @@ if TYPE_CHECKING: from poetry.config.config import Config + from poetry.core.packages.utils.link import Link from poetry.poetry import Poetry from pytest_mock import MockerFixture @@ -395,3 +396,49 @@ def test_bundler_should_build_a_venv_at_specified_path_if_centralized_venv_exist • Bundled simple-project (1.2.3) into {path} """ assert expected == io.fetch_output() + + +def test_bundler_platform_override( + io: BufferedIO, tmpdir: str, mocker: MockerFixture, config: Config +) -> None: + poetry = Factory().create_poetry( + Path(__file__).parent.parent / "fixtures" / "project_with_binary_wheel" + ) + poetry.set_config(config) + + # TODO BW: I need to patch poetry.installation.chooser.Chooser._get_links (package: Package) -> list[Link]: + mocker.patch("poetry.installation.executor.Executor._execute_uninstall") + mocker.patch("poetry.installation.executor.Executor._execute_update") + mock_download_link = mocker.patch("poetry.installation.executor.Executor._download_link") + mocker.patch("poetry.installation.wheel_installer.WheelInstaller.install") + + def get_installed_links() -> dict[str, str]: + return { + call[0][0].package.name: call[0][1].filename + for call in mock_download_link.call_args_list + } + + + bundler = VenvBundler() + bundler.set_path(Path(tmpdir)) + bundler.set_remove(True) + + bundler.set_platform("manylinux_2_28_x86_64") + bundler.bundle(poetry, io) + + installed_link_by_package = get_installed_links() + assert "manylinux_2_28_x86_64" in installed_link_by_package["cryptography"] + assert "manylinux_2_17_x86_64" in installed_link_by_package["cffi"] + assert "py3-none-any.whl" in installed_link_by_package["pycparser"] + + bundler.set_platform("manylinux2014_x86_64") + bundler.bundle(poetry, io) + installed_link_by_package = get_installed_links() + assert "manylinux2014_x86_64" in installed_link_by_package["cryptography"] + assert "manylinux_2_17_x86_64" in installed_link_by_package["cffi"] + assert "py3-none-any.whl" in installed_link_by_package["pycparser"] + + # bundler.set_platform("macosx_10_9") + # bundler.bundle(poetry, io) + # installed_link_by_package = get_installed_links() + # assert "macosx_10_9_x86_64" in installed_link_by_package["cryptography"] diff --git a/tests/fixtures/project_with_binary_wheel/README.md b/tests/fixtures/project_with_binary_wheel/README.md new file mode 100644 index 0000000..e69de29 diff --git a/tests/fixtures/project_with_binary_wheel/poetry.lock b/tests/fixtures/project_with_binary_wheel/poetry.lock new file mode 100644 index 0000000..dc3e369 --- /dev/null +++ b/tests/fixtures/project_with_binary_wheel/poetry.lock @@ -0,0 +1,145 @@ +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. + +[[package]] +name = "cffi" +version = "1.17.1" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, + {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, + {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, + {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, + {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, + {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, + {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, + {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, + {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, + {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, + {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, + {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, + {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, + {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, + {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, +] + +[package.dependencies] +pycparser = "*" + +[[package]] +name = "cryptography" +version = "43.0.1" +description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +optional = false +python-versions = ">=3.7" +files = [ + {file = "cryptography-43.0.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:8385d98f6a3bf8bb2d65a73e17ed87a3ba84f6991c155691c51112075f9ffc5d"}, + {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27e613d7077ac613e399270253259d9d53872aaf657471473ebfc9a52935c062"}, + {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68aaecc4178e90719e95298515979814bda0cbada1256a4485414860bd7ab962"}, + {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:de41fd81a41e53267cb020bb3a7212861da53a7d39f863585d13ea11049cf277"}, + {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f98bf604c82c416bc829e490c700ca1553eafdf2912a91e23a79d97d9801372a"}, + {file = "cryptography-43.0.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:61ec41068b7b74268fa86e3e9e12b9f0c21fcf65434571dbb13d954bceb08042"}, + {file = "cryptography-43.0.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:014f58110f53237ace6a408b5beb6c427b64e084eb451ef25a28308270086494"}, + {file = "cryptography-43.0.1-cp37-abi3-win32.whl", hash = "sha256:2bd51274dcd59f09dd952afb696bf9c61a7a49dfc764c04dd33ef7a6b502a1e2"}, + {file = "cryptography-43.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:666ae11966643886c2987b3b721899d250855718d6d9ce41b521252a17985f4d"}, + {file = "cryptography-43.0.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:ac119bb76b9faa00f48128b7f5679e1d8d437365c5d26f1c2c3f0da4ce1b553d"}, + {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bbcce1a551e262dfbafb6e6252f1ae36a248e615ca44ba302df077a846a8806"}, + {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58d4e9129985185a06d849aa6df265bdd5a74ca6e1b736a77959b498e0505b85"}, + {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d03a475165f3134f773d1388aeb19c2d25ba88b6a9733c5c590b9ff7bbfa2e0c"}, + {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:511f4273808ab590912a93ddb4e3914dfd8a388fed883361b02dea3791f292e1"}, + {file = "cryptography-43.0.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:80eda8b3e173f0f247f711eef62be51b599b5d425c429b5d4ca6a05e9e856baa"}, + {file = "cryptography-43.0.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:38926c50cff6f533f8a2dae3d7f19541432610d114a70808f0926d5aaa7121e4"}, + {file = "cryptography-43.0.1-cp39-abi3-win32.whl", hash = "sha256:a575913fb06e05e6b4b814d7f7468c2c660e8bb16d8d5a1faf9b33ccc569dd47"}, + {file = "cryptography-43.0.1-cp39-abi3-win_amd64.whl", hash = "sha256:d75601ad10b059ec832e78823b348bfa1a59f6b8d545db3a24fd44362a1564cb"}, + {file = "cryptography-43.0.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ea25acb556320250756e53f9e20a4177515f012c9eaea17eb7587a8c4d8ae034"}, + {file = "cryptography-43.0.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c1332724be35d23a854994ff0b66530119500b6053d0bd3363265f7e5e77288d"}, + {file = "cryptography-43.0.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fba1007b3ef89946dbbb515aeeb41e30203b004f0b4b00e5e16078b518563289"}, + {file = "cryptography-43.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5b43d1ea6b378b54a1dc99dd8a2b5be47658fe9a7ce0a58ff0b55f4b43ef2b84"}, + {file = "cryptography-43.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:88cce104c36870d70c49c7c8fd22885875d950d9ee6ab54df2745f83ba0dc365"}, + {file = "cryptography-43.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:9d3cdb25fa98afdd3d0892d132b8d7139e2c087da1712041f6b762e4f807cc96"}, + {file = "cryptography-43.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e710bf40870f4db63c3d7d929aa9e09e4e7ee219e703f949ec4073b4294f6172"}, + {file = "cryptography-43.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7c05650fe8023c5ed0d46793d4b7d7e6cd9c04e68eabe5b0aeea836e37bdcec2"}, + {file = "cryptography-43.0.1.tar.gz", hash = "sha256:203e92a75716d8cfb491dc47c79e17d0d9207ccffcbcb35f598fbe463ae3444d"}, +] + +[package.dependencies] +cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} + +[package.extras] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] +docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"] +nox = ["nox"] +pep8test = ["check-sdist", "click", "mypy", "ruff"] +sdist = ["build"] +ssh = ["bcrypt (>=3.1.5)"] +test = ["certifi", "cryptography-vectors (==43.0.1)", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test-randomorder = ["pytest-randomly"] + +[[package]] +name = "pycparser" +version = "2.22" +description = "C parser in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.8" +content-hash = "19d494cbff48b9b5b1224dd0e296ad5bbe66bba8708606aa0339fc60033f5b2d" diff --git a/tests/fixtures/project_with_binary_wheel/project_with_binary_wheel/__init__.py b/tests/fixtures/project_with_binary_wheel/project_with_binary_wheel/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/fixtures/project_with_binary_wheel/pyproject.toml b/tests/fixtures/project_with_binary_wheel/pyproject.toml new file mode 100644 index 0000000..4776aaa --- /dev/null +++ b/tests/fixtures/project_with_binary_wheel/pyproject.toml @@ -0,0 +1,15 @@ +[tool.poetry] +name = "project-with-binary-wheel" +version = "0.1.0" +description = "" +authors = ["BrandonLWhite "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.8" +cryptography = "^43.0.1" + + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/tests/fixtures/project_with_binary_wheel/tests/__init__.py b/tests/fixtures/project_with_binary_wheel/tests/__init__.py new file mode 100644 index 0000000..e69de29 From cc2aaaf7fca72ee0b1d4a041da8628b149857065 Mon Sep 17 00:00:00 2001 From: BrandonLWhite Date: Wed, 9 Oct 2024 11:50:43 -0500 Subject: [PATCH 04/18] Add macosx support --- .../bundlers/venv_bundler.py | 15 ++++++++++++++- tests/bundlers/test_venv_bundler.py | 18 +++++++++++++----- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/poetry_plugin_bundle/bundlers/venv_bundler.py b/src/poetry_plugin_bundle/bundlers/venv_bundler.py index 1611aed..a5845d5 100644 --- a/src/poetry_plugin_bundle/bundlers/venv_bundler.py +++ b/src/poetry_plugin_bundle/bundlers/venv_bundler.py @@ -279,7 +279,7 @@ def create_supported_tags(platform: str, interpreter: str, max_python_version: t elif platform.startswith("musllinux"): raise NotImplementedError(f"Platform {platform} not supported") elif platform.startswith("macosx"): - raise NotImplementedError(f"Platform {platform} not supported") + supported_platforms = create_supported_macosx_platforms(platform) else: raise NotImplementedError(f"Platform {platform} not supported") @@ -331,3 +331,16 @@ def normalize_legacy_manylinux_alias(tag: str) -> str: return tag return os_replacement + tag_arch_suffix + + +def create_supported_macosx_platforms(platform: str) -> list[str]: + import re + from packaging.tags import mac_platforms + match = re.match("macosx_([0-9]+)_([0-9]+)_(.*)", platform) + if not match: + raise ValueError(f"Invalid macosx tag: {platform}") + tag_major_str, tag_minor_str, tag_arch = match.groups() + tag_major_max = int(tag_major_str) + tag_minor_max = int(tag_minor_str) + + return list(mac_platforms(version=(tag_major_max,tag_minor_max), arch=tag_arch)) \ No newline at end of file diff --git a/tests/bundlers/test_venv_bundler.py b/tests/bundlers/test_venv_bundler.py index b1de0e5..0d272a0 100644 --- a/tests/bundlers/test_venv_bundler.py +++ b/tests/bundlers/test_venv_bundler.py @@ -418,7 +418,6 @@ def get_installed_links() -> dict[str, str]: for call in mock_download_link.call_args_list } - bundler = VenvBundler() bundler.set_path(Path(tmpdir)) bundler.set_remove(True) @@ -438,7 +437,16 @@ def get_installed_links() -> dict[str, str]: assert "manylinux_2_17_x86_64" in installed_link_by_package["cffi"] assert "py3-none-any.whl" in installed_link_by_package["pycparser"] - # bundler.set_platform("macosx_10_9") - # bundler.bundle(poetry, io) - # installed_link_by_package = get_installed_links() - # assert "macosx_10_9_x86_64" in installed_link_by_package["cryptography"] + bundler.set_platform("macosx_10_9_x86_64") + bundler.bundle(poetry, io) + installed_link_by_package = get_installed_links() + assert "macosx_10_9_universal2" in installed_link_by_package["cryptography"] + assert "macosx_10_9_x86_64" in installed_link_by_package["cffi"] + assert "py3-none-any.whl" in installed_link_by_package["pycparser"] + + bundler.set_platform("macosx_11_0_arm64") + bundler.bundle(poetry, io) + installed_link_by_package = get_installed_links() + assert "macosx_10_9_universal2" in installed_link_by_package["cryptography"] + assert "macosx_11_0_arm64" in installed_link_by_package["cffi"] + assert "py3-none-any.whl" in installed_link_by_package["pycparser"] From 712693ad1929f10e8f1f659946b6fcad8ee3ce09 Mon Sep 17 00:00:00 2001 From: BrandonLWhite Date: Wed, 9 Oct 2024 12:09:48 -0500 Subject: [PATCH 05/18] Add musllinux support --- .../bundlers/venv_bundler.py | 19 +++++++++++++++++-- tests/bundlers/test_venv_bundler.py | 17 +++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/poetry_plugin_bundle/bundlers/venv_bundler.py b/src/poetry_plugin_bundle/bundlers/venv_bundler.py index a5845d5..03d62aa 100644 --- a/src/poetry_plugin_bundle/bundlers/venv_bundler.py +++ b/src/poetry_plugin_bundle/bundlers/venv_bundler.py @@ -277,7 +277,7 @@ def create_supported_tags(platform: str, interpreter: str, max_python_version: t if platform.startswith("manylinux"): supported_platforms = create_supported_manylinux_platforms(platform) elif platform.startswith("musllinux"): - raise NotImplementedError(f"Platform {platform} not supported") + supported_platforms = create_supported_musllinux_platforms(platform) elif platform.startswith("macosx"): supported_platforms = create_supported_macosx_platforms(platform) else: @@ -343,4 +343,19 @@ def create_supported_macosx_platforms(platform: str) -> list[str]: tag_major_max = int(tag_major_str) tag_minor_max = int(tag_minor_str) - return list(mac_platforms(version=(tag_major_max,tag_minor_max), arch=tag_arch)) \ No newline at end of file + return list(mac_platforms(version=(tag_major_max,tag_minor_max), arch=tag_arch)) + + +def create_supported_musllinux_platforms(platform: str) -> list[str]: + import re + match = re.match("musllinux_([0-9]+)_([0-9]+)_(.*)", platform) + if not match: + raise ValueError(f"Invalid musllinux tag: {platform}") + tag_major_str, tag_minor_str, tag_arch = match.groups() + tag_major_max = int(tag_major_str) + tag_minor_max = int(tag_minor_str) + + return [ + f"musllinux_{tag_major_max}_{minor}_{tag_arch}" + for minor in range(tag_minor_max, -1, -1) + ] \ No newline at end of file diff --git a/tests/bundlers/test_venv_bundler.py b/tests/bundlers/test_venv_bundler.py index 0d272a0..68dd914 100644 --- a/tests/bundlers/test_venv_bundler.py +++ b/tests/bundlers/test_venv_bundler.py @@ -11,6 +11,7 @@ from cleo.formatters.style import Style from cleo.io.buffered_io import BufferedIO from poetry.core.packages.package import Package +from poetry.core.packages.utils.link import Link from poetry.factory import Factory from poetry.installation.operations.install import Install from poetry.puzzle.exceptions import SolverProblemError @@ -25,7 +26,6 @@ if TYPE_CHECKING: from poetry.config.config import Config - from poetry.core.packages.utils.link import Link from poetry.poetry import Poetry from pytest_mock import MockerFixture @@ -406,7 +406,13 @@ def test_bundler_platform_override( ) poetry.set_config(config) - # TODO BW: I need to patch poetry.installation.chooser.Chooser._get_links (package: Package) -> list[Link]: + def get_links_fake(package: Package) -> list[Link]: + return [ + Link(f"https://example.com/{file['file']}") + for file in package.files + ] + + mocker.patch("poetry.installation.chooser.Chooser._get_links", side_effect=get_links_fake) mocker.patch("poetry.installation.executor.Executor._execute_uninstall") mocker.patch("poetry.installation.executor.Executor._execute_update") mock_download_link = mocker.patch("poetry.installation.executor.Executor._download_link") @@ -450,3 +456,10 @@ def get_installed_links() -> dict[str, str]: assert "macosx_10_9_universal2" in installed_link_by_package["cryptography"] assert "macosx_11_0_arm64" in installed_link_by_package["cffi"] assert "py3-none-any.whl" in installed_link_by_package["pycparser"] + + bundler.set_platform("musllinux_1_2_aarch64") + bundler.bundle(poetry, io) + installed_link_by_package = get_installed_links() + assert "musllinux_1_2_aarch64" in installed_link_by_package["cryptography"] + assert "musllinux_1_1_aarch64" in installed_link_by_package["cffi"] + assert "py3-none-any.whl" in installed_link_by_package["pycparser"] \ No newline at end of file From ef1dd36e3d26ee9524ccc67310b3aa185c44bfb7 Mon Sep 17 00:00:00 2001 From: BrandonLWhite Date: Thu, 24 Oct 2024 12:26:06 -0500 Subject: [PATCH 06/18] Generate supported tags --- .../bundlers/utils/__init__.py | 0 .../bundlers/utils/platforms.py | 130 ++++++++++++++++++ .../bundlers/venv_bundler.py | 119 +--------------- 3 files changed, 133 insertions(+), 116 deletions(-) create mode 100644 src/poetry_plugin_bundle/bundlers/utils/__init__.py create mode 100644 src/poetry_plugin_bundle/bundlers/utils/platforms.py diff --git a/src/poetry_plugin_bundle/bundlers/utils/__init__.py b/src/poetry_plugin_bundle/bundlers/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/poetry_plugin_bundle/bundlers/utils/platforms.py b/src/poetry_plugin_bundle/bundlers/utils/platforms.py new file mode 100644 index 0000000..0b3c615 --- /dev/null +++ b/src/poetry_plugin_bundle/bundlers/utils/platforms.py @@ -0,0 +1,130 @@ +from __future__ import annotations +from dataclasses import dataclass +from typing import TYPE_CHECKING + + +if TYPE_CHECKING: + from packaging.tags import Tag + from poetry.utils.env import Env + + +@dataclass +class PlatformTagParseResult: + platform: str + version_major: int + version_minor: int + arch: str + + @staticmethod + def parse(tag: str) -> PlatformTagParseResult: + import re + match = re.match("([a-z]+)_([0-9]+)_([0-9]+)_(.*)", tag) + if not match: + raise ValueError(f"Invalid platform tag: {tag}") + platform, version_major_str, version_minor_str, arch = match.groups() + return PlatformTagParseResult( + platform=platform, + version_major=int(version_major_str), + version_minor=int(version_minor_str), + arch=arch + ) + + def to_tag(self) -> str: + return "_".join([self.platform, self.version_major, self.version_minor, self.arch]) + + +def create_supported_tags(platform: str, env: Env) -> list[Tag]: + """ + """ + from packaging.tags import cpython_tags, compatible_tags, generic_tags, INTERPRETER_SHORT_NAMES + + if platform.startswith("manylinux"): + supported_platforms = create_supported_manylinux_platforms(platform) + elif platform.startswith("musllinux"): + supported_platforms = create_supported_musllinux_platforms(platform) + elif platform.startswith("macosx"): + supported_platforms = create_supported_macosx_platforms(platform) + else: + raise NotImplementedError(f"Platform {platform} not supported") + + python_implementation = env.python_implementation.lower() + python_version=env.version_info[:2] + interpreter_name = INTERPRETER_SHORT_NAMES.get(python_implementation, python_implementation) + interpreter = None + + if interpreter_name == "cp": + tags = list(cpython_tags(python_version=python_version, platforms=supported_platforms)) + interpreter = f"{interpreter_name}{python_version[0]}{python_version[1]}" + else: + tags = list(generic_tags(interpreter=interpreter, abis = [], platforms=supported_platforms)) + + tags.extend(compatible_tags(interpreter=interpreter, python_version=python_version, platforms=supported_platforms)) + + return tags + + +def create_supported_manylinux_platforms(platform: str) -> list[str]: + """ + https://peps.python.org/pep-0600/ + manylinux_${GLIBCMAJOR}_${GLIBCMINOR}_${ARCH} + + For now, only GLIBCMAJOR "2" is supported. It is unclear if there will be a need to support a future major + version like "3" and if specified, how generate the compatible 2.x version tags. + """ + import re + + # Implementation based on https://peps.python.org/pep-0600/#package-installers + + tag = normalize_legacy_manylinux_alias(platform) + + parsed = PlatformTagParseResult.parse(tag) + return [ + f"{parsed.platform}_{parsed.version_major}_{tag_minor}_{parsed.arch}" + for tag_minor in range(parsed.version_minor, -1, -1) + ] + + +LEGACY_MANYLINUX_ALIASES = { + "manylinux1": "manylinux_2_5", + "manylinux2010": "manylinux_2_12", + "manylinux2014": "manylinux_2_17", +} + + +def normalize_legacy_manylinux_alias(tag: str) -> str: + tag_os_index_end = tag.index("_") + tag_os = tag[:tag_os_index_end] + tag_arch_suffix = tag[tag_os_index_end:] + os_replacement = LEGACY_MANYLINUX_ALIASES.get(tag_os) + if not os_replacement: + return tag + + return os_replacement + tag_arch_suffix + + +def create_supported_macosx_platforms(platform: str) -> list[str]: + import re + from packaging.tags import mac_platforms + match = re.match("macosx_([0-9]+)_([0-9]+)_(.*)", platform) + if not match: + raise ValueError(f"Invalid macosx tag: {platform}") + tag_major_str, tag_minor_str, tag_arch = match.groups() + tag_major_max = int(tag_major_str) + tag_minor_max = int(tag_minor_str) + + return list(mac_platforms(version=(tag_major_max,tag_minor_max), arch=tag_arch)) + + +def create_supported_musllinux_platforms(platform: str) -> list[str]: + import re + match = re.match("musllinux_([0-9]+)_([0-9]+)_(.*)", platform) + if not match: + raise ValueError(f"Invalid musllinux tag: {platform}") + tag_major_str, tag_minor_str, tag_arch = match.groups() + tag_major_max = int(tag_major_str) + tag_minor_max = int(tag_minor_str) + + return [ + f"musllinux_{tag_major_max}_{minor}_{tag_arch}" + for minor in range(tag_minor_max, -1, -1) + ] \ No newline at end of file diff --git a/src/poetry_plugin_bundle/bundlers/venv_bundler.py b/src/poetry_plugin_bundle/bundlers/venv_bundler.py index 03d62aa..d34c1fe 100644 --- a/src/poetry_plugin_bundle/bundlers/venv_bundler.py +++ b/src/poetry_plugin_bundle/bundlers/venv_bundler.py @@ -241,121 +241,8 @@ def _write(self, io: IO | SectionOutput, message: str) -> None: def constrain_env_platform(self, env: Env) -> None: """ TODO BW DOCME - This isn't quite achieving what I want. It is causing earlier but compatible platforms to be discarded. - I need to be able to somehow generate all of the earlier compatible platforms starting from the specified - platform. - The key is in .venv/lib/python3.11/site-packages/packaging/tags.py - It starts with sys_tags() - Is there a way I can query for compatibility? - - yield from _manylinux.platform_tags(archs) - - Idea: Use the poetry.lock file to build a list of all the tags and then filter down - based on the argument platform. Nah, that will break with the manylinux value wonkiness. - - See src/pip/_internal/utils/compatibility_tags.py - _custom_manylinux_platforms - _expand_allowed_platforms - - Wait, how does Poetry parse the wheel filenames to determine if it is compatible? - These involve ambiguous underscore values like "manylinux_2_28_x86_64" - Check out the poetry Wheel class. it might be helpful. """ - + from .utils.platforms import create_supported_tags # TODO BW: Dynamically generate the interpreter and max python version. - env._supported_tags = create_supported_tags(platform=self._platform, interpreter="cp39", max_python_version=(3,9)) - -if TYPE_CHECKING: - from packaging.tags import Tag - - -def create_supported_tags(platform: str, interpreter: str, max_python_version: tuple[int]) -> list[Tag]: - """ - """ - from packaging.tags import cpython_tags, compatible_tags - - if platform.startswith("manylinux"): - supported_platforms = create_supported_manylinux_platforms(platform) - elif platform.startswith("musllinux"): - supported_platforms = create_supported_musllinux_platforms(platform) - elif platform.startswith("macosx"): - supported_platforms = create_supported_macosx_platforms(platform) - else: - raise NotImplementedError(f"Platform {platform} not supported") - - tags = list(cpython_tags(python_version=max_python_version, platforms=supported_platforms)) - - tags.extend(compatible_tags(interpreter=interpreter, python_version=max_python_version, platforms=supported_platforms)) - - return tags - - -def create_supported_manylinux_platforms(platform: str) -> list[str]: - """ - https://peps.python.org/pep-0600/ - manylinux_${GLIBCMAJOR}_${GLIBCMINOR}_${ARCH} - - For now, only GLIBCMAJOR "2" is supported. It is unclear if there will be a need to support a future major - version like "3" and if specified, how generate the compatible 2.x version tags. - """ - import re - - # Implementation based on https://peps.python.org/pep-0600/#package-installers - - tag = normalize_legacy_manylinux_alias(platform) - match = re.match("manylinux_([0-9]+)_([0-9]+)_(.*)", tag) - if not match: - raise ValueError(f"Invalid manylinux tag: {tag}") - tag_major_str, tag_minor_str, tag_arch = match.groups() - tag_major_max = int(tag_major_str) - tag_minor_max = int(tag_minor_str) - - return [ - f"manylinux_{tag_major_max}_{tag_minor}_{tag_arch}" - for tag_minor in range(tag_minor_max, -1, -1) - ] - - -LEGACY_MANYLINUX_ALIASES = { - "manylinux1": "manylinux_2_5", - "manylinux2010": "manylinux_2_12", - "manylinux2014": "manylinux_2_17", -} - -def normalize_legacy_manylinux_alias(tag: str) -> str: - tag_os_index_end = tag.index("_") - tag_os = tag[:tag_os_index_end] - tag_arch_suffix = tag[tag_os_index_end:] - os_replacement = LEGACY_MANYLINUX_ALIASES.get(tag_os) - if not os_replacement: - return tag - - return os_replacement + tag_arch_suffix - - -def create_supported_macosx_platforms(platform: str) -> list[str]: - import re - from packaging.tags import mac_platforms - match = re.match("macosx_([0-9]+)_([0-9]+)_(.*)", platform) - if not match: - raise ValueError(f"Invalid macosx tag: {platform}") - tag_major_str, tag_minor_str, tag_arch = match.groups() - tag_major_max = int(tag_major_str) - tag_minor_max = int(tag_minor_str) - - return list(mac_platforms(version=(tag_major_max,tag_minor_max), arch=tag_arch)) - - -def create_supported_musllinux_platforms(platform: str) -> list[str]: - import re - match = re.match("musllinux_([0-9]+)_([0-9]+)_(.*)", platform) - if not match: - raise ValueError(f"Invalid musllinux tag: {platform}") - tag_major_str, tag_minor_str, tag_arch = match.groups() - tag_major_max = int(tag_major_str) - tag_minor_max = int(tag_minor_str) - - return [ - f"musllinux_{tag_major_max}_{minor}_{tag_arch}" - for minor in range(tag_minor_max, -1, -1) - ] \ No newline at end of file + # TODO BW: Mutate the env object from within create_supported_tags (introduce a new function named override_supported_tags) + env._supported_tags = create_supported_tags(self._platform, env) From 9af4f1541dfa37baa550a78f18ecdd44d33faf77 Mon Sep 17 00:00:00 2001 From: BrandonLWhite Date: Thu, 24 Oct 2024 15:51:43 -0500 Subject: [PATCH 07/18] Doc comments --- src/poetry_plugin_bundle/bundlers/venv_bundler.py | 4 +--- src/poetry_plugin_bundle/console/commands/bundle/venv.py | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/poetry_plugin_bundle/bundlers/venv_bundler.py b/src/poetry_plugin_bundle/bundlers/venv_bundler.py index d34c1fe..b6be86a 100644 --- a/src/poetry_plugin_bundle/bundlers/venv_bundler.py +++ b/src/poetry_plugin_bundle/bundlers/venv_bundler.py @@ -240,9 +240,7 @@ def _write(self, io: IO | SectionOutput, message: str) -> None: def constrain_env_platform(self, env: Env) -> None: """ - TODO BW DOCME + Set the argument environment's supported tags based on the configured platform override. """ from .utils.platforms import create_supported_tags - # TODO BW: Dynamically generate the interpreter and max python version. - # TODO BW: Mutate the env object from within create_supported_tags (introduce a new function named override_supported_tags) env._supported_tags = create_supported_tags(self._platform, env) diff --git a/src/poetry_plugin_bundle/console/commands/bundle/venv.py b/src/poetry_plugin_bundle/console/commands/bundle/venv.py index 96b6dc6..5e031e7 100644 --- a/src/poetry_plugin_bundle/console/commands/bundle/venv.py +++ b/src/poetry_plugin_bundle/console/commands/bundle/venv.py @@ -48,7 +48,7 @@ class BundleVenvCommand(BundleCommand): option( "platform", None, - "TODO BW DOCME", + "Only use wheels compatible with the specified platform. Defaults to the platform of the running system.", flag=False, value_required=True, ), From 1c1f1554cb562eb931c51bbf77f059ae016e4fb7 Mon Sep 17 00:00:00 2001 From: BrandonLWhite Date: Fri, 25 Oct 2024 08:54:23 -0500 Subject: [PATCH 08/18] Lint --- .../bundlers/venv_bundler.py | 3 +- .../console/commands/bundle/venv.py | 3 +- .../{bundlers => }/utils/__init__.py | 0 .../{bundlers => }/utils/platforms.py | 51 ++++++++++++++----- tests/bundlers/test_venv_bundler.py | 15 +++--- 5 files changed, 51 insertions(+), 21 deletions(-) rename src/poetry_plugin_bundle/{bundlers => }/utils/__init__.py (100%) rename src/poetry_plugin_bundle/{bundlers => }/utils/platforms.py (73%) diff --git a/src/poetry_plugin_bundle/bundlers/venv_bundler.py b/src/poetry_plugin_bundle/bundlers/venv_bundler.py index b6be86a..2a512ff 100644 --- a/src/poetry_plugin_bundle/bundlers/venv_bundler.py +++ b/src/poetry_plugin_bundle/bundlers/venv_bundler.py @@ -242,5 +242,6 @@ def constrain_env_platform(self, env: Env) -> None: """ Set the argument environment's supported tags based on the configured platform override. """ - from .utils.platforms import create_supported_tags + from poetry_plugin_bundle.utils.platforms import create_supported_tags + env._supported_tags = create_supported_tags(self._platform, env) diff --git a/src/poetry_plugin_bundle/console/commands/bundle/venv.py b/src/poetry_plugin_bundle/console/commands/bundle/venv.py index 5e031e7..390c327 100644 --- a/src/poetry_plugin_bundle/console/commands/bundle/venv.py +++ b/src/poetry_plugin_bundle/console/commands/bundle/venv.py @@ -48,7 +48,8 @@ class BundleVenvCommand(BundleCommand): option( "platform", None, - "Only use wheels compatible with the specified platform. Defaults to the platform of the running system.", + "Only use wheels compatible with the specified platform. Otherwise the default behavior uses the platform " + " of the running system.", flag=False, value_required=True, ), diff --git a/src/poetry_plugin_bundle/bundlers/utils/__init__.py b/src/poetry_plugin_bundle/utils/__init__.py similarity index 100% rename from src/poetry_plugin_bundle/bundlers/utils/__init__.py rename to src/poetry_plugin_bundle/utils/__init__.py diff --git a/src/poetry_plugin_bundle/bundlers/utils/platforms.py b/src/poetry_plugin_bundle/utils/platforms.py similarity index 73% rename from src/poetry_plugin_bundle/bundlers/utils/platforms.py rename to src/poetry_plugin_bundle/utils/platforms.py index 0b3c615..0800ec6 100644 --- a/src/poetry_plugin_bundle/bundlers/utils/platforms.py +++ b/src/poetry_plugin_bundle/utils/platforms.py @@ -1,4 +1,5 @@ from __future__ import annotations + from dataclasses import dataclass from typing import TYPE_CHECKING @@ -18,6 +19,7 @@ class PlatformTagParseResult: @staticmethod def parse(tag: str) -> PlatformTagParseResult: import re + match = re.match("([a-z]+)_([0-9]+)_([0-9]+)_(.*)", tag) if not match: raise ValueError(f"Invalid platform tag: {tag}") @@ -26,17 +28,27 @@ def parse(tag: str) -> PlatformTagParseResult: platform=platform, version_major=int(version_major_str), version_minor=int(version_minor_str), - arch=arch + arch=arch, ) def to_tag(self) -> str: - return "_".join([self.platform, self.version_major, self.version_minor, self.arch]) + return "_".join( + [self.platform, self.version_major, self.version_minor, self.arch] + ) def create_supported_tags(platform: str, env: Env) -> list[Tag]: """ + Given a platform specifier string, generate a list of compatible tags for the argument environment's interpreter. + + Refer to: + https://packaging.python.org/en/latest/specifications/platform-compatibility-tags/#platform-tag + https://pip.pypa.io/en/stable/cli/pip_install/#cmdoption-platform """ - from packaging.tags import cpython_tags, compatible_tags, generic_tags, INTERPRETER_SHORT_NAMES + from packaging.tags import INTERPRETER_SHORT_NAMES + from packaging.tags import compatible_tags + from packaging.tags import cpython_tags + from packaging.tags import generic_tags if platform.startswith("manylinux"): supported_platforms = create_supported_manylinux_platforms(platform) @@ -48,17 +60,31 @@ def create_supported_tags(platform: str, env: Env) -> list[Tag]: raise NotImplementedError(f"Platform {platform} not supported") python_implementation = env.python_implementation.lower() - python_version=env.version_info[:2] - interpreter_name = INTERPRETER_SHORT_NAMES.get(python_implementation, python_implementation) + python_version = env.version_info[:2] + interpreter_name = INTERPRETER_SHORT_NAMES.get( + python_implementation, python_implementation + ) interpreter = None if interpreter_name == "cp": - tags = list(cpython_tags(python_version=python_version, platforms=supported_platforms)) + tags = list( + cpython_tags(python_version=python_version, platforms=supported_platforms) + ) interpreter = f"{interpreter_name}{python_version[0]}{python_version[1]}" else: - tags = list(generic_tags(interpreter=interpreter, abis = [], platforms=supported_platforms)) + tags = list( + generic_tags( + interpreter=interpreter, abis=[], platforms=supported_platforms + ) + ) - tags.extend(compatible_tags(interpreter=interpreter, python_version=python_version, platforms=supported_platforms)) + tags.extend( + compatible_tags( + interpreter=interpreter, + python_version=python_version, + platforms=supported_platforms, + ) + ) return tags @@ -71,8 +97,6 @@ def create_supported_manylinux_platforms(platform: str) -> list[str]: For now, only GLIBCMAJOR "2" is supported. It is unclear if there will be a need to support a future major version like "3" and if specified, how generate the compatible 2.x version tags. """ - import re - # Implementation based on https://peps.python.org/pep-0600/#package-installers tag = normalize_legacy_manylinux_alias(platform) @@ -104,7 +128,9 @@ def normalize_legacy_manylinux_alias(tag: str) -> str: def create_supported_macosx_platforms(platform: str) -> list[str]: import re + from packaging.tags import mac_platforms + match = re.match("macosx_([0-9]+)_([0-9]+)_(.*)", platform) if not match: raise ValueError(f"Invalid macosx tag: {platform}") @@ -112,11 +138,12 @@ def create_supported_macosx_platforms(platform: str) -> list[str]: tag_major_max = int(tag_major_str) tag_minor_max = int(tag_minor_str) - return list(mac_platforms(version=(tag_major_max,tag_minor_max), arch=tag_arch)) + return list(mac_platforms(version=(tag_major_max, tag_minor_max), arch=tag_arch)) def create_supported_musllinux_platforms(platform: str) -> list[str]: import re + match = re.match("musllinux_([0-9]+)_([0-9]+)_(.*)", platform) if not match: raise ValueError(f"Invalid musllinux tag: {platform}") @@ -127,4 +154,4 @@ def create_supported_musllinux_platforms(platform: str) -> list[str]: return [ f"musllinux_{tag_major_max}_{minor}_{tag_arch}" for minor in range(tag_minor_max, -1, -1) - ] \ No newline at end of file + ] diff --git a/tests/bundlers/test_venv_bundler.py b/tests/bundlers/test_venv_bundler.py index 68dd914..0c77a18 100644 --- a/tests/bundlers/test_venv_bundler.py +++ b/tests/bundlers/test_venv_bundler.py @@ -407,15 +407,16 @@ def test_bundler_platform_override( poetry.set_config(config) def get_links_fake(package: Package) -> list[Link]: - return [ - Link(f"https://example.com/{file['file']}") - for file in package.files - ] + return [Link(f"https://example.com/{file['file']}") for file in package.files] - mocker.patch("poetry.installation.chooser.Chooser._get_links", side_effect=get_links_fake) + mocker.patch( + "poetry.installation.chooser.Chooser._get_links", side_effect=get_links_fake + ) mocker.patch("poetry.installation.executor.Executor._execute_uninstall") mocker.patch("poetry.installation.executor.Executor._execute_update") - mock_download_link = mocker.patch("poetry.installation.executor.Executor._download_link") + mock_download_link = mocker.patch( + "poetry.installation.executor.Executor._download_link" + ) mocker.patch("poetry.installation.wheel_installer.WheelInstaller.install") def get_installed_links() -> dict[str, str]: @@ -462,4 +463,4 @@ def get_installed_links() -> dict[str, str]: installed_link_by_package = get_installed_links() assert "musllinux_1_2_aarch64" in installed_link_by_package["cryptography"] assert "musllinux_1_1_aarch64" in installed_link_by_package["cffi"] - assert "py3-none-any.whl" in installed_link_by_package["pycparser"] \ No newline at end of file + assert "py3-none-any.whl" in installed_link_by_package["pycparser"] From e02e63d527cb445be6253e8acb5e511033cd82cf Mon Sep 17 00:00:00 2001 From: BrandonLWhite Date: Fri, 25 Oct 2024 09:10:56 -0500 Subject: [PATCH 09/18] Mypy --- src/poetry_plugin_bundle/bundlers/venv_bundler.py | 6 +++--- src/poetry_plugin_bundle/utils/platforms.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/poetry_plugin_bundle/bundlers/venv_bundler.py b/src/poetry_plugin_bundle/bundlers/venv_bundler.py index 2a512ff..761eaa9 100644 --- a/src/poetry_plugin_bundle/bundlers/venv_bundler.py +++ b/src/poetry_plugin_bundle/bundlers/venv_bundler.py @@ -138,7 +138,7 @@ def create_venv_at_path( ) if self._platform: - self.constrain_env_platform(env) + self.constrain_env_platform(env, self._platform) self._write(io, f"{message}: Installing dependencies") @@ -238,10 +238,10 @@ def _write(self, io: IO | SectionOutput, message: str) -> None: io.overwrite(message) - def constrain_env_platform(self, env: Env) -> None: + def constrain_env_platform(self, env: Env, platform: str) -> None: """ Set the argument environment's supported tags based on the configured platform override. """ from poetry_plugin_bundle.utils.platforms import create_supported_tags - env._supported_tags = create_supported_tags(self._platform, env) + env._supported_tags = create_supported_tags(platform, env) diff --git a/src/poetry_plugin_bundle/utils/platforms.py b/src/poetry_plugin_bundle/utils/platforms.py index 0800ec6..e40b696 100644 --- a/src/poetry_plugin_bundle/utils/platforms.py +++ b/src/poetry_plugin_bundle/utils/platforms.py @@ -33,7 +33,7 @@ def parse(tag: str) -> PlatformTagParseResult: def to_tag(self) -> str: return "_".join( - [self.platform, self.version_major, self.version_minor, self.arch] + [self.platform, str(self.version_major), str(self.version_minor), self.arch] ) From e422b99f78f248d8eb9e7f8446f7d68ef88ecf6b Mon Sep 17 00:00:00 2001 From: BrandonLWhite Date: Fri, 25 Oct 2024 09:46:07 -0500 Subject: [PATCH 10/18] Fix failing tests in py38 --- tests/bundlers/test_venv_bundler.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/bundlers/test_venv_bundler.py b/tests/bundlers/test_venv_bundler.py index 0c77a18..ad09a3a 100644 --- a/tests/bundlers/test_venv_bundler.py +++ b/tests/bundlers/test_venv_bundler.py @@ -431,7 +431,6 @@ def get_installed_links() -> dict[str, str]: bundler.set_platform("manylinux_2_28_x86_64") bundler.bundle(poetry, io) - installed_link_by_package = get_installed_links() assert "manylinux_2_28_x86_64" in installed_link_by_package["cryptography"] assert "manylinux_2_17_x86_64" in installed_link_by_package["cffi"] @@ -455,12 +454,14 @@ def get_installed_links() -> dict[str, str]: bundler.bundle(poetry, io) installed_link_by_package = get_installed_links() assert "macosx_10_9_universal2" in installed_link_by_package["cryptography"] - assert "macosx_11_0_arm64" in installed_link_by_package["cffi"] + expected_cffi_platform = "macosx_11_0_arm64" if sys.version_info >= (3, 9) else "cffi-1.17.1.tar.gz" + assert expected_cffi_platform in installed_link_by_package["cffi"] assert "py3-none-any.whl" in installed_link_by_package["pycparser"] bundler.set_platform("musllinux_1_2_aarch64") bundler.bundle(poetry, io) installed_link_by_package = get_installed_links() assert "musllinux_1_2_aarch64" in installed_link_by_package["cryptography"] - assert "musllinux_1_1_aarch64" in installed_link_by_package["cffi"] + expected_cffi_platform = "musllinux_1_1_aarch64" if sys.version_info >= (3, 9) else "cffi-1.17.1.tar.gz" + assert expected_cffi_platform in installed_link_by_package["cffi"] assert "py3-none-any.whl" in installed_link_by_package["pycparser"] From 5e0c35998955fd9fcf6fcaa9cc615b7d75475b0d Mon Sep 17 00:00:00 2001 From: BrandonLWhite Date: Fri, 25 Oct 2024 11:23:22 -0500 Subject: [PATCH 11/18] Lint --- tests/bundlers/test_venv_bundler.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/bundlers/test_venv_bundler.py b/tests/bundlers/test_venv_bundler.py index ad09a3a..e232d2c 100644 --- a/tests/bundlers/test_venv_bundler.py +++ b/tests/bundlers/test_venv_bundler.py @@ -454,7 +454,9 @@ def get_installed_links() -> dict[str, str]: bundler.bundle(poetry, io) installed_link_by_package = get_installed_links() assert "macosx_10_9_universal2" in installed_link_by_package["cryptography"] - expected_cffi_platform = "macosx_11_0_arm64" if sys.version_info >= (3, 9) else "cffi-1.17.1.tar.gz" + expected_cffi_platform = ( + "macosx_11_0_arm64" if sys.version_info >= (3, 9) else "cffi-1.17.1.tar.gz" + ) assert expected_cffi_platform in installed_link_by_package["cffi"] assert "py3-none-any.whl" in installed_link_by_package["pycparser"] @@ -462,6 +464,8 @@ def get_installed_links() -> dict[str, str]: bundler.bundle(poetry, io) installed_link_by_package = get_installed_links() assert "musllinux_1_2_aarch64" in installed_link_by_package["cryptography"] - expected_cffi_platform = "musllinux_1_1_aarch64" if sys.version_info >= (3, 9) else "cffi-1.17.1.tar.gz" + expected_cffi_platform = ( + "musllinux_1_1_aarch64" if sys.version_info >= (3, 9) else "cffi-1.17.1.tar.gz" + ) assert expected_cffi_platform in installed_link_by_package["cffi"] assert "py3-none-any.whl" in installed_link_by_package["pycparser"] From 89dc4c37b346842f72bca8ccbc6e6dfe98da4797 Mon Sep 17 00:00:00 2001 From: BrandonLWhite Date: Mon, 6 Jan 2025 17:13:33 -0600 Subject: [PATCH 12/18] Fix merge issue --- tests/bundlers/test_venv_bundler.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/tests/bundlers/test_venv_bundler.py b/tests/bundlers/test_venv_bundler.py index 9f00ef8..3b1ce44 100644 --- a/tests/bundlers/test_venv_bundler.py +++ b/tests/bundlers/test_venv_bundler.py @@ -406,10 +406,24 @@ def test_bundler_non_package_mode( ) poetry.set_config(config) -) -> None: - poetry = Factory().create_poetry( - ) - poetry.set_config(config) + mocker.patch("poetry.installation.executor.Executor._execute_operation") + + bundler = VenvBundler() + bundler.set_path(tmp_venv.path) + bundler.set_remove(True) + + assert bundler.bundle(poetry, io) + + path = str(tmp_venv.path) + expected = f"""\ + • Bundling simple-project-non-package-mode (1.2.3) into {path} + • Bundling simple-project-non-package-mode (1.2.3) into {path}: Creating a virtual environment using Poetry-determined Python + • Bundling simple-project-non-package-mode (1.2.3) into {path}: Installing dependencies + • Bundling simple-project-non-package-mode (1.2.3) into {path}: Skipping installation for non package project simple-project-non-package-mode + • Bundled simple-project-non-package-mode (1.2.3) into {path} +""" + assert expected == io.fetch_output() + def test_bundler_platform_override( io: BufferedIO, tmpdir: str, mocker: MockerFixture, config: Config From 1aaf26c3b671c4aae00c5cbbe7cb87d2b6b0c208 Mon Sep 17 00:00:00 2001 From: BrandonLWhite Date: Mon, 6 Jan 2025 17:30:48 -0600 Subject: [PATCH 13/18] Fix failing test in py13 --- tests/bundlers/test_venv_bundler.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/bundlers/test_venv_bundler.py b/tests/bundlers/test_venv_bundler.py index 3b1ce44..d8570c1 100644 --- a/tests/bundlers/test_venv_bundler.py +++ b/tests/bundlers/test_venv_bundler.py @@ -474,7 +474,10 @@ def get_installed_links() -> dict[str, str]: bundler.bundle(poetry, io) installed_link_by_package = get_installed_links() assert "macosx_10_9_universal2" in installed_link_by_package["cryptography"] - assert "macosx_10_9_x86_64" in installed_link_by_package["cffi"] + expected_cffi_platform = ( + "macosx_10_9_x86_64" if sys.version_info < (3, 13) else "cffi-1.17.1.tar.gz" + ) + assert expected_cffi_platform in installed_link_by_package["cffi"] assert "py3-none-any.whl" in installed_link_by_package["pycparser"] bundler.set_platform("macosx_11_0_arm64") From 4a5e7e33abdd1269f2c09e72389c5e60c9ba6899 Mon Sep 17 00:00:00 2001 From: BrandonLWhite Date: Tue, 7 Jan 2025 10:09:24 -0600 Subject: [PATCH 14/18] Added tests for platforms.py --- tests/utils/__init__.py | 0 tests/utils/test_platforms.py | 74 +++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 tests/utils/__init__.py create mode 100644 tests/utils/test_platforms.py diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/utils/test_platforms.py b/tests/utils/test_platforms.py new file mode 100644 index 0000000..c9675fc --- /dev/null +++ b/tests/utils/test_platforms.py @@ -0,0 +1,74 @@ +from poetry.utils.env import MockEnv +import poetry_plugin_bundle.utils.platforms as platforms + + +def _get_supported_tags_set(platform: str, python_version_info: tuple[int, int, int]) -> set[str]: + env = MockEnv(version_info=python_version_info) + result = platforms.create_supported_tags(platform, env) + return { str(tag) for tag in result } + + +def _test_create_supported_tags(platform: str, python_version_info: tuple[int, int, int], expected_tags: set[str], unexpected_tags: set[str]): + result_set = _get_supported_tags_set(platform, python_version_info) + + assert result_set.issuperset(expected_tags) + assert not result_set.intersection(unexpected_tags) + + +def test_create_supported_tags_manylinux(): + _test_create_supported_tags( + platform="manylinux_2_12_x86_64", + python_version_info=(3, 12, 1), + expected_tags={ + "cp312-cp312-manylinux_2_12_x86_64", + "cp312-none-manylinux_2_12_x86_64", + "cp312-abi3-manylinux_2_12_x86_64", + "cp312-cp312-manylinux_2_1_x86_64", + "cp311-abi3-manylinux_2_12_x86_64", + "py312-none-manylinux_2_12_x86_64", + "py312-none-any", + "cp312-none-any", + }, + unexpected_tags={ + "cp313-cp313-manylinux_2_12_x86_64", + "cp312-cp312-manylinux_2_13_x86_64" + } + ) + + +def test_create_supported_tags_legacy_manylinux_aliases(): + _test_create_supported_tags( + platform="manylinux1_x86_64", + python_version_info=(3, 10, 2), + expected_tags={ + "cp310-cp310-manylinux_2_5_x86_64", + "cp310-cp310-manylinux_2_1_x86_64", + }, + unexpected_tags={ + "cp310-cp310-manylinux_2_6_x86_64", + } + ) + + _test_create_supported_tags( + platform="manylinux2010_x86_64", + python_version_info=(3, 10, 2), + expected_tags={ + "cp310-cp310-manylinux_2_12_x86_64", + "cp310-cp310-manylinux_2_1_x86_64", + }, + unexpected_tags={ + "cp310-cp310-manylinux_2_13_x86_64", + } + ) + + _test_create_supported_tags( + platform="manylinux2014_x86_64", + python_version_info=(3, 11, 9), + expected_tags={ + "cp311-cp311-manylinux_2_17_x86_64", + "cp311-cp311-manylinux_2_1_x86_64", + }, + unexpected_tags={ + "cp311-cp311-manylinux_2_24_x86_64", + } + ) \ No newline at end of file From 99427aa74c9327d2e91d8d2b30df4bf9c53831c1 Mon Sep 17 00:00:00 2001 From: BrandonLWhite Date: Thu, 9 Jan 2025 11:43:15 -0600 Subject: [PATCH 15/18] Add more platform.py tests --- tests/utils/test_platforms.py | 85 ++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/tests/utils/test_platforms.py b/tests/utils/test_platforms.py index c9675fc..ed72925 100644 --- a/tests/utils/test_platforms.py +++ b/tests/utils/test_platforms.py @@ -1,3 +1,5 @@ +import pytest + from poetry.utils.env import MockEnv import poetry_plugin_bundle.utils.platforms as platforms @@ -43,6 +45,9 @@ def test_create_supported_tags_legacy_manylinux_aliases(): expected_tags={ "cp310-cp310-manylinux_2_5_x86_64", "cp310-cp310-manylinux_2_1_x86_64", + "py312-none-manylinux_2_12_x86_64", + "py312-none-any", + "cp312-none-any", }, unexpected_tags={ "cp310-cp310-manylinux_2_6_x86_64", @@ -71,4 +76,82 @@ def test_create_supported_tags_legacy_manylinux_aliases(): unexpected_tags={ "cp311-cp311-manylinux_2_24_x86_64", } - ) \ No newline at end of file + ) + + +def test_create_supported_tags_macosx(): + _test_create_supported_tags( + platform="macosx_11_0_arm64", + python_version_info=(3, 11, 8), + expected_tags={ + "cp311-abi3-macosx_11_0_arm64", + "cp311-abi3-macosx_10_12_universal2", + "cp311-none-macosx_11_0_universal2", + 'py311-none-any', + }, + unexpected_tags={ + "cp311-none-macosx_11_1_universal2", + } + ) + + _test_create_supported_tags( + platform="macosx_10_9_x86_64", + python_version_info=(3, 11, 8), + expected_tags={ + "cp311-abi3-macosx_10_9_universal2", + "cp311-abi3-macosx_10_9_x86_64", + "cp311-abi3-macosx_10_9_intel", + "cp311-none-macosx_10_7_universal2", + 'py311-none-any', + }, + unexpected_tags={ + "cp311-none-macosx_11_1_universal2", + "cp311-abi3-macosx_11_0_arm64", + } + ) + + +def test_create_supported_tags_musllinux(): + _test_create_supported_tags( + platform="musllinux_1_1_x86_64", + python_version_info=(3, 13, 1), + expected_tags={ + "cp313-cp313-musllinux_1_1_x86_64", + "cp313-abi3-musllinux_1_1_x86_64", + "py312-none-any", + "cp313-none-any", + }, + unexpected_tags={ + "cp313-cp313-musllinux_1_2_x86_64", + } + ) + + +def test_create_supported_tags_unsupported_platform(): + env = MockEnv(version_info=(3, 12, 1)) + + unsupported_platforms = [ + "win32", + "linux", + "foobar", + ] + for platform in unsupported_platforms: + with pytest.raises(NotImplementedError): + platforms.create_supported_tags(platform, env) + + +def test_create_supported_tags_malformed_platforms(): + env = MockEnv(version_info=(3, 12, 1)) + + malformed_platforms = [ + "macosx_11_blah_arm64", + "macosx", + "manylinux_blammo_12_x86_64", + "manylinux_x86_64", + "manylinux", + "musllinux_?_1_x86_64", + "musllinux", + ] + for platform in malformed_platforms: + with pytest.raises(ValueError): + platforms.create_supported_tags(platform, env) From 423d37b1e5148f3a15453cbfd9838dfa185e5c0d Mon Sep 17 00:00:00 2001 From: BrandonLWhite Date: Thu, 9 Jan 2025 11:44:11 -0600 Subject: [PATCH 16/18] Lint --- tests/utils/test_platforms.py | 36 ++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/tests/utils/test_platforms.py b/tests/utils/test_platforms.py index ed72925..0c597fa 100644 --- a/tests/utils/test_platforms.py +++ b/tests/utils/test_platforms.py @@ -1,16 +1,26 @@ +from __future__ import annotations + import pytest from poetry.utils.env import MockEnv + import poetry_plugin_bundle.utils.platforms as platforms -def _get_supported_tags_set(platform: str, python_version_info: tuple[int, int, int]) -> set[str]: +def _get_supported_tags_set( + platform: str, python_version_info: tuple[int, int, int] +) -> set[str]: env = MockEnv(version_info=python_version_info) result = platforms.create_supported_tags(platform, env) - return { str(tag) for tag in result } + return {str(tag) for tag in result} -def _test_create_supported_tags(platform: str, python_version_info: tuple[int, int, int], expected_tags: set[str], unexpected_tags: set[str]): +def _test_create_supported_tags( + platform: str, + python_version_info: tuple[int, int, int], + expected_tags: set[str], + unexpected_tags: set[str], +): result_set = _get_supported_tags_set(platform, python_version_info) assert result_set.issuperset(expected_tags) @@ -33,8 +43,8 @@ def test_create_supported_tags_manylinux(): }, unexpected_tags={ "cp313-cp313-manylinux_2_12_x86_64", - "cp312-cp312-manylinux_2_13_x86_64" - } + "cp312-cp312-manylinux_2_13_x86_64", + }, ) @@ -51,7 +61,7 @@ def test_create_supported_tags_legacy_manylinux_aliases(): }, unexpected_tags={ "cp310-cp310-manylinux_2_6_x86_64", - } + }, ) _test_create_supported_tags( @@ -63,7 +73,7 @@ def test_create_supported_tags_legacy_manylinux_aliases(): }, unexpected_tags={ "cp310-cp310-manylinux_2_13_x86_64", - } + }, ) _test_create_supported_tags( @@ -75,7 +85,7 @@ def test_create_supported_tags_legacy_manylinux_aliases(): }, unexpected_tags={ "cp311-cp311-manylinux_2_24_x86_64", - } + }, ) @@ -87,11 +97,11 @@ def test_create_supported_tags_macosx(): "cp311-abi3-macosx_11_0_arm64", "cp311-abi3-macosx_10_12_universal2", "cp311-none-macosx_11_0_universal2", - 'py311-none-any', + "py311-none-any", }, unexpected_tags={ "cp311-none-macosx_11_1_universal2", - } + }, ) _test_create_supported_tags( @@ -102,12 +112,12 @@ def test_create_supported_tags_macosx(): "cp311-abi3-macosx_10_9_x86_64", "cp311-abi3-macosx_10_9_intel", "cp311-none-macosx_10_7_universal2", - 'py311-none-any', + "py311-none-any", }, unexpected_tags={ "cp311-none-macosx_11_1_universal2", "cp311-abi3-macosx_11_0_arm64", - } + }, ) @@ -123,7 +133,7 @@ def test_create_supported_tags_musllinux(): }, unexpected_tags={ "cp313-cp313-musllinux_1_2_x86_64", - } + }, ) From 4c6d9282871704eb1d0ee04a162ea101c6dd9e39 Mon Sep 17 00:00:00 2001 From: BrandonLWhite Date: Thu, 9 Jan 2025 11:54:01 -0600 Subject: [PATCH 17/18] Add None return types. --- tests/utils/test_platforms.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/utils/test_platforms.py b/tests/utils/test_platforms.py index 0c597fa..a2c1939 100644 --- a/tests/utils/test_platforms.py +++ b/tests/utils/test_platforms.py @@ -20,14 +20,14 @@ def _test_create_supported_tags( python_version_info: tuple[int, int, int], expected_tags: set[str], unexpected_tags: set[str], -): +) -> None: result_set = _get_supported_tags_set(platform, python_version_info) assert result_set.issuperset(expected_tags) assert not result_set.intersection(unexpected_tags) -def test_create_supported_tags_manylinux(): +def test_create_supported_tags_manylinux() -> None: _test_create_supported_tags( platform="manylinux_2_12_x86_64", python_version_info=(3, 12, 1), @@ -48,7 +48,7 @@ def test_create_supported_tags_manylinux(): ) -def test_create_supported_tags_legacy_manylinux_aliases(): +def test_create_supported_tags_legacy_manylinux_aliases() -> None: _test_create_supported_tags( platform="manylinux1_x86_64", python_version_info=(3, 10, 2), @@ -89,7 +89,7 @@ def test_create_supported_tags_legacy_manylinux_aliases(): ) -def test_create_supported_tags_macosx(): +def test_create_supported_tags_macosx() -> None: _test_create_supported_tags( platform="macosx_11_0_arm64", python_version_info=(3, 11, 8), @@ -121,7 +121,7 @@ def test_create_supported_tags_macosx(): ) -def test_create_supported_tags_musllinux(): +def test_create_supported_tags_musllinux() -> None: _test_create_supported_tags( platform="musllinux_1_1_x86_64", python_version_info=(3, 13, 1), @@ -137,7 +137,7 @@ def test_create_supported_tags_musllinux(): ) -def test_create_supported_tags_unsupported_platform(): +def test_create_supported_tags_unsupported_platform() -> None: env = MockEnv(version_info=(3, 12, 1)) unsupported_platforms = [ @@ -150,7 +150,7 @@ def test_create_supported_tags_unsupported_platform(): platforms.create_supported_tags(platform, env) -def test_create_supported_tags_malformed_platforms(): +def test_create_supported_tags_malformed_platforms() -> None: env = MockEnv(version_info=(3, 12, 1)) malformed_platforms = [ From 81b6b19e270c927e84635ab4ab2c3e3323b14b39 Mon Sep 17 00:00:00 2001 From: BrandonLWhite Date: Thu, 9 Jan 2025 13:03:15 -0600 Subject: [PATCH 18/18] Fix failing test --- tests/utils/test_platforms.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/utils/test_platforms.py b/tests/utils/test_platforms.py index a2c1939..2cb42b3 100644 --- a/tests/utils/test_platforms.py +++ b/tests/utils/test_platforms.py @@ -55,9 +55,6 @@ def test_create_supported_tags_legacy_manylinux_aliases() -> None: expected_tags={ "cp310-cp310-manylinux_2_5_x86_64", "cp310-cp310-manylinux_2_1_x86_64", - "py312-none-manylinux_2_12_x86_64", - "py312-none-any", - "cp312-none-any", }, unexpected_tags={ "cp310-cp310-manylinux_2_6_x86_64",