[Python-checkins] bpo-26544: Fixed implementation of platform.libc_ver(). (GH-7684). (GH-8193) (GH-8196)

Serhiy Storchaka webhook-mailer at python.org
Mon Jul 9 07:39:10 EDT 2018


https://github.com/python/cpython/commit/b1e6e5615a8e82fcf569368fac5c5b0385929855
commit: b1e6e5615a8e82fcf569368fac5c5b0385929855
branch: 2.7
author: Serhiy Storchaka <storchaka at gmail.com>
committer: GitHub <noreply at github.com>
date: 2018-07-09T14:39:06+03:00
summary:

bpo-26544: Fixed implementation of platform.libc_ver(). (GH-7684). (GH-8193) (GH-8196)

(cherry picked from commit 2a9b8babf0d09946ebebfdb2931cc0d3db5a1d3d).
(cherry picked from commit 7c43b801503c802ed6ea4b811f5bc73791249d94)

files:
A Misc/NEWS.d/next/Library/2018-06-13-20-33-29.bpo-26544.hQ1oMt.rst
M Lib/platform.py
M Lib/test/test_platform.py

diff --git a/Lib/platform.py b/Lib/platform.py
index 55f2fa89957f..44a612b28fce 100755
--- a/Lib/platform.py
+++ b/Lib/platform.py
@@ -140,9 +140,7 @@
                           '|'
                           '(libc(_\w+)?\.so(?:\.(\d[0-9.]*))?)')
 
-def libc_ver(executable=sys.executable,lib='',version='',
-
-             chunksize=2048):
+def libc_ver(executable=sys.executable,lib='',version='', chunksize=2048):
 
     """ Tries to determine the libc version that the file executable
         (which defaults to the Python interpreter) is linked against.
@@ -157,40 +155,42 @@ def libc_ver(executable=sys.executable,lib='',version='',
         The file is read and scanned in chunks of chunksize bytes.
 
     """
+    from distutils.version import LooseVersion as V
     if hasattr(os.path, 'realpath'):
         # Python 2.2 introduced os.path.realpath(); it is used
         # here to work around problems with Cygwin not being
         # able to open symlinks for reading
         executable = os.path.realpath(executable)
-    f = open(executable,'rb')
-    binary = f.read(chunksize)
-    pos = 0
-    while 1:
-        m = _libc_search.search(binary,pos)
-        if not m:
-            binary = f.read(chunksize)
-            if not binary:
-                break
-            pos = 0
-            continue
-        libcinit,glibc,glibcversion,so,threads,soversion = m.groups()
-        if libcinit and not lib:
-            lib = 'libc'
-        elif glibc:
-            if lib != 'glibc':
-                lib = 'glibc'
-                version = glibcversion
-            elif glibcversion > version:
-                version = glibcversion
-        elif so:
-            if lib != 'glibc':
+    with open(executable, 'rb') as f:
+        binary = f.read(chunksize)
+        pos = 0
+        while pos < len(binary):
+            m = _libc_search.search(binary,pos)
+            if not m or m.end() == len(binary):
+                chunk = f.read(chunksize)
+                if chunk:
+                    binary = binary[max(pos, len(binary) - 1000):] + chunk
+                    pos = 0
+                    continue
+                if not m:
+                    break
+            libcinit,glibc,glibcversion,so,threads,soversion = m.groups()
+            if libcinit and not lib:
                 lib = 'libc'
-                if soversion and soversion > version:
-                    version = soversion
-                if threads and version[-len(threads):] != threads:
-                    version = version + threads
-        pos = m.end()
-    f.close()
+            elif glibc:
+                if lib != 'glibc':
+                    lib = 'glibc'
+                    version = glibcversion
+                elif V(glibcversion) > V(version):
+                    version = glibcversion
+            elif so:
+                if lib != 'glibc':
+                    lib = 'libc'
+                    if soversion and (not version or V(soversion) > V(version)):
+                        version = soversion
+                    if threads and version[-len(threads):] != threads:
+                        version = version + threads
+            pos = m.end()
     return lib,version
 
 def _dist_try_harder(distname,version,id):
@@ -451,6 +451,7 @@ def popen(cmd, mode='r', bufsize=None):
     else:
         return popen(cmd,mode,bufsize)
 
+
 def _norm_version(version, build=''):
 
     """ Normalize the version and build strings and return a single
diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py
index f754550f95d5..542763d46dfd 100644
--- a/Lib/test/test_platform.py
+++ b/Lib/test/test_platform.py
@@ -4,7 +4,7 @@
 import platform
 import subprocess
 
-from test import test_support
+from test import support
 
 class PlatformTest(unittest.TestCase):
     def test_architecture(self):
@@ -18,7 +18,7 @@ def get(python):
                 p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
                 return p.communicate()
             real = os.path.realpath(sys.executable)
-            link = os.path.abspath(test_support.TESTFN)
+            link = os.path.abspath(support.TESTFN)
             os.symlink(real, link)
             try:
                 self.assertEqual(get(real), get(link))
@@ -163,7 +163,7 @@ def test_uname_win32_ARCHITEW6432(self):
         # using it, per
         # http://blogs.msdn.com/david.wang/archive/2006/03/26/HOWTO-Detect-Process-Bitness.aspx
         try:
-            with test_support.EnvironmentVarGuard() as environ:
+            with support.EnvironmentVarGuard() as environ:
                 if 'PROCESSOR_ARCHITEW6432' in environ:
                     del environ['PROCESSOR_ARCHITEW6432']
                 environ['PROCESSOR_ARCHITECTURE'] = 'foo'
@@ -247,7 +247,6 @@ def test_dist(self):
         res = platform.dist()
 
     def test_libc_ver(self):
-        import os
         if os.path.isdir(sys.executable) and \
            os.path.exists(sys.executable+'.exe'):
             # Cygwin horror
@@ -256,6 +255,13 @@ def test_libc_ver(self):
             executable = sys.executable
         res = platform.libc_ver(executable)
 
+        self.addCleanup(support.unlink, support.TESTFN)
+        with open(support.TESTFN, 'wb') as f:
+            f.write(b'x'*(16384-10))
+            f.write(b'GLIBC_1.23.4\0GLIBC_1.9\0GLIBC_1.21\0')
+        self.assertEqual(platform.libc_ver(support.TESTFN),
+                         ('glibc', '1.23.4'))
+
     def test_parse_release_file(self):
 
         for input, output in (
@@ -275,7 +281,7 @@ def test_parse_release_file(self):
 
 
 def test_main():
-    test_support.run_unittest(
+    support.run_unittest(
         PlatformTest
     )
 
diff --git a/Misc/NEWS.d/next/Library/2018-06-13-20-33-29.bpo-26544.hQ1oMt.rst b/Misc/NEWS.d/next/Library/2018-06-13-20-33-29.bpo-26544.hQ1oMt.rst
new file mode 100644
index 000000000000..e2cd0bad6e2c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2018-06-13-20-33-29.bpo-26544.hQ1oMt.rst
@@ -0,0 +1,2 @@
+Fixed implementation of :func:`platform.libc_ver`. It almost always returned
+version '2.9' for glibc.



More information about the Python-checkins mailing list