fix(pypi) backport python_full_version fix to Python (#2833)

Handling of `python_full_version` correctly has been fixed in the
Starlark
implementation in #2793 and in this PR I am backporting the changes to
handle
the full python version target platform strings so that we can have the
same
behaviour for now.

At the same time I have simplified and got rid of the specialization
handling
in the Python algorithm just like I did in the starlark, which
simplifies the
tests and makes the algorithm more correct.

Summary:
* Handle `cp3x.y_os_arch` strings in the `platform.py`
* Produce correct strings when the `micro_version` is unset. Note, that
we use version `0` in evaluating but we use the default version in the
config setting. This is to keep compatibility with the current behaviour
when the target platform is not fully specified (which would be the case
for WORKSPACE users).
* Adjust the tests and the code to be more similar to the starlark impl.

Work towards #2830
diff --git a/python/private/pypi/whl_installer/platform.py b/python/private/pypi/whl_installer/platform.py
index 11dd6e3..ff267fe 100644
--- a/python/private/pypi/whl_installer/platform.py
+++ b/python/private/pypi/whl_installer/platform.py
@@ -18,7 +18,7 @@
 import sys
 from dataclasses import dataclass
 from enum import Enum
-from typing import Any, Dict, Iterator, List, Optional, Union
+from typing import Any, Dict, Iterator, List, Optional, Tuple, Union
 
 
 class OS(Enum):
@@ -77,8 +77,8 @@
     return int(value.value)
 
 
-def host_interpreter_minor_version() -> int:
-    return sys.version_info.minor
+def host_interpreter_version() -> Tuple[int, int]:
+    return (sys.version_info.minor, sys.version_info.micro)
 
 
 @dataclass(frozen=True)
@@ -86,16 +86,23 @@
     os: Optional[OS] = None
     arch: Optional[Arch] = None
     minor_version: Optional[int] = None
+    micro_version: Optional[int] = None
 
     @classmethod
     def all(
         cls,
         want_os: Optional[OS] = None,
         minor_version: Optional[int] = None,
+        micro_version: Optional[int] = None,
     ) -> List["Platform"]:
         return sorted(
             [
-                cls(os=os, arch=arch, minor_version=minor_version)
+                cls(
+                    os=os,
+                    arch=arch,
+                    minor_version=minor_version,
+                    micro_version=micro_version,
+                )
                 for os in OS
                 for arch in Arch
                 if not want_os or want_os == os
@@ -112,32 +119,16 @@
             A list of parsed values which makes the signature the same as
             `Platform.all` and `Platform.from_string`.
         """
+        minor, micro = host_interpreter_version()
         return [
             Platform(
                 os=OS.interpreter(),
                 arch=Arch.interpreter(),
-                minor_version=host_interpreter_minor_version(),
+                minor_version=minor,
+                micro_version=micro,
             )
         ]
 
-    def all_specializations(self) -> Iterator["Platform"]:
-        """Return the platform itself and all its unambiguous specializations.
-
-        For more info about specializations see
-        https://bazel.build/docs/configurable-attributes
-        """
-        yield self
-        if self.arch is None:
-            for arch in Arch:
-                yield Platform(os=self.os, arch=arch, minor_version=self.minor_version)
-        if self.os is None:
-            for os in OS:
-                yield Platform(os=os, arch=self.arch, minor_version=self.minor_version)
-        if self.arch is None and self.os is None:
-            for os in OS:
-                for arch in Arch:
-                    yield Platform(os=os, arch=arch, minor_version=self.minor_version)
-
     def __lt__(self, other: Any) -> bool:
         """Add a comparison method, so that `sorted` returns the most specialized platforms first."""
         if not isinstance(other, Platform) or other is None:
@@ -153,24 +144,15 @@
 
     def __str__(self) -> str:
         if self.minor_version is None:
-            if self.os is None and self.arch is None:
-                return "//conditions:default"
+            return f"{self.os}_{self.arch}"
 
-            if self.arch is None:
-                return f"@platforms//os:{self.os}"
-            else:
-                return f"{self.os}_{self.arch}"
+        minor_version = self.minor_version
+        micro_version = self.micro_version
 
-        if self.arch is None and self.os is None:
-            return f"@//python/config_settings:is_python_3.{self.minor_version}"
-
-        if self.arch is None:
-            return f"cp3{self.minor_version}_{self.os}_anyarch"
-
-        if self.os is None:
-            return f"cp3{self.minor_version}_anyos_{self.arch}"
-
-        return f"cp3{self.minor_version}_{self.os}_{self.arch}"
+        if micro_version is None:
+            return f"cp3{minor_version}_{self.os}_{self.arch}"
+        else:
+            return f"cp3{minor_version}.{micro_version}_{self.os}_{self.arch}"
 
     @classmethod
     def from_string(cls, platform: Union[str, List[str]]) -> List["Platform"]:
@@ -190,7 +172,17 @@
             os, _, arch = tail.partition("_")
             arch = arch or "*"
 
-            minor_version = int(abi[len("cp3") :]) if abi else None
+            if abi:
+                tail = abi[len("cp3") :]
+                minor_version, _, micro_version = tail.partition(".")
+                minor_version = int(minor_version)
+                if micro_version == "":
+                    micro_version = None
+                else:
+                    micro_version = int(micro_version)
+            else:
+                minor_version = None
+                micro_version = None
 
             if arch != "*":
                 ret.add(
@@ -198,6 +190,7 @@
                         os=OS[os] if os != "*" else None,
                         arch=Arch[arch],
                         minor_version=minor_version,
+                        micro_version=micro_version,
                     )
                 )
 
@@ -206,6 +199,7 @@
                     cls.all(
                         want_os=OS[os] if os != "*" else None,
                         minor_version=minor_version,
+                        micro_version=micro_version,
                     )
                 )
 
@@ -282,7 +276,12 @@
 
     def env_markers(self, extra: str) -> Dict[str, str]:
         # If it is None, use the host version
-        minor_version = self.minor_version or host_interpreter_minor_version()
+        if self.minor_version is None:
+            minor, micro = host_interpreter_version()
+        else:
+            minor, micro = self.minor_version, self.micro_version
+
+        micro = micro or 0
 
         return {
             "extra": extra,
@@ -292,12 +291,9 @@
             "platform_system": self.platform_system,
             "platform_release": "",  # unset
             "platform_version": "",  # unset
-            "python_version": f"3.{minor_version}",
-            # FIXME @aignas 2024-01-14: is putting zero last a good idea? Maybe we should
-            # use `20` or something else to avoid having weird issues where the full version is used for
-            # matching and the author decides to only support 3.y.5 upwards.
-            "implementation_version": f"3.{minor_version}.0",
-            "python_full_version": f"3.{minor_version}.0",
+            "python_version": f"3.{minor}",
+            "implementation_version": f"3.{minor}.{micro}",
+            "python_full_version": f"3.{minor}.{micro}",
             # we assume that the following are the same as the interpreter used to setup the deps:
             # "implementation_name": "cpython"
             # "platform_python_implementation: "CPython",
diff --git a/python/private/pypi/whl_installer/wheel.py b/python/private/pypi/whl_installer/wheel.py
index d95b33a..fce706a 100644
--- a/python/private/pypi/whl_installer/wheel.py
+++ b/python/private/pypi/whl_installer/wheel.py
@@ -27,7 +27,7 @@
 
 from python.private.pypi.whl_installer.platform import (
     Platform,
-    host_interpreter_minor_version,
+    host_interpreter_version,
 )
 
 
@@ -62,12 +62,13 @@
         """
         self.name: str = Deps._normalize(name)
         self._platforms: Set[Platform] = platforms or set()
-        self._target_versions = {p.minor_version for p in platforms or {}}
-        self._default_minor_version = None
-        if platforms and len(self._target_versions) > 2:
+        self._target_versions = {(p.minor_version, p.micro_version) for p in platforms or {}}
+        if platforms and len(self._target_versions) > 1:
             # TODO @aignas 2024-06-23: enable this to be set via a CLI arg
             # for being more explicit.
-            self._default_minor_version = host_interpreter_minor_version()
+            self._default_minor_version, _ = host_interpreter_version()
+        else:
+            self._default_minor_version = None
 
         if None in self._target_versions and len(self._target_versions) > 2:
             raise ValueError(
@@ -88,8 +89,13 @@
         # Then add all of the requirements in order
         self._deps: Set[str] = set()
         self._select: Dict[Platform, Set[str]] = defaultdict(set)
+
+        reqs_by_name = {}
         for req in reqs:
-            self._add_req(req, want_extras)
+            reqs_by_name.setdefault(req.name, []).append(req)
+
+        for reqs in reqs_by_name.values():
+            self._add_req(reqs, want_extras)
 
     def _add(self, dep: str, platform: Optional[Platform]):
         dep = Deps._normalize(dep)
@@ -123,50 +129,6 @@
         # Add the platform-specific dep
         self._select[platform].add(dep)
 
-        # Add the dep to specializations of the given platform if they
-        # exist in the select statement.
-        for p in platform.all_specializations():
-            if p not in self._select:
-                continue
-
-            self._select[p].add(dep)
-
-        if len(self._select[platform]) == 1:
-            # We are adding a new item to the select and we need to ensure that
-            # existing dependencies from less specialized platforms are propagated
-            # to the newly added dependency set.
-            for p, deps in self._select.items():
-                # Check if the existing platform overlaps with the given platform
-                if p == platform or platform not in p.all_specializations():
-                    continue
-
-                self._select[platform].update(self._select[p])
-
-    def _maybe_add_common_dep(self, dep):
-        if len(self._target_versions) < 2:
-            return
-
-        platforms = [Platform()] + [
-            Platform(minor_version=v) for v in self._target_versions
-        ]
-
-        # If the dep is targeting all target python versions, lets add it to
-        # the common dependency list to simplify the select statements.
-        for p in platforms:
-            if p not in self._select:
-                return
-
-            if dep not in self._select[p]:
-                return
-
-        # All of the python version-specific branches have the dep, so lets add
-        # it to the common deps.
-        self._deps.add(dep)
-        for p in platforms:
-            self._select[p].remove(dep)
-            if not self._select[p]:
-                self._select.pop(p)
-
     @staticmethod
     def _normalize(name: str) -> str:
         return re.sub(r"[-_.]+", "_", name).lower()
@@ -227,66 +189,40 @@
 
         return extras
 
-    def _add_req(self, req: Requirement, extras: Set[str]) -> None:
-        if req.marker is None:
+    def _add_req(self, reqs: List[Requirement], extras: Set[str]) -> None:
+        platforms_to_add = set()
+        for req in reqs:
+            if req.marker is None:
+                self._add(req.name, None)
+                return
+
+            for plat in self._platforms:
+                if plat in platforms_to_add:
+                    # marker evaluation is more expensive than this check
+                    continue
+
+                added = False
+                for extra in extras:
+                    if added:
+                        break
+
+                    if req.marker.evaluate(plat.env_markers(extra)):
+                        platforms_to_add.add(plat)
+                        added = True
+                        break
+
+        if len(platforms_to_add) == len(self._platforms):
+            # the dep is in all target platforms, let's just add it to the regular
+            # list
             self._add(req.name, None)
             return
 
-        marker_str = str(req.marker)
-
-        if not self._platforms:
-            if any(req.marker.evaluate({"extra": extra}) for extra in extras):
-                self._add(req.name, None)
-            return
-
-        # NOTE @aignas 2023-12-08: in order to have reasonable select statements
-        # we do have to have some parsing of the markers, so it begs the question
-        # if packaging should be reimplemented in Starlark to have the best solution
-        # for now we will implement it in Python and see what the best parsing result
-        # can be before making this decision.
-        match_os = any(
-            tag in marker_str
-            for tag in [
-                "os_name",
-                "sys_platform",
-                "platform_system",
-            ]
-        )
-        match_arch = "platform_machine" in marker_str
-        match_version = "version" in marker_str
-
-        if not (match_os or match_arch or match_version):
-            if any(req.marker.evaluate({"extra": extra}) for extra in extras):
-                self._add(req.name, None)
-            return
-
-        for plat in self._platforms:
-            if not any(
-                req.marker.evaluate(plat.env_markers(extra)) for extra in extras
-            ):
-                continue
-
-            if match_arch and self._default_minor_version:
+        for plat in platforms_to_add:
+            if self._default_minor_version is not None:
                 self._add(req.name, plat)
-                if plat.minor_version == self._default_minor_version:
-                    self._add(req.name, Platform(plat.os, plat.arch))
-            elif match_arch:
-                self._add(req.name, Platform(plat.os, plat.arch))
-            elif match_os and self._default_minor_version:
-                self._add(req.name, Platform(plat.os, minor_version=plat.minor_version))
-                if plat.minor_version == self._default_minor_version:
-                    self._add(req.name, Platform(plat.os))
-            elif match_os:
-                self._add(req.name, Platform(plat.os))
-            elif match_version and self._default_minor_version:
-                self._add(req.name, Platform(minor_version=plat.minor_version))
-                if plat.minor_version == self._default_minor_version:
-                    self._add(req.name, Platform())
-            elif match_version:
-                self._add(req.name, None)
 
-        # Merge to common if possible after processing all platforms
-        self._maybe_add_common_dep(req.name)
+            if self._default_minor_version is None or plat.minor_version == self._default_minor_version:
+                self._add(req.name, Platform(os = plat.os, arch = plat.arch))
 
     def build(self) -> FrozenDeps:
         return FrozenDeps(
diff --git a/tests/pypi/whl_installer/platform_test.py b/tests/pypi/whl_installer/platform_test.py
index 2aeb4ca..ad65650 100644
--- a/tests/pypi/whl_installer/platform_test.py
+++ b/tests/pypi/whl_installer/platform_test.py
@@ -5,13 +5,13 @@
     OS,
     Arch,
     Platform,
-    host_interpreter_minor_version,
+    host_interpreter_version,
 )
 
 
 class MinorVersionTest(unittest.TestCase):
     def test_host(self):
-        host = host_interpreter_minor_version()
+        host = host_interpreter_version()
         self.assertIsNotNone(host)
 
 
@@ -32,10 +32,14 @@
         want = Platform(os=OS.linux, arch=Arch.x86_64, minor_version=3)
         self.assertEqual(want, got[0])
 
+        got = Platform.from_string("cp33.0_linux_x86_64")
+        want = Platform(os=OS.linux, arch=Arch.x86_64, minor_version=3, micro_version=0)
+        self.assertEqual(want, got[0])
+
     def test_can_get_all_for_py_version(self):
-        cp39 = Platform.all(minor_version=9)
+        cp39 = Platform.all(minor_version=9, micro_version=0)
         self.assertEqual(21, len(cp39), f"Got {cp39}")
-        self.assertEqual(cp39, Platform.from_string("cp39_*"))
+        self.assertEqual(cp39, Platform.from_string("cp39.0_*"))
 
     def test_can_get_all_for_os(self):
         linuxes = Platform.all(OS.linux, minor_version=9)
@@ -47,67 +51,6 @@
         self.assertEqual(7, len(linuxes))
         self.assertEqual(linuxes, Platform.from_string("linux_*"))
 
-    def test_specific_version_specializations(self):
-        any_py33 = Platform(minor_version=3)
-
-        # When
-        all_specializations = list(any_py33.all_specializations())
-
-        want = (
-            [any_py33]
-            + [
-                Platform(arch=arch, minor_version=any_py33.minor_version)
-                for arch in Arch
-            ]
-            + [Platform(os=os, minor_version=any_py33.minor_version) for os in OS]
-            + Platform.all(minor_version=any_py33.minor_version)
-        )
-        self.assertEqual(want, all_specializations)
-
-    def test_aarch64_specializations(self):
-        any_aarch64 = Platform(arch=Arch.aarch64)
-        all_specializations = list(any_aarch64.all_specializations())
-        want = [
-            Platform(os=None, arch=Arch.aarch64),
-            Platform(os=OS.linux, arch=Arch.aarch64),
-            Platform(os=OS.osx, arch=Arch.aarch64),
-            Platform(os=OS.windows, arch=Arch.aarch64),
-        ]
-        self.assertEqual(want, all_specializations)
-
-    def test_linux_specializations(self):
-        any_linux = Platform(os=OS.linux)
-        all_specializations = list(any_linux.all_specializations())
-        want = [
-            Platform(os=OS.linux, arch=None),
-            Platform(os=OS.linux, arch=Arch.x86_64),
-            Platform(os=OS.linux, arch=Arch.x86_32),
-            Platform(os=OS.linux, arch=Arch.aarch64),
-            Platform(os=OS.linux, arch=Arch.ppc),
-            Platform(os=OS.linux, arch=Arch.ppc64le),
-            Platform(os=OS.linux, arch=Arch.s390x),
-            Platform(os=OS.linux, arch=Arch.arm),
-        ]
-        self.assertEqual(want, all_specializations)
-
-    def test_osx_specializations(self):
-        any_osx = Platform(os=OS.osx)
-        all_specializations = list(any_osx.all_specializations())
-        # NOTE @aignas 2024-01-14: even though in practice we would only have
-        # Python on osx aarch64 and osx x86_64, we return all arch posibilities
-        # to make the code simpler.
-        want = [
-            Platform(os=OS.osx, arch=None),
-            Platform(os=OS.osx, arch=Arch.x86_64),
-            Platform(os=OS.osx, arch=Arch.x86_32),
-            Platform(os=OS.osx, arch=Arch.aarch64),
-            Platform(os=OS.osx, arch=Arch.ppc),
-            Platform(os=OS.osx, arch=Arch.ppc64le),
-            Platform(os=OS.osx, arch=Arch.s390x),
-            Platform(os=OS.osx, arch=Arch.arm),
-        ]
-        self.assertEqual(want, all_specializations)
-
     def test_platform_sort(self):
         platforms = [
             Platform(os=OS.linux, arch=None),
diff --git a/tests/pypi/whl_installer/wheel_test.py b/tests/pypi/whl_installer/wheel_test.py
index 404218e..6921fe6 100644
--- a/tests/pypi/whl_installer/wheel_test.py
+++ b/tests/pypi/whl_installer/wheel_test.py
@@ -5,7 +5,7 @@
 from python.private.pypi.whl_installer.platform import OS, Arch, Platform
 
 _HOST_INTERPRETER_FN = (
-    "python.private.pypi.whl_installer.wheel.host_interpreter_minor_version"
+    "python.private.pypi.whl_installer.wheel.host_interpreter_version"
 )
 
 
@@ -20,108 +20,56 @@
         self.assertEqual({}, got.deps_select)
 
     def test_can_add_os_specific_deps(self):
-        deps = wheel.Deps(
-            "foo",
-            requires_dist=[
-                "bar",
-                "an_osx_dep; sys_platform=='darwin'",
-                "posix_dep; os_name=='posix'",
-                "win_dep; os_name=='nt'",
-            ],
-            platforms={
+        for platforms in [
+            {
                 Platform(os=OS.linux, arch=Arch.x86_64),
                 Platform(os=OS.osx, arch=Arch.x86_64),
                 Platform(os=OS.osx, arch=Arch.aarch64),
                 Platform(os=OS.windows, arch=Arch.x86_64),
             },
-        )
-
-        got = deps.build()
-
-        self.assertEqual(["bar"], got.deps)
-        self.assertEqual(
             {
-                "@platforms//os:linux": ["posix_dep"],
-                "@platforms//os:osx": ["an_osx_dep", "posix_dep"],
-                "@platforms//os:windows": ["win_dep"],
-            },
-            got.deps_select,
-        )
-
-    def test_can_add_os_specific_deps_with_specific_python_version(self):
-        deps = wheel.Deps(
-            "foo",
-            requires_dist=[
-                "bar",
-                "an_osx_dep; sys_platform=='darwin'",
-                "posix_dep; os_name=='posix'",
-                "win_dep; os_name=='nt'",
-            ],
-            platforms={
                 Platform(os=OS.linux, arch=Arch.x86_64, minor_version=8),
                 Platform(os=OS.osx, arch=Arch.x86_64, minor_version=8),
                 Platform(os=OS.osx, arch=Arch.aarch64, minor_version=8),
                 Platform(os=OS.windows, arch=Arch.x86_64, minor_version=8),
             },
-        )
-
-        got = deps.build()
-
-        self.assertEqual(["bar"], got.deps)
-        self.assertEqual(
             {
-                "@platforms//os:linux": ["posix_dep"],
-                "@platforms//os:osx": ["an_osx_dep", "posix_dep"],
-                "@platforms//os:windows": ["win_dep"],
+                Platform(
+                    os=OS.linux, arch=Arch.x86_64, minor_version=8, micro_version=1
+                ),
+                Platform(os=OS.osx, arch=Arch.x86_64, minor_version=8, micro_version=1),
+                Platform(
+                    os=OS.osx, arch=Arch.aarch64, minor_version=8, micro_version=1
+                ),
+                Platform(
+                    os=OS.windows, arch=Arch.x86_64, minor_version=8, micro_version=1
+                ),
             },
-            got.deps_select,
-        )
+        ]:
+            with self.subTest():
+                deps = wheel.Deps(
+                    "foo",
+                    requires_dist=[
+                        "bar",
+                        "an_osx_dep; sys_platform=='darwin'",
+                        "posix_dep; os_name=='posix'",
+                        "win_dep; os_name=='nt'",
+                    ],
+                    platforms=platforms,
+                )
 
-    def test_deps_are_added_to_more_specialized_platforms(self):
-        got = wheel.Deps(
-            "foo",
-            requires_dist=[
-                "m1_dep; sys_platform=='darwin' and platform_machine=='arm64'",
-                "mac_dep; sys_platform=='darwin'",
-            ],
-            platforms={
-                Platform(os=OS.osx, arch=Arch.x86_64),
-                Platform(os=OS.osx, arch=Arch.aarch64),
-            },
-        ).build()
+                got = deps.build()
 
-        self.assertEqual(
-            wheel.FrozenDeps(
-                deps=[],
-                deps_select={
-                    "osx_aarch64": ["m1_dep", "mac_dep"],
-                    "@platforms//os:osx": ["mac_dep"],
-                },
-            ),
-            got,
-        )
-
-    def test_deps_from_more_specialized_platforms_are_propagated(self):
-        got = wheel.Deps(
-            "foo",
-            requires_dist=[
-                "a_mac_dep; sys_platform=='darwin'",
-                "m1_dep; sys_platform=='darwin' and platform_machine=='arm64'",
-            ],
-            platforms={
-                Platform(os=OS.osx, arch=Arch.x86_64),
-                Platform(os=OS.osx, arch=Arch.aarch64),
-            },
-        ).build()
-
-        self.assertEqual([], got.deps)
-        self.assertEqual(
-            {
-                "osx_aarch64": ["a_mac_dep", "m1_dep"],
-                "@platforms//os:osx": ["a_mac_dep"],
-            },
-            got.deps_select,
-        )
+                self.assertEqual(["bar"], got.deps)
+                self.assertEqual(
+                    {
+                        "linux_x86_64": ["posix_dep"],
+                        "osx_aarch64": ["an_osx_dep", "posix_dep"],
+                        "osx_x86_64": ["an_osx_dep", "posix_dep"],
+                        "windows_x86_64": ["win_dep"],
+                    },
+                    got.deps_select,
+                )
 
     def test_non_platform_markers_are_added_to_common_deps(self):
         got = wheel.Deps(
@@ -185,7 +133,7 @@
     def test_can_get_deps_based_on_specific_python_version(self):
         requires_dist = [
             "bar",
-            "baz; python_version < '3.8'",
+            "baz; python_full_version < '3.7.3'",
             "posix_dep; os_name=='posix' and python_version >= '3.8'",
         ]
 
@@ -196,6 +144,15 @@
                 Platform(os=OS.linux, arch=Arch.x86_64, minor_version=8),
             ],
         ).build()
+        py373_deps = wheel.Deps(
+            "foo",
+            requires_dist=requires_dist,
+            platforms=[
+                Platform(
+                    os=OS.linux, arch=Arch.x86_64, minor_version=7, micro_version=3
+                ),
+            ],
+        ).build()
         py37_deps = wheel.Deps(
             "foo",
             requires_dist=requires_dist,
@@ -206,11 +163,12 @@
 
         self.assertEqual(["bar", "baz"], py37_deps.deps)
         self.assertEqual({}, py37_deps.deps_select)
-        self.assertEqual(["bar"], py38_deps.deps)
-        self.assertEqual({"@platforms//os:linux": ["posix_dep"]}, py38_deps.deps_select)
+        self.assertEqual(["bar"], py373_deps.deps)
+        self.assertEqual({}, py37_deps.deps_select)
+        self.assertEqual(["bar", "posix_dep"], py38_deps.deps)
+        self.assertEqual({}, py38_deps.deps_select)
 
-    @mock.patch(_HOST_INTERPRETER_FN)
-    def test_no_version_select_when_single_version(self, mock_host_interpreter_version):
+    def test_no_version_select_when_single_version(self):
         requires_dist = [
             "bar",
             "baz; python_version >= '3.8'",
@@ -218,7 +176,6 @@
             "posix_dep_with_version; os_name=='posix' and python_version >= '3.8'",
             "arch_dep; platform_machine=='x86_64' and python_version >= '3.8'",
         ]
-        mock_host_interpreter_version.return_value = 7
 
         self.maxDiff = None
 
@@ -226,19 +183,19 @@
             "foo",
             requires_dist=requires_dist,
             platforms=[
-                Platform(os=os, arch=Arch.x86_64, minor_version=minor)
-                for minor in [8]
+                Platform(
+                    os=os, arch=Arch.x86_64, minor_version=minor, micro_version=micro
+                )
+                for minor, micro in [(8, 4)]
                 for os in [OS.linux, OS.windows]
             ],
         )
         got = deps.build()
 
-        self.assertEqual(["bar", "baz"], got.deps)
+        self.assertEqual(["arch_dep", "bar", "baz"], got.deps)
         self.assertEqual(
             {
-                "@platforms//os:linux": ["posix_dep", "posix_dep_with_version"],
-                "linux_x86_64": ["arch_dep", "posix_dep", "posix_dep_with_version"],
-                "windows_x86_64": ["arch_dep"],
+                "linux_x86_64": ["posix_dep", "posix_dep_with_version"],
             },
             got.deps_select,
         )
@@ -253,7 +210,7 @@
             "posix_dep_with_version; os_name=='posix' and python_version >= '3.8'",
             "arch_dep; platform_machine=='x86_64' and python_version < '3.8'",
         ]
-        mock_host_interpreter_version.return_value = 7
+        mock_host_interpreter_version.return_value = (7, 4)
 
         self.maxDiff = None
 
@@ -261,8 +218,10 @@
             "foo",
             requires_dist=requires_dist,
             platforms=[
-                Platform(os=os, arch=Arch.x86_64, minor_version=minor)
-                for minor in [7, 8, 9]
+                Platform(
+                    os=os, arch=Arch.x86_64, minor_version=minor, micro_version=micro
+                )
+                for minor, micro in [(7, 4), (8, 8), (9, 8)]
                 for os in [OS.linux, OS.windows]
             ],
         )
@@ -271,24 +230,20 @@
         self.assertEqual(["bar"], got.deps)
         self.assertEqual(
             {
-                "//conditions:default": ["baz"],
-                "@//python/config_settings:is_python_3.7": ["baz"],
-                "@//python/config_settings:is_python_3.8": ["baz_new"],
-                "@//python/config_settings:is_python_3.9": ["baz_new"],
-                "@platforms//os:linux": ["baz", "posix_dep"],
-                "cp37_linux_x86_64": ["arch_dep", "baz", "posix_dep"],
-                "cp37_windows_x86_64": ["arch_dep", "baz"],
-                "cp37_linux_anyarch": ["baz", "posix_dep"],
-                "cp38_linux_anyarch": [
+                "cp37.4_linux_x86_64": ["arch_dep", "baz", "posix_dep"],
+                "cp37.4_windows_x86_64": ["arch_dep", "baz"],
+                "cp38.8_linux_x86_64": [
                     "baz_new",
                     "posix_dep",
                     "posix_dep_with_version",
                 ],
-                "cp39_linux_anyarch": [
+                "cp38.8_windows_x86_64": ["baz_new"],
+                "cp39.8_linux_x86_64": [
                     "baz_new",
                     "posix_dep",
                     "posix_dep_with_version",
                 ],
+                "cp39.8_windows_x86_64": ["baz_new"],
                 "linux_x86_64": ["arch_dep", "baz", "posix_dep"],
                 "windows_x86_64": ["arch_dep", "baz"],
             },
@@ -304,7 +259,9 @@
             "baz (<2,>=1.11) ; python_version < '3.8'",
             "baz (<2,>=1.14) ; python_version >= '3.8'",
         ]
-        mock_host_version.return_value = 8
+        mock_host_version.return_value = (8, 4)
+
+        self.maxDiff = None
 
         deps = wheel.Deps(
             "foo",
@@ -313,12 +270,12 @@
         )
         got = deps.build()
 
-        self.assertEqual(["bar", "baz"], got.deps)
         self.assertEqual({}, got.deps_select)
+        self.assertEqual(["bar", "baz"], got.deps)
 
     @mock.patch(_HOST_INTERPRETER_FN)
     def test_deps_are_not_duplicated(self, mock_host_version):
-        mock_host_version.return_value = 7
+        mock_host_version.return_value = (7, 4)
 
         # See an example in
         # https://files.pythonhosted.org/packages/76/9e/db1c2d56c04b97981c06663384f45f28950a73d9acf840c4006d60d0a1ff/opencv_python-4.9.0.80-cp37-abi3-win32.whl.metadata
@@ -347,7 +304,7 @@
     def test_deps_are_not_duplicated_when_encountering_platform_dep_first(
         self, mock_host_version
     ):
-        mock_host_version.return_value = 7
+        mock_host_version.return_value = (7, 1)
 
         # Note, that we are sorting the incoming `requires_dist` and we need to ensure that we are not getting any
         # issues even if the platform-specific line comes first.
@@ -356,15 +313,32 @@
             "bar >=0.5.0 ; python_version >= '3.9'",
         ]
 
+        self.maxDiff = None
+
         deps = wheel.Deps(
             "foo",
             requires_dist=requires_dist,
-            platforms=Platform.from_string(["cp37_*", "cp310_*"]),
+            platforms=Platform.from_string(
+                [
+                    "cp37.1_linux_x86_64",
+                    "cp37.1_linux_aarch64",
+                    "cp310_linux_x86_64",
+                    "cp310_linux_aarch64",
+                ]
+            ),
         )
         got = deps.build()
 
-        self.assertEqual(["bar"], got.deps)
-        self.assertEqual({}, got.deps_select)
+        self.assertEqual([], got.deps)
+        self.assertEqual(
+            {
+                "cp310_linux_aarch64": ["bar"],
+                "cp310_linux_x86_64": ["bar"],
+                "cp37.1_linux_aarch64": ["bar"],
+                "linux_aarch64": ["bar"],
+            },
+            got.deps_select,
+        )
 
 
 if __name__ == "__main__":