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",
+    ]

Reply via email to