Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-dep-logic for openSUSE:Factory checked in at 2024-07-01 11:19:46 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-dep-logic (Old) and /work/SRC/openSUSE:Factory/.python-dep-logic.new.18349 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-dep-logic" Mon Jul 1 11:19:46 2024 rev:3 rq:1184006 version:0.3.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-dep-logic/python-dep-logic.changes 2024-03-07 18:32:37.868131310 +0100 +++ /work/SRC/openSUSE:Factory/.python-dep-logic.new.18349/python-dep-logic.changes 2024-07-01 11:20:07.274516012 +0200 @@ -1,0 +2,8 @@ +Sat Jun 29 16:04:51 UTC 2024 - Dirk Müller <dmuel...@suse.com> + +- update to 0.3.0: + * New module dep_logic.tags for compatibility check with wheel + tags + * Use the same marker environment for current platform + +------------------------------------------------------------------- Old: ---- dep_logic-0.2.0.tar.gz New: ---- dep_logic-0.3.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-dep-logic.spec ++++++ --- /var/tmp/diff_new_pack.MJAVcU/_old 2024-07-01 11:20:08.014542971 +0200 +++ /var/tmp/diff_new_pack.MJAVcU/_new 2024-07-01 11:20:08.014542971 +0200 @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-dep-logic -Version: 0.2.0 +Version: 0.3.0 Release: 0 Summary: Python dependency specifications supporting logical operations License: Apache-2.0 ++++++ dep_logic-0.2.0.tar.gz -> dep_logic-0.3.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dep_logic-0.2.0/PKG-INFO new/dep_logic-0.3.0/PKG-INFO --- old/dep_logic-0.2.0/PKG-INFO 1970-01-01 01:00:00.000000000 +0100 +++ new/dep_logic-0.3.0/PKG-INFO 1970-01-01 01:00:00.000000000 +0100 @@ -1,8 +1,8 @@ Metadata-Version: 2.1 Name: dep-logic -Version: 0.2.0 +Version: 0.3.0 Summary: Python dependency specifications supporting logical operations -Keywords: dependency specification logic packaging +Keywords: dependency,specification,logic,packaging Author-Email: Frost Ming <m...@frostming.com> License: Apache-2.0 Classifier: Intended Audience :: Developers @@ -74,6 +74,12 @@ Furthermore, `poetry-core` does not always comply with PEP-508. As a result, this project aims to offer a lightweight utility for dependency specification logic using [PyPA's packaging](https://github.com/pypa/packaging). +Submodules: + +- `dep_logic.specifiers` - PEP 440 version specifiers +- `dep_logic.markers` - PEP 508 environment markers +- `dep_logic.tags` - PEP 425 platform tags + ## Caveats Logic operations with `===<string>` specifiers is partially supported. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dep_logic-0.2.0/README.md new/dep_logic-0.3.0/README.md --- old/dep_logic-0.2.0/README.md 2024-02-23 06:00:55.137874400 +0100 +++ new/dep_logic-0.3.0/README.md 2024-06-28 11:09:19.946395600 +0200 @@ -55,6 +55,12 @@ Furthermore, `poetry-core` does not always comply with PEP-508. As a result, this project aims to offer a lightweight utility for dependency specification logic using [PyPA's packaging](https://github.com/pypa/packaging). +Submodules: + +- `dep_logic.specifiers` - PEP 440 version specifiers +- `dep_logic.markers` - PEP 508 environment markers +- `dep_logic.tags` - PEP 425 platform tags + ## Caveats Logic operations with `===<string>` specifiers is partially supported. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dep_logic-0.2.0/pyproject.toml new/dep_logic-0.3.0/pyproject.toml --- old/dep_logic-0.2.0/pyproject.toml 2024-02-23 06:01:06.997811300 +0100 +++ new/dep_logic-0.3.0/pyproject.toml 2024-06-28 11:09:32.842571500 +0200 @@ -26,7 +26,7 @@ "Programming Language :: Python :: 3.12", "License :: OSI Approved :: Apache Software License", ] -version = "0.2.0" +version = "0.3.0" [project.license] text = "Apache-2.0" @@ -39,6 +39,15 @@ [tool.ruff] line-length = 88 +src = [ + "src", +] +exclude = [ + "tests/fixtures", +] +target-version = "py310" + +[tool.ruff.lint] extend-select = [ "I", "B", @@ -53,18 +62,11 @@ "B019", "B905", ] -src = [ - "src", -] -exclude = [ - "tests/fixtures", -] -target-version = "py310" -[tool.ruff.mccabe] +[tool.ruff.lint.mccabe] max-complexity = 10 -[tool.ruff.isort] +[tool.ruff.lint.isort] known-first-party = [ "dep_logic", ] @@ -91,4 +93,4 @@ venvPath = "." venv = ".venv" pythonVersion = "3.11" -reportPrivateImportUsage = "information" +reportPrivateImportUsage = "none" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dep_logic-0.2.0/src/dep_logic/tags/__init__.py new/dep_logic-0.3.0/src/dep_logic/tags/__init__.py --- old/dep_logic-0.2.0/src/dep_logic/tags/__init__.py 1970-01-01 01:00:00.000000000 +0100 +++ new/dep_logic-0.3.0/src/dep_logic/tags/__init__.py 2024-06-28 11:09:19.946395600 +0200 @@ -0,0 +1,11 @@ +from .platform import Platform, PlatformError +from .tags import EnvSpec, InvalidWheelFilename, TagsError, UnsupportedImplementation + +__all__ = [ + "Platform", + "PlatformError", + "TagsError", + "UnsupportedImplementation", + "InvalidWheelFilename", + "EnvSpec", +] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dep_logic-0.2.0/src/dep_logic/tags/os.py new/dep_logic-0.3.0/src/dep_logic/tags/os.py --- old/dep_logic-0.2.0/src/dep_logic/tags/os.py 1970-01-01 01:00:00.000000000 +0100 +++ new/dep_logic-0.3.0/src/dep_logic/tags/os.py 2024-06-28 11:09:19.946395600 +0200 @@ -0,0 +1,60 @@ +from dataclasses import dataclass + + +class Os: + def __str__(self) -> str: + return self.__class__.__name__ + + +@dataclass(frozen=True) +class Manylinux(Os): + major: int + minor: int + + +@dataclass(frozen=True) +class Musllinux(Os): + major: int + minor: int + + +@dataclass(frozen=True) +class Windows(Os): + pass + + +@dataclass(frozen=True) +class Macos(Os): + major: int + minor: int + + +@dataclass(frozen=True) +class FreeBsd(Os): + release: str + + +@dataclass(frozen=True) +class NetBsd(Os): + release: str + + +@dataclass(frozen=True) +class OpenBsd(Os): + release: str + + +@dataclass(frozen=True) +class Dragonfly(Os): + release: str + + +@dataclass(frozen=True) +class Illumos(Os): + release: str + arch: str + + +@dataclass(frozen=True) +class Haiku(Os): + release: str diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dep_logic-0.2.0/src/dep_logic/tags/platform.py new/dep_logic-0.3.0/src/dep_logic/tags/platform.py --- old/dep_logic-0.2.0/src/dep_logic/tags/platform.py 1970-01-01 01:00:00.000000000 +0100 +++ new/dep_logic-0.3.0/src/dep_logic/tags/platform.py 2024-06-28 11:09:19.946395600 +0200 @@ -0,0 +1,322 @@ +# Abstractions for understanding the current platform (operating system and architecture). +from __future__ import annotations + +import sys +from dataclasses import dataclass +from enum import Enum +from functools import cached_property + +from . import os + + +class PlatformError(Exception): + pass + + +@dataclass(frozen=True) +class Platform: + os: os.Os + arch: Arch + + @classmethod + def parse(cls, platform: str) -> Platform: + """Parse a platform string (e.g., `linux_x86_64`, `macosx_10_9_x86_64`, or `win_amd64`) + + Available operating systems: + - `linux`: an alias for `manylinux_2_17_x86_64` + - `windows`: an alias for `win_x86_64` + - `macos`: an alias for `macos_12_0_arm64` + - `alpine`: an alias for `musllinux_1_2_x86_64` + - `windows_amd64`: an alias for `win_x86_64` + - `windows_x86` + - `macos_arm64`: an alias for `macos_12_0_arm64` + - `macos_x86_64`: an alias for `macos_12_0_x86_64` + - `macos_X_Y_arm64` + - `macos_X_Y_x86_64` + - `manylinux_X_Y_x86_64` + - `manylinux_X_Y_aarch64` + - `musllinux_X_Y_x86_64` + - `musllinux_X_Y_aarch64` + """ + if platform == "linux": + return cls(os.Manylinux(2, 17), Arch.X86_64) + elif platform == "windows": + return cls(os.Windows(), Arch.X86_64) + elif platform == "macos": + return cls(os.Macos(12, 0), Arch.Aarch64) + elif platform == "alpine": + return cls(os.Musllinux(1, 2), Arch.X86_64) + elif platform == "windows_amd64": + return cls(os.Windows(), Arch.X86_64) + elif platform == "windows_x86": + return cls(os.Windows(), Arch.X86) + elif platform == "macos_arm64": + return cls(os.Macos(12, 0), Arch.Aarch64) + elif platform == "macos_x86_64": + return cls(os.Macos(12, 0), Arch.X86_64) + elif platform.startswith("macos_"): + parts = platform.split("_") + major = int(parts[1]) + minor = int(parts[2]) + return cls(os.Macos(major, minor), Arch.parse(parts[3])) + elif platform.startswith("musllinux_"): + parts = platform.split("_") + major = int(parts[1]) + minor = int(parts[2]) + return cls(os.Musllinux(major, minor), Arch.parse(parts[3])) + elif platform.startswith("manylinux_"): + parts = platform.split("_") + major = int(parts[1]) + minor = int(parts[2]) + return cls(os.Manylinux(major, minor), Arch.parse(parts[3])) + else: + raise PlatformError( + f"Unsupported platform {platform}, expected one of {cls.choices()}" + ) + + @classmethod + def current(cls) -> Platform: + """Return the current platform.""" + import platform + + system = platform.system() + arch = Arch.parse(platform.machine()) + if system == "Linux": + libc_ver = platform.libc_ver()[1] + if libc_ver: + parts = libc_ver.split(".") + return cls(os.Manylinux(int(parts[0]), int(parts[1])), arch) + else: # musl + from packaging._musllinux import _get_musl_version + + musl_version = _get_musl_version(sys.executable) + if musl_version is None: + raise PlatformError( + "Failed to detect musl version or glibc version" + ) + return cls(os.Musllinux(musl_version.major, musl_version.minor), arch) + elif system == "Windows": + return cls(os.Windows(), arch) + elif system == "Darwin": + mac_ver = platform.mac_ver()[0].split(".") + return cls(os.Macos(int(mac_ver[0]), int(mac_ver[1])), arch) + else: + raise PlatformError("Unsupported platform") + + @classmethod + def choices(cls) -> list[str]: + return [ + "linux", + "windows", + "macos", + "alpine", + "windows_amd64", + "windows_x86", + "macos_arm64", + "macos_x86_64", + "macos_X_Y_arm64", + "macos_X_Y_x86_64", + "manylinux_X_Y_x86_64", + "manylinux_X_Y_aarch64", + "musllinux_X_Y_x86_64", + "musllinux_X_Y_aarch64", + ] + + @cached_property + def compatible_tags(self) -> list[str]: + """Returns the compatible tags for the current [`Platform`] (e.g., `manylinux_2_17`, + `macosx_11_0_arm64`, or `win_amd64`). + + We have two cases: Actual platform specific tags (including "merged" tags such as universal2) + and "any". + + Bit of a mess, needs to be cleaned up. + """ + os_ = self.os + arch = self.arch + platform_tags: list[str] = [] + if isinstance(os_, os.Manylinux): + if (min_minor := arch.get_minimum_manylinux_minor()) is not None: + for minor in range(os_.minor, min_minor - 1, -1): + platform_tags.append(f"manylinux_{os_.major}_{minor}_{arch}") + # Support legacy manylinux tags with lower priority + # <https://peps.python.org/pep-0600/#legacy-manylinux-tags> + if minor == 12: + platform_tags.append(f"manylinux2010_{arch}") + if minor == 17: + platform_tags.append(f"manylinux2014_{arch}") + if minor == 5: + platform_tags.append(f"manylinux1_{arch}") + # Non-manylinux is lowest priority + # <https://github.com/pypa/packaging/blob/fd4f11139d1c884a637be8aa26bb60a31fbc9411/packaging/tags.py#L444> + platform_tags.append(f"linux_{arch}") + elif isinstance(os_, os.Musllinux): + platform_tags.append(f"linux_{arch}") + for minor in range(1, os_.minor + 1): + # musl 1.1 is the lowest supported version in musllinux + platform_tags.append(f"musllinux_{os_.major}_{minor}_{arch}") + elif isinstance(os_, os.Macos) and arch == Arch.X86_64: + if os_.major == 10: + for minor in range(os_.minor, 3, -1): + for binary_format in arch.get_mac_binary_formats(): + platform_tags.append(f"macosx_10_{minor}_{binary_format}") + elif isinstance(os_.major, int) and os_.major >= 11: + # Starting with Mac OS 11, each yearly release bumps the major version number. + # The minor versions are now the midyear updates. + for major in range(os_.major, 10, -1): + for binary_format in arch.get_mac_binary_formats(): + platform_tags.append(f"macosx_{major}_0_{binary_format}") + # The "universal2" binary format can have a macOS version earlier than 11.0 + # when the x86_64 part of the binary supports that version of macOS. + for minor in range(16, 3, -1): + for binary_format in arch.get_mac_binary_formats(): + platform_tags.append(f"macosx_10_{minor}_{binary_format}") + else: + raise PlatformError(f"Unsupported macOS version {os_.major}") + elif isinstance(os_, os.Macos) and arch == Arch.Aarch64: + # Starting with Mac OS 11, each yearly release bumps the major version number. + # The minor versions are now the midyear updates. + for major in range(os_.major, 10, -1): + for binary_format in arch.get_mac_binary_formats(): + platform_tags.append(f"macosx_{major}_0_{binary_format}") + # The "universal2" binary format can have a macOS version earlier than 11.0 + # when the x86_64 part of the binary supports that version of macOS. + for minor in range(16, 3, -1): + platform_tags.append(f"macosx_10_{minor}_universal2") + elif isinstance(os_, os.Windows): + if arch == Arch.X86: + platform_tags.append("win32") + elif arch == Arch.X86_64: + platform_tags.append("win_amd64") + elif arch == Arch.Aarch64: + platform_tags.append("win_arm64") + else: + raise PlatformError(f"Unsupported Windows architecture {arch}") + elif isinstance( + os_, (os.FreeBsd, os.NetBsd, os.OpenBsd, os.Dragonfly, os.Haiku) + ): + release = os_.release.replace(".", "_").replace("-", "_") + platform_tags.append(f"{str(os_).lower()}_{release}_{arch}") + elif isinstance(os_, os.Illumos): + # See https://github.com/python/cpython/blob/46c8d915715aa2bd4d697482aa051fe974d440e1/Lib/sysconfig.py#L722-L730 + try: + major, other = os_.release.split("_", 1) + except ValueError: + platform_tags.append(f"{str(os_).lower()}_{os_.release}_{arch}") + else: + major_ver = int(major) + if major_ver >= 5: + # SunOS 5 == Solaris 2 + release = f"{major_ver - 3}_{other}" + arch = f"{arch}_64bit" + platform_tags.append(f"solaris_{release}_{arch}") + else: + raise PlatformError( + f"Unsupported operating system and architecture combination: {os_} {arch}" + ) + return platform_tags + + @cached_property + def os_name(self) -> str: + return "nt" if isinstance(self.os, os.Windows) else "posix" + + @cached_property + def sys_platform(self) -> str: + if isinstance(self.os, os.Windows): + return "win32" + elif isinstance(self.os, (os.Macos, os.Illumos)): + return "darwin" + else: + return "linux" + + @cached_property + def platform_machine(self) -> str: + if isinstance(self.os, (os.Windows, os.Macos)) and self.arch == Arch.Aarch64: + return "arm64" + if isinstance(self.os, os.Windows) and self.arch == Arch.X86_64: + return "AMD64" + return str(self.arch) + + @cached_property + def platform_release(self) -> str: + return "" + + @cached_property + def platform_version(self) -> str: + return "" + + @cached_property + def platform_system(self) -> str: + if isinstance(self.os, os.Macos): + return "Darwin" + if isinstance(self.os, os.Windows): + return "Windows" + return "Linux" + + def is_current(self) -> bool: + current = self.current() + return isinstance(self.os, type(current.os)) and self.arch == current.arch + + def markers(self) -> dict[str, str]: + if self.is_current(): + return {} + return { + "os_name": self.os_name, + "platform_machine": self.platform_machine, + "platform_release": self.platform_release, + "platform_system": self.platform_system, + "platform_version": self.platform_version, + "sys_platform": self.sys_platform, + } + + +class Arch(Enum): + Aarch64 = "aarch64" + Armv6L = "armv6l" + Armv7L = "armv7l" + Powerpc64Le = "ppc64le" + Powerpc64 = "ppc64" + X86 = "x86" + X86_64 = "x86_64" + S390X = "s390x" + + def __str__(self) -> str: + return self.value + + def get_minimum_manylinux_minor(self) -> int | None: + if self in [ + Arch.Aarch64, + Arch.Armv7L, + Arch.Powerpc64, + Arch.Powerpc64Le, + Arch.S390X, + ]: + return 17 + elif self in [Arch.X86, Arch.X86_64]: + return 5 + else: + return None + + def get_mac_binary_formats(self) -> list[str]: + formats = [self.value] + + if self == Arch.X86_64: + formats.extend(["intel", "fat64", "fat32"]) + + if self in [Arch.X86_64, Arch.Aarch64]: + formats.append("universal2") + + if self == Arch.X86_64: + formats.append("universal") + + return formats + + @classmethod + def parse(cls, arch: str) -> Arch: + if arch in ("i386", "i686"): + return cls.X86 + if arch == "amd64": + return cls.X86_64 + if arch == "arm64": + return cls.Aarch64 + return cls(arch) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dep_logic-0.2.0/src/dep_logic/tags/tags.py new/dep_logic-0.3.0/src/dep_logic/tags/tags.py --- old/dep_logic-0.2.0/src/dep_logic/tags/tags.py 1970-01-01 01:00:00.000000000 +0100 +++ new/dep_logic-0.3.0/src/dep_logic/tags/tags.py 2024-06-28 11:09:19.946395600 +0200 @@ -0,0 +1,187 @@ +from __future__ import annotations + +from dataclasses import dataclass +from platform import python_implementation, python_version +from typing import TYPE_CHECKING + +from ..specifiers import InvalidSpecifier, VersionSpecifier, parse_version_specifier +from .platform import Platform + +if TYPE_CHECKING: + from typing import Literal + + +def parse_wheel_tags(filename: str) -> tuple[list[str], list[str], list[str]]: + if not filename.endswith(".whl"): + raise InvalidWheelFilename( + f"Invalid wheel filename (extension must be '.whl'): {filename}" + ) + + filename = filename[:-4] + dashes = filename.count("-") + if dashes not in (4, 5): + raise InvalidWheelFilename( + f"Invalid wheel filename (wrong number of parts): {filename}" + ) + + parts = filename.split("-") + python, abi, platform = parts[-3:] + return python.split("."), abi.split("."), platform.split(".") + + +def _ensure_version_specifier(spec: str) -> VersionSpecifier: + parsed = parse_version_specifier(spec) + if not isinstance(parsed, VersionSpecifier): + raise InvalidSpecifier(f"Invalid version specifier {spec}") + return parsed + + +class TagsError(Exception): + pass + + +class InvalidWheelFilename(TagsError, ValueError): + pass + + +class UnsupportedImplementation(TagsError, ValueError): + pass + + +@dataclass(frozen=True) +class Implementation: + name: Literal["cpython", "pypy", "pyston"] + gil_disabled: bool = False + + @property + def short(self) -> str: + if self.name == "cpython": + return "cp" + elif self.name == "pypy": + return "pp" + else: + return "pt" + + @classmethod + def current(cls) -> Implementation: + import sysconfig + + implementation = python_implementation() + + return cls.parse( + implementation.lower(), sysconfig.get_config_var("Py_GIL_DISABLED") or False + ) + + @classmethod + def parse(cls, name: str, gil_disabled: bool = False) -> Implementation: + if gil_disabled and name != "cpython": + raise UnsupportedImplementation("Only CPython supports GIL disabled mode") + if name in ("cpython", "pypy", "pyston"): + return Implementation(name, gil_disabled) + else: + raise UnsupportedImplementation( + f"Unsupported implementation: {name}, expected cpython, pypy, or pyston" + ) + + +@dataclass(frozen=True) +class EnvSpec: + requires_python: VersionSpecifier + platform: Platform + implementation: Implementation + + @classmethod + def from_spec( + cls, + requires_python: str, + platform: str, + implementation: str, + gil_disabled: bool = False, + ) -> EnvSpec: + return cls( + _ensure_version_specifier(requires_python), + Platform.parse(platform), + Implementation.parse(implementation, gil_disabled=gil_disabled), + ) + + @classmethod + def current(cls) -> EnvSpec: + requires_python = _ensure_version_specifier(f"=={python_version()}") + platform = Platform.current() + implementation = Implementation.current() + return cls(requires_python, platform, implementation) + + def _evaluate_python( + self, python_tag: str, abi_tag: str + ) -> tuple[int, int, int] | None: + impl, major, minor = python_tag[:2], python_tag[2], python_tag[3:] + if impl not in [self.implementation.short, "py"]: + return None + abi_impl = ( + abi_tag.split("_", 1)[0] + .replace("pypy", "pp") + .replace("pyston", "pt") + .lower() + ) + if impl == "cp" and abi_impl == "abi3": + if ( + parse_version_specifier(f">={major}.{minor or 0}") + & self.requires_python + ).is_empty(): + return None + return (int(major), int(minor or 0), 1) # 1 for abi3 + # cp36-cp36m-* + # cp312-cp312m-* + # pp310-pypy310_pp75-* + if abi_impl != "none" and not abi_impl.startswith(python_tag.lower()): + return None + if major and minor: + wheel_range = parse_version_specifier(f"=={major}.{minor}.*") + else: + wheel_range = parse_version_specifier(f"=={major}.*") + if (wheel_range & self.requires_python).is_empty(): + return None + return (int(major), int(minor or 0), 0 if abi_impl == "none" else 2) + + def _evaluate_platform(self, platform_tag: str) -> int | None: + platform_tags = [*self.platform.compatible_tags, "any"] + if platform_tag not in platform_tags: + return None + return len(platform_tags) - platform_tags.index(platform_tag) + + def compatibility( + self, + wheel_python_tags: list[str], + wheel_abi_tags: list[str], + wheel_platform_tags: list[str], + ) -> tuple[int, int, int, int] | None: + python_abi_combinations = ( + (python_tag, abi_tag) + for python_tag in wheel_python_tags + for abi_tag in wheel_abi_tags + ) + python_compat = max( + filter( + None, (self._evaluate_python(*comb) for comb in python_abi_combinations) + ), + default=None, + ) + if python_compat is None: + return None + platform_compat = max( + filter(None, map(self._evaluate_platform, wheel_platform_tags)), + default=None, + ) + if platform_compat is None: + return None + return (*python_compat, platform_compat) + + def wheel_compatibility( + self, wheel_filename: str + ) -> tuple[int, int, int, int] | None: + wheel_python_tags, wheel_abi_tags, wheel_platform_tags = parse_wheel_tags( + wheel_filename + ) + return self.compatibility( + wheel_python_tags, wheel_abi_tags, wheel_platform_tags + ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dep_logic-0.2.0/src/dep_logic/utils.py new/dep_logic-0.3.0/src/dep_logic/utils.py --- old/dep_logic-0.2.0/src/dep_logic/utils.py 2024-02-23 06:00:55.137874400 +0100 +++ new/dep_logic-0.3.0/src/dep_logic/utils.py 2024-06-28 11:09:19.946395600 +0200 @@ -25,11 +25,9 @@ class Ident(Protocol): - def __hash__(self) -> int: - ... + def __hash__(self) -> int: ... - def __eq__(self, __value: object) -> bool: - ... + def __eq__(self, __value: object) -> bool: ... T = TypeVar("T", bound=Ident) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dep_logic-0.2.0/tests/specifier/test_arbitrary.py new/dep_logic-0.3.0/tests/specifier/test_arbitrary.py --- old/dep_logic-0.2.0/tests/specifier/test_arbitrary.py 2024-02-23 06:00:55.137874400 +0100 +++ new/dep_logic-0.3.0/tests/specifier/test_arbitrary.py 2024-06-28 11:09:19.946395600 +0200 @@ -42,6 +42,6 @@ def test_arbitrary_unsupported(a: str, b: str, operand: str) -> None: with pytest.raises(ValueError): if operand == "and": - parse_version_specifier(a) & parse_version_specifier(b) + _ = parse_version_specifier(a) & parse_version_specifier(b) else: - parse_version_specifier(a) | parse_version_specifier(b) + _ = parse_version_specifier(a) | parse_version_specifier(b) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dep_logic-0.2.0/tests/tags/test_platform.py new/dep_logic-0.3.0/tests/tags/test_platform.py --- old/dep_logic-0.2.0/tests/tags/test_platform.py 1970-01-01 01:00:00.000000000 +0100 +++ new/dep_logic-0.3.0/tests/tags/test_platform.py 2024-06-28 11:09:19.946395600 +0200 @@ -0,0 +1,334 @@ +import pytest + +from dep_logic.tags import os +from dep_logic.tags.platform import Arch, Platform + + +def test_platform_tags_manylinux(): + tags = Platform(os.Manylinux(2, 20), Arch.X86_64).compatible_tags + assert tags == [ + "manylinux_2_20_x86_64", + "manylinux_2_19_x86_64", + "manylinux_2_18_x86_64", + "manylinux_2_17_x86_64", + "manylinux2014_x86_64", + "manylinux_2_16_x86_64", + "manylinux_2_15_x86_64", + "manylinux_2_14_x86_64", + "manylinux_2_13_x86_64", + "manylinux_2_12_x86_64", + "manylinux2010_x86_64", + "manylinux_2_11_x86_64", + "manylinux_2_10_x86_64", + "manylinux_2_9_x86_64", + "manylinux_2_8_x86_64", + "manylinux_2_7_x86_64", + "manylinux_2_6_x86_64", + "manylinux_2_5_x86_64", + "manylinux1_x86_64", + "linux_x86_64", + ] + + +def test_platform_tags_macos(): + tags = Platform(os.Macos(21, 6), Arch.X86_64).compatible_tags + assert tags == [ + "macosx_21_0_x86_64", + "macosx_21_0_intel", + "macosx_21_0_fat64", + "macosx_21_0_fat32", + "macosx_21_0_universal2", + "macosx_21_0_universal", + "macosx_20_0_x86_64", + "macosx_20_0_intel", + "macosx_20_0_fat64", + "macosx_20_0_fat32", + "macosx_20_0_universal2", + "macosx_20_0_universal", + "macosx_19_0_x86_64", + "macosx_19_0_intel", + "macosx_19_0_fat64", + "macosx_19_0_fat32", + "macosx_19_0_universal2", + "macosx_19_0_universal", + "macosx_18_0_x86_64", + "macosx_18_0_intel", + "macosx_18_0_fat64", + "macosx_18_0_fat32", + "macosx_18_0_universal2", + "macosx_18_0_universal", + "macosx_17_0_x86_64", + "macosx_17_0_intel", + "macosx_17_0_fat64", + "macosx_17_0_fat32", + "macosx_17_0_universal2", + "macosx_17_0_universal", + "macosx_16_0_x86_64", + "macosx_16_0_intel", + "macosx_16_0_fat64", + "macosx_16_0_fat32", + "macosx_16_0_universal2", + "macosx_16_0_universal", + "macosx_15_0_x86_64", + "macosx_15_0_intel", + "macosx_15_0_fat64", + "macosx_15_0_fat32", + "macosx_15_0_universal2", + "macosx_15_0_universal", + "macosx_14_0_x86_64", + "macosx_14_0_intel", + "macosx_14_0_fat64", + "macosx_14_0_fat32", + "macosx_14_0_universal2", + "macosx_14_0_universal", + "macosx_13_0_x86_64", + "macosx_13_0_intel", + "macosx_13_0_fat64", + "macosx_13_0_fat32", + "macosx_13_0_universal2", + "macosx_13_0_universal", + "macosx_12_0_x86_64", + "macosx_12_0_intel", + "macosx_12_0_fat64", + "macosx_12_0_fat32", + "macosx_12_0_universal2", + "macosx_12_0_universal", + "macosx_11_0_x86_64", + "macosx_11_0_intel", + "macosx_11_0_fat64", + "macosx_11_0_fat32", + "macosx_11_0_universal2", + "macosx_11_0_universal", + "macosx_10_16_x86_64", + "macosx_10_16_intel", + "macosx_10_16_fat64", + "macosx_10_16_fat32", + "macosx_10_16_universal2", + "macosx_10_16_universal", + "macosx_10_15_x86_64", + "macosx_10_15_intel", + "macosx_10_15_fat64", + "macosx_10_15_fat32", + "macosx_10_15_universal2", + "macosx_10_15_universal", + "macosx_10_14_x86_64", + "macosx_10_14_intel", + "macosx_10_14_fat64", + "macosx_10_14_fat32", + "macosx_10_14_universal2", + "macosx_10_14_universal", + "macosx_10_13_x86_64", + "macosx_10_13_intel", + "macosx_10_13_fat64", + "macosx_10_13_fat32", + "macosx_10_13_universal2", + "macosx_10_13_universal", + "macosx_10_12_x86_64", + "macosx_10_12_intel", + "macosx_10_12_fat64", + "macosx_10_12_fat32", + "macosx_10_12_universal2", + "macosx_10_12_universal", + "macosx_10_11_x86_64", + "macosx_10_11_intel", + "macosx_10_11_fat64", + "macosx_10_11_fat32", + "macosx_10_11_universal2", + "macosx_10_11_universal", + "macosx_10_10_x86_64", + "macosx_10_10_intel", + "macosx_10_10_fat64", + "macosx_10_10_fat32", + "macosx_10_10_universal2", + "macosx_10_10_universal", + "macosx_10_9_x86_64", + "macosx_10_9_intel", + "macosx_10_9_fat64", + "macosx_10_9_fat32", + "macosx_10_9_universal2", + "macosx_10_9_universal", + "macosx_10_8_x86_64", + "macosx_10_8_intel", + "macosx_10_8_fat64", + "macosx_10_8_fat32", + "macosx_10_8_universal2", + "macosx_10_8_universal", + "macosx_10_7_x86_64", + "macosx_10_7_intel", + "macosx_10_7_fat64", + "macosx_10_7_fat32", + "macosx_10_7_universal2", + "macosx_10_7_universal", + "macosx_10_6_x86_64", + "macosx_10_6_intel", + "macosx_10_6_fat64", + "macosx_10_6_fat32", + "macosx_10_6_universal2", + "macosx_10_6_universal", + "macosx_10_5_x86_64", + "macosx_10_5_intel", + "macosx_10_5_fat64", + "macosx_10_5_fat32", + "macosx_10_5_universal2", + "macosx_10_5_universal", + "macosx_10_4_x86_64", + "macosx_10_4_intel", + "macosx_10_4_fat64", + "macosx_10_4_fat32", + "macosx_10_4_universal2", + "macosx_10_4_universal", + ] + + tags = Platform(os.Macos(14, 0), Arch.X86_64).compatible_tags + assert tags == [ + "macosx_14_0_x86_64", + "macosx_14_0_intel", + "macosx_14_0_fat64", + "macosx_14_0_fat32", + "macosx_14_0_universal2", + "macosx_14_0_universal", + "macosx_13_0_x86_64", + "macosx_13_0_intel", + "macosx_13_0_fat64", + "macosx_13_0_fat32", + "macosx_13_0_universal2", + "macosx_13_0_universal", + "macosx_12_0_x86_64", + "macosx_12_0_intel", + "macosx_12_0_fat64", + "macosx_12_0_fat32", + "macosx_12_0_universal2", + "macosx_12_0_universal", + "macosx_11_0_x86_64", + "macosx_11_0_intel", + "macosx_11_0_fat64", + "macosx_11_0_fat32", + "macosx_11_0_universal2", + "macosx_11_0_universal", + "macosx_10_16_x86_64", + "macosx_10_16_intel", + "macosx_10_16_fat64", + "macosx_10_16_fat32", + "macosx_10_16_universal2", + "macosx_10_16_universal", + "macosx_10_15_x86_64", + "macosx_10_15_intel", + "macosx_10_15_fat64", + "macosx_10_15_fat32", + "macosx_10_15_universal2", + "macosx_10_15_universal", + "macosx_10_14_x86_64", + "macosx_10_14_intel", + "macosx_10_14_fat64", + "macosx_10_14_fat32", + "macosx_10_14_universal2", + "macosx_10_14_universal", + "macosx_10_13_x86_64", + "macosx_10_13_intel", + "macosx_10_13_fat64", + "macosx_10_13_fat32", + "macosx_10_13_universal2", + "macosx_10_13_universal", + "macosx_10_12_x86_64", + "macosx_10_12_intel", + "macosx_10_12_fat64", + "macosx_10_12_fat32", + "macosx_10_12_universal2", + "macosx_10_12_universal", + "macosx_10_11_x86_64", + "macosx_10_11_intel", + "macosx_10_11_fat64", + "macosx_10_11_fat32", + "macosx_10_11_universal2", + "macosx_10_11_universal", + "macosx_10_10_x86_64", + "macosx_10_10_intel", + "macosx_10_10_fat64", + "macosx_10_10_fat32", + "macosx_10_10_universal2", + "macosx_10_10_universal", + "macosx_10_9_x86_64", + "macosx_10_9_intel", + "macosx_10_9_fat64", + "macosx_10_9_fat32", + "macosx_10_9_universal2", + "macosx_10_9_universal", + "macosx_10_8_x86_64", + "macosx_10_8_intel", + "macosx_10_8_fat64", + "macosx_10_8_fat32", + "macosx_10_8_universal2", + "macosx_10_8_universal", + "macosx_10_7_x86_64", + "macosx_10_7_intel", + "macosx_10_7_fat64", + "macosx_10_7_fat32", + "macosx_10_7_universal2", + "macosx_10_7_universal", + "macosx_10_6_x86_64", + "macosx_10_6_intel", + "macosx_10_6_fat64", + "macosx_10_6_fat32", + "macosx_10_6_universal2", + "macosx_10_6_universal", + "macosx_10_5_x86_64", + "macosx_10_5_intel", + "macosx_10_5_fat64", + "macosx_10_5_fat32", + "macosx_10_5_universal2", + "macosx_10_5_universal", + "macosx_10_4_x86_64", + "macosx_10_4_intel", + "macosx_10_4_fat64", + "macosx_10_4_fat32", + "macosx_10_4_universal2", + "macosx_10_4_universal", + ] + + tags = Platform(os.Macos(10, 6), Arch.X86_64).compatible_tags + assert tags == [ + "macosx_10_6_x86_64", + "macosx_10_6_intel", + "macosx_10_6_fat64", + "macosx_10_6_fat32", + "macosx_10_6_universal2", + "macosx_10_6_universal", + "macosx_10_5_x86_64", + "macosx_10_5_intel", + "macosx_10_5_fat64", + "macosx_10_5_fat32", + "macosx_10_5_universal2", + "macosx_10_5_universal", + "macosx_10_4_x86_64", + "macosx_10_4_intel", + "macosx_10_4_fat64", + "macosx_10_4_fat32", + "macosx_10_4_universal2", + "macosx_10_4_universal", + ] + + +def test_platform_tags_windows(): + tags = Platform(os.Windows(), Arch.X86_64).compatible_tags + assert tags == ["win_amd64"] + + +def test_platform_tags_musl(): + tags = Platform(os.Musllinux(1, 2), Arch.Aarch64).compatible_tags + assert tags == ["linux_aarch64", "musllinux_1_1_aarch64", "musllinux_1_2_aarch64"] + + +@pytest.mark.parametrize( + "text,expected", + [ + ("linux", Platform(os.Manylinux(2, 17), Arch.X86_64)), + ("macos", Platform(os.Macos(12, 0), Arch.Aarch64)), + ("windows", Platform(os.Windows(), Arch.X86_64)), + ("alpine", Platform(os.Musllinux(1, 2), Arch.X86_64)), + ("manylinux_2_20_aarch64", Platform(os.Manylinux(2, 20), Arch.Aarch64)), + ("macos_14_0_arm64", Platform(os.Macos(14, 0), Arch.Aarch64)), + ("windows_amd64", Platform(os.Windows(), Arch.X86_64)), + ], +) +def test_parse_platform(text, expected): + assert Platform.parse(text) == expected diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dep_logic-0.2.0/tests/tags/test_tags.py new/dep_logic-0.3.0/tests/tags/test_tags.py --- old/dep_logic-0.2.0/tests/tags/test_tags.py 1970-01-01 01:00:00.000000000 +0100 +++ new/dep_logic-0.3.0/tests/tags/test_tags.py 2024-06-28 11:09:19.946395600 +0200 @@ -0,0 +1,41 @@ +from dep_logic.tags import EnvSpec + + +def test_check_wheel_tags(): + wheels = [ + "protobuf-5.27.2-cp310-abi3-win32.whl", + "protobuf-5.27.2-cp310-abi3-win_amd64.whl", + "protobuf-5.27.2-cp38-abi3-macosx_10_9_universal2.whl", + "protobuf-5.27.2-cp38-abi3-manylinux2014_aarch64.whl", + "protobuf-5.27.2-cp38-abi3-manylinux2014_x86_64.whl", + "protobuf-5.27.2-cp38-cp38-win32.whl", + "protobuf-5.27.2-cp38-cp38-win_amd64.whl", + "protobuf-5.27.2-cp39-cp39-win32.whl", + "protobuf-5.27.2-cp39-cp39-win_amd64.whl", + "protobuf-5.27.2-py3-none-any.whl", + ] + + linux_env = EnvSpec.from_spec(">=3.9", "linux", "cpython") + wheel_compats = { + f: c + for f, c in {f: linux_env.wheel_compatibility(f) for f in wheels}.items() + if c is not None + } + filtered_wheels = sorted(wheel_compats, key=wheel_compats.__getitem__, reverse=True) + assert filtered_wheels == [ + "protobuf-5.27.2-cp38-abi3-manylinux2014_x86_64.whl", + "protobuf-5.27.2-py3-none-any.whl", + ] + + windows_env = EnvSpec.from_spec(">=3.9", "windows", "cpython") + wheel_compats = { + f: c + for f, c in {f: windows_env.wheel_compatibility(f) for f in wheels}.items() + if c is not None + } + filtered_wheels = sorted(wheel_compats, key=wheel_compats.__getitem__, reverse=True) + assert filtered_wheels == [ + "protobuf-5.27.2-cp310-abi3-win_amd64.whl", + "protobuf-5.27.2-cp39-cp39-win_amd64.whl", + "protobuf-5.27.2-py3-none-any.whl", + ]