From bd36b452a2e98a706a348fd807a743eea7474cee Mon Sep 17 00:00:00 2001 From: mayeut Date: Sun, 27 Feb 2022 19:21:45 +0100 Subject: [PATCH] fix: macOS platform tags with old macOS SDK This retrieves the real macOS version to compute macOS platform tags when the python interpreter is built with an old macOS SDK. fixes #497 --- packaging/tags.py | 17 +++++++++++++++++ tests/test_tags.py | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/packaging/tags.py b/packaging/tags.py index 744cf2cb3..5b6c5ffd0 100644 --- a/packaging/tags.py +++ b/packaging/tags.py @@ -4,6 +4,7 @@ import logging import platform +import subprocess import sys import sysconfig from importlib.machinery import EXTENSION_SUFFIXES @@ -356,6 +357,22 @@ def mac_platforms( version_str, _, cpu_arch = platform.mac_ver() if version is None: version = cast("MacVersion", tuple(map(int, version_str.split(".")[:2]))) + if version == (10, 16): + # When built against an older macOS SDK, Python will report macOS 10.16 + # instead of the real version. + version_str = subprocess.run( + [ + sys.executable, + "-sS", + "-c", + "import platform; print(platform.mac_ver()[0])", + ], + check=True, + env={"SYSTEM_VERSION_COMPAT": "0"}, + stdout=subprocess.PIPE, + universal_newlines=True, + ).stdout + version = cast("MacVersion", tuple(map(int, version_str.split(".")[:2]))) else: version = version if arch is None: diff --git a/tests/test_tags.py b/tests/test_tags.py index 446dee4ef..06cd3b4a2 100644 --- a/tests/test_tags.py +++ b/tests/test_tags.py @@ -4,6 +4,7 @@ import collections.abc +import subprocess try: import ctypes @@ -230,12 +231,48 @@ def test_version_detection(self, monkeypatch): version = platform.mac_ver()[0].split(".") major = version[0] minor = version[1] if major == "10" else "0" - expected = f"macosx_{major}_{minor}" + + platforms = list(tags.mac_platforms(arch="x86_64")) + if (major, minor) == ("10", "16"): + print(platforms, "macosx_11+") + # For 10.16, the real version is at least 11.0. + prefix, major, minor, _ = platforms[0].split("_", maxsplit=3) + assert prefix == "macosx" + assert int(major) >= 11 + assert minor == "0" + else: + expected = f"macosx_{major}_{minor}_" + print(platforms, expected) + assert platforms[0].startswith(expected) + + def test_version_detection_10_15(self, monkeypatch): + monkeypatch.setattr( + platform, "mac_ver", lambda: ("10.15", ("", "", ""), "x86_64") + ) + expected = "macosx_10_15_" platforms = list(tags.mac_platforms(arch="x86_64")) print(platforms, expected) assert platforms[0].startswith(expected) + def test_version_detection_compatibility(self, monkeypatch): + if platform.system() != "Darwin": + monkeypatch.setattr( + subprocess, + "run", + lambda *args, **kwargs: subprocess.CompletedProcess( + [], 0, stdout="10.15" + ), + ) + monkeypatch.setattr( + platform, "mac_ver", lambda: ("10.16", ("", "", ""), "x86_64") + ) + unexpected = "macosx_10_16_" + + platforms = list(tags.mac_platforms(arch="x86_64")) + print(platforms, unexpected) + assert not platforms[0].startswith(unexpected) + @pytest.mark.parametrize("arch", ["x86_64", "i386"]) def test_arch_detection(self, arch, monkeypatch): if platform.system() != "Darwin" or platform.mac_ver()[2] != arch: