Skip to content

Commit

Permalink
Implement PEP 513: manylinux1 platform tags
Browse files Browse the repository at this point in the history
  • Loading branch information
rmcgibbo authored and ogrisel committed Feb 24, 2016
1 parent 09b99e8 commit 3e67145
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 2 deletions.
54 changes: 52 additions & 2 deletions pip/pep425tags.py
Expand Up @@ -124,7 +124,54 @@ def get_platform():
split_ver = release.split('.')
return 'macosx_{0}_{1}_{2}'.format(split_ver[0], split_ver[1], machine)
# XXX remove distutils dependency
return distutils.util.get_platform().replace('.', '_').replace('-', '_')
result = distutils.util.get_platform().replace('.', '_').replace('-', '_')
if result == "linux_x86_64" and sys.maxsize == 2147483647:
result = "linux_i686"
return result


def is_manylinux1_compatible():
# Only Linux, and only x86-64 / i686
if get_platform() not in ("linux_x86_64", "linux_i686"):
return False

# Check for presence of _manylinux module
try:
import _manylinux
return bool(_manylinux.manylinux1_compatible)
except (ImportError, AttributeError):
# Fall through to heuristic check below
pass

# Check glibc version. CentOS 5 uses glibc 2.5.
return have_compatible_glibc(2, 5)


def have_compatible_glibc(major, minimum_minor):
import ctypes
process_namespace = ctypes.CDLL(None)
try:
gnu_get_libc_version = process_namespace.gnu_get_libc_version
except AttributeError:
# Symbol doesn't exist -> therefore, we are not linked to
# glibc.
return False

# Call gnu_get_libc_version, which returns a string like "2.5".
gnu_get_libc_version.restype = ctypes.c_char_p
version_str = gnu_get_libc_version()
# py2 / py3 compatibility:
if not isinstance(version_str, str):
version_str = version_str.decode("ascii")

# Parse string and check against requested version.
version = [int(piece) for piece in version_str.split(".")]
assert len(version) == 2
if major != version[0]:
return False
if minimum_minor > version[1]:
return False
return True


def get_supported(versions=None, noarch=False):
Expand Down Expand Up @@ -189,6 +236,8 @@ def get_supported(versions=None, noarch=False):
else:
# arch pattern didn't match (?!)
arches = [arch]
elif is_manylinux1_compatible():
arches = [arch.replace('linux', 'manylinux1'), arch]
else:
arches = [arch]

Expand All @@ -198,7 +247,8 @@ def get_supported(versions=None, noarch=False):
supported.append(('%s%s' % (impl, versions[0]), abi, arch))

# Has binaries, does not use the Python API:
supported.append(('py%s' % (versions[0][0]), 'none', arch))
for arch in arches:
supported.append(('py%s' % (versions[0][0]), 'none', arch))

# No abi / arch, but requires our implementation:
for i, version in enumerate(versions):
Expand Down
55 changes: 55 additions & 0 deletions tests/unit/test_pep425tags.py
Expand Up @@ -104,3 +104,58 @@ def test_manual_abi_dm_flags(self):
Test that the `dm` flags are set on a PyDebug, Pymalloc ABI tag.
"""
self.abi_tag_unicode('dm', {'Py_DEBUG': True, 'WITH_PYMALLOC': True})


class TestManylinux1Tags(object):

@patch('pip.pep425tags.get_platform', lambda: 'linux_x86_64')
@patch('pip.pep425tags.have_compatible_glibc', lambda major, minor: True)
def test_manylinux1_compatible_on_linux_x86_64(self):
"""
Test that manylinux1 is enabled on linux_x86_64
"""
assert pep425tags.is_manylinux1_compatible()

@patch('pip.pep425tags.get_platform', lambda: 'linux_i686')
@patch('pip.pep425tags.have_compatible_glibc', lambda major, minor: True)
def test_manylinux1_compatible_on_linux_i686(self):
"""
Test that manylinux1 is enabled on linux_i686
"""
assert pep425tags.is_manylinux1_compatible()

@patch('pip.pep425tags.get_platform', lambda: 'linux_x86_64')
@patch('pip.pep425tags.have_compatible_glibc', lambda major, minor: False)
def test_manylinux1_2(self):
"""
Test that manylinux1 is disabled with incompatible glibc
"""
assert not pep425tags.is_manylinux1_compatible()

@patch('pip.pep425tags.get_platform', lambda: 'arm6vl')
@patch('pip.pep425tags.have_compatible_glibc', lambda major, minor: True)
def test_manylinux1_3(self):
"""
Test that manylinux1 is disabled on arm6vl
"""
assert not pep425tags.is_manylinux1_compatible()

@patch('pip.pep425tags.get_platform', lambda: 'linux_x86_64')
@patch('pip.pep425tags.have_compatible_glibc', lambda major, minor: True)
@patch('sys.platform', 'linux2')
def test_manylinux1_tag_is_first(self):
"""
Test that the more specific tag manylinux1 comes first.
"""
groups = {}
for pyimpl, abi, arch in pep425tags.get_supported():
groups.setdefault((pyimpl, abi), []).append(arch)

for arches in groups.values():
if arches == ['any']:
continue
# Expect the most specific arch first:
if len(arches) == 3:
assert arches == ['manylinux1_x86_64', 'linux_x86_64', 'any']
else:
assert arches == ['manylinux1_x86_64', 'linux_x86_64']

0 comments on commit 3e67145

Please sign in to comment.