platform.py revision eb9957065acaafbf3d8ebee4770ecb13ea0c07c0
190f5ba538bf40bcf4fd41049c7bf4296d3ffc9c7Benjamin Peterson#!/usr/bin/env python3
2246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
38ab27dfa135dc1f3f3f156db2ae5e13c46eeb5a4Brett Cannon""" This module tries to retrieve as much platform-identifying data as
4246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    possible. It makes this information available via function APIs.
5246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
6246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    If called from the command line, it prints the platform
7246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    information concatenated as single string to stdout. The output
8246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    format is useable as part of a filename.
9246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
10246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg"""
11246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    This module is maintained by Marc-Andre Lemburg <mal@egenix.com>.
12246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    If you find problems, please submit bug reports/patches via the
134ac9ce4f9a33a330a555ae8015e2f2ae2780fafbBenjamin Peterson#    Python bug tracker (http://bugs.python.org) and assign them to "lemburg".
14246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#
15246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    Still needed:
16246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    * more support for WinCE
17246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    * support for MS-DOS (PythonDX ?)
18246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    * support for Amiga and other still unsupported platforms running Python
19246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    * support for additional Linux distributions
20246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#
218ab27dfa135dc1f3f3f156db2ae5e13c46eeb5a4Brett Cannon#    Many thanks to all those who helped adding platform-specific
22246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    checks (in no particular order):
23246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#
24246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#      Charles G Waldman, David Arnold, Gordon McMillan, Ben Darnell,
25246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#      Jeff Bauer, Cliff Crawford, Ivan Van Laningham, Josef
26246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#      Betancourt, Randall Hopper, Karl Putland, John Farrell, Greg
27246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#      Andruk, Just van Rossum, Thomas Heller, Mark R. Levinson, Mark
28246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#      Hammond, Bill Tutt, Hans Nowak, Uwe Zessin (OpenVMS support),
29b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower#      Colin Kong, Trent Mick, Guido van Rossum, Anthony Baxter, Steve
30b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower#      Dower
31246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#
32246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    History:
33380f417e15dd36e6656a4f65e9c5ccd75134b8c1Marc-André Lemburg#
34380f417e15dd36e6656a4f65e9c5ccd75134b8c1Marc-André Lemburg#    <see CVS and SVN checkin messages for history>
35380f417e15dd36e6656a4f65e9c5ccd75134b8c1Marc-André Lemburg#
36b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower#    1.0.8 - changed Windows support to read version from kernel32.dll
37e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti#    1.0.7 - added DEV_NULL
38fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters#    1.0.6 - added linux_distribution()
39fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters#    1.0.5 - fixed Java support to allow running the module on Jython
40fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters#    1.0.4 - added IronPython support
41cdc7923f6d1c9731d81f299569b1ea72de7eb212Marc-André Lemburg#    1.0.3 - added normalization of Windows system name
4291e83e209d66d4b7a892c9360f9e524d6e282191Marc-André Lemburg#    1.0.2 - added more Windows support
43366a0feb9a7794a9f72ab0b37d36b6427e6d3bd1Marc-André Lemburg#    1.0.1 - reformatted to make doc.py happy
44246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    1.0.0 - reformatted a bit and checked into Python CVS
45246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.8.0 - added sys.version parser and various new access
46246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#            APIs (python_version(), python_compiler(), etc.)
47246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.7.2 - fixed architecture() to use sizeof(pointer) where available
48246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.7.1 - added support for Caldera OpenLinux
49246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.7.0 - some fixes for WinCE; untabified the source file
50246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.6.2 - support for OpenVMS - requires version 1.5.2-V006 or higher and
51246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#            vms_lib.getsyi() configured
52246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.6.1 - added code to prevent 'uname -p' on platforms which are
53246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#            known not to support it
54246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.6.0 - fixed win32_ver() to hopefully work on Win95,98,NT and Win2k;
55246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#            did some cleanup of the interfaces - some APIs have changed
56246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.5.5 - fixed another type in the MacOS code... should have
57246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#            used more coffee today ;-)
58246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.5.4 - fixed a few typos in the MacOS code
59246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.5.3 - added experimental MacOS support; added better popen()
60246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#            workarounds in _syscmd_ver() -- still not 100% elegant
61246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#            though
62246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.5.2 - fixed uname() to return '' instead of 'unknown' in all
63246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#            return values (the system uname command tends to return
64eb9957065acaafbf3d8ebee4770ecb13ea0c07c0Martin Panter#            'unknown' instead of just leaving the field empty)
65246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.5.1 - included code for slackware dist; added exception handlers
66246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#            to cover up situations where platforms don't have os.popen
67246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#            (e.g. Mac) or fail on socket.gethostname(); fixed libc
68246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#            detection RE
69246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.5.0 - changed the API names referring to system commands to *syscmd*;
70246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#            added java_ver(); made syscmd_ver() a private
71246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#            API (was system_ver() in previous versions) -- use uname()
72246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#            instead; extended the win32_ver() to also return processor
73246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#            type information
74246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.4.0 - added win32_ver() and modified the platform() output for WinXX
75246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.3.4 - fixed a bug in _follow_symlinks()
76246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.3.3 - fixed popen() and "file" command invokation bugs
77246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.3.2 - added architecture() API and support for it in platform()
78246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.3.1 - fixed syscmd_ver() RE to support Windows NT
79246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.3.0 - added system alias support
80246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.2.3 - removed 'wince' again... oh well.
81246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.2.2 - added 'wince' to syscmd_ver() supported platforms
82246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.2.1 - added cache logic and changed the platform string format
83246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.2.0 - changed the API to use functions instead of module globals
84246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#            since some action take too long to be run on module import
85246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    0.1.0 - first release
86246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#
87246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    You can always get the latest version of this module at:
88246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#
89246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#             http://www.egenix.com/files/python/platform.py
90246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#
91246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg#    If that URL should fail, try contacting the author.
92246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
93246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg__copyright__ = """
94246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    Copyright (c) 1999-2000, Marc-Andre Lemburg; mailto:mal@lemburg.com
9546a9900e099a82cda7328b0de16d6fffe52ee62aBenjamin Peterson    Copyright (c) 2000-2010, eGenix.com Software GmbH; mailto:info@egenix.com
96246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
97246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    Permission to use, copy, modify, and distribute this software and its
98246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    documentation for any purpose and without fee or royalty is hereby granted,
99246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    provided that the above copyright notice appear in all copies and that
100246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    both that copyright notice and this permission notice appear in
101246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    supporting documentation or portions thereof, including modifications,
102246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    that you make.
103246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
104246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    EGENIX.COM SOFTWARE GMBH DISCLAIMS ALL WARRANTIES WITH REGARD TO
105246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
106246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
107246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
108246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
109246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
110246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    WITH THE USE OR PERFORMANCE OF THIS SOFTWARE !
111246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
112246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg"""
113246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
114e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti__version__ = '1.0.7'
115246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
11668386bc0b88eb4b7c9aeb4f753114dc85f8df5b6Larry Hastingsimport collections
117fc990e942fb55be78e8352f4913749e91cac381dJesus Ceaimport sys, os, re, subprocess
118246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1191392f71c3927c9d81969200f5dfff9fb832cde0bBerker Peksagimport warnings
1201392f71c3927c9d81969200f5dfff9fb832cde0bBerker Peksag
121e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti### Globals & Constants
122e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti
123e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti# Determine the platform's /dev/null device
124e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalottitry:
125e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti    DEV_NULL = os.devnull
126e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalottiexcept AttributeError:
127e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti    # os.devnull was added in Python 2.4, so emulate it for earlier
128e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti    # Python versions
129ced3936894cec493b93c1144c543d51048268288Victor Stinner    if sys.platform in ('dos', 'win32', 'win16'):
130e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti        # Use the old CP/M NUL as device name
131e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti        DEV_NULL = 'NUL'
132e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti    else:
133e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti        # Standard Unix uses /dev/null
134e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti        DEV_NULL = '/dev/null'
135e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti
136620c48b7ea7a1ad3af23725afdac1e6a2b3e6cefVictor Stinner# Directory to search for configuration information on Unix.
137620c48b7ea7a1ad3af23725afdac1e6a2b3e6cefVictor Stinner# Constant used by test_platform to test linux_distribution().
138620c48b7ea7a1ad3af23725afdac1e6a2b3e6cefVictor Stinner_UNIXCONFDIR = '/etc'
139620c48b7ea7a1ad3af23725afdac1e6a2b3e6cefVictor Stinner
140246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg### Platform specific APIs
141246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
142ba7c226095703f63c78b00e56f1db8d99ac3a54aAntoine Pitrou_libc_search = re.compile(b'(__libc_init)'
143ba7c226095703f63c78b00e56f1db8d99ac3a54aAntoine Pitrou                          b'|'
144ba7c226095703f63c78b00e56f1db8d99ac3a54aAntoine Pitrou                          b'(GLIBC_([0-9.]+))'
145ba7c226095703f63c78b00e56f1db8d99ac3a54aAntoine Pitrou                          b'|'
146ba7c226095703f63c78b00e56f1db8d99ac3a54aAntoine Pitrou                          br'(libc(_\w+)?\.so(?:\.(\d[0-9.]*))?)', re.ASCII)
147366a0feb9a7794a9f72ab0b37d36b6427e6d3bd1Marc-André Lemburg
148ced3936894cec493b93c1144c543d51048268288Victor Stinnerdef libc_ver(executable=sys.executable, lib='', version='',
149246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
150ba7c226095703f63c78b00e56f1db8d99ac3a54aAntoine Pitrou             chunksize=16384):
151246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1528ab27dfa135dc1f3f3f156db2ae5e13c46eeb5a4Brett Cannon    """ Tries to determine the libc version that the file executable
1538ab27dfa135dc1f3f3f156db2ae5e13c46eeb5a4Brett Cannon        (which defaults to the Python interpreter) is linked against.
154246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
155246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        Returns a tuple of strings (lib,version) which default to the
156246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        given parameters in case the lookup fails.
157246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
158246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        Note that the function has intimate knowledge of how different
1598ab27dfa135dc1f3f3f156db2ae5e13c46eeb5a4Brett Cannon        libc versions add symbols to the executable and thus is probably
1608ab27dfa135dc1f3f3f156db2ae5e13c46eeb5a4Brett Cannon        only useable for executables compiled using gcc.
161246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
162246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        The file is read and scanned in chunks of chunksize bytes.
163246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
164246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
165fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    if hasattr(os.path, 'realpath'):
166fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        # Python 2.2 introduced os.path.realpath(); it is used
167fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        # here to work around problems with Cygwin not being
168fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        # able to open symlinks for reading
169fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        executable = os.path.realpath(executable)
17046ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka    with open(executable, 'rb') as f:
17146ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka        binary = f.read(chunksize)
17246ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka        pos = 0
17346ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka        while 1:
17446ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka            if b'libc' in binary or b'GLIBC' in binary:
17546ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka                m = _libc_search.search(binary, pos)
17646ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka            else:
17746ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka                m = None
17846ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka            if not m:
17946ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka                binary = f.read(chunksize)
18046ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka                if not binary:
18146ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka                    break
18246ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka                pos = 0
18346ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka                continue
18446ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka            libcinit, glibc, glibcversion, so, threads, soversion = [
18546ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka                s.decode('latin1') if s is not None else s
18646ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka                for s in m.groups()]
18746ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka            if libcinit and not lib:
188246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                lib = 'libc'
18946ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka            elif glibc:
19046ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka                if lib != 'glibc':
19146ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka                    lib = 'glibc'
19246ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka                    version = glibcversion
19346ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka                elif glibcversion > version:
19446ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka                    version = glibcversion
19546ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka            elif so:
19646ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka                if lib != 'glibc':
19746ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka                    lib = 'libc'
19846ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka                    if soversion and soversion > version:
19946ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka                        version = soversion
20046ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka                    if threads and version[-len(threads):] != threads:
20146ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka                        version = version + threads
20246ba6c8563922f043cad6423202ee0119614c807Serhiy Storchaka            pos = m.end()
203ced3936894cec493b93c1144c543d51048268288Victor Stinner    return lib, version
204246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
205ced3936894cec493b93c1144c543d51048268288Victor Stinnerdef _dist_try_harder(distname, version, id):
206246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
2070eadaac7dc3ae49974c105ff9e8c1e98a04d7d5aTim Peters    """ Tries some special tricks to get the distribution
208246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        information in case the default method fails.
209246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
210246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        Currently supports older SuSE Linux, Caldera OpenLinux and
211246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        Slackware Linux distributions.
212246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
213246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
214246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if os.path.exists('/var/adm/inst-log/info'):
215246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # SuSE Linux stores distribution information in that file
216246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        distname = 'SuSE'
2177dde792e62c8adeaf5d633dc89e18d16067add8eFlorent Xicluna        for line in open('/var/adm/inst-log/info'):
2189d72bb452bced3a100f07f8a9e30c4495a9ec41aNeal Norwitz            tv = line.split()
219246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            if len(tv) == 2:
220ced3936894cec493b93c1144c543d51048268288Victor Stinner                tag, value = tv
221246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            else:
222246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                continue
223246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            if tag == 'MIN_DIST_VERSION':
2249d72bb452bced3a100f07f8a9e30c4495a9ec41aNeal Norwitz                version = value.strip()
225246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            elif tag == 'DIST_IDENT':
2269d72bb452bced3a100f07f8a9e30c4495a9ec41aNeal Norwitz                values = value.split('-')
227246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                id = values[2]
228ced3936894cec493b93c1144c543d51048268288Victor Stinner        return distname, version, id
229246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
230246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if os.path.exists('/etc/.installed'):
231246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # Caldera OpenLinux has some infos in that file (thanks to Colin Kong)
2327dde792e62c8adeaf5d633dc89e18d16067add8eFlorent Xicluna        for line in open('/etc/.installed'):
2339d72bb452bced3a100f07f8a9e30c4495a9ec41aNeal Norwitz            pkg = line.split('-')
234246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            if len(pkg) >= 2 and pkg[0] == 'OpenLinux':
235246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                # XXX does Caldera support non Intel platforms ? If yes,
236246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                #     where can we find the needed id ?
237ced3936894cec493b93c1144c543d51048268288Victor Stinner                return 'OpenLinux', pkg[1], id
238246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
239246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if os.path.isdir('/usr/lib/setup'):
24030b9d5d3af043fc2687ad11a188a34fe355e20efEzio Melotti        # Check for slackware version tag file (thanks to Greg Andruk)
241246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        verfiles = os.listdir('/usr/lib/setup')
242843c734ddda3e317eee97dfdd32ff15ceede22fcGuido van Rossum        for n in range(len(verfiles)-1, -1, -1):
243246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            if verfiles[n][:14] != 'slack-version-':
244246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                del verfiles[n]
245246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        if verfiles:
246246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            verfiles.sort()
247246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            distname = 'slackware'
248246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            version = verfiles[-1][14:]
249ced3936894cec493b93c1144c543d51048268288Victor Stinner            return distname, version, id
250246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
251ced3936894cec493b93c1144c543d51048268288Victor Stinner    return distname, version, id
252246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
253fd036451bf0e0ade8783e21df801abf7be96d020Antoine Pitrou_release_filename = re.compile(r'(\w+)[-_](release|version)', re.ASCII)
254fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters_lsb_release_version = re.compile(r'(.+)'
255fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                                   ' release '
256fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                                   '([\d.]+)'
257fd036451bf0e0ade8783e21df801abf7be96d020Antoine Pitrou                                   '[^(]*(?:\((.+)\))?', re.ASCII)
258fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters_release_version = re.compile(r'([^0-9]+)'
259fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                               '(?: release )?'
260fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                               '([\d.]+)'
261fd036451bf0e0ade8783e21df801abf7be96d020Antoine Pitrou                               '[^(]*(?:\((.+)\))?', re.ASCII)
262fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
263fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters# See also http://www.novell.com/coolsolutions/feature/11251.html
2649fe394c1be9401c2b207b943f82e30af4ee32ab6Thomas Wouters# and http://linuxmafia.com/faq/Admin/release-files.html
265fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters# and http://data.linux-ntfs.org/rpm/whichrpm
266fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters# and http://www.die.net/doc/linux/man/man1/lsb_release.1.html
267fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
268dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes_supported_dists = (
269dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes    'SuSE', 'debian', 'fedora', 'redhat', 'centos',
270dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes    'mandrake', 'mandriva', 'rocks', 'slackware', 'yellowdog', 'gentoo',
271ab88803a8addf36ae3fc7e9270ebbed869f7f191Antoine Pitrou    'UnitedLinux', 'turbolinux', 'arch', 'mageia')
272fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
273fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Woutersdef _parse_release_file(firstline):
2749fe394c1be9401c2b207b943f82e30af4ee32ab6Thomas Wouters
275250014793e9ed7d6cfc6e25ac502bcb124895d23Benjamin Peterson    # Default to empty 'version' and 'id' strings.  Both defaults are used
276250014793e9ed7d6cfc6e25ac502bcb124895d23Benjamin Peterson    # when 'firstline' is empty.  'id' defaults to empty when an id can not
277250014793e9ed7d6cfc6e25ac502bcb124895d23Benjamin Peterson    # be deduced.
278250014793e9ed7d6cfc6e25ac502bcb124895d23Benjamin Peterson    version = ''
279250014793e9ed7d6cfc6e25ac502bcb124895d23Benjamin Peterson    id = ''
280250014793e9ed7d6cfc6e25ac502bcb124895d23Benjamin Peterson
281fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    # Parse the first line
282fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    m = _lsb_release_version.match(firstline)
283fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    if m is not None:
284fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        # LSB format: "distro release x.x (codename)"
285fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        return tuple(m.groups())
286fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
287fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    # Pre-LSB format: "distro x.x (codename)"
288fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    m = _release_version.match(firstline)
289fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    if m is not None:
290fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        return tuple(m.groups())
291fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
29230b9d5d3af043fc2687ad11a188a34fe355e20efEzio Melotti    # Unknown format... take the first two words
2939d72bb452bced3a100f07f8a9e30c4495a9ec41aNeal Norwitz    l = firstline.strip().split()
294fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    if l:
295fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        version = l[0]
296fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        if len(l) > 1:
297fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            id = l[1]
298fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    return '', version, id
299fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
300fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Woutersdef linux_distribution(distname='', version='', id='',
301fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
302fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                       supported_dists=_supported_dists,
303fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                       full_distribution_name=1):
3042f3742b0d8dbe025f2f9e496938a6d344e6881adBerker Peksag    import warnings
3052f3742b0d8dbe025f2f9e496938a6d344e6881adBerker Peksag    warnings.warn("dist() and linux_distribution() functions are deprecated "
3068d8221f0d674ea032337a82d1ad1d0d146510390Berker Peksag                  "in Python 3.5", PendingDeprecationWarning, stacklevel=2)
3072f3742b0d8dbe025f2f9e496938a6d344e6881adBerker Peksag    return _linux_distribution(distname, version, id, supported_dists,
3082f3742b0d8dbe025f2f9e496938a6d344e6881adBerker Peksag                               full_distribution_name)
3092f3742b0d8dbe025f2f9e496938a6d344e6881adBerker Peksag
3102f3742b0d8dbe025f2f9e496938a6d344e6881adBerker Peksagdef _linux_distribution(distname, version, id, supported_dists,
3112f3742b0d8dbe025f2f9e496938a6d344e6881adBerker Peksag                        full_distribution_name):
312246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
3138ab27dfa135dc1f3f3f156db2ae5e13c46eeb5a4Brett Cannon    """ Tries to determine the name of the Linux OS distribution name.
314246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
315246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        The function first looks for a distribution release file in
316246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        /etc and then reverts to _dist_try_harder() in case no
317246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        suitable files are found.
318246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
319fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        supported_dists may be given to define the set of Linux
320fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        distributions to look for. It defaults to a list of currently
321fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        supported Linux distributions identified by their release file
322fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        name.
323fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
324fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        If full_distribution_name is true (default), the full
325fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        distribution read from the OS is returned. Otherwise the short
326fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        name taken from supported_dists is used.
327fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
328ced3936894cec493b93c1144c543d51048268288Victor Stinner        Returns a tuple (distname, version, id) which default to the
329246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        args given as parameters.
330246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
331246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
332246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    try:
333620c48b7ea7a1ad3af23725afdac1e6a2b3e6cefVictor Stinner        etc = os.listdir(_UNIXCONFDIR)
334ad28c7f9dad791567afa0624acfb3ba430851965Andrew Svetlov    except OSError:
335246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # Probably not a Unix system
336ced3936894cec493b93c1144c543d51048268288Victor Stinner        return distname, version, id
337fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    etc.sort()
338246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    for file in etc:
339366a0feb9a7794a9f72ab0b37d36b6427e6d3bd1Marc-André Lemburg        m = _release_filename.match(file)
340fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        if m is not None:
341ced3936894cec493b93c1144c543d51048268288Victor Stinner            _distname, dummy = m.groups()
342246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            if _distname in supported_dists:
343246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                distname = _distname
344246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                break
345246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    else:
346ced3936894cec493b93c1144c543d51048268288Victor Stinner        return _dist_try_harder(distname, version, id)
3479fe394c1be9401c2b207b943f82e30af4ee32ab6Thomas Wouters
348fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    # Read the first line
349620c48b7ea7a1ad3af23725afdac1e6a2b3e6cefVictor Stinner    with open(os.path.join(_UNIXCONFDIR, file), 'r',
350620c48b7ea7a1ad3af23725afdac1e6a2b3e6cefVictor Stinner              encoding='utf-8', errors='surrogateescape') as f:
3517dde792e62c8adeaf5d633dc89e18d16067add8eFlorent Xicluna        firstline = f.readline()
352fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    _distname, _version, _id = _parse_release_file(firstline)
353fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
354fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    if _distname and full_distribution_name:
355fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        distname = _distname
356fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    if _version:
357fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        version = _version
358fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    if _id:
359fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        id = _id
360fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    return distname, version, id
361fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
362fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters# To maintain backwards compatibility:
3639fe394c1be9401c2b207b943f82e30af4ee32ab6Thomas Wouters
364ced3936894cec493b93c1144c543d51048268288Victor Stinnerdef dist(distname='', version='', id='',
365fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
366fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters         supported_dists=_supported_dists):
367fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
368fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    """ Tries to determine the name of the Linux OS distribution name.
369fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
370fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        The function first looks for a distribution release file in
371fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        /etc and then reverts to _dist_try_harder() in case no
372fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        suitable files are found.
373fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
374ced3936894cec493b93c1144c543d51048268288Victor Stinner        Returns a tuple (distname, version, id) which default to the
375fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        args given as parameters.
376fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
377fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    """
3782f3742b0d8dbe025f2f9e496938a6d344e6881adBerker Peksag    import warnings
3792f3742b0d8dbe025f2f9e496938a6d344e6881adBerker Peksag    warnings.warn("dist() and linux_distribution() functions are deprecated "
3808d8221f0d674ea032337a82d1ad1d0d146510390Berker Peksag                  "in Python 3.5", PendingDeprecationWarning, stacklevel=2)
3812f3742b0d8dbe025f2f9e496938a6d344e6881adBerker Peksag    return _linux_distribution(distname, version, id,
3822f3742b0d8dbe025f2f9e496938a6d344e6881adBerker Peksag                               supported_dists=supported_dists,
3832f3742b0d8dbe025f2f9e496938a6d344e6881adBerker Peksag                               full_distribution_name=0)
384246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
385877766dee8e60c7971ed0cabba89fbe981c2ab1bAntoine Pitroudef popen(cmd, mode='r', bufsize=-1):
386246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
387246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """ Portable popen() interface.
388246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
38925000d4d31dfa5842776aa92f234ea6672489c67Victor Stinner    import warnings
39025000d4d31dfa5842776aa92f234ea6672489c67Victor Stinner    warnings.warn('use os.popen instead', DeprecationWarning, stacklevel=2)
3911dfd3803064f2ee4b6e0bae3c60ca39e5f3919caVictor Stinner    return os.popen(cmd, mode, bufsize)
392246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
393fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Woutersdef _norm_version(version, build=''):
394246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
3958ab27dfa135dc1f3f3f156db2ae5e13c46eeb5a4Brett Cannon    """ Normalize the version and build strings and return a single
396e5a7fad356a98f931bbe0d2c9e4b18854510c3ddWalter Dörwald        version string using the format major.minor.build (or patchlevel).
397246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
3989d72bb452bced3a100f07f8a9e30c4495a9ec41aNeal Norwitz    l = version.split('.')
399246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if build:
400246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        l.append(build)
401246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    try:
402ced3936894cec493b93c1144c543d51048268288Victor Stinner        ints = map(int, l)
403246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    except ValueError:
404246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        strings = l
405246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    else:
406ced3936894cec493b93c1144c543d51048268288Victor Stinner        strings = list(map(str, ints))
4079d72bb452bced3a100f07f8a9e30c4495a9ec41aNeal Norwitz    version = '.'.join(strings[:3])
408246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    return version
409246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
410366a0feb9a7794a9f72ab0b37d36b6427e6d3bd1Marc-André Lemburg_ver_output = re.compile(r'(?:([\w ]+) ([\w.]+) '
411366a0feb9a7794a9f72ab0b37d36b6427e6d3bd1Marc-André Lemburg                         '.*'
412e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti                         '\[.* ([\d.]+)\])')
413e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti
414e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti# Examples of VER command output:
415e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti#
416e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti#   Windows 2000:  Microsoft Windows 2000 [Version 5.00.2195]
417e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti#   Windows XP:    Microsoft Windows XP [Version 5.1.2600]
418e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti#   Windows Vista: Microsoft Windows [Version 6.0.6002]
419e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti#
420e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti# Note that the "Version" string gets localized on different
421e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti# Windows versions.
422366a0feb9a7794a9f72ab0b37d36b6427e6d3bd1Marc-André Lemburg
423fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Woutersdef _syscmd_ver(system='', release='', version='',
424246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
425ced3936894cec493b93c1144c543d51048268288Victor Stinner               supported_platforms=('win32', 'win16', 'dos')):
426246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
427246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """ Tries to figure out the OS version used and returns
428ced3936894cec493b93c1144c543d51048268288Victor Stinner        a tuple (system, release, version).
4290eadaac7dc3ae49974c105ff9e8c1e98a04d7d5aTim Peters
430246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        It uses the "ver" shell command for this which is known
431f1af7057208da7b3d15703645688fea971a4fb5eJesus Cea        to exists on Windows, DOS. XXX Others too ?
432246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
433246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        In case this fails, the given parameters are used as
434246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        defaults.
435246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
436246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
437246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if sys.platform not in supported_platforms:
438ced3936894cec493b93c1144c543d51048268288Victor Stinner        return system, release, version
439246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
440246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    # Try some common cmd strings
441ced3936894cec493b93c1144c543d51048268288Victor Stinner    for cmd in ('ver', 'command /c ver', 'cmd /c ver'):
442246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        try:
443cae101f5ecd8fee38a37ce8fa46c141cd8a522efSteve Dower            pipe = os.popen(cmd)
444246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            info = pipe.read()
445246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            if pipe.close():
446ad28c7f9dad791567afa0624acfb3ba430851965Andrew Svetlov                raise OSError('command failed')
44713925008dc11f2a235627dc8c0440c0ce99171d9Ezio Melotti            # XXX How can I suppress shell errors from being written
448246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            #     to stderr ?
449ad28c7f9dad791567afa0624acfb3ba430851965Andrew Svetlov        except OSError as why:
450ced3936894cec493b93c1144c543d51048268288Victor Stinner            #print 'Command %s failed: %s' % (cmd, why)
451246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            continue
452246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        else:
453246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            break
454246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    else:
455ced3936894cec493b93c1144c543d51048268288Victor Stinner        return system, release, version
456246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
457246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    # Parse the output
4589d72bb452bced3a100f07f8a9e30c4495a9ec41aNeal Norwitz    info = info.strip()
459366a0feb9a7794a9f72ab0b37d36b6427e6d3bd1Marc-André Lemburg    m = _ver_output.match(info)
460fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    if m is not None:
461ced3936894cec493b93c1144c543d51048268288Victor Stinner        system, release, version = m.groups()
462246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # Strip trailing dots from version and release
463246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        if release[-1] == '.':
464246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            release = release[:-1]
465246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        if version[-1] == '.':
466246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            version = version[:-1]
467246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # Normalize the version and build strings (eliminating additional
468246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # zeros)
469246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        version = _norm_version(version)
470ced3936894cec493b93c1144c543d51048268288Victor Stinner    return system, release, version
471246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
472b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower_WIN32_CLIENT_RELEASES = {
473b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    (5, 0): "2000",
474b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    (5, 1): "XP",
475b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    # Strictly, 5.2 client is XP 64-bit, but platform.py historically
476b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    # has always called it 2003 Server
477b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    (5, 2): "2003Server",
478b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    (5, None): "post2003",
479b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower
480b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    (6, 0): "Vista",
481b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    (6, 1): "7",
482b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    (6, 2): "8",
483b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    (6, 3): "8.1",
484b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    (6, None): "post8.1",
485b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower
486b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    (10, 0): "10",
487b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    (10, None): "post10",
488b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower}
489b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower
490b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower# Server release name lookup will default to client names if necessary
491b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower_WIN32_SERVER_RELEASES = {
492b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    (5, 2): "2003Server",
493b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower
494b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    (6, 0): "2008Server",
495b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    (6, 1): "2008ServerR2",
496b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    (6, 2): "2012Server",
497b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    (6, 3): "2012ServerR2",
498b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    (6, None): "post2012ServerR2",
499b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower}
500b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower
501b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dowerdef _get_real_winver(maj, min, build):
502b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    if maj < 6 or (maj == 6 and min < 2):
503b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower        return maj, min, build
504b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower
505b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    from ctypes import (c_buffer, POINTER, byref, create_unicode_buffer,
506b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower                        Structure, WinDLL)
507b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    from ctypes.wintypes import DWORD, HANDLE
508b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower
509b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    class VS_FIXEDFILEINFO(Structure):
510b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower        _fields_ = [
511b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower            ("dwSignature", DWORD),
512b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower            ("dwStrucVersion", DWORD),
513b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower            ("dwFileVersionMS", DWORD),
514b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower            ("dwFileVersionLS", DWORD),
515b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower            ("dwProductVersionMS", DWORD),
516b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower            ("dwProductVersionLS", DWORD),
517b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower            ("dwFileFlagsMask", DWORD),
518b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower            ("dwFileFlags", DWORD),
519b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower            ("dwFileOS", DWORD),
520b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower            ("dwFileType", DWORD),
521b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower            ("dwFileSubtype", DWORD),
522b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower            ("dwFileDateMS", DWORD),
523b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower            ("dwFileDateLS", DWORD),
524b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower        ]
525b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower
526b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    kernel32 = WinDLL('kernel32')
527b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    version = WinDLL('version')
528b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower
529b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    # We will immediately double the length up to MAX_PATH, but the
530b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    # path may be longer, so we retry until the returned string is
531b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    # shorter than our buffer.
532b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    name_len = actual_len = 130
533b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    while actual_len == name_len:
534b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower        name_len *= 2
535b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower        name = create_unicode_buffer(name_len)
536b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower        actual_len = kernel32.GetModuleFileNameW(HANDLE(kernel32._handle),
537b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower                                                 name, len(name))
538b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower        if not actual_len:
539b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower            return maj, min, build
540b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower
541b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    size = version.GetFileVersionInfoSizeW(name, None)
542b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    if not size:
543b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower        return maj, min, build
544b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower
545b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    ver_block = c_buffer(size)
546b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    if (not version.GetFileVersionInfoW(name, None, size, ver_block) or
547b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower        not ver_block):
548b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower        return maj, min, build
549b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower
550b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    pvi = POINTER(VS_FIXEDFILEINFO)()
551b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    if not version.VerQueryValueW(ver_block, "", byref(pvi), byref(DWORD())):
552b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower        return maj, min, build
553b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower
554b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    maj = pvi.contents.dwProductVersionMS >> 16
555b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    min = pvi.contents.dwProductVersionMS & 0xFFFF
556b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    build = pvi.contents.dwProductVersionLS >> 16
557b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower
558b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    return maj, min, build
559246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
560b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dowerdef win32_ver(release='', version='', csd='', ptype=''):
5618f278f166255bb02dbee21e98689bb2fed58b3dfSteve Dower    try:
5628f278f166255bb02dbee21e98689bb2fed58b3dfSteve Dower        from sys import getwindowsversion
5638f278f166255bb02dbee21e98689bb2fed58b3dfSteve Dower    except ImportError:
5648f278f166255bb02dbee21e98689bb2fed58b3dfSteve Dower        return release, version, csd, ptype
56502781dc7541b79e499c06ead64535c317efc460eChristian Heimes    try:
566b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower        from winreg import OpenKeyEx, QueryValueEx, CloseKey, HKEY_LOCAL_MACHINE
567cd171c8e92c10d327151400fd8f16b11a4964615Brett Cannon    except ImportError:
568b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower        from _winreg import OpenKeyEx, QueryValueEx, CloseKey, HKEY_LOCAL_MACHINE
569246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
570b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    winver = getwindowsversion()
571b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    maj, min, build = _get_real_winver(*winver[:3])
572b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    version = '{0}.{1}.{2}'.format(maj, min, build)
573246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
574b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    release = (_WIN32_CLIENT_RELEASES.get((maj, min)) or
575b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower               _WIN32_CLIENT_RELEASES.get((maj, None)) or
576b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower               release)
577246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
578b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    # getwindowsversion() reflect the compatibility mode Python is
579b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    # running under, and so the service pack value is only going to be
580b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    # valid if the versions match.
581b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    if winver[:2] == (maj, min):
58202781dc7541b79e499c06ead64535c317efc460eChristian Heimes        try:
583b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower            csd = 'SP{}'.format(winver.service_pack_major)
58402781dc7541b79e499c06ead64535c317efc460eChristian Heimes        except AttributeError:
585b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower            if csd[:13] == 'Service Pack ':
586b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower                csd = 'SP' + csd[13:]
587e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti
588b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    # VER_NT_SERVER = 3
589126c9c17efedc6f69d5d86de4b660f3b44e635e4Steve Dower    if getattr(winver, 'product', None) == 3:
590b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower        release = (_WIN32_SERVER_RELEASES.get((maj, min)) or
591b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower                   _WIN32_SERVER_RELEASES.get((maj, None)) or
592b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower                   release)
593246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
594b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    key = None
595246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    try:
596b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower        key = OpenKeyEx(HKEY_LOCAL_MACHINE,
597b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower                        r'SOFTWARE\Microsoft\Windows NT\CurrentVersion')
598b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower        ptype = QueryValueEx(key, 'CurrentType')[0]
599246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    except:
600b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower        pass
601b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower    finally:
602b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower        if key:
603b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower            CloseKey(key)
604b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower
605ced3936894cec493b93c1144c543d51048268288Victor Stinner    return release, version, csd, ptype
606246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
607b9f4feab1b9c9ffa8ea29af3d82bc536f9f3005aSteve Dower
608e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussorendef _mac_ver_xml():
609e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren    fn = '/System/Library/CoreServices/SystemVersion.plist'
610e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren    if not os.path.exists(fn):
611e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren        return None
612e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren
613e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren    try:
614e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren        import plistlib
615cd171c8e92c10d327151400fd8f16b11a4964615Brett Cannon    except ImportError:
616e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren        return None
617e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren
618936dfae2e22b5b58d01416ddf47218c20bfde5e6Ned Deily    with open(fn, 'rb') as f:
619936dfae2e22b5b58d01416ddf47218c20bfde5e6Ned Deily        pl = plistlib.load(f)
620e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren    release = pl['ProductVersion']
621ced3936894cec493b93c1144c543d51048268288Victor Stinner    versioninfo = ('', '', '')
622605a62ddb1c19978ee194a40a458f072e3242a31Larry Hastings    machine = os.uname().machine
623fcd77016b31ea9fb5311695f5ca82cf6c235da87Ronald Oussoren    if machine in ('ppc', 'Power Macintosh'):
6249a3777e525b389ec5881c3f80a482fb821ab3ea5Ezio Melotti        # Canonical name
625e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren        machine = 'PowerPC'
626e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren
627ced3936894cec493b93c1144c543d51048268288Victor Stinner    return release, versioninfo, machine
628e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren
629e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren
630ced3936894cec493b93c1144c543d51048268288Victor Stinnerdef mac_ver(release='', versioninfo=('', '', ''), machine=''):
631e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren
632e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren    """ Get MacOS version information and return it as tuple (release,
633e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren        versioninfo, machine) with versioninfo being a tuple (version,
634e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren        dev_stage, non_release_version).
635e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren
63630b9d5d3af043fc2687ad11a188a34fe355e20efEzio Melotti        Entries which cannot be determined are set to the parameter values
637e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren        which default to ''. All tuple entries are strings.
638e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren    """
639e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren
640e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren    # First try reading the information from an XML file which should
641e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren    # always be present
642e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren    info = _mac_ver_xml()
643e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren    if info is not None:
644e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren        return info
645e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren
646e186e384f4fb11158b448d94f37aaf2a3ed6b45eRonald Oussoren    # If that also doesn't work return the default values
647ced3936894cec493b93c1144c543d51048268288Victor Stinner    return release, versioninfo, machine
648246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
649ced3936894cec493b93c1144c543d51048268288Victor Stinnerdef _java_getprop(name, default):
650246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
651246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    from java.lang import System
652246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    try:
653fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        value = System.getProperty(name)
654fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        if value is None:
655fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            return default
656fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        return value
657fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    except AttributeError:
658246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        return default
659246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
660ced3936894cec493b93c1144c543d51048268288Victor Stinnerdef java_ver(release='', vendor='', vminfo=('', '', ''), osinfo=('', '', '')):
6610eadaac7dc3ae49974c105ff9e8c1e98a04d7d5aTim Peters
6628ab27dfa135dc1f3f3f156db2ae5e13c46eeb5a4Brett Cannon    """ Version interface for Jython.
663246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
664ced3936894cec493b93c1144c543d51048268288Victor Stinner        Returns a tuple (release, vendor, vminfo, osinfo) with vminfo being
665ced3936894cec493b93c1144c543d51048268288Victor Stinner        a tuple (vm_name, vm_release, vm_vendor) and osinfo being a
666ced3936894cec493b93c1144c543d51048268288Victor Stinner        tuple (os_name, os_version, os_arch).
667246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
668246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        Values which cannot be determined are set to the defaults
669246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        given as parameters (which all default to '').
670246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
671246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
672246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    # Import the needed APIs
673246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    try:
674246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        import java.lang
675cd171c8e92c10d327151400fd8f16b11a4964615Brett Cannon    except ImportError:
676ced3936894cec493b93c1144c543d51048268288Victor Stinner        return release, vendor, vminfo, osinfo
677246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
678fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    vendor = _java_getprop('java.vendor', vendor)
679fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    release = _java_getprop('java.version', release)
680fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    vm_name, vm_release, vm_vendor = vminfo
681fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    vm_name = _java_getprop('java.vm.name', vm_name)
682fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    vm_vendor = _java_getprop('java.vm.vendor', vm_vendor)
683fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    vm_release = _java_getprop('java.vm.version', vm_release)
684fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    vminfo = vm_name, vm_release, vm_vendor
685fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    os_name, os_version, os_arch = osinfo
686fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    os_arch = _java_getprop('java.os.arch', os_arch)
687fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    os_name = _java_getprop('java.os.name', os_name)
688fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    os_version = _java_getprop('java.os.version', os_version)
689fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    osinfo = os_name, os_version, os_arch
690fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
691fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    return release, vendor, vminfo, osinfo
692246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
693246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg### System name aliasing
694246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
695ced3936894cec493b93c1144c543d51048268288Victor Stinnerdef system_alias(system, release, version):
696246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
697ced3936894cec493b93c1144c543d51048268288Victor Stinner    """ Returns (system, release, version) aliased to common
698246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        marketing names used for some systems.
699246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
700246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        It also does some reordering of the information in some cases
701246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        where it would otherwise cause confusion.
702246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
703246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
704246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if system == 'Rhapsody':
705246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # Apple's BSD derivative
706246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # XXX How can we determine the marketing release number ?
707ced3936894cec493b93c1144c543d51048268288Victor Stinner        return 'MacOS X Server', system+release, version
708246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
709246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    elif system == 'SunOS':
710246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # Sun's OS
711246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        if release < '5':
712246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            # These releases use the old name SunOS
713ced3936894cec493b93c1144c543d51048268288Victor Stinner            return system, release, version
714246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # Modify release (marketing release = SunOS release - 3)
7159d72bb452bced3a100f07f8a9e30c4495a9ec41aNeal Norwitz        l = release.split('.')
716246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        if l:
717246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            try:
718246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                major = int(l[0])
719246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            except ValueError:
720246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                pass
721246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            else:
722246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                major = major - 3
723246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                l[0] = str(major)
7249d72bb452bced3a100f07f8a9e30c4495a9ec41aNeal Norwitz                release = '.'.join(l)
725246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        if release < '6':
726246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            system = 'Solaris'
727246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        else:
728246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            # XXX Whatever the new SunOS marketing name is...
729246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            system = 'Solaris'
730246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
731246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    elif system == 'IRIX64':
732246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # IRIX reports IRIX64 on platforms with 64-bit support; yet it
733246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # is really a version and not a different platform, since 32-bit
734246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # apps are also supported..
735246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        system = 'IRIX'
736246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        if version:
737246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            version = version + ' (64bit)'
738246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        else:
739246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            version = '64bit'
740246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
741ced3936894cec493b93c1144c543d51048268288Victor Stinner    elif system in ('win32', 'win16'):
742246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # In case one of the other tricks
743246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        system = 'Windows'
744246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
745ced3936894cec493b93c1144c543d51048268288Victor Stinner    return system, release, version
746246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
747246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg### Various internal helpers
748246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
749246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburgdef _platform(*args):
750246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
751246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """ Helper to format the platform string in a filename
752246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        compatible format e.g. "system-version-machine".
753246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
754246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    # Format the platform string
7559d72bb452bced3a100f07f8a9e30c4495a9ec41aNeal Norwitz    platform = '-'.join(x.strip() for x in filter(len, args))
756246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
757246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    # Cleanup some possible filename obstacles...
758ced3936894cec493b93c1144c543d51048268288Victor Stinner    platform = platform.replace(' ', '_')
759ced3936894cec493b93c1144c543d51048268288Victor Stinner    platform = platform.replace('/', '-')
760ced3936894cec493b93c1144c543d51048268288Victor Stinner    platform = platform.replace('\\', '-')
761ced3936894cec493b93c1144c543d51048268288Victor Stinner    platform = platform.replace(':', '-')
762ced3936894cec493b93c1144c543d51048268288Victor Stinner    platform = platform.replace(';', '-')
763ced3936894cec493b93c1144c543d51048268288Victor Stinner    platform = platform.replace('"', '-')
764ced3936894cec493b93c1144c543d51048268288Victor Stinner    platform = platform.replace('(', '-')
765ced3936894cec493b93c1144c543d51048268288Victor Stinner    platform = platform.replace(')', '-')
766246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
767246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    # No need to report 'unknown' information...
768ced3936894cec493b93c1144c543d51048268288Victor Stinner    platform = platform.replace('unknown', '')
769246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
770246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    # Fold '--'s and remove trailing '-'
771246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    while 1:
772ced3936894cec493b93c1144c543d51048268288Victor Stinner        cleaned = platform.replace('--', '-')
773246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        if cleaned == platform:
774246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            break
775246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        platform = cleaned
776246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    while platform[-1] == '-':
777246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        platform = platform[:-1]
778246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
779246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    return platform
780246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
781246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburgdef _node(default=''):
782246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
783246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """ Helper to determine the node name of this machine.
784246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
785246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    try:
786246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        import socket
787cd171c8e92c10d327151400fd8f16b11a4964615Brett Cannon    except ImportError:
788246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # No sockets...
789246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        return default
790246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    try:
791246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        return socket.gethostname()
7920832af6628ca5ac02d0226899725297dd508470bAndrew Svetlov    except OSError:
793246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # Still not working...
794246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        return default
795246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
796246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburgdef _follow_symlinks(filepath):
797246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
798246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """ In case filepath is a symlink, follow it until a
799246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        real file is reached.
800246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
801673f7efa08850e42d077cab38683be2e4764b876Georg Brandl    filepath = os.path.abspath(filepath)
802246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    while os.path.islink(filepath):
803246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        filepath = os.path.normpath(
804ced3936894cec493b93c1144c543d51048268288Victor Stinner            os.path.join(os.path.dirname(filepath), os.readlink(filepath)))
805246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    return filepath
806246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
807ced3936894cec493b93c1144c543d51048268288Victor Stinnerdef _syscmd_uname(option, default=''):
808246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
809246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """ Interface to the system's uname command.
810246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
811ced3936894cec493b93c1144c543d51048268288Victor Stinner    if sys.platform in ('dos', 'win32', 'win16'):
812246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # XXX Others too ?
813246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        return default
814246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    try:
815e52e3786c67e16b7b8adba71227f9e3c5350d7a6Alexandre Vassalotti        f = os.popen('uname %s 2> %s' % (option, DEV_NULL))
816ad28c7f9dad791567afa0624acfb3ba430851965Andrew Svetlov    except (AttributeError, OSError):
817246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        return default
8189d72bb452bced3a100f07f8a9e30c4495a9ec41aNeal Norwitz    output = f.read().strip()
819246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    rc = f.close()
820246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if not output or rc:
821246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        return default
822246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    else:
823246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        return output
824246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
825ced3936894cec493b93c1144c543d51048268288Victor Stinnerdef _syscmd_file(target, default=''):
826246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
827246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """ Interface to the system's file command.
828246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
829246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        The function uses the -b option of the file command to have it
830ddfb2c3a338a8c1550774648f816e96c41f59de1Victor Stinner        omit the filename in its output. Follow the symlinks. It returns
831ddfb2c3a338a8c1550774648f816e96c41f59de1Victor Stinner        default in case the command should fail.
832246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
833246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
834ced3936894cec493b93c1144c543d51048268288Victor Stinner    if sys.platform in ('dos', 'win32', 'win16'):
835d26782e8639df937fac1ef3f208986274138d5c1Hirokazu Yamamoto        # XXX Others too ?
836d26782e8639df937fac1ef3f208986274138d5c1Hirokazu Yamamoto        return default
837fc990e942fb55be78e8352f4913749e91cac381dJesus Cea    target = _follow_symlinks(target)
838246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    try:
839685fffa8f427b3a768b232170752565d58c32112Jesus Cea        proc = subprocess.Popen(['file', target],
840685fffa8f427b3a768b232170752565d58c32112Jesus Cea                stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
841e8801e2e44b4ffcfdfc6e2857e7afc90ba6abc38Jesus Cea
842ad28c7f9dad791567afa0624acfb3ba430851965Andrew Svetlov    except (AttributeError, OSError):
843246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        return default
844cb95996fdc6956365642dd42f86dfb380f923fa5Jesus Cea    output = proc.communicate()[0].decode('latin-1')
845fc990e942fb55be78e8352f4913749e91cac381dJesus Cea    rc = proc.wait()
846246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if not output or rc:
847246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        return default
848246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    else:
849246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        return output
850246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
851246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg### Information about the used architecture
852246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
853246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg# Default values for architecture; non-empty strings override the
854246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg# defaults given as parameters
855246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg_default_architecture = {
856ced3936894cec493b93c1144c543d51048268288Victor Stinner    'win32': ('', 'WindowsPE'),
857ced3936894cec493b93c1144c543d51048268288Victor Stinner    'win16': ('', 'Windows'),
858ced3936894cec493b93c1144c543d51048268288Victor Stinner    'dos': ('', 'MSDOS'),
859246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg}
860246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
861ced3936894cec493b93c1144c543d51048268288Victor Stinnerdef architecture(executable=sys.executable, bits='', linkage=''):
862246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
863246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """ Queries the given executable (defaults to the Python interpreter
8648ab27dfa135dc1f3f3f156db2ae5e13c46eeb5a4Brett Cannon        binary) for various architecture information.
865246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
866ced3936894cec493b93c1144c543d51048268288Victor Stinner        Returns a tuple (bits, linkage) which contains information about
867246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        the bit architecture and the linkage format used for the
868246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        executable. Both values are returned as strings.
869246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
870246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        Values that cannot be determined are returned as given by the
871246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        parameter presets. If bits is given as '', the sizeof(pointer)
872246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        (or sizeof(long) on Python version < 1.5.2) is used as
873246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        indicator for the supported pointer size.
874246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
875246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        The function relies on the system's "file" command to do the
876246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        actual work. This is available on most if not all Unix
8778ab27dfa135dc1f3f3f156db2ae5e13c46eeb5a4Brett Cannon        platforms. On some non-Unix platforms where the "file" command
8788ab27dfa135dc1f3f3f156db2ae5e13c46eeb5a4Brett Cannon        does not exist and the executable is set to the Python interpreter
8798ab27dfa135dc1f3f3f156db2ae5e13c46eeb5a4Brett Cannon        binary defaults from _default_architecture are used.
880246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
881246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
882246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    # Use the sizeof(pointer) as default number of bits if nothing
883246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    # else is given as default.
884246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if not bits:
885246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        import struct
886246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        try:
887246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            size = struct.calcsize('P')
888246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        except struct.error:
889246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            # Older installations can only query longs
890246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            size = struct.calcsize('l')
891246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        bits = str(size*8) + 'bit'
8920eadaac7dc3ae49974c105ff9e8c1e98a04d7d5aTim Peters
893246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    # Get data from the 'file' system command
894fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    if executable:
895ddfb2c3a338a8c1550774648f816e96c41f59de1Victor Stinner        fileout = _syscmd_file(executable, '')
896fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    else:
897ddfb2c3a338a8c1550774648f816e96c41f59de1Victor Stinner        fileout = ''
898246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
899ddfb2c3a338a8c1550774648f816e96c41f59de1Victor Stinner    if not fileout and \
900246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg       executable == sys.executable:
901246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # "file" command did not return anything; we'll try to provide
9020eadaac7dc3ae49974c105ff9e8c1e98a04d7d5aTim Peters        # some sensible defaults then...
903e2b70bcf7401477936fba99a8bf4a1f759ecc8a3Guido van Rossum        if sys.platform in _default_architecture:
904ced3936894cec493b93c1144c543d51048268288Victor Stinner            b, l = _default_architecture[sys.platform]
905246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            if b:
906246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                bits = b
907246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            if l:
908246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                linkage = l
909ced3936894cec493b93c1144c543d51048268288Victor Stinner        return bits, linkage
910246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
911246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if 'executable' not in fileout:
912246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # Format not supported
913ced3936894cec493b93c1144c543d51048268288Victor Stinner        return bits, linkage
914246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
915246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    # Bits
916246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if '32-bit' in fileout:
917246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        bits = '32bit'
918246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    elif 'N32' in fileout:
919246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # On Irix only
920246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        bits = 'n32bit'
921246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    elif '64-bit' in fileout:
922246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        bits = '64bit'
923246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
924246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    # Linkage
925246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if 'ELF' in fileout:
926246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        linkage = 'ELF'
927246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    elif 'PE' in fileout:
928246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # E.g. Windows uses this format
929246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        if 'Windows' in fileout:
930246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            linkage = 'WindowsPE'
931246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        else:
932246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            linkage = 'PE'
933246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    elif 'COFF' in fileout:
934246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        linkage = 'COFF'
935246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    elif 'MS-DOS' in fileout:
936246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        linkage = 'MSDOS'
937246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    else:
938246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # XXX the A.OUT format also falls under this class...
939246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        pass
940246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
941ced3936894cec493b93c1144c543d51048268288Victor Stinner    return bits, linkage
942246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
943246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg### Portable uname() interface
9440eadaac7dc3ae49974c105ff9e8c1e98a04d7d5aTim Peters
94568386bc0b88eb4b7c9aeb4f753114dc85f8df5b6Larry Hastingsuname_result = collections.namedtuple("uname_result",
94668386bc0b88eb4b7c9aeb4f753114dc85f8df5b6Larry Hastings                    "system node release version machine processor")
94768386bc0b88eb4b7c9aeb4f753114dc85f8df5b6Larry Hastings
948246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg_uname_cache = None
949246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
950246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburgdef uname():
951246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
952246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """ Fairly portable uname interface. Returns a tuple
953ced3936894cec493b93c1144c543d51048268288Victor Stinner        of strings (system, node, release, version, machine, processor)
954246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        identifying the underlying platform.
955246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
956246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        Note that unlike the os.uname function this also returns
9578ab27dfa135dc1f3f3f156db2ae5e13c46eeb5a4Brett Cannon        possible processor information as an additional tuple entry.
958246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
959246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        Entries which cannot be determined are set to ''.
960246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
961246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
962246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    global _uname_cache
96335c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc    no_os_uname = 0
964246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
965246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if _uname_cache is not None:
966246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        return _uname_cache
967246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
96835c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc    processor = ''
96935c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc
970246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    # Get some infos from the builtin os.uname API...
971246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    try:
972ced3936894cec493b93c1144c543d51048268288Victor Stinner        system, node, release, version, machine = os.uname()
973246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    except AttributeError:
97435c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc        no_os_uname = 1
97535c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc
97662e2ca219311a111873892910ad441659faeaefaGeorg Brandl    if no_os_uname or not list(filter(None, (system, node, release, version, machine))):
97735c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc        # Hmm, no there is either no uname or uname has returned
97835c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc        #'unknowns'... we'll have to poke around the system then.
97935c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc        if no_os_uname:
98035c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc            system = sys.platform
98135c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc            release = ''
98235c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc            version = ''
98335c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc            node = _node()
98435c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc            machine = ''
98535c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc
9867a01984aba532b731dd6a06610b0ce523bef4f5eAmaury Forgeot d'Arc        use_syscmd_ver = 1
987246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
988246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # Try win32_ver() on win32 platforms
989246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        if system == 'win32':
990ced3936894cec493b93c1144c543d51048268288Victor Stinner            release, version, csd, ptype = win32_ver()
991246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            if release and version:
992246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                use_syscmd_ver = 0
99302781dc7541b79e499c06ead64535c317efc460eChristian Heimes            # Try to use the PROCESSOR_* environment variables
994fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            # available on Win XP and later; see
995fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            # http://support.microsoft.com/kb/888731 and
996fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            # http://www.geocities.com/rick_lively/MANUALS/ENV/MSWIN/PROCESSI.HTM
99735c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc            if not machine:
998ca2edce67695b73e21a64a352632feedc08ccf29R. David Murray                # WOW64 processes mask the native architecture
999ca2edce67695b73e21a64a352632feedc08ccf29R. David Murray                if "PROCESSOR_ARCHITEW6432" in os.environ:
1000ca2edce67695b73e21a64a352632feedc08ccf29R. David Murray                    machine = os.environ.get("PROCESSOR_ARCHITEW6432", '')
1001ca2edce67695b73e21a64a352632feedc08ccf29R. David Murray                else:
1002ca2edce67695b73e21a64a352632feedc08ccf29R. David Murray                    machine = os.environ.get('PROCESSOR_ARCHITECTURE', '')
100335c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc            if not processor:
100435c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc                processor = os.environ.get('PROCESSOR_IDENTIFIER', machine)
10050eadaac7dc3ae49974c105ff9e8c1e98a04d7d5aTim Peters
1006246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # Try the 'ver' system command available on some
1007246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # platforms
1008246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        if use_syscmd_ver:
1009ced3936894cec493b93c1144c543d51048268288Victor Stinner            system, release, version = _syscmd_ver(system)
1010cdc7923f6d1c9731d81f299569b1ea72de7eb212Marc-André Lemburg            # Normalize system to what win32_ver() normally returns
1011cdc7923f6d1c9731d81f299569b1ea72de7eb212Marc-André Lemburg            # (_syscmd_ver() tends to return the vendor name as well)
1012cdc7923f6d1c9731d81f299569b1ea72de7eb212Marc-André Lemburg            if system == 'Microsoft Windows':
1013cdc7923f6d1c9731d81f299569b1ea72de7eb212Marc-André Lemburg                system = 'Windows'
1014cd16bf640405065e4702539632ce577536207d88Guido van Rossum            elif system == 'Microsoft' and release == 'Windows':
1015cd16bf640405065e4702539632ce577536207d88Guido van Rossum                # Under Windows Vista and Windows Server 2008,
1016cd16bf640405065e4702539632ce577536207d88Guido van Rossum                # Microsoft changed the output of the ver command. The
1017cd16bf640405065e4702539632ce577536207d88Guido van Rossum                # release is no longer printed.  This causes the
1018cd16bf640405065e4702539632ce577536207d88Guido van Rossum                # system and release to be misidentified.
1019cd16bf640405065e4702539632ce577536207d88Guido van Rossum                system = 'Windows'
1020cd16bf640405065e4702539632ce577536207d88Guido van Rossum                if '6.0' == version[:3]:
1021cd16bf640405065e4702539632ce577536207d88Guido van Rossum                    release = 'Vista'
1022cd16bf640405065e4702539632ce577536207d88Guido van Rossum                else:
1023cd16bf640405065e4702539632ce577536207d88Guido van Rossum                    release = ''
1024246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1025246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # In case we still don't know anything useful, we'll try to
1026246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # help ourselves
1027ced3936894cec493b93c1144c543d51048268288Victor Stinner        if system in ('win32', 'win16'):
1028246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            if not version:
1029246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                if system == 'win32':
1030246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                    version = '32bit'
1031246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                else:
1032246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                    version = '16bit'
1033246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            system = 'Windows'
1034246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1035246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        elif system[:4] == 'java':
1036ced3936894cec493b93c1144c543d51048268288Victor Stinner            release, vendor, vminfo, osinfo = java_ver()
1037246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            system = 'Java'
10389d72bb452bced3a100f07f8a9e30c4495a9ec41aNeal Norwitz            version = ', '.join(vminfo)
1039246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            if not version:
1040246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                version = vendor
1041246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
104235c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc    # System specific extensions
104335c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc    if system == 'OpenVMS':
104435c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc        # OpenVMS seems to have release and version mixed up
104535c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc        if not release or release == '0':
104635c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc            release = version
104735c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc            version = ''
104835c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc        # Get processor information
104935c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc        try:
105035c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc            import vms_lib
1051cd171c8e92c10d327151400fd8f16b11a4964615Brett Cannon        except ImportError:
105235c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc            pass
1053246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        else:
1054ced3936894cec493b93c1144c543d51048268288Victor Stinner            csid, cpu_number = vms_lib.getsyi('SYI$_CPU', 0)
105535c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc            if (cpu_number >= 128):
105635c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc                processor = 'Alpha'
105735c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc            else:
105835c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc                processor = 'VAX'
105935c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc    if not processor:
106035c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc        # Get processor information from the uname system command
1061ced3936894cec493b93c1144c543d51048268288Victor Stinner        processor = _syscmd_uname('-p', '')
1062246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
106335c8658a74d9b51c6c4755514b02fe3f9d6bb6b8Amaury Forgeot d'Arc    #If any unknowns still exist, replace them with ''s, which are more portable
1064246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if system == 'unknown':
1065246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        system = ''
1066246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if node == 'unknown':
1067246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        node = ''
1068246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if release == 'unknown':
1069246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        release = ''
1070246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if version == 'unknown':
1071246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        version = ''
1072246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if machine == 'unknown':
1073246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        machine = ''
1074246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if processor == 'unknown':
1075246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        processor = ''
10761b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters
10771b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters    #  normalize name
10781b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters    if system == 'Microsoft' and release == 'Windows':
10791b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters        system = 'Windows'
10801b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters        release = 'Vista'
10811b7f891f416830d0c46ca1c9e1bfe62f05cda655Thomas Wouters
1082ced3936894cec493b93c1144c543d51048268288Victor Stinner    _uname_cache = uname_result(system, node, release, version,
1083ced3936894cec493b93c1144c543d51048268288Victor Stinner                                machine, processor)
1084246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    return _uname_cache
1085246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1086246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg### Direct interfaces to some of the uname() return values
1087246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1088246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburgdef system():
1089246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1090246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """ Returns the system/OS name, e.g. 'Linux', 'Windows' or 'Java'.
1091246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1092246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        An empty string is returned if the value cannot be determined.
1093246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1094246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
109568386bc0b88eb4b7c9aeb4f753114dc85f8df5b6Larry Hastings    return uname().system
1096246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1097246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburgdef node():
1098246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
10998ab27dfa135dc1f3f3f156db2ae5e13c46eeb5a4Brett Cannon    """ Returns the computer's network name (which may not be fully
11008ab27dfa135dc1f3f3f156db2ae5e13c46eeb5a4Brett Cannon        qualified)
1101246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1102246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        An empty string is returned if the value cannot be determined.
1103246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1104246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
110568386bc0b88eb4b7c9aeb4f753114dc85f8df5b6Larry Hastings    return uname().node
1106246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1107246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburgdef release():
1108246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1109246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """ Returns the system's release, e.g. '2.2.0' or 'NT'
1110246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1111246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        An empty string is returned if the value cannot be determined.
1112246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1113246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
111468386bc0b88eb4b7c9aeb4f753114dc85f8df5b6Larry Hastings    return uname().release
1115246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1116246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburgdef version():
1117246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1118246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """ Returns the system's release version, e.g. '#3 on degas'
1119246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1120246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        An empty string is returned if the value cannot be determined.
1121246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1122246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
112368386bc0b88eb4b7c9aeb4f753114dc85f8df5b6Larry Hastings    return uname().version
1124246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1125246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburgdef machine():
1126246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1127246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """ Returns the machine type, e.g. 'i386'
1128246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1129246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        An empty string is returned if the value cannot be determined.
1130246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1131246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
113268386bc0b88eb4b7c9aeb4f753114dc85f8df5b6Larry Hastings    return uname().machine
1133246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1134246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburgdef processor():
1135246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1136246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """ Returns the (true) processor name, e.g. 'amdk6'
1137246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1138246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        An empty string is returned if the value cannot be
1139246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        determined. Note that many platforms do not provide this
1140246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        information or simply return the same value as for machine(),
1141246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        e.g.  NetBSD does this.
1142246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1143246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
114468386bc0b88eb4b7c9aeb4f753114dc85f8df5b6Larry Hastings    return uname().processor
1145246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1146246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg### Various APIs for extracting information from sys.version
1147246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1148fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters_sys_version_parser = re.compile(
11494e50553823c16a65d80f6734b4ac303c18640380Martin Panter    r'([\w.+]+)\s*'  # "version<space>"
11504e50553823c16a65d80f6734b4ac303c18640380Martin Panter    r'\(#?([^,]+)'  # "(#buildno"
11514e50553823c16a65d80f6734b4ac303c18640380Martin Panter    r'(?:,\s*([\w ]*)'  # ", builddate"
11524e50553823c16a65d80f6734b4ac303c18640380Martin Panter    r'(?:,\s*([\w :]*))?)?\)\s*'  # ", buildtime)<space>"
11534e50553823c16a65d80f6734b4ac303c18640380Martin Panter    r'\[([^\]]+)\]?', re.ASCII)  # "[compiler]"
1154fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1155fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters_ironpython_sys_version_parser = re.compile(
1156fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    r'IronPython\s*'
1157fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    '([\d\.]+)'
1158fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    '(?: \(([\d\.]+)\))?'
1159fd036451bf0e0ade8783e21df801abf7be96d020Antoine Pitrou    ' on (.NET [\d\.]+)', re.ASCII)
1160246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1161f076f53386c422060517b8f088eadff3a80e48e6Ezio Melotti# IronPython covering 2.6 and 2.7
1162f076f53386c422060517b8f088eadff3a80e48e6Ezio Melotti_ironpython26_sys_version_parser = re.compile(
1163f076f53386c422060517b8f088eadff3a80e48e6Ezio Melotti    r'([\d.]+)\s*'
1164f076f53386c422060517b8f088eadff3a80e48e6Ezio Melotti    '\(IronPython\s*'
1165f076f53386c422060517b8f088eadff3a80e48e6Ezio Melotti    '[\d.]+\s*'
1166f076f53386c422060517b8f088eadff3a80e48e6Ezio Melotti    '\(([\d.]+)\) on ([\w.]+ [\d.]+(?: \(\d+-bit\))?)\)'
1167f076f53386c422060517b8f088eadff3a80e48e6Ezio Melotti)
1168f076f53386c422060517b8f088eadff3a80e48e6Ezio Melotti
1169e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson_pypy_sys_version_parser = re.compile(
1170e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson    r'([\w.+]+)\s*'
1171e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson    '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
1172e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson    '\[PyPy [^\]]+\]?')
1173e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson
1174fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters_sys_version_cache = {}
1175fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1176fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Woutersdef _sys_version(sys_version=None):
1177246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1178246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """ Returns a parsed version of Python's sys.version as tuple
11795f28b7b7978ad96fef83e2b41017bdd7ab8a082fBenjamin Peterson        (name, version, branch, revision, buildno, builddate, compiler)
11805f28b7b7978ad96fef83e2b41017bdd7ab8a082fBenjamin Peterson        referring to the Python implementation name, version, branch,
11815f28b7b7978ad96fef83e2b41017bdd7ab8a082fBenjamin Peterson        revision, build number, build date/time as string and the compiler
11825f28b7b7978ad96fef83e2b41017bdd7ab8a082fBenjamin Peterson        identification string.
1183246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1184246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        Note that unlike the Python sys.version, the returned value
1185246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        for the Python version will always include the patchlevel (it
1186246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        defaults to '.0').
1187246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1188fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        The function returns empty strings for tuple entries that
1189fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        cannot be determined.
1190fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1191fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        sys_version may be given to parse an alternative version
1192fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        string, e.g. if the version was read from a different Python
1193fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        interpreter.
1194fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1195246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
1196fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    # Get the Python version
1197fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    if sys_version is None:
1198fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        sys_version = sys.version
1199246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1200fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    # Try the cache first
1201fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    result = _sys_version_cache.get(sys_version, None)
1202fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    if result is not None:
1203fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        return result
1204fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1205fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    # Parse it
1206f076f53386c422060517b8f088eadff3a80e48e6Ezio Melotti    if 'IronPython' in sys_version:
1207fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        # IronPython
1208fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        name = 'IronPython'
1209f076f53386c422060517b8f088eadff3a80e48e6Ezio Melotti        if sys_version.startswith('IronPython'):
1210f076f53386c422060517b8f088eadff3a80e48e6Ezio Melotti            match = _ironpython_sys_version_parser.match(sys_version)
1211f076f53386c422060517b8f088eadff3a80e48e6Ezio Melotti        else:
1212f076f53386c422060517b8f088eadff3a80e48e6Ezio Melotti            match = _ironpython26_sys_version_parser.match(sys_version)
1213f076f53386c422060517b8f088eadff3a80e48e6Ezio Melotti
1214fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        if match is None:
1215fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            raise ValueError(
1216fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                'failed to parse IronPython sys.version: %s' %
1217fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                repr(sys_version))
1218f076f53386c422060517b8f088eadff3a80e48e6Ezio Melotti
1219fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        version, alt_version, compiler = match.groups()
1220fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        buildno = ''
1221fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        builddate = ''
1222fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1223f076f53386c422060517b8f088eadff3a80e48e6Ezio Melotti    elif sys.platform.startswith('java'):
1224fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        # Jython
1225fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        name = 'Jython'
1226e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson        match = _sys_version_parser.match(sys_version)
1227fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        if match is None:
1228fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            raise ValueError(
1229fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                'failed to parse Jython sys.version: %s' %
1230fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                repr(sys_version))
1231e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson        version, buildno, builddate, buildtime, _ = match.groups()
12324e50553823c16a65d80f6734b4ac303c18640380Martin Panter        if builddate is None:
12334e50553823c16a65d80f6734b4ac303c18640380Martin Panter            builddate = ''
1234fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        compiler = sys.platform
1235e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson
1236e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson    elif "PyPy" in sys_version:
1237e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson        # PyPy
1238e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson        name = "PyPy"
1239e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson        match = _pypy_sys_version_parser.match(sys_version)
1240e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson        if match is None:
1241e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson            raise ValueError("failed to parse PyPy sys.version: %s" %
1242e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson                             repr(sys_version))
1243e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson        version, buildno, builddate, buildtime = match.groups()
1244e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson        compiler = ""
1245fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1246fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    else:
1247fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        # CPython
1248fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        match = _sys_version_parser.match(sys_version)
1249fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        if match is None:
1250fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters            raise ValueError(
1251fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                'failed to parse CPython sys.version: %s' %
1252fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters                repr(sys_version))
1253fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        version, buildno, builddate, buildtime, compiler = \
1254fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters              match.groups()
1255e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson        name = 'CPython'
12564e50553823c16a65d80f6734b4ac303c18640380Martin Panter        if builddate is None:
12574e50553823c16a65d80f6734b4ac303c18640380Martin Panter            builddate = ''
12584e50553823c16a65d80f6734b4ac303c18640380Martin Panter        elif buildtime:
12594e50553823c16a65d80f6734b4ac303c18640380Martin Panter            builddate = builddate + ' ' + buildtime
1260fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
12618256242b30005b8a1b52e79149558ad36f1307d6Georg Brandl    if hasattr(sys, '_mercurial'):
12628256242b30005b8a1b52e79149558ad36f1307d6Georg Brandl        _, branch, revision = sys._mercurial
12638256242b30005b8a1b52e79149558ad36f1307d6Georg Brandl    elif hasattr(sys, 'subversion'):
1264e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson        # sys.subversion was added in Python 2.5
1265e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson        _, branch, revision = sys.subversion
1266e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson    else:
1267e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson        branch = ''
1268e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson        revision = ''
1269e549ead8263819ac47f60cdd0239592750888f0bBenjamin Peterson
1270fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    # Add the patchlevel version if missing
12719d72bb452bced3a100f07f8a9e30c4495a9ec41aNeal Norwitz    l = version.split('.')
1272246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if len(l) == 2:
1273246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        l.append('0')
12749d72bb452bced3a100f07f8a9e30c4495a9ec41aNeal Norwitz        version = '.'.join(l)
1275fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1276fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    # Build and cache the result
1277fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    result = (name, version, branch, revision, buildno, builddate, compiler)
1278fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    _sys_version_cache[sys_version] = result
1279fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    return result
1280fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1281fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Woutersdef python_implementation():
1282fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1283fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    """ Returns a string identifying the Python implementation.
1284fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1285fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        Currently, the following implementations are identified:
1286f16898bc80fafeaf025606ea00e841c310b8df39Ezio Melotti          'CPython' (C implementation of Python),
1287f16898bc80fafeaf025606ea00e841c310b8df39Ezio Melotti          'IronPython' (.NET implementation of Python),
1288f16898bc80fafeaf025606ea00e841c310b8df39Ezio Melotti          'Jython' (Java implementation of Python),
1289f16898bc80fafeaf025606ea00e841c310b8df39Ezio Melotti          'PyPy' (Python implementation of Python).
1290fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1291fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    """
1292fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    return _sys_version()[0]
1293246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1294246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburgdef python_version():
1295246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1296246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """ Returns the Python version as string 'major.minor.patchlevel'
1297246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1298246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        Note that unlike the Python sys.version, the returned value
1299246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        will always include the patchlevel (it defaults to 0).
1300246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1301246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
1302fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    return _sys_version()[1]
1303246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1304246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburgdef python_version_tuple():
1305246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1306246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """ Returns the Python version as tuple (major, minor, patchlevel)
1307246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        of strings.
1308246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1309246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        Note that unlike the Python sys.version, the returned value
1310246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        will always include the patchlevel (it defaults to 0).
1311246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1312246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
13139d72bb452bced3a100f07f8a9e30c4495a9ec41aNeal Norwitz    return tuple(_sys_version()[1].split('.'))
1314fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1315fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Woutersdef python_branch():
1316fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1317fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    """ Returns a string identifying the Python implementation
1318fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        branch.
1319fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1320fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        For CPython this is the Subversion branch from which the
1321fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        Python binary was built.
1322fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1323fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        If not available, an empty string is returned.
1324fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1325fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    """
13269fe394c1be9401c2b207b943f82e30af4ee32ab6Thomas Wouters
1327fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    return _sys_version()[2]
1328fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1329fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Woutersdef python_revision():
1330fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1331fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    """ Returns a string identifying the Python implementation
1332fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        revision.
1333fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1334fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        For CPython this is the Subversion revision from which the
1335fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        Python binary was built.
1336fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1337fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        If not available, an empty string is returned.
1338fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters
1339fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    """
1340fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    return _sys_version()[3]
1341246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1342246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburgdef python_build():
1343246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1344246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """ Returns a tuple (buildno, builddate) stating the Python
1345246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        build number and date as strings.
1346246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1347246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
1348fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    return _sys_version()[4:6]
1349246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1350246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburgdef python_compiler():
1351246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1352246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """ Returns a string identifying the compiler used for compiling
1353246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        Python.
1354246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1355246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
1356fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters    return _sys_version()[6]
1357246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1358246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg### The Opus Magnum of platform strings :-)
1359246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
136091e83e209d66d4b7a892c9360f9e524d6e282191Marc-André Lemburg_platform_cache = {}
1361246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1362246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburgdef platform(aliased=0, terse=0):
1363246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1364246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """ Returns a single string identifying the underlying platform
1365246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        with as much useful information as possible (but no more :).
13660eadaac7dc3ae49974c105ff9e8c1e98a04d7d5aTim Peters
1367246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        The output is intended to be human readable rather than
1368246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        machine parseable. It may look different on different
1369246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        platforms and this is intended.
1370246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1371246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        If "aliased" is true, the function will use aliases for
1372246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        various platforms that report system names which differ from
1373246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        their common names, e.g. SunOS will be reported as
1374246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        Solaris. The system_alias() function is used to implement
1375246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        this.
1376246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1377246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        Setting terse to true causes the function to return only the
1378246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        absolute minimum information needed to identify the platform.
1379246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1380246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    """
138191e83e209d66d4b7a892c9360f9e524d6e282191Marc-André Lemburg    result = _platform_cache.get((aliased, terse), None)
138291e83e209d66d4b7a892c9360f9e524d6e282191Marc-André Lemburg    if result is not None:
138391e83e209d66d4b7a892c9360f9e524d6e282191Marc-André Lemburg        return result
1384246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1385246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    # Get uname information and then apply platform specific cosmetics
1386246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    # to it...
1387ced3936894cec493b93c1144c543d51048268288Victor Stinner    system, node, release, version, machine, processor = uname()
1388246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if machine == processor:
1389246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        processor = ''
1390246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if aliased:
1391ced3936894cec493b93c1144c543d51048268288Victor Stinner        system, release, version = system_alias(system, release, version)
1392246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1393246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    if system == 'Windows':
1394246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # MS platforms
1395ced3936894cec493b93c1144c543d51048268288Victor Stinner        rel, vers, csd, ptype = win32_ver(version)
1396246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        if terse:
1397ced3936894cec493b93c1144c543d51048268288Victor Stinner            platform = _platform(system, release)
1398246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        else:
1399ced3936894cec493b93c1144c543d51048268288Victor Stinner            platform = _platform(system, release, version, csd)
1400246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1401246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    elif system in ('Linux',):
1402246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # Linux based systems
14031392f71c3927c9d81969200f5dfff9fb832cde0bBerker Peksag        with warnings.catch_warnings():
14041392f71c3927c9d81969200f5dfff9fb832cde0bBerker Peksag            # see issue #1322 for more information
14051392f71c3927c9d81969200f5dfff9fb832cde0bBerker Peksag            warnings.filterwarnings(
14061392f71c3927c9d81969200f5dfff9fb832cde0bBerker Peksag                'ignore',
14071392f71c3927c9d81969200f5dfff9fb832cde0bBerker Peksag                'dist\(\) and linux_distribution\(\) '
14081392f71c3927c9d81969200f5dfff9fb832cde0bBerker Peksag                'functions are deprecated .*',
14091392f71c3927c9d81969200f5dfff9fb832cde0bBerker Peksag                PendingDeprecationWarning,
14101392f71c3927c9d81969200f5dfff9fb832cde0bBerker Peksag            )
14111392f71c3927c9d81969200f5dfff9fb832cde0bBerker Peksag            distname, distversion, distid = dist('')
1412246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        if distname and not terse:
1413ced3936894cec493b93c1144c543d51048268288Victor Stinner            platform = _platform(system, release, machine, processor,
1414246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                                 'with',
1415ced3936894cec493b93c1144c543d51048268288Victor Stinner                                 distname, distversion, distid)
1416246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        else:
1417246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg            # If the distribution name is unknown check for libc vs. glibc
1418ced3936894cec493b93c1144c543d51048268288Victor Stinner            libcname, libcversion = libc_ver(sys.executable)
1419ced3936894cec493b93c1144c543d51048268288Victor Stinner            platform = _platform(system, release, machine, processor,
1420246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                                 'with',
1421246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                                 libcname+libcversion)
1422246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    elif system == 'Java':
1423246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # Java platforms
1424ced3936894cec493b93c1144c543d51048268288Victor Stinner        r, v, vminfo, (os_name, os_version, os_arch) = java_ver()
1425fc7bb8c786fd9cb3b1ab84e1976620d0ab545777Thomas Wouters        if terse or not os_name:
1426ced3936894cec493b93c1144c543d51048268288Victor Stinner            platform = _platform(system, release, version)
1427246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        else:
1428ced3936894cec493b93c1144c543d51048268288Victor Stinner            platform = _platform(system, release, version,
1429246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg                                 'on',
1430ced3936894cec493b93c1144c543d51048268288Victor Stinner                                 os_name, os_version, os_arch)
1431246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1432246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    elif system == 'MacOS':
1433246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # MacOS platforms
1434246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        if terse:
1435ced3936894cec493b93c1144c543d51048268288Victor Stinner            platform = _platform(system, release)
1436246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        else:
1437ced3936894cec493b93c1144c543d51048268288Victor Stinner            platform = _platform(system, release, machine)
1438246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1439246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    else:
1440246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        # Generic handler
1441246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        if terse:
1442ced3936894cec493b93c1144c543d51048268288Victor Stinner            platform = _platform(system, release)
1443246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg        else:
1444ced3936894cec493b93c1144c543d51048268288Victor Stinner            bits, linkage = architecture(sys.executable)
1445ced3936894cec493b93c1144c543d51048268288Victor Stinner            platform = _platform(system, release, machine,
1446ced3936894cec493b93c1144c543d51048268288Victor Stinner                                 processor, bits, linkage)
14470eadaac7dc3ae49974c105ff9e8c1e98a04d7d5aTim Peters
144891e83e209d66d4b7a892c9360f9e524d6e282191Marc-André Lemburg    _platform_cache[(aliased, terse)] = platform
1449246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    return platform
1450246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1451246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg### Command line interface
1452246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg
1453246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburgif __name__ == '__main__':
1454246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    # Default is to print the aliased verbose platform string
14550eadaac7dc3ae49974c105ff9e8c1e98a04d7d5aTim Peters    terse = ('terse' in sys.argv or '--terse' in sys.argv)
1456246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    aliased = (not 'nonaliased' in sys.argv and not '--nonaliased' in sys.argv)
1457ced3936894cec493b93c1144c543d51048268288Victor Stinner    print(platform(aliased, terse))
1458246d847475d041a823dbc3cc3aceae46e97de937Marc-André Lemburg    sys.exit(0)
1459