diff --git a/Doc/library/platform.rst b/Doc/library/platform.rst index 60c6089ad3ccb58..576e25d3377fb75 100644 --- a/Doc/library/platform.rst +++ b/Doc/library/platform.rst @@ -35,10 +35,9 @@ Cross Platform ``sizeof(long)`` on Python version < 1.5.2) is used as indicator for the supported pointer size. - The function relies on the system's :file:`file` command to do the actual work. - This is available on most if not all Unix platforms and some non-Unix platforms - and then only if the executable points to the Python interpreter. Reasonable - defaults are used when the above needs are not met. + If the *executable* parameter is set, the function relies on the system's + :file:`file` command to do the actual work. This is available on most Unix + platforms. .. note:: @@ -50,6 +49,10 @@ Cross Platform is_64bits = sys.maxsize > 2**32 + .. versionchanged:: 3.8 + The system's :file:`file` command is now longer used if the *executable* + parameter is not set. + .. function:: machine() diff --git a/Lib/platform.py b/Lib/platform.py index 0fe841c71ce675e..3e1a6ced6809d05 100755 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -171,7 +171,7 @@ def libc_ver(executable=None, lib='', version='', chunksize=16384): The file is read and scanned in chunks of chunksize bytes. """ - if executable is None: + if executable is None or executable == sys.executable: try: ver = os.confstr('CS_GNU_LIBC_VERSION') # parse 'glibc 2.28' as ('glibc', '2.28') @@ -618,15 +618,9 @@ def _syscmd_file(target, default=''): ### Information about the used architecture -# Default values for architecture; non-empty strings override the -# defaults given as parameters -_default_architecture = { - 'win32': ('', 'WindowsPE'), - 'win16': ('', 'Windows'), - 'dos': ('', 'MSDOS'), -} +_DEFAULT_LINKAGE = {'win32': 'WindowsPE'} -def architecture(executable=sys.executable, bits='', linkage=''): +def architecture(executable=None, bits='', linkage=''): """ Queries the given executable (defaults to the Python interpreter binary) for various architecture information. @@ -640,11 +634,9 @@ def architecture(executable=sys.executable, bits='', linkage=''): (or sizeof(long) on Python version < 1.5.2) is used as indicator for the supported pointer size. - The function relies on the system's "file" command to do the - actual work. This is available on most if not all Unix - platforms. On some non-Unix platforms where the "file" command - does not exist and the executable is set to the Python interpreter - binary defaults from _default_architecture are used. + If the executable parameter is set, the function relies on the system's + "file" command to do the actual work. This is available on most Unix + platforms. """ # Use the sizeof(pointer) as default number of bits if nothing @@ -654,24 +646,17 @@ def architecture(executable=sys.executable, bits='', linkage=''): size = struct.calcsize('P') bits = str(size * 8) + 'bit' + # bpo-35348: For Python executable, don't use the file command + if executable is None or executable == sys.executable: + linkage = _DEFAULT_LINKAGE.get(sys.platform, linkage) + return bits, linkage + # Get data from the 'file' system command if executable: fileout = _syscmd_file(executable, '') else: fileout = '' - if not fileout and \ - executable == sys.executable: - # "file" command did not return anything; we'll try to provide - # some sensible defaults then... - if sys.platform in _default_architecture: - b, l = _default_architecture[sys.platform] - if b: - bits = b - if l: - linkage = l - return bits, linkage - if 'executable' not in fileout: # Format not supported return bits, linkage diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py index 9cf17726d92e0dc..7ef9353a9cf85b3 100644 --- a/Lib/test/test_platform.py +++ b/Lib/test/test_platform.py @@ -1,5 +1,6 @@ import os import platform +import struct import subprocess import sys import sysconfig @@ -16,7 +17,13 @@ def clear_caches(self): platform._uname_cache = None def test_architecture(self): - res = platform.architecture() + bits, linkage = platform.architecture() + pointer_bits = struct.calcsize('P') * 8 + self.assertEqual(bits, f"{pointer_bits}bit") + if sys.platform == 'win32': + self.assertEqual(linkage, 'WindowsPE') + else: + self.assertEqual(linkage, '') @support.skip_unless_symlink def test_architecture_via_symlink(self): # issue3762 diff --git a/Misc/NEWS.d/next/Library/2018-12-17-10-01-15.bpo-35348.rUPsJI.rst b/Misc/NEWS.d/next/Library/2018-12-17-10-01-15.bpo-35348.rUPsJI.rst new file mode 100644 index 000000000000000..e286801a2b7ebd7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-12-17-10-01-15.bpo-35348.rUPsJI.rst @@ -0,0 +1,2 @@ +Fix :func:`platform.architecture` for macOS universal binaries: it no longer +uses the system's ``file`` command if the *executable* parameter is not set.