From 00d3e53db5fa2b43b777f3bbddd80a2770e901ca Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Sat, 7 Nov 2020 14:59:30 +0800 Subject: [PATCH 1/5] Pull in distutils.util.get_host_platform() --- packaging/tags.py | 92 +++++++++++++++++++++++++++++++++++++++++++--- tests/test_tags.py | 34 ++++++++--------- 2 files changed, 104 insertions(+), 22 deletions(-) diff --git a/packaging/tags.py b/packaging/tags.py index d637f1b6..51b1d7a7 100644 --- a/packaging/tags.py +++ b/packaging/tags.py @@ -4,8 +4,6 @@ from __future__ import absolute_import -import distutils.util - try: from importlib.machinery import EXTENSION_SUFFIXES except ImportError: # pragma: no cover @@ -611,7 +609,7 @@ def _parse_glibc_version(version_str): return (int(m.group("major")), int(m.group("minor"))) -_glibc_version = [] # type: List[Tuple[int, int]] +_glibc_version = [] # type: List[Tuple[int, int]] def _get_glibc_version(): @@ -779,9 +777,93 @@ def _manylinux_tags(linux, arch): yield linux.replace("linux", legacy_tag) +def _get_host_platform(): + # type: () -> str + """Return a string that identifies the current platform. This is used mainly to + distinguish platform-specific build directories and platform-specific built + distributions. Typically includes the OS name and version and the + architecture (as supplied by 'os.uname()'), although the exact information + included depends on the OS; eg. on Linux, the kernel version isn't + particularly important. + + Examples of returned values: + linux-i586 + linux-alpha (?) + solaris-2.6-sun4u + + Windows will return one of: + win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc) + win32 (all others - specifically, sys.platform is returned) + + For other non-POSIX platforms, currently just returns 'sys.platform'. + + """ + if os.name == 'nt': + if 'amd64' in sys.version.lower(): + return 'win-amd64' + if '(arm)' in sys.version.lower(): + return 'win-arm32' + if '(arm64)' in sys.version.lower(): + return 'win-arm64' + return sys.platform + + # Set for cross builds explicitly + if "_PYTHON_HOST_PLATFORM" in os.environ: + return os.environ["_PYTHON_HOST_PLATFORM"] + + if os.name != "posix" or not hasattr(os, 'uname'): + # XXX what about the architecture? NT is Intel or Alpha, + # Mac OS is M68k or PPC, etc. + return sys.platform + + # Try to distinguish various flavours of Unix + + (osname, host, release, version, machine) = os.uname() + + # Convert the OS name to lowercase, remove '/' characters, and translate + # spaces (for "Power Macintosh") + osname = osname.lower().replace('/', '') + machine = machine.replace(' ', '_') + machine = machine.replace('/', '-') + + if osname[:5] == "linux": + # At least on Linux/Intel, 'machine' is the processor -- + # i386, etc. + # XXX what about Alpha, SPARC, etc? + return "%s-%s" % (osname, machine) + elif osname[:5] == "sunos": + if release[0] >= "5": # SunOS 5 == Solaris 2 + osname = "solaris" + release = "%d.%s" % (int(release[0]) - 3, release[2:]) + # We can't use "platform.architecture()[0]" because a + # bootstrap problem. We use a dict to get an error + # if some suspicious happens. + bitness = {2147483647: "32bit", 9223372036854775807: "64bit"} + machine += ".%s" % bitness[sys.maxsize] + # fall through to standard osname-release-machine representation + elif osname[:3] == "aix": + from _aix_support import aix_platform + return cast(str, aix_platform()) + elif osname[:6] == "cygwin": + osname = "cygwin" + rel_re = re.compile(r'[\d.]+', re.ASCII) + m = rel_re.match(release) + if m: + release = m.group() + elif osname[:6] == "darwin": + import distutils.sysconfig + import _osx_support + osname, release, machine = _osx_support.get_platform_osx( + distutils.sysconfig.get_config_vars(), + osname, release, machine, + ) + + return "%s-%s-%s" % (osname, release, machine) + + def _linux_platforms(is_32bit=_32_BIT_INTERPRETER): # type: (bool) -> Iterator[str] - linux = _normalize_string(distutils.util.get_platform()) + linux = _normalize_string(_get_host_platform()) if is_32bit: if linux == "linux_x86_64": linux = "linux_i686" @@ -796,7 +878,7 @@ def _linux_platforms(is_32bit=_32_BIT_INTERPRETER): def _generic_platforms(): # type: () -> Iterator[str] - yield _normalize_string(distutils.util.get_platform()) + yield _normalize_string(_get_host_platform()) def _platform_tags(): diff --git a/tests/test_tags.py b/tests/test_tags.py index 6b0e5b6e..6bab766c 100644 --- a/tests/test_tags.py +++ b/tests/test_tags.py @@ -11,7 +11,7 @@ import ctypes except ImportError: ctypes = None -import distutils.util + import os import platform import re @@ -492,14 +492,14 @@ def test_glibc_version_string_none(self, monkeypatch): def test_linux_platforms_32_64bit_on_64bit_os( self, arch, is_32bit, expected, monkeypatch ): - monkeypatch.setattr(distutils.util, "get_platform", lambda: arch) + monkeypatch.setattr(tags, "_get_host_platform", lambda: arch) monkeypatch.setattr(os, "confstr", lambda x: "glibc 2.20", raising=False) monkeypatch.setattr(tags, "_is_manylinux_compatible", lambda *args: False) linux_platform = list(tags._linux_platforms(is_32bit=is_32bit))[-1] assert linux_platform == expected def test_linux_platforms_manylinux_unsupported(self, monkeypatch): - monkeypatch.setattr(distutils.util, "get_platform", lambda: "linux_x86_64") + monkeypatch.setattr(tags, "_get_host_platform", lambda: "linux_x86_64") monkeypatch.setattr(os, "confstr", lambda x: "glibc 2.20", raising=False) monkeypatch.setattr(tags, "_is_manylinux_compatible", lambda *args: False) linux_platform = list(tags._linux_platforms(is_32bit=False)) @@ -509,7 +509,7 @@ def test_linux_platforms_manylinux1(self, monkeypatch): monkeypatch.setattr( tags, "_is_manylinux_compatible", lambda name, *args: name == "manylinux1" ) - monkeypatch.setattr(distutils.util, "get_platform", lambda: "linux_x86_64") + monkeypatch.setattr(tags, "_get_host_platform", lambda: "linux_x86_64") monkeypatch.setattr(platform, "machine", lambda: "x86_64") monkeypatch.setattr(os, "confstr", lambda x: "glibc 2.20", raising=False) platforms = list(tags._linux_platforms(is_32bit=False)) @@ -517,7 +517,7 @@ def test_linux_platforms_manylinux1(self, monkeypatch): assert platforms == ["manylinux1_" + arch, "linux_" + arch] def test_linux_platforms_manylinux2010(self, monkeypatch): - monkeypatch.setattr(distutils.util, "get_platform", lambda: "linux_x86_64") + monkeypatch.setattr(tags, "_get_host_platform", lambda: "linux_x86_64") monkeypatch.setattr(platform, "machine", lambda: "x86_64") monkeypatch.setattr(os, "confstr", lambda x: "glibc 2.12", raising=False) platforms = list(tags._linux_platforms(is_32bit=False)) @@ -538,7 +538,7 @@ def test_linux_platforms_manylinux2010(self, monkeypatch): assert platforms == expected def test_linux_platforms_manylinux2014(self, monkeypatch): - monkeypatch.setattr(distutils.util, "get_platform", lambda: "linux_x86_64") + monkeypatch.setattr(tags, "_get_host_platform", lambda: "linux_x86_64") monkeypatch.setattr(platform, "machine", lambda: "x86_64") monkeypatch.setattr(os, "confstr", lambda x: "glibc 2.17", raising=False) platforms = list(tags._linux_platforms(is_32bit=False)) @@ -571,7 +571,7 @@ def test_linux_platforms_manylinux2014_armhf_abi(self, monkeypatch): "_is_manylinux_compatible", lambda name, *args: name == "manylinux2014", ) - monkeypatch.setattr(distutils.util, "get_platform", lambda: "linux_armv7l") + monkeypatch.setattr(tags, "_get_host_platform", lambda: "linux_armv7l") monkeypatch.setattr( sys, "executable", @@ -583,7 +583,7 @@ def test_linux_platforms_manylinux2014_armhf_abi(self, monkeypatch): def test_linux_platforms_manylinux2014_i386_abi(self, monkeypatch): monkeypatch.setattr(tags, "_glibc_version_string", lambda: "2.17") - monkeypatch.setattr(distutils.util, "get_platform", lambda: "linux_x86_64") + monkeypatch.setattr(tags, "_get_host_platform", lambda: "linux_x86_64") monkeypatch.setattr( sys, "executable", @@ -615,7 +615,7 @@ def test_linux_platforms_manylinux_glibc3(self, monkeypatch): # test for a future glic 3.x version monkeypatch.setattr(tags, "_glibc_version_string", lambda: "3.2") monkeypatch.setattr(tags, "_is_manylinux_compatible", lambda name, *args: True) - monkeypatch.setattr(distutils.util, "get_platform", lambda: "linux_aarch64") + monkeypatch.setattr(tags, "_get_host_platform", lambda: "linux_aarch64") monkeypatch.setattr( sys, "executable", @@ -633,7 +633,7 @@ def test_linux_platforms_manylinux2014_armv6l(self, monkeypatch): monkeypatch.setattr( tags, "_is_manylinux_compatible", lambda name, _: name == "manylinux2014" ) - monkeypatch.setattr(distutils.util, "get_platform", lambda: "linux_armv6l") + monkeypatch.setattr(tags, "_get_host_platform", lambda: "linux_armv6l") monkeypatch.setattr(os, "confstr", lambda x: "glibc 2.20", raising=False) platforms = list(tags._linux_platforms(is_32bit=True)) expected = ["linux_armv6l"] @@ -648,7 +648,7 @@ def test_linux_platforms_not_manylinux_abi( ): monkeypatch.setattr(tags, "_is_manylinux_compatible", lambda name, _: False) monkeypatch.setattr( - distutils.util, "get_platform", lambda: "linux_{}".format(machine) + tags, "_get_host_platform", lambda: "linux_{}".format(machine) ) monkeypatch.setattr( sys, @@ -995,7 +995,7 @@ def test__generic_abi_no_soabi(self, monkeypatch): assert not list(tags._generic_abi()) def test_generic_platforms(self): - platform = distutils.util.get_platform().replace("-", "_") + platform = tags._get_host_platform().replace("-", "_") platform = platform.replace(".", "_") assert list(tags._generic_platforms()) == [platform] @@ -1269,14 +1269,14 @@ def test_generic(self, monkeypatch): assert result[-1] == expected def test_linux_platforms_manylinux2014_armv6l(self, monkeypatch, manylinux_module): - monkeypatch.setattr(distutils.util, "get_platform", lambda: "linux_armv6l") + monkeypatch.setattr(tags, "_get_host_platform", lambda: "linux_armv6l") monkeypatch.setattr(os, "confstr", lambda x: "glibc 2.20", raising=False) platforms = list(tags._linux_platforms(is_32bit=True)) expected = ["linux_armv6l"] assert platforms == expected def test_skip_manylinux_2014(self, monkeypatch, manylinux_module): - monkeypatch.setattr(distutils.util, "get_platform", lambda: "linux_ppc64") + monkeypatch.setattr(tags, "_get_host_platform", lambda: "linux_ppc64") monkeypatch.setattr(tags, "_get_glibc_version", lambda: (2, 20)) monkeypatch.setattr( manylinux_module, "manylinux2014_compatible", False, raising=False @@ -1300,7 +1300,7 @@ def test_linux_platforms_not_manylinux_abi( self, monkeypatch, manylinux_module, machine, abi, alt_machine ): monkeypatch.setattr( - distutils.util, "get_platform", lambda: "linux_{}".format(machine) + tags, "_get_host_platform", lambda: "linux_{}".format(machine) ) monkeypatch.setattr( sys, @@ -1326,7 +1326,7 @@ def manylinux_compatible(tag_major, tag_minor, tag_arch): monkeypatch.setattr(tags, "_get_glibc_version", lambda: (major, minor)) monkeypatch.setattr( - distutils.util, "get_platform", lambda: "linux_{}".format(machine) + tags, "_get_host_platform", lambda: "linux_{}".format(machine) ) monkeypatch.setattr( manylinux_module, @@ -1349,7 +1349,7 @@ def manylinux_compatible(tag_major, tag_minor, tag_arch): return None monkeypatch.setattr(tags, "_get_glibc_version", lambda: (2, 30)) - monkeypatch.setattr(distutils.util, "get_platform", lambda: "linux_x86_64") + monkeypatch.setattr(tags, "_get_host_platform", lambda: "linux_x86_64") monkeypatch.setattr( manylinux_module, "manylinux_compatible", From 06b458320f6aa9848617df0f78a52441e19c614c Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Sat, 7 Nov 2020 14:59:46 +0800 Subject: [PATCH 2/5] Replace distutils.sysconfig call with sysconfig _osx_support.get_platform_osx() only uses three configs: * MACOSX_DEPLOYMENT_TARGET * CFLAGS * _OSX_SUPPORT_INITIAL_CFLAGS All of these should be identical from both sources. --- packaging/tags.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/tags.py b/packaging/tags.py index 51b1d7a7..27c45dca 100644 --- a/packaging/tags.py +++ b/packaging/tags.py @@ -851,10 +851,10 @@ def _get_host_platform(): if m: release = m.group() elif osname[:6] == "darwin": - import distutils.sysconfig + import sysconfig import _osx_support osname, release, machine = _osx_support.get_platform_osx( - distutils.sysconfig.get_config_vars(), + sysconfig.get_config_vars(), osname, release, machine, ) From 6ec5a26b06b57c9b733e2dfb7bc4f2c386aaf9b8 Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Sat, 7 Nov 2020 15:04:25 +0800 Subject: [PATCH 3/5] Modernize _get_host_platform() Black-ify, and replace %-formatting with str.format() --- packaging/tags.py | 56 +++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/packaging/tags.py b/packaging/tags.py index 27c45dca..37dc2b7d 100644 --- a/packaging/tags.py +++ b/packaging/tags.py @@ -779,12 +779,13 @@ def _manylinux_tags(linux, arch): def _get_host_platform(): # type: () -> str - """Return a string that identifies the current platform. This is used mainly to - distinguish platform-specific build directories and platform-specific built - distributions. Typically includes the OS name and version and the - architecture (as supplied by 'os.uname()'), although the exact information - included depends on the OS; eg. on Linux, the kernel version isn't - particularly important. + """Return a string that identifies the current platform. + + This is used mainly to distinguish platform-specific build directories and + platform-specific built distributions. Typically includes the OS name and + version and the architecture (as supplied by 'os.uname()'), although the + exact information included depends on the OS; eg. on Linux, the kernel + version isn't particularly important. Examples of returned values: linux-i586 @@ -796,22 +797,21 @@ def _get_host_platform(): win32 (all others - specifically, sys.platform is returned) For other non-POSIX platforms, currently just returns 'sys.platform'. - """ - if os.name == 'nt': - if 'amd64' in sys.version.lower(): - return 'win-amd64' - if '(arm)' in sys.version.lower(): - return 'win-arm32' - if '(arm64)' in sys.version.lower(): - return 'win-arm64' + if os.name == "nt": + if "amd64" in sys.version.lower(): + return "win-amd64" + if "(arm)" in sys.version.lower(): + return "win-arm32" + if "(arm64)" in sys.version.lower(): + return "win-arm64" return sys.platform # Set for cross builds explicitly if "_PYTHON_HOST_PLATFORM" in os.environ: return os.environ["_PYTHON_HOST_PLATFORM"] - if os.name != "posix" or not hasattr(os, 'uname'): + if os.name != "posix" or not hasattr(os, "uname"): # XXX what about the architecture? NT is Intel or Alpha, # Mac OS is M68k or PPC, etc. return sys.platform @@ -822,43 +822,43 @@ def _get_host_platform(): # Convert the OS name to lowercase, remove '/' characters, and translate # spaces (for "Power Macintosh") - osname = osname.lower().replace('/', '') - machine = machine.replace(' ', '_') - machine = machine.replace('/', '-') + osname = osname.lower().replace("/", "") + machine = machine.replace(" ", "_") + machine = machine.replace("/", "-") if osname[:5] == "linux": - # At least on Linux/Intel, 'machine' is the processor -- - # i386, etc. + # At least on Linux/Intel, 'machine' is the processor -- i386, etc. # XXX what about Alpha, SPARC, etc? - return "%s-%s" % (osname, machine) + return "{}-{}".format(osname, machine) elif osname[:5] == "sunos": - if release[0] >= "5": # SunOS 5 == Solaris 2 + if release[0] >= "5": # SunOS 5 == Solaris 2 osname = "solaris" - release = "%d.%s" % (int(release[0]) - 3, release[2:]) + release = "{}.{}".format(int(release[0]) - 3, release[2:]) # We can't use "platform.architecture()[0]" because a # bootstrap problem. We use a dict to get an error # if some suspicious happens. bitness = {2147483647: "32bit", 9223372036854775807: "64bit"} - machine += ".%s" % bitness[sys.maxsize] + machine += ".{}".format(bitness[sys.maxsize]) # fall through to standard osname-release-machine representation elif osname[:3] == "aix": from _aix_support import aix_platform + return cast(str, aix_platform()) elif osname[:6] == "cygwin": osname = "cygwin" - rel_re = re.compile(r'[\d.]+', re.ASCII) + rel_re = re.compile(r"[\d.]+", re.ASCII) m = rel_re.match(release) if m: release = m.group() elif osname[:6] == "darwin": import sysconfig import _osx_support + osname, release, machine = _osx_support.get_platform_osx( - sysconfig.get_config_vars(), - osname, release, machine, + sysconfig.get_config_vars(), osname, release, machine ) - return "%s-%s-%s" % (osname, release, machine) + return "{}-{}-{}".format(osname, release, machine) def _linux_platforms(is_32bit=_32_BIT_INTERPRETER): From 02faa59bfc2448d3b7e47db0c68d102a5f7b7616 Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Sat, 7 Nov 2020 15:39:09 +0800 Subject: [PATCH 4/5] Fix re.ASCII usage on Python 2 --- packaging/tags.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packaging/tags.py b/packaging/tags.py index 37dc2b7d..3e33adc6 100644 --- a/packaging/tags.py +++ b/packaging/tags.py @@ -21,6 +21,7 @@ import sysconfig import warnings +from ._compat import PY2 from ._typing import TYPE_CHECKING, cast if TYPE_CHECKING: # pragma: no cover @@ -846,7 +847,10 @@ def _get_host_platform(): return cast(str, aix_platform()) elif osname[:6] == "cygwin": osname = "cygwin" - rel_re = re.compile(r"[\d.]+", re.ASCII) + if PY2: # Python 2 does not have re.ASCII. + rel_re = re.compile(r"[\d.]+") + else: + rel_re = re.compile(r"[\d.]+", re.ASCII) m = rel_re.match(release) if m: release = m.group() From 2f3c6f6baaa797ed76d19bc7e4a08e122655d757 Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Thu, 4 Feb 2021 10:14:35 +0800 Subject: [PATCH 5/5] Use sysconfig for _aix_support and _osx_support --- packaging/tags.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/packaging/tags.py b/packaging/tags.py index 3e33adc6..9208cee7 100644 --- a/packaging/tags.py +++ b/packaging/tags.py @@ -842,9 +842,7 @@ def _get_host_platform(): machine += ".{}".format(bitness[sys.maxsize]) # fall through to standard osname-release-machine representation elif osname[:3] == "aix": - from _aix_support import aix_platform - - return cast(str, aix_platform()) + return sysconfig.get_platform() elif osname[:6] == "cygwin": osname = "cygwin" if PY2: # Python 2 does not have re.ASCII. @@ -855,12 +853,7 @@ def _get_host_platform(): if m: release = m.group() elif osname[:6] == "darwin": - import sysconfig - import _osx_support - - osname, release, machine = _osx_support.get_platform_osx( - sysconfig.get_config_vars(), osname, release, machine - ) + return sysconfig.get_platform() return "{}-{}-{}".format(osname, release, machine)