Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions Doc/library/platform.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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::

Expand All @@ -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()

Expand Down
37 changes: 11 additions & 26 deletions Lib/platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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
Expand Down
9 changes: 8 additions & 1 deletion Lib/test/test_platform.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import platform
import struct
import subprocess
import sys
import sysconfig
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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.