diff --git a/packaging/tags.py b/packaging/tags.py index d637f1b6..9208cee7 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 @@ -23,6 +21,7 @@ import sysconfig import warnings +from ._compat import PY2 from ._typing import TYPE_CHECKING, cast if TYPE_CHECKING: # pragma: no cover @@ -611,7 +610,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 +778,89 @@ 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 "{}-{}".format(osname, machine) + elif osname[:5] == "sunos": + if release[0] >= "5": # SunOS 5 == Solaris 2 + osname = "solaris" + 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 += ".{}".format(bitness[sys.maxsize]) + # fall through to standard osname-release-machine representation + elif osname[:3] == "aix": + return sysconfig.get_platform() + elif osname[:6] == "cygwin": + osname = "cygwin" + 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() + elif osname[:6] == "darwin": + return sysconfig.get_platform() + + return "{}-{}-{}".format(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 +875,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",