blob: c4ffe95bca3db601108ee1dc2e740c1d129df005 [file] [log] [blame]
Benjamin Peterson90f5ba52010-03-11 22:53:45 +00001#!/usr/bin/env python3
Marc-André Lemburg246d8472003-04-24 11:36:11 +00002
Brett Cannon8ab27df2003-08-05 03:52:04 +00003""" This module tries to retrieve as much platform-identifying data as
Marc-André Lemburg246d8472003-04-24 11:36:11 +00004 possible. It makes this information available via function APIs.
5
6 If called from the command line, it prints the platform
7 information concatenated as single string to stdout. The output
8 format is useable as part of a filename.
9
10"""
11# This module is maintained by Marc-Andre Lemburg <mal@egenix.com>.
12# If you find problems, please submit bug reports/patches via the
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +000013# Python bug tracker (http://bugs.python.org) and assign them to "lemburg".
Marc-André Lemburg246d8472003-04-24 11:36:11 +000014#
Marc-André Lemburg246d8472003-04-24 11:36:11 +000015# Still needed:
16# * more support for WinCE
17# * support for MS-DOS (PythonDX ?)
18# * support for Amiga and other still unsupported platforms running Python
19# * support for additional Linux distributions
20#
Brett Cannon8ab27df2003-08-05 03:52:04 +000021# Many thanks to all those who helped adding platform-specific
Marc-André Lemburg246d8472003-04-24 11:36:11 +000022# checks (in no particular order):
23#
24# Charles G Waldman, David Arnold, Gordon McMillan, Ben Darnell,
25# Jeff Bauer, Cliff Crawford, Ivan Van Laningham, Josef
26# Betancourt, Randall Hopper, Karl Putland, John Farrell, Greg
27# Andruk, Just van Rossum, Thomas Heller, Mark R. Levinson, Mark
28# Hammond, Bill Tutt, Hans Nowak, Uwe Zessin (OpenVMS support),
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +000029# Colin Kong, Trent Mick, Guido van Rossum, Anthony Baxter
Marc-André Lemburg246d8472003-04-24 11:36:11 +000030#
31# History:
Marc-André Lemburg380f4172005-11-07 16:11:02 +000032#
33# <see CVS and SVN checkin messages for history>
34#
Alexandre Vassalottie52e3782009-07-17 09:18:18 +000035# 1.0.7 - added DEV_NULL
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +000036# 1.0.6 - added linux_distribution()
37# 1.0.5 - fixed Java support to allow running the module on Jython
38# 1.0.4 - added IronPython support
Marc-André Lemburgcdc79232004-06-19 17:17:00 +000039# 1.0.3 - added normalization of Windows system name
Marc-André Lemburg91e83e22004-03-25 18:35:12 +000040# 1.0.2 - added more Windows support
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +000041# 1.0.1 - reformatted to make doc.py happy
Marc-André Lemburg246d8472003-04-24 11:36:11 +000042# 1.0.0 - reformatted a bit and checked into Python CVS
43# 0.8.0 - added sys.version parser and various new access
44# APIs (python_version(), python_compiler(), etc.)
45# 0.7.2 - fixed architecture() to use sizeof(pointer) where available
46# 0.7.1 - added support for Caldera OpenLinux
47# 0.7.0 - some fixes for WinCE; untabified the source file
48# 0.6.2 - support for OpenVMS - requires version 1.5.2-V006 or higher and
49# vms_lib.getsyi() configured
50# 0.6.1 - added code to prevent 'uname -p' on platforms which are
51# known not to support it
52# 0.6.0 - fixed win32_ver() to hopefully work on Win95,98,NT and Win2k;
53# did some cleanup of the interfaces - some APIs have changed
54# 0.5.5 - fixed another type in the MacOS code... should have
55# used more coffee today ;-)
56# 0.5.4 - fixed a few typos in the MacOS code
57# 0.5.3 - added experimental MacOS support; added better popen()
58# workarounds in _syscmd_ver() -- still not 100% elegant
59# though
60# 0.5.2 - fixed uname() to return '' instead of 'unknown' in all
61# return values (the system uname command tends to return
62# 'unknown' instead of just leaving the field emtpy)
63# 0.5.1 - included code for slackware dist; added exception handlers
64# to cover up situations where platforms don't have os.popen
65# (e.g. Mac) or fail on socket.gethostname(); fixed libc
66# detection RE
67# 0.5.0 - changed the API names referring to system commands to *syscmd*;
68# added java_ver(); made syscmd_ver() a private
69# API (was system_ver() in previous versions) -- use uname()
70# instead; extended the win32_ver() to also return processor
71# type information
72# 0.4.0 - added win32_ver() and modified the platform() output for WinXX
73# 0.3.4 - fixed a bug in _follow_symlinks()
74# 0.3.3 - fixed popen() and "file" command invokation bugs
75# 0.3.2 - added architecture() API and support for it in platform()
76# 0.3.1 - fixed syscmd_ver() RE to support Windows NT
77# 0.3.0 - added system alias support
78# 0.2.3 - removed 'wince' again... oh well.
79# 0.2.2 - added 'wince' to syscmd_ver() supported platforms
80# 0.2.1 - added cache logic and changed the platform string format
81# 0.2.0 - changed the API to use functions instead of module globals
82# since some action take too long to be run on module import
83# 0.1.0 - first release
84#
85# You can always get the latest version of this module at:
86#
87# http://www.egenix.com/files/python/platform.py
88#
89# If that URL should fail, try contacting the author.
90
91__copyright__ = """
92 Copyright (c) 1999-2000, Marc-Andre Lemburg; mailto:mal@lemburg.com
Benjamin Peterson46a99002010-01-09 18:45:30 +000093 Copyright (c) 2000-2010, eGenix.com Software GmbH; mailto:info@egenix.com
Marc-André Lemburg246d8472003-04-24 11:36:11 +000094
95 Permission to use, copy, modify, and distribute this software and its
96 documentation for any purpose and without fee or royalty is hereby granted,
97 provided that the above copyright notice appear in all copies and that
98 both that copyright notice and this permission notice appear in
99 supporting documentation or portions thereof, including modifications,
100 that you make.
101
102 EGENIX.COM SOFTWARE GMBH DISCLAIMS ALL WARRANTIES WITH REGARD TO
103 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
104 FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
105 INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
106 FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
107 NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
108 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE !
109
110"""
111
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000112__version__ = '1.0.7'
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000113
Larry Hastings68386bc2012-06-24 14:30:41 -0700114import collections
Jesus Ceafc990e92012-10-04 13:51:43 +0200115import sys, os, re, subprocess
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000116
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000117### Globals & Constants
118
119# Determine the platform's /dev/null device
120try:
121 DEV_NULL = os.devnull
122except AttributeError:
123 # os.devnull was added in Python 2.4, so emulate it for earlier
124 # Python versions
Victor Stinnerced39362013-12-09 00:14:52 +0100125 if sys.platform in ('dos', 'win32', 'win16'):
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000126 # Use the old CP/M NUL as device name
127 DEV_NULL = 'NUL'
128 else:
129 # Standard Unix uses /dev/null
130 DEV_NULL = '/dev/null'
131
Victor Stinner620c48b2013-12-09 00:01:27 +0100132# Directory to search for configuration information on Unix.
133# Constant used by test_platform to test linux_distribution().
134_UNIXCONFDIR = '/etc'
135
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000136### Platform specific APIs
137
Antoine Pitrouba7c2262011-10-07 13:26:59 +0200138_libc_search = re.compile(b'(__libc_init)'
139 b'|'
140 b'(GLIBC_([0-9.]+))'
141 b'|'
142 br'(libc(_\w+)?\.so(?:\.(\d[0-9.]*))?)', re.ASCII)
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000143
Victor Stinnerced39362013-12-09 00:14:52 +0100144def libc_ver(executable=sys.executable, lib='', version='',
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000145
Antoine Pitrouba7c2262011-10-07 13:26:59 +0200146 chunksize=16384):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000147
Brett Cannon8ab27df2003-08-05 03:52:04 +0000148 """ Tries to determine the libc version that the file executable
149 (which defaults to the Python interpreter) is linked against.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000150
151 Returns a tuple of strings (lib,version) which default to the
152 given parameters in case the lookup fails.
153
154 Note that the function has intimate knowledge of how different
Brett Cannon8ab27df2003-08-05 03:52:04 +0000155 libc versions add symbols to the executable and thus is probably
156 only useable for executables compiled using gcc.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000157
158 The file is read and scanned in chunks of chunksize bytes.
159
160 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000161 if hasattr(os.path, 'realpath'):
162 # Python 2.2 introduced os.path.realpath(); it is used
163 # here to work around problems with Cygwin not being
164 # able to open symlinks for reading
165 executable = os.path.realpath(executable)
Victor Stinnerced39362013-12-09 00:14:52 +0100166 f = open(executable, 'rb')
Antoine Pitrouba7c2262011-10-07 13:26:59 +0200167 binary = f.read(chunksize)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000168 pos = 0
169 while 1:
Antoine Pitrouba7c2262011-10-07 13:26:59 +0200170 if b'libc' in binary or b'GLIBC' in binary:
Victor Stinnerced39362013-12-09 00:14:52 +0100171 m = _libc_search.search(binary, pos)
Antoine Pitrouba7c2262011-10-07 13:26:59 +0200172 else:
173 m = None
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000174 if not m:
Antoine Pitrouba7c2262011-10-07 13:26:59 +0200175 binary = f.read(chunksize)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000176 if not binary:
177 break
178 pos = 0
179 continue
Victor Stinnerced39362013-12-09 00:14:52 +0100180 libcinit, glibc, glibcversion, so, threads, soversion = [
Antoine Pitrouba7c2262011-10-07 13:26:59 +0200181 s.decode('latin1') if s is not None else s
182 for s in m.groups()]
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000183 if libcinit and not lib:
184 lib = 'libc'
185 elif glibc:
186 if lib != 'glibc':
187 lib = 'glibc'
188 version = glibcversion
189 elif glibcversion > version:
190 version = glibcversion
191 elif so:
192 if lib != 'glibc':
193 lib = 'libc'
Victor Stinner87448812011-12-15 21:42:03 +0100194 if soversion and soversion > version:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000195 version = soversion
196 if threads and version[-len(threads):] != threads:
197 version = version + threads
198 pos = m.end()
199 f.close()
Victor Stinnerced39362013-12-09 00:14:52 +0100200 return lib, version
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000201
Victor Stinnerced39362013-12-09 00:14:52 +0100202def _dist_try_harder(distname, version, id):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000203
Tim Peters0eadaac2003-04-24 16:02:54 +0000204 """ Tries some special tricks to get the distribution
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000205 information in case the default method fails.
206
207 Currently supports older SuSE Linux, Caldera OpenLinux and
208 Slackware Linux distributions.
209
210 """
211 if os.path.exists('/var/adm/inst-log/info'):
212 # SuSE Linux stores distribution information in that file
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000213 distname = 'SuSE'
Florent Xicluna7dde7922010-09-03 19:52:03 +0000214 for line in open('/var/adm/inst-log/info'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000215 tv = line.split()
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000216 if len(tv) == 2:
Victor Stinnerced39362013-12-09 00:14:52 +0100217 tag, value = tv
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000218 else:
219 continue
220 if tag == 'MIN_DIST_VERSION':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000221 version = value.strip()
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000222 elif tag == 'DIST_IDENT':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000223 values = value.split('-')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000224 id = values[2]
Victor Stinnerced39362013-12-09 00:14:52 +0100225 return distname, version, id
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000226
227 if os.path.exists('/etc/.installed'):
228 # Caldera OpenLinux has some infos in that file (thanks to Colin Kong)
Florent Xicluna7dde7922010-09-03 19:52:03 +0000229 for line in open('/etc/.installed'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000230 pkg = line.split('-')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000231 if len(pkg) >= 2 and pkg[0] == 'OpenLinux':
232 # XXX does Caldera support non Intel platforms ? If yes,
233 # where can we find the needed id ?
Victor Stinnerced39362013-12-09 00:14:52 +0100234 return 'OpenLinux', pkg[1], id
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000235
236 if os.path.isdir('/usr/lib/setup'):
Ezio Melotti30b9d5d2013-08-17 15:50:46 +0300237 # Check for slackware version tag file (thanks to Greg Andruk)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000238 verfiles = os.listdir('/usr/lib/setup')
Guido van Rossum843c7342004-05-04 18:18:59 +0000239 for n in range(len(verfiles)-1, -1, -1):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000240 if verfiles[n][:14] != 'slack-version-':
241 del verfiles[n]
242 if verfiles:
243 verfiles.sort()
244 distname = 'slackware'
245 version = verfiles[-1][14:]
Victor Stinnerced39362013-12-09 00:14:52 +0100246 return distname, version, id
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000247
Victor Stinnerced39362013-12-09 00:14:52 +0100248 return distname, version, id
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000249
Antoine Pitroufd036452008-08-19 17:56:33 +0000250_release_filename = re.compile(r'(\w+)[-_](release|version)', re.ASCII)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000251_lsb_release_version = re.compile(r'(.+)'
252 ' release '
253 '([\d.]+)'
Antoine Pitroufd036452008-08-19 17:56:33 +0000254 '[^(]*(?:\((.+)\))?', re.ASCII)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000255_release_version = re.compile(r'([^0-9]+)'
256 '(?: release )?'
257 '([\d.]+)'
Antoine Pitroufd036452008-08-19 17:56:33 +0000258 '[^(]*(?:\((.+)\))?', re.ASCII)
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000259
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000260# See also http://www.novell.com/coolsolutions/feature/11251.html
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000261# and http://linuxmafia.com/faq/Admin/release-files.html
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000262# and http://data.linux-ntfs.org/rpm/whichrpm
263# and http://www.die.net/doc/linux/man/man1/lsb_release.1.html
Marc-André Lemburg380f4172005-11-07 16:11:02 +0000264
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000265_supported_dists = (
266 'SuSE', 'debian', 'fedora', 'redhat', 'centos',
267 'mandrake', 'mandriva', 'rocks', 'slackware', 'yellowdog', 'gentoo',
Antoine Pitrouab888032012-06-24 22:20:18 +0200268 'UnitedLinux', 'turbolinux', 'arch', 'mageia')
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000269
270def _parse_release_file(firstline):
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000271
Benjamin Peterson25001472010-01-25 03:37:42 +0000272 # Default to empty 'version' and 'id' strings. Both defaults are used
273 # when 'firstline' is empty. 'id' defaults to empty when an id can not
274 # be deduced.
275 version = ''
276 id = ''
277
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000278 # Parse the first line
279 m = _lsb_release_version.match(firstline)
280 if m is not None:
281 # LSB format: "distro release x.x (codename)"
282 return tuple(m.groups())
283
284 # Pre-LSB format: "distro x.x (codename)"
285 m = _release_version.match(firstline)
286 if m is not None:
287 return tuple(m.groups())
288
Ezio Melotti30b9d5d2013-08-17 15:50:46 +0300289 # Unknown format... take the first two words
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000290 l = firstline.strip().split()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000291 if l:
292 version = l[0]
293 if len(l) > 1:
294 id = l[1]
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000295 return '', version, id
296
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000297def linux_distribution(distname='', version='', id='',
298
299 supported_dists=_supported_dists,
300 full_distribution_name=1):
301
302 """ Tries to determine the name of the Linux OS distribution name.
303
304 The function first looks for a distribution release file in
305 /etc and then reverts to _dist_try_harder() in case no
306 suitable files are found.
307
308 supported_dists may be given to define the set of Linux
309 distributions to look for. It defaults to a list of currently
310 supported Linux distributions identified by their release file
311 name.
312
313 If full_distribution_name is true (default), the full
314 distribution read from the OS is returned. Otherwise the short
315 name taken from supported_dists is used.
316
Victor Stinnerced39362013-12-09 00:14:52 +0100317 Returns a tuple (distname, version, id) which default to the
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000318 args given as parameters.
319
320 """
321 try:
Victor Stinner620c48b2013-12-09 00:01:27 +0100322 etc = os.listdir(_UNIXCONFDIR)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200323 except OSError:
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000324 # Probably not a Unix system
Victor Stinnerced39362013-12-09 00:14:52 +0100325 return distname, version, id
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000326 etc.sort()
327 for file in etc:
328 m = _release_filename.match(file)
329 if m is not None:
Victor Stinnerced39362013-12-09 00:14:52 +0100330 _distname, dummy = m.groups()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000331 if _distname in supported_dists:
332 distname = _distname
333 break
334 else:
Victor Stinnerced39362013-12-09 00:14:52 +0100335 return _dist_try_harder(distname, version, id)
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000336
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000337 # Read the first line
Victor Stinner620c48b2013-12-09 00:01:27 +0100338 with open(os.path.join(_UNIXCONFDIR, file), 'r',
339 encoding='utf-8', errors='surrogateescape') as f:
Florent Xicluna7dde7922010-09-03 19:52:03 +0000340 firstline = f.readline()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000341 _distname, _version, _id = _parse_release_file(firstline)
342
343 if _distname and full_distribution_name:
344 distname = _distname
345 if _version:
346 version = _version
347 if _id:
348 id = _id
349 return distname, version, id
350
351# To maintain backwards compatibility:
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000352
Victor Stinnerced39362013-12-09 00:14:52 +0100353def dist(distname='', version='', id='',
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000354
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000355 supported_dists=_supported_dists):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000356
Brett Cannon8ab27df2003-08-05 03:52:04 +0000357 """ Tries to determine the name of the Linux OS distribution name.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000358
359 The function first looks for a distribution release file in
360 /etc and then reverts to _dist_try_harder() in case no
361 suitable files are found.
362
Victor Stinnerced39362013-12-09 00:14:52 +0100363 Returns a tuple (distname, version, id) which default to the
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000364 args given as parameters.
365
366 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000367 return linux_distribution(distname, version, id,
368 supported_dists=supported_dists,
369 full_distribution_name=0)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000370
Antoine Pitrou877766d2011-03-19 17:00:37 +0100371def popen(cmd, mode='r', bufsize=-1):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000372
373 """ Portable popen() interface.
374 """
Victor Stinner25000d42011-05-24 00:16:16 +0200375 import warnings
376 warnings.warn('use os.popen instead', DeprecationWarning, stacklevel=2)
Victor Stinner1dfd3802011-03-03 12:54:07 +0000377 return os.popen(cmd, mode, bufsize)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000378
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000379def _norm_version(version, build=''):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000380
Brett Cannon8ab27df2003-08-05 03:52:04 +0000381 """ Normalize the version and build strings and return a single
Walter Dörwalde5a7fad2005-11-21 17:01:27 +0000382 version string using the format major.minor.build (or patchlevel).
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000383 """
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000384 l = version.split('.')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000385 if build:
386 l.append(build)
387 try:
Victor Stinnerced39362013-12-09 00:14:52 +0100388 ints = map(int, l)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000389 except ValueError:
390 strings = l
391 else:
Victor Stinnerced39362013-12-09 00:14:52 +0100392 strings = list(map(str, ints))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000393 version = '.'.join(strings[:3])
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000394 return version
395
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000396_ver_output = re.compile(r'(?:([\w ]+) ([\w.]+) '
397 '.*'
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000398 '\[.* ([\d.]+)\])')
399
400# Examples of VER command output:
401#
402# Windows 2000: Microsoft Windows 2000 [Version 5.00.2195]
403# Windows XP: Microsoft Windows XP [Version 5.1.2600]
404# Windows Vista: Microsoft Windows [Version 6.0.6002]
405#
406# Note that the "Version" string gets localized on different
407# Windows versions.
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000408
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000409def _syscmd_ver(system='', release='', version='',
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000410
Victor Stinnerced39362013-12-09 00:14:52 +0100411 supported_platforms=('win32', 'win16', 'dos')):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000412
413 """ Tries to figure out the OS version used and returns
Victor Stinnerced39362013-12-09 00:14:52 +0100414 a tuple (system, release, version).
Tim Peters0eadaac2003-04-24 16:02:54 +0000415
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000416 It uses the "ver" shell command for this which is known
Jesus Ceaf1af7052012-10-05 02:48:46 +0200417 to exists on Windows, DOS. XXX Others too ?
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000418
419 In case this fails, the given parameters are used as
420 defaults.
421
422 """
423 if sys.platform not in supported_platforms:
Victor Stinnerced39362013-12-09 00:14:52 +0100424 return system, release, version
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000425
426 # Try some common cmd strings
Victor Stinnerced39362013-12-09 00:14:52 +0100427 for cmd in ('ver', 'command /c ver', 'cmd /c ver'):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000428 try:
429 pipe = popen(cmd)
430 info = pipe.read()
431 if pipe.close():
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200432 raise OSError('command failed')
Ezio Melotti13925002011-03-16 11:05:33 +0200433 # XXX How can I suppress shell errors from being written
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000434 # to stderr ?
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200435 except OSError as why:
Victor Stinnerced39362013-12-09 00:14:52 +0100436 #print 'Command %s failed: %s' % (cmd, why)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000437 continue
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000438 else:
439 break
440 else:
Victor Stinnerced39362013-12-09 00:14:52 +0100441 return system, release, version
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000442
443 # Parse the output
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000444 info = info.strip()
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000445 m = _ver_output.match(info)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000446 if m is not None:
Victor Stinnerced39362013-12-09 00:14:52 +0100447 system, release, version = m.groups()
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000448 # Strip trailing dots from version and release
449 if release[-1] == '.':
450 release = release[:-1]
451 if version[-1] == '.':
452 version = version[:-1]
453 # Normalize the version and build strings (eliminating additional
454 # zeros)
455 version = _norm_version(version)
Victor Stinnerced39362013-12-09 00:14:52 +0100456 return system, release, version
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000457
Victor Stinnerced39362013-12-09 00:14:52 +0100458def _win32_getvalue(key, name, default=''):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000459
460 """ Read a value for name from the registry key.
461
462 In case this fails, default is returned.
463
464 """
Christian Heimes02781dc2008-03-21 01:11:52 +0000465 try:
466 # Use win32api if available
467 from win32api import RegQueryValueEx
Brett Cannoncd171c82013-07-04 17:43:24 -0400468 except ImportError:
Georg Brandl38feaf02008-05-25 07:45:51 +0000469 # On Python 2.0 and later, emulate using winreg
470 import winreg
471 RegQueryValueEx = winreg.QueryValueEx
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000472 try:
Victor Stinnerced39362013-12-09 00:14:52 +0100473 return RegQueryValueEx(key, name)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000474 except:
475 return default
476
Victor Stinnerced39362013-12-09 00:14:52 +0100477def win32_ver(release='', version='', csd='', ptype=''):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000478
479 """ Get additional version information from the Windows Registry
Victor Stinnerced39362013-12-09 00:14:52 +0100480 and return a tuple (version, csd, ptype) referring to version
Brian Curtin10dda6e2012-02-01 15:14:00 -0600481 number, CSD level (service pack), and OS type (multi/single
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000482 processor).
483
484 As a hint: ptype returns 'Uniprocessor Free' on single
485 processor NT machines and 'Multiprocessor Free' on multi
486 processor machines. The 'Free' refers to the OS version being
487 free of debugging code. It could also state 'Checked' which
488 means the OS version uses debugging code, i.e. code that
489 checks arguments, ranges, etc. (Thomas Heller).
490
Christian Heimes02781dc2008-03-21 01:11:52 +0000491 Note: this function works best with Mark Hammond's win32
492 package installed, but also on Python 2.3 and later. It
493 obviously only runs on Win32 compatible platforms.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000494
495 """
496 # XXX Is there any way to find out the processor type on WinXX ?
497 # XXX Is win32 available on Windows CE ?
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000498 #
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000499 # Adapted from code posted by Karl Putland to comp.lang.python.
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000500 #
501 # The mappings between reg. values and release names can be found
502 # here: http://msdn.microsoft.com/library/en-us/sysinfo/base/osversioninfo_str.asp
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000503
504 # Import the needed APIs
505 try:
Christian Heimes02781dc2008-03-21 01:11:52 +0000506 from win32api import RegQueryValueEx, RegOpenKeyEx, \
507 RegCloseKey, GetVersionEx
508 from win32con import HKEY_LOCAL_MACHINE, VER_PLATFORM_WIN32_NT, \
509 VER_PLATFORM_WIN32_WINDOWS, VER_NT_WORKSTATION
Brett Cannoncd171c82013-07-04 17:43:24 -0400510 except ImportError:
Christian Heimes02781dc2008-03-21 01:11:52 +0000511 # Emulate the win32api module using Python APIs
512 try:
513 sys.getwindowsversion
514 except AttributeError:
515 # No emulation possible, so return the defaults...
Victor Stinnerced39362013-12-09 00:14:52 +0100516 return release, version, csd, ptype
Christian Heimes02781dc2008-03-21 01:11:52 +0000517 else:
Georg Brandl38feaf02008-05-25 07:45:51 +0000518 # Emulation using winreg (added in Python 2.0) and
Christian Heimes02781dc2008-03-21 01:11:52 +0000519 # sys.getwindowsversion() (added in Python 2.3)
Georg Brandl38feaf02008-05-25 07:45:51 +0000520 import winreg
Christian Heimes02781dc2008-03-21 01:11:52 +0000521 GetVersionEx = sys.getwindowsversion
Georg Brandl38feaf02008-05-25 07:45:51 +0000522 RegQueryValueEx = winreg.QueryValueEx
523 RegOpenKeyEx = winreg.OpenKeyEx
524 RegCloseKey = winreg.CloseKey
525 HKEY_LOCAL_MACHINE = winreg.HKEY_LOCAL_MACHINE
Christian Heimes02781dc2008-03-21 01:11:52 +0000526 VER_PLATFORM_WIN32_WINDOWS = 1
527 VER_PLATFORM_WIN32_NT = 2
528 VER_NT_WORKSTATION = 1
Brian Curtin6e2824d2010-05-06 03:05:50 +0000529 VER_NT_SERVER = 3
530 REG_SZ = 1
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000531
532 # Find out the registry key and some general version infos
Brian Curtin6e2824d2010-05-06 03:05:50 +0000533 winver = GetVersionEx()
Victor Stinnerced39362013-12-09 00:14:52 +0100534 maj, min, buildno, plat, csd = winver
535 version = '%i.%i.%i' % (maj, min, buildno & 0xFFFF)
Brian Curtin6e2824d2010-05-06 03:05:50 +0000536 if hasattr(winver, "service_pack"):
537 if winver.service_pack != "":
538 csd = 'SP%s' % winver.service_pack_major
539 else:
540 if csd[:13] == 'Service Pack ':
541 csd = 'SP' + csd[13:]
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000542
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000543 if plat == VER_PLATFORM_WIN32_WINDOWS:
544 regkey = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion'
545 # Try to guess the release name
546 if maj == 4:
547 if min == 0:
548 release = '95'
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000549 elif min == 10:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000550 release = '98'
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000551 elif min == 90:
552 release = 'Me'
553 else:
554 release = 'postMe'
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000555 elif maj == 5:
556 release = '2000'
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000557
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000558 elif plat == VER_PLATFORM_WIN32_NT:
559 regkey = 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion'
560 if maj <= 4:
561 release = 'NT'
562 elif maj == 5:
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000563 if min == 0:
564 release = '2000'
565 elif min == 1:
566 release = 'XP'
567 elif min == 2:
568 release = '2003Server'
569 else:
570 release = 'post2003'
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000571 elif maj == 6:
Brian Curtin6e2824d2010-05-06 03:05:50 +0000572 if hasattr(winver, "product_type"):
573 product_type = winver.product_type
574 else:
575 product_type = VER_NT_WORKSTATION
576 # Without an OSVERSIONINFOEX capable sys.getwindowsversion(),
577 # or help from the registry, we cannot properly identify
578 # non-workstation versions.
Christian Heimes02781dc2008-03-21 01:11:52 +0000579 try:
Brian Curtin6e2824d2010-05-06 03:05:50 +0000580 key = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey)
581 name, type = RegQueryValueEx(key, "ProductName")
582 # Discard any type that isn't REG_SZ
583 if type == REG_SZ and name.find("Server") != -1:
584 product_type = VER_NT_SERVER
Andrew Svetlov2606a6f2012-12-19 14:33:35 +0200585 except OSError:
Brian Curtin6e2824d2010-05-06 03:05:50 +0000586 # Use default of VER_NT_WORKSTATION
587 pass
588
589 if min == 0:
590 if product_type == VER_NT_WORKSTATION:
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000591 release = 'Vista'
592 else:
Brian Curtin6e2824d2010-05-06 03:05:50 +0000593 release = '2008Server'
594 elif min == 1:
595 if product_type == VER_NT_WORKSTATION:
596 release = '7'
597 else:
598 release = '2008ServerR2'
Brian Curtin0b960f52012-10-11 16:07:52 -0500599 elif min == 2:
600 if product_type == VER_NT_WORKSTATION:
601 release = '8'
602 else:
603 release = '2012Server'
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000604 else:
Brian Curtin0b960f52012-10-11 16:07:52 -0500605 release = 'post2012Server'
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000606
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000607 else:
608 if not release:
609 # E.g. Win3.1 with win32s
Victor Stinnerced39362013-12-09 00:14:52 +0100610 release = '%i.%i' % (maj, min)
611 return release, version, csd, ptype
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000612
613 # Open the registry key
614 try:
Christian Heimes02781dc2008-03-21 01:11:52 +0000615 keyCurVer = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000616 # Get a value to make sure the key exists...
Christian Heimes02781dc2008-03-21 01:11:52 +0000617 RegQueryValueEx(keyCurVer, 'SystemRoot')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000618 except:
Victor Stinnerced39362013-12-09 00:14:52 +0100619 return release, version, csd, ptype
Tim Peters0eadaac2003-04-24 16:02:54 +0000620
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000621 # Parse values
622 #subversion = _win32_getvalue(keyCurVer,
623 # 'SubVersionNumber',
624 # ('',1))[0]
625 #if subversion:
626 # release = release + subversion # 95a, 95b, etc.
627 build = _win32_getvalue(keyCurVer,
628 'CurrentBuildNumber',
Victor Stinnerced39362013-12-09 00:14:52 +0100629 ('', 1))[0]
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000630 ptype = _win32_getvalue(keyCurVer,
631 'CurrentType',
Victor Stinnerced39362013-12-09 00:14:52 +0100632 (ptype, 1))[0]
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000633
634 # Normalize version
Victor Stinnerced39362013-12-09 00:14:52 +0100635 version = _norm_version(version, build)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000636
637 # Close key
638 RegCloseKey(keyCurVer)
Victor Stinnerced39362013-12-09 00:14:52 +0100639 return release, version, csd, ptype
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000640
Ronald Oussorene186e382010-07-23 11:54:59 +0000641def _mac_ver_xml():
642 fn = '/System/Library/CoreServices/SystemVersion.plist'
643 if not os.path.exists(fn):
644 return None
645
646 try:
647 import plistlib
Brett Cannoncd171c82013-07-04 17:43:24 -0400648 except ImportError:
Ronald Oussorene186e382010-07-23 11:54:59 +0000649 return None
650
Ned Deily936dfae2014-01-13 11:34:19 -0800651 with open(fn, 'rb') as f:
652 pl = plistlib.load(f)
Ronald Oussorene186e382010-07-23 11:54:59 +0000653 release = pl['ProductVersion']
Victor Stinnerced39362013-12-09 00:14:52 +0100654 versioninfo = ('', '', '')
Larry Hastings605a62d2012-06-24 04:33:36 -0700655 machine = os.uname().machine
Ronald Oussorenfcd77012010-08-03 07:42:42 +0000656 if machine in ('ppc', 'Power Macintosh'):
Ezio Melotti9a3777e2013-08-17 15:53:55 +0300657 # Canonical name
Ronald Oussorene186e382010-07-23 11:54:59 +0000658 machine = 'PowerPC'
659
Victor Stinnerced39362013-12-09 00:14:52 +0100660 return release, versioninfo, machine
Ronald Oussorene186e382010-07-23 11:54:59 +0000661
662
Victor Stinnerced39362013-12-09 00:14:52 +0100663def mac_ver(release='', versioninfo=('', '', ''), machine=''):
Ronald Oussorene186e382010-07-23 11:54:59 +0000664
665 """ Get MacOS version information and return it as tuple (release,
666 versioninfo, machine) with versioninfo being a tuple (version,
667 dev_stage, non_release_version).
668
Ezio Melotti30b9d5d2013-08-17 15:50:46 +0300669 Entries which cannot be determined are set to the parameter values
Ronald Oussorene186e382010-07-23 11:54:59 +0000670 which default to ''. All tuple entries are strings.
671 """
672
673 # First try reading the information from an XML file which should
674 # always be present
675 info = _mac_ver_xml()
676 if info is not None:
677 return info
678
Ronald Oussorene186e382010-07-23 11:54:59 +0000679 # If that also doesn't work return the default values
Victor Stinnerced39362013-12-09 00:14:52 +0100680 return release, versioninfo, machine
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000681
Victor Stinnerced39362013-12-09 00:14:52 +0100682def _java_getprop(name, default):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000683
684 from java.lang import System
685 try:
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000686 value = System.getProperty(name)
687 if value is None:
688 return default
689 return value
690 except AttributeError:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000691 return default
692
Victor Stinnerced39362013-12-09 00:14:52 +0100693def java_ver(release='', vendor='', vminfo=('', '', ''), osinfo=('', '', '')):
Tim Peters0eadaac2003-04-24 16:02:54 +0000694
Brett Cannon8ab27df2003-08-05 03:52:04 +0000695 """ Version interface for Jython.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000696
Victor Stinnerced39362013-12-09 00:14:52 +0100697 Returns a tuple (release, vendor, vminfo, osinfo) with vminfo being
698 a tuple (vm_name, vm_release, vm_vendor) and osinfo being a
699 tuple (os_name, os_version, os_arch).
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000700
701 Values which cannot be determined are set to the defaults
702 given as parameters (which all default to '').
703
704 """
705 # Import the needed APIs
706 try:
707 import java.lang
Brett Cannoncd171c82013-07-04 17:43:24 -0400708 except ImportError:
Victor Stinnerced39362013-12-09 00:14:52 +0100709 return release, vendor, vminfo, osinfo
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000710
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000711 vendor = _java_getprop('java.vendor', vendor)
712 release = _java_getprop('java.version', release)
713 vm_name, vm_release, vm_vendor = vminfo
714 vm_name = _java_getprop('java.vm.name', vm_name)
715 vm_vendor = _java_getprop('java.vm.vendor', vm_vendor)
716 vm_release = _java_getprop('java.vm.version', vm_release)
717 vminfo = vm_name, vm_release, vm_vendor
718 os_name, os_version, os_arch = osinfo
719 os_arch = _java_getprop('java.os.arch', os_arch)
720 os_name = _java_getprop('java.os.name', os_name)
721 os_version = _java_getprop('java.os.version', os_version)
722 osinfo = os_name, os_version, os_arch
Tim Peters0eadaac2003-04-24 16:02:54 +0000723
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000724 return release, vendor, vminfo, osinfo
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000725
726### System name aliasing
727
Victor Stinnerced39362013-12-09 00:14:52 +0100728def system_alias(system, release, version):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000729
Victor Stinnerced39362013-12-09 00:14:52 +0100730 """ Returns (system, release, version) aliased to common
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000731 marketing names used for some systems.
732
733 It also does some reordering of the information in some cases
734 where it would otherwise cause confusion.
735
736 """
737 if system == 'Rhapsody':
738 # Apple's BSD derivative
739 # XXX How can we determine the marketing release number ?
Victor Stinnerced39362013-12-09 00:14:52 +0100740 return 'MacOS X Server', system+release, version
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000741
742 elif system == 'SunOS':
743 # Sun's OS
744 if release < '5':
745 # These releases use the old name SunOS
Victor Stinnerced39362013-12-09 00:14:52 +0100746 return system, release, version
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000747 # Modify release (marketing release = SunOS release - 3)
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000748 l = release.split('.')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000749 if l:
750 try:
751 major = int(l[0])
752 except ValueError:
753 pass
754 else:
755 major = major - 3
756 l[0] = str(major)
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000757 release = '.'.join(l)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000758 if release < '6':
759 system = 'Solaris'
760 else:
761 # XXX Whatever the new SunOS marketing name is...
762 system = 'Solaris'
763
764 elif system == 'IRIX64':
765 # IRIX reports IRIX64 on platforms with 64-bit support; yet it
766 # is really a version and not a different platform, since 32-bit
767 # apps are also supported..
768 system = 'IRIX'
769 if version:
770 version = version + ' (64bit)'
771 else:
772 version = '64bit'
773
Victor Stinnerced39362013-12-09 00:14:52 +0100774 elif system in ('win32', 'win16'):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000775 # In case one of the other tricks
776 system = 'Windows'
777
Victor Stinnerced39362013-12-09 00:14:52 +0100778 return system, release, version
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000779
780### Various internal helpers
781
782def _platform(*args):
783
784 """ Helper to format the platform string in a filename
785 compatible format e.g. "system-version-machine".
786 """
787 # Format the platform string
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000788 platform = '-'.join(x.strip() for x in filter(len, args))
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000789
790 # Cleanup some possible filename obstacles...
Victor Stinnerced39362013-12-09 00:14:52 +0100791 platform = platform.replace(' ', '_')
792 platform = platform.replace('/', '-')
793 platform = platform.replace('\\', '-')
794 platform = platform.replace(':', '-')
795 platform = platform.replace(';', '-')
796 platform = platform.replace('"', '-')
797 platform = platform.replace('(', '-')
798 platform = platform.replace(')', '-')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000799
800 # No need to report 'unknown' information...
Victor Stinnerced39362013-12-09 00:14:52 +0100801 platform = platform.replace('unknown', '')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000802
803 # Fold '--'s and remove trailing '-'
804 while 1:
Victor Stinnerced39362013-12-09 00:14:52 +0100805 cleaned = platform.replace('--', '-')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000806 if cleaned == platform:
807 break
808 platform = cleaned
809 while platform[-1] == '-':
810 platform = platform[:-1]
811
812 return platform
813
814def _node(default=''):
815
816 """ Helper to determine the node name of this machine.
817 """
818 try:
819 import socket
Brett Cannoncd171c82013-07-04 17:43:24 -0400820 except ImportError:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000821 # No sockets...
822 return default
823 try:
824 return socket.gethostname()
Andrew Svetlov0832af62012-12-18 23:10:48 +0200825 except OSError:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000826 # Still not working...
827 return default
828
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000829def _follow_symlinks(filepath):
830
831 """ In case filepath is a symlink, follow it until a
832 real file is reached.
833 """
Georg Brandl673f7ef2008-01-05 21:20:19 +0000834 filepath = os.path.abspath(filepath)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000835 while os.path.islink(filepath):
836 filepath = os.path.normpath(
Victor Stinnerced39362013-12-09 00:14:52 +0100837 os.path.join(os.path.dirname(filepath), os.readlink(filepath)))
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000838 return filepath
839
Victor Stinnerced39362013-12-09 00:14:52 +0100840def _syscmd_uname(option, default=''):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000841
842 """ Interface to the system's uname command.
843 """
Victor Stinnerced39362013-12-09 00:14:52 +0100844 if sys.platform in ('dos', 'win32', 'win16'):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000845 # XXX Others too ?
846 return default
847 try:
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000848 f = os.popen('uname %s 2> %s' % (option, DEV_NULL))
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200849 except (AttributeError, OSError):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000850 return default
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000851 output = f.read().strip()
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000852 rc = f.close()
853 if not output or rc:
854 return default
855 else:
856 return output
857
Victor Stinnerced39362013-12-09 00:14:52 +0100858def _syscmd_file(target, default=''):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000859
860 """ Interface to the system's file command.
861
862 The function uses the -b option of the file command to have it
Victor Stinnerddfb2c32010-08-13 16:30:15 +0000863 omit the filename in its output. Follow the symlinks. It returns
864 default in case the command should fail.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000865
866 """
Victor Stinnerced39362013-12-09 00:14:52 +0100867 if sys.platform in ('dos', 'win32', 'win16'):
Hirokazu Yamamotod26782e2008-09-01 14:35:47 +0000868 # XXX Others too ?
869 return default
Jesus Ceafc990e92012-10-04 13:51:43 +0200870 target = _follow_symlinks(target)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000871 try:
Jesus Cea685fffa2012-10-05 05:21:42 +0200872 proc = subprocess.Popen(['file', target],
873 stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
Jesus Ceae8801e22012-10-04 13:56:23 +0200874
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200875 except (AttributeError, OSError):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000876 return default
Jesus Ceacb959962012-10-05 05:31:31 +0200877 output = proc.communicate()[0].decode('latin-1')
Jesus Ceafc990e92012-10-04 13:51:43 +0200878 rc = proc.wait()
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000879 if not output or rc:
880 return default
881 else:
882 return output
883
884### Information about the used architecture
885
886# Default values for architecture; non-empty strings override the
887# defaults given as parameters
888_default_architecture = {
Victor Stinnerced39362013-12-09 00:14:52 +0100889 'win32': ('', 'WindowsPE'),
890 'win16': ('', 'Windows'),
891 'dos': ('', 'MSDOS'),
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000892}
893
Victor Stinnerced39362013-12-09 00:14:52 +0100894def architecture(executable=sys.executable, bits='', linkage=''):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000895
896 """ Queries the given executable (defaults to the Python interpreter
Brett Cannon8ab27df2003-08-05 03:52:04 +0000897 binary) for various architecture information.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000898
Victor Stinnerced39362013-12-09 00:14:52 +0100899 Returns a tuple (bits, linkage) which contains information about
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000900 the bit architecture and the linkage format used for the
901 executable. Both values are returned as strings.
902
903 Values that cannot be determined are returned as given by the
904 parameter presets. If bits is given as '', the sizeof(pointer)
905 (or sizeof(long) on Python version < 1.5.2) is used as
906 indicator for the supported pointer size.
907
908 The function relies on the system's "file" command to do the
909 actual work. This is available on most if not all Unix
Brett Cannon8ab27df2003-08-05 03:52:04 +0000910 platforms. On some non-Unix platforms where the "file" command
911 does not exist and the executable is set to the Python interpreter
912 binary defaults from _default_architecture are used.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000913
914 """
915 # Use the sizeof(pointer) as default number of bits if nothing
916 # else is given as default.
917 if not bits:
918 import struct
919 try:
920 size = struct.calcsize('P')
921 except struct.error:
922 # Older installations can only query longs
923 size = struct.calcsize('l')
924 bits = str(size*8) + 'bit'
Tim Peters0eadaac2003-04-24 16:02:54 +0000925
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000926 # Get data from the 'file' system command
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000927 if executable:
Victor Stinnerddfb2c32010-08-13 16:30:15 +0000928 fileout = _syscmd_file(executable, '')
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000929 else:
Victor Stinnerddfb2c32010-08-13 16:30:15 +0000930 fileout = ''
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000931
Victor Stinnerddfb2c32010-08-13 16:30:15 +0000932 if not fileout and \
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000933 executable == sys.executable:
934 # "file" command did not return anything; we'll try to provide
Tim Peters0eadaac2003-04-24 16:02:54 +0000935 # some sensible defaults then...
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000936 if sys.platform in _default_architecture:
Victor Stinnerced39362013-12-09 00:14:52 +0100937 b, l = _default_architecture[sys.platform]
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000938 if b:
939 bits = b
940 if l:
941 linkage = l
Victor Stinnerced39362013-12-09 00:14:52 +0100942 return bits, linkage
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000943
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000944 if 'executable' not in fileout:
945 # Format not supported
Victor Stinnerced39362013-12-09 00:14:52 +0100946 return bits, linkage
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000947
948 # Bits
949 if '32-bit' in fileout:
950 bits = '32bit'
951 elif 'N32' in fileout:
952 # On Irix only
953 bits = 'n32bit'
954 elif '64-bit' in fileout:
955 bits = '64bit'
956
957 # Linkage
958 if 'ELF' in fileout:
959 linkage = 'ELF'
960 elif 'PE' in fileout:
961 # E.g. Windows uses this format
962 if 'Windows' in fileout:
963 linkage = 'WindowsPE'
964 else:
965 linkage = 'PE'
966 elif 'COFF' in fileout:
967 linkage = 'COFF'
968 elif 'MS-DOS' in fileout:
969 linkage = 'MSDOS'
970 else:
971 # XXX the A.OUT format also falls under this class...
972 pass
973
Victor Stinnerced39362013-12-09 00:14:52 +0100974 return bits, linkage
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000975
976### Portable uname() interface
Tim Peters0eadaac2003-04-24 16:02:54 +0000977
Larry Hastings68386bc2012-06-24 14:30:41 -0700978uname_result = collections.namedtuple("uname_result",
979 "system node release version machine processor")
980
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000981_uname_cache = None
982
983def uname():
984
985 """ Fairly portable uname interface. Returns a tuple
Victor Stinnerced39362013-12-09 00:14:52 +0100986 of strings (system, node, release, version, machine, processor)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000987 identifying the underlying platform.
988
989 Note that unlike the os.uname function this also returns
Brett Cannon8ab27df2003-08-05 03:52:04 +0000990 possible processor information as an additional tuple entry.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000991
992 Entries which cannot be determined are set to ''.
993
994 """
995 global _uname_cache
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +0000996 no_os_uname = 0
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000997
998 if _uname_cache is not None:
999 return _uname_cache
1000
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001001 processor = ''
1002
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001003 # Get some infos from the builtin os.uname API...
1004 try:
Victor Stinnerced39362013-12-09 00:14:52 +01001005 system, node, release, version, machine = os.uname()
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001006 except AttributeError:
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001007 no_os_uname = 1
1008
Georg Brandl62e2ca22010-07-31 21:54:24 +00001009 if no_os_uname or not list(filter(None, (system, node, release, version, machine))):
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001010 # Hmm, no there is either no uname or uname has returned
1011 #'unknowns'... we'll have to poke around the system then.
1012 if no_os_uname:
1013 system = sys.platform
1014 release = ''
1015 version = ''
1016 node = _node()
1017 machine = ''
1018
Amaury Forgeot d'Arc7a019842008-06-17 21:42:46 +00001019 use_syscmd_ver = 1
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001020
1021 # Try win32_ver() on win32 platforms
1022 if system == 'win32':
Victor Stinnerced39362013-12-09 00:14:52 +01001023 release, version, csd, ptype = win32_ver()
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001024 if release and version:
1025 use_syscmd_ver = 0
Christian Heimes02781dc2008-03-21 01:11:52 +00001026 # Try to use the PROCESSOR_* environment variables
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001027 # available on Win XP and later; see
1028 # http://support.microsoft.com/kb/888731 and
1029 # http://www.geocities.com/rick_lively/MANUALS/ENV/MSWIN/PROCESSI.HTM
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001030 if not machine:
R. David Murrayca2edce2010-03-22 17:48:48 +00001031 # WOW64 processes mask the native architecture
1032 if "PROCESSOR_ARCHITEW6432" in os.environ:
1033 machine = os.environ.get("PROCESSOR_ARCHITEW6432", '')
1034 else:
1035 machine = os.environ.get('PROCESSOR_ARCHITECTURE', '')
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001036 if not processor:
1037 processor = os.environ.get('PROCESSOR_IDENTIFIER', machine)
Tim Peters0eadaac2003-04-24 16:02:54 +00001038
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001039 # Try the 'ver' system command available on some
1040 # platforms
1041 if use_syscmd_ver:
Victor Stinnerced39362013-12-09 00:14:52 +01001042 system, release, version = _syscmd_ver(system)
Marc-André Lemburgcdc79232004-06-19 17:17:00 +00001043 # Normalize system to what win32_ver() normally returns
1044 # (_syscmd_ver() tends to return the vendor name as well)
1045 if system == 'Microsoft Windows':
1046 system = 'Windows'
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001047 elif system == 'Microsoft' and release == 'Windows':
1048 # Under Windows Vista and Windows Server 2008,
1049 # Microsoft changed the output of the ver command. The
1050 # release is no longer printed. This causes the
1051 # system and release to be misidentified.
1052 system = 'Windows'
1053 if '6.0' == version[:3]:
1054 release = 'Vista'
1055 else:
1056 release = ''
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001057
1058 # In case we still don't know anything useful, we'll try to
1059 # help ourselves
Victor Stinnerced39362013-12-09 00:14:52 +01001060 if system in ('win32', 'win16'):
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001061 if not version:
1062 if system == 'win32':
1063 version = '32bit'
1064 else:
1065 version = '16bit'
1066 system = 'Windows'
1067
1068 elif system[:4] == 'java':
Victor Stinnerced39362013-12-09 00:14:52 +01001069 release, vendor, vminfo, osinfo = java_ver()
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001070 system = 'Java'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001071 version = ', '.join(vminfo)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001072 if not version:
1073 version = vendor
1074
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001075 # System specific extensions
1076 if system == 'OpenVMS':
1077 # OpenVMS seems to have release and version mixed up
1078 if not release or release == '0':
1079 release = version
1080 version = ''
1081 # Get processor information
1082 try:
1083 import vms_lib
Brett Cannoncd171c82013-07-04 17:43:24 -04001084 except ImportError:
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001085 pass
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001086 else:
Victor Stinnerced39362013-12-09 00:14:52 +01001087 csid, cpu_number = vms_lib.getsyi('SYI$_CPU', 0)
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001088 if (cpu_number >= 128):
1089 processor = 'Alpha'
1090 else:
1091 processor = 'VAX'
1092 if not processor:
1093 # Get processor information from the uname system command
Victor Stinnerced39362013-12-09 00:14:52 +01001094 processor = _syscmd_uname('-p', '')
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001095
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001096 #If any unknowns still exist, replace them with ''s, which are more portable
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001097 if system == 'unknown':
1098 system = ''
1099 if node == 'unknown':
1100 node = ''
1101 if release == 'unknown':
1102 release = ''
1103 if version == 'unknown':
1104 version = ''
1105 if machine == 'unknown':
1106 machine = ''
1107 if processor == 'unknown':
1108 processor = ''
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001109
1110 # normalize name
1111 if system == 'Microsoft' and release == 'Windows':
1112 system = 'Windows'
1113 release = 'Vista'
1114
Victor Stinnerced39362013-12-09 00:14:52 +01001115 _uname_cache = uname_result(system, node, release, version,
1116 machine, processor)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001117 return _uname_cache
1118
1119### Direct interfaces to some of the uname() return values
1120
1121def system():
1122
1123 """ Returns the system/OS name, e.g. 'Linux', 'Windows' or 'Java'.
1124
1125 An empty string is returned if the value cannot be determined.
1126
1127 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001128 return uname().system
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001129
1130def node():
1131
Brett Cannon8ab27df2003-08-05 03:52:04 +00001132 """ Returns the computer's network name (which may not be fully
1133 qualified)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001134
1135 An empty string is returned if the value cannot be determined.
1136
1137 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001138 return uname().node
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001139
1140def release():
1141
1142 """ Returns the system's release, e.g. '2.2.0' or 'NT'
1143
1144 An empty string is returned if the value cannot be determined.
1145
1146 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001147 return uname().release
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001148
1149def version():
1150
1151 """ Returns the system's release version, e.g. '#3 on degas'
1152
1153 An empty string is returned if the value cannot be determined.
1154
1155 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001156 return uname().version
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001157
1158def machine():
1159
1160 """ Returns the machine type, e.g. 'i386'
1161
1162 An empty string is returned if the value cannot be determined.
1163
1164 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001165 return uname().machine
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001166
1167def processor():
1168
1169 """ Returns the (true) processor name, e.g. 'amdk6'
1170
1171 An empty string is returned if the value cannot be
1172 determined. Note that many platforms do not provide this
1173 information or simply return the same value as for machine(),
1174 e.g. NetBSD does this.
1175
1176 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001177 return uname().processor
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001178
1179### Various APIs for extracting information from sys.version
1180
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001181_sys_version_parser = re.compile(
1182 r'([\w.+]+)\s*'
1183 '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
Antoine Pitroufd036452008-08-19 17:56:33 +00001184 '\[([^\]]+)\]?', re.ASCII)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001185
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001186_ironpython_sys_version_parser = re.compile(
1187 r'IronPython\s*'
1188 '([\d\.]+)'
1189 '(?: \(([\d\.]+)\))?'
Antoine Pitroufd036452008-08-19 17:56:33 +00001190 ' on (.NET [\d\.]+)', re.ASCII)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001191
Ezio Melottif076f532013-10-21 03:03:32 +03001192# IronPython covering 2.6 and 2.7
1193_ironpython26_sys_version_parser = re.compile(
1194 r'([\d.]+)\s*'
1195 '\(IronPython\s*'
1196 '[\d.]+\s*'
1197 '\(([\d.]+)\) on ([\w.]+ [\d.]+(?: \(\d+-bit\))?)\)'
1198)
1199
Benjamin Petersone549ead2009-03-28 21:42:05 +00001200_pypy_sys_version_parser = re.compile(
1201 r'([\w.+]+)\s*'
1202 '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
1203 '\[PyPy [^\]]+\]?')
1204
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001205_sys_version_cache = {}
1206
1207def _sys_version(sys_version=None):
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001208
1209 """ Returns a parsed version of Python's sys.version as tuple
Benjamin Peterson5f28b7b2009-03-26 21:49:58 +00001210 (name, version, branch, revision, buildno, builddate, compiler)
1211 referring to the Python implementation name, version, branch,
1212 revision, build number, build date/time as string and the compiler
1213 identification string.
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001214
1215 Note that unlike the Python sys.version, the returned value
1216 for the Python version will always include the patchlevel (it
1217 defaults to '.0').
1218
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001219 The function returns empty strings for tuple entries that
1220 cannot be determined.
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001221
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001222 sys_version may be given to parse an alternative version
1223 string, e.g. if the version was read from a different Python
1224 interpreter.
1225
1226 """
1227 # Get the Python version
1228 if sys_version is None:
1229 sys_version = sys.version
1230
1231 # Try the cache first
1232 result = _sys_version_cache.get(sys_version, None)
1233 if result is not None:
1234 return result
1235
1236 # Parse it
Ezio Melottif076f532013-10-21 03:03:32 +03001237 if 'IronPython' in sys_version:
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001238 # IronPython
1239 name = 'IronPython'
Ezio Melottif076f532013-10-21 03:03:32 +03001240 if sys_version.startswith('IronPython'):
1241 match = _ironpython_sys_version_parser.match(sys_version)
1242 else:
1243 match = _ironpython26_sys_version_parser.match(sys_version)
1244
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001245 if match is None:
1246 raise ValueError(
1247 'failed to parse IronPython sys.version: %s' %
1248 repr(sys_version))
Ezio Melottif076f532013-10-21 03:03:32 +03001249
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001250 version, alt_version, compiler = match.groups()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001251 buildno = ''
1252 builddate = ''
1253
Ezio Melottif076f532013-10-21 03:03:32 +03001254 elif sys.platform.startswith('java'):
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001255 # Jython
1256 name = 'Jython'
Benjamin Petersone549ead2009-03-28 21:42:05 +00001257 match = _sys_version_parser.match(sys_version)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001258 if match is None:
1259 raise ValueError(
1260 'failed to parse Jython sys.version: %s' %
1261 repr(sys_version))
Benjamin Petersone549ead2009-03-28 21:42:05 +00001262 version, buildno, builddate, buildtime, _ = match.groups()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001263 compiler = sys.platform
Benjamin Petersone549ead2009-03-28 21:42:05 +00001264
1265 elif "PyPy" in sys_version:
1266 # PyPy
1267 name = "PyPy"
1268 match = _pypy_sys_version_parser.match(sys_version)
1269 if match is None:
1270 raise ValueError("failed to parse PyPy sys.version: %s" %
1271 repr(sys_version))
1272 version, buildno, builddate, buildtime = match.groups()
1273 compiler = ""
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001274
1275 else:
1276 # CPython
1277 match = _sys_version_parser.match(sys_version)
1278 if match is None:
1279 raise ValueError(
1280 'failed to parse CPython sys.version: %s' %
1281 repr(sys_version))
1282 version, buildno, builddate, buildtime, compiler = \
1283 match.groups()
Benjamin Petersone549ead2009-03-28 21:42:05 +00001284 name = 'CPython'
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001285 builddate = builddate + ' ' + buildtime
1286
Georg Brandl82562422011-03-05 21:09:22 +01001287 if hasattr(sys, '_mercurial'):
1288 _, branch, revision = sys._mercurial
1289 elif hasattr(sys, 'subversion'):
Benjamin Petersone549ead2009-03-28 21:42:05 +00001290 # sys.subversion was added in Python 2.5
1291 _, branch, revision = sys.subversion
1292 else:
1293 branch = ''
1294 revision = ''
1295
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001296 # Add the patchlevel version if missing
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001297 l = version.split('.')
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001298 if len(l) == 2:
1299 l.append('0')
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001300 version = '.'.join(l)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001301
1302 # Build and cache the result
1303 result = (name, version, branch, revision, buildno, builddate, compiler)
1304 _sys_version_cache[sys_version] = result
1305 return result
1306
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001307def python_implementation():
1308
1309 """ Returns a string identifying the Python implementation.
1310
1311 Currently, the following implementations are identified:
Ezio Melottif16898b2011-05-04 18:37:50 +03001312 'CPython' (C implementation of Python),
1313 'IronPython' (.NET implementation of Python),
1314 'Jython' (Java implementation of Python),
1315 'PyPy' (Python implementation of Python).
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001316
1317 """
1318 return _sys_version()[0]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001319
1320def python_version():
1321
1322 """ Returns the Python version as string 'major.minor.patchlevel'
1323
1324 Note that unlike the Python sys.version, the returned value
1325 will always include the patchlevel (it defaults to 0).
1326
1327 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001328 return _sys_version()[1]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001329
1330def python_version_tuple():
1331
1332 """ Returns the Python version as tuple (major, minor, patchlevel)
1333 of strings.
1334
1335 Note that unlike the Python sys.version, the returned value
1336 will always include the patchlevel (it defaults to 0).
1337
1338 """
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001339 return tuple(_sys_version()[1].split('.'))
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001340
1341def python_branch():
1342
1343 """ Returns a string identifying the Python implementation
1344 branch.
1345
1346 For CPython this is the Subversion branch from which the
1347 Python binary was built.
1348
1349 If not available, an empty string is returned.
1350
1351 """
Thomas Wouters9fe394c2007-02-05 01:24:16 +00001352
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001353 return _sys_version()[2]
1354
1355def python_revision():
1356
1357 """ Returns a string identifying the Python implementation
1358 revision.
1359
1360 For CPython this is the Subversion revision from which the
1361 Python binary was built.
1362
1363 If not available, an empty string is returned.
1364
1365 """
1366 return _sys_version()[3]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001367
1368def python_build():
1369
1370 """ Returns a tuple (buildno, builddate) stating the Python
1371 build number and date as strings.
1372
1373 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001374 return _sys_version()[4:6]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001375
1376def python_compiler():
1377
1378 """ Returns a string identifying the compiler used for compiling
1379 Python.
1380
1381 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001382 return _sys_version()[6]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001383
1384### The Opus Magnum of platform strings :-)
1385
Marc-André Lemburg91e83e22004-03-25 18:35:12 +00001386_platform_cache = {}
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001387
1388def platform(aliased=0, terse=0):
1389
1390 """ Returns a single string identifying the underlying platform
1391 with as much useful information as possible (but no more :).
Tim Peters0eadaac2003-04-24 16:02:54 +00001392
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001393 The output is intended to be human readable rather than
1394 machine parseable. It may look different on different
1395 platforms and this is intended.
1396
1397 If "aliased" is true, the function will use aliases for
1398 various platforms that report system names which differ from
1399 their common names, e.g. SunOS will be reported as
1400 Solaris. The system_alias() function is used to implement
1401 this.
1402
1403 Setting terse to true causes the function to return only the
1404 absolute minimum information needed to identify the platform.
1405
1406 """
Marc-André Lemburg91e83e22004-03-25 18:35:12 +00001407 result = _platform_cache.get((aliased, terse), None)
1408 if result is not None:
1409 return result
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001410
1411 # Get uname information and then apply platform specific cosmetics
1412 # to it...
Victor Stinnerced39362013-12-09 00:14:52 +01001413 system, node, release, version, machine, processor = uname()
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001414 if machine == processor:
1415 processor = ''
1416 if aliased:
Victor Stinnerced39362013-12-09 00:14:52 +01001417 system, release, version = system_alias(system, release, version)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001418
1419 if system == 'Windows':
1420 # MS platforms
Victor Stinnerced39362013-12-09 00:14:52 +01001421 rel, vers, csd, ptype = win32_ver(version)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001422 if terse:
Victor Stinnerced39362013-12-09 00:14:52 +01001423 platform = _platform(system, release)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001424 else:
Victor Stinnerced39362013-12-09 00:14:52 +01001425 platform = _platform(system, release, version, csd)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001426
1427 elif system in ('Linux',):
1428 # Linux based systems
Victor Stinnerced39362013-12-09 00:14:52 +01001429 distname, distversion, distid = dist('')
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001430 if distname and not terse:
Victor Stinnerced39362013-12-09 00:14:52 +01001431 platform = _platform(system, release, machine, processor,
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001432 'with',
Victor Stinnerced39362013-12-09 00:14:52 +01001433 distname, distversion, distid)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001434 else:
1435 # If the distribution name is unknown check for libc vs. glibc
Victor Stinnerced39362013-12-09 00:14:52 +01001436 libcname, libcversion = libc_ver(sys.executable)
1437 platform = _platform(system, release, machine, processor,
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001438 'with',
1439 libcname+libcversion)
1440 elif system == 'Java':
1441 # Java platforms
Victor Stinnerced39362013-12-09 00:14:52 +01001442 r, v, vminfo, (os_name, os_version, os_arch) = java_ver()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001443 if terse or not os_name:
Victor Stinnerced39362013-12-09 00:14:52 +01001444 platform = _platform(system, release, version)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001445 else:
Victor Stinnerced39362013-12-09 00:14:52 +01001446 platform = _platform(system, release, version,
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001447 'on',
Victor Stinnerced39362013-12-09 00:14:52 +01001448 os_name, os_version, os_arch)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001449
1450 elif system == 'MacOS':
1451 # MacOS platforms
1452 if terse:
Victor Stinnerced39362013-12-09 00:14:52 +01001453 platform = _platform(system, release)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001454 else:
Victor Stinnerced39362013-12-09 00:14:52 +01001455 platform = _platform(system, release, machine)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001456
1457 else:
1458 # Generic handler
1459 if terse:
Victor Stinnerced39362013-12-09 00:14:52 +01001460 platform = _platform(system, release)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001461 else:
Victor Stinnerced39362013-12-09 00:14:52 +01001462 bits, linkage = architecture(sys.executable)
1463 platform = _platform(system, release, machine,
1464 processor, bits, linkage)
Tim Peters0eadaac2003-04-24 16:02:54 +00001465
Marc-André Lemburg91e83e22004-03-25 18:35:12 +00001466 _platform_cache[(aliased, terse)] = platform
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001467 return platform
1468
1469### Command line interface
1470
1471if __name__ == '__main__':
1472 # Default is to print the aliased verbose platform string
Tim Peters0eadaac2003-04-24 16:02:54 +00001473 terse = ('terse' in sys.argv or '--terse' in sys.argv)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001474 aliased = (not 'nonaliased' in sys.argv and not '--nonaliased' in sys.argv)
Victor Stinnerced39362013-12-09 00:14:52 +01001475 print(platform(aliased, terse))
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001476 sys.exit(0)