blob: 11b501e7d732e61f0b2060eae692291d2ca4c91e [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:
506 import win32api
Christian Heimes02781dc2008-03-21 01:11:52 +0000507 from win32api import RegQueryValueEx, RegOpenKeyEx, \
508 RegCloseKey, GetVersionEx
509 from win32con import HKEY_LOCAL_MACHINE, VER_PLATFORM_WIN32_NT, \
510 VER_PLATFORM_WIN32_WINDOWS, VER_NT_WORKSTATION
Brett Cannoncd171c82013-07-04 17:43:24 -0400511 except ImportError:
Christian Heimes02781dc2008-03-21 01:11:52 +0000512 # Emulate the win32api module using Python APIs
513 try:
514 sys.getwindowsversion
515 except AttributeError:
516 # No emulation possible, so return the defaults...
Victor Stinnerced39362013-12-09 00:14:52 +0100517 return release, version, csd, ptype
Christian Heimes02781dc2008-03-21 01:11:52 +0000518 else:
Georg Brandl38feaf02008-05-25 07:45:51 +0000519 # Emulation using winreg (added in Python 2.0) and
Christian Heimes02781dc2008-03-21 01:11:52 +0000520 # sys.getwindowsversion() (added in Python 2.3)
Georg Brandl38feaf02008-05-25 07:45:51 +0000521 import winreg
Christian Heimes02781dc2008-03-21 01:11:52 +0000522 GetVersionEx = sys.getwindowsversion
Georg Brandl38feaf02008-05-25 07:45:51 +0000523 RegQueryValueEx = winreg.QueryValueEx
524 RegOpenKeyEx = winreg.OpenKeyEx
525 RegCloseKey = winreg.CloseKey
526 HKEY_LOCAL_MACHINE = winreg.HKEY_LOCAL_MACHINE
Christian Heimes02781dc2008-03-21 01:11:52 +0000527 VER_PLATFORM_WIN32_WINDOWS = 1
528 VER_PLATFORM_WIN32_NT = 2
529 VER_NT_WORKSTATION = 1
Brian Curtin6e2824d2010-05-06 03:05:50 +0000530 VER_NT_SERVER = 3
531 REG_SZ = 1
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000532
533 # Find out the registry key and some general version infos
Brian Curtin6e2824d2010-05-06 03:05:50 +0000534 winver = GetVersionEx()
Victor Stinnerced39362013-12-09 00:14:52 +0100535 maj, min, buildno, plat, csd = winver
536 version = '%i.%i.%i' % (maj, min, buildno & 0xFFFF)
Brian Curtin6e2824d2010-05-06 03:05:50 +0000537 if hasattr(winver, "service_pack"):
538 if winver.service_pack != "":
539 csd = 'SP%s' % winver.service_pack_major
540 else:
541 if csd[:13] == 'Service Pack ':
542 csd = 'SP' + csd[13:]
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000543
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000544 if plat == VER_PLATFORM_WIN32_WINDOWS:
545 regkey = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion'
546 # Try to guess the release name
547 if maj == 4:
548 if min == 0:
549 release = '95'
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000550 elif min == 10:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000551 release = '98'
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000552 elif min == 90:
553 release = 'Me'
554 else:
555 release = 'postMe'
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000556 elif maj == 5:
557 release = '2000'
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000558
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000559 elif plat == VER_PLATFORM_WIN32_NT:
560 regkey = 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion'
561 if maj <= 4:
562 release = 'NT'
563 elif maj == 5:
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000564 if min == 0:
565 release = '2000'
566 elif min == 1:
567 release = 'XP'
568 elif min == 2:
569 release = '2003Server'
570 else:
571 release = 'post2003'
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000572 elif maj == 6:
Brian Curtin6e2824d2010-05-06 03:05:50 +0000573 if hasattr(winver, "product_type"):
574 product_type = winver.product_type
575 else:
576 product_type = VER_NT_WORKSTATION
577 # Without an OSVERSIONINFOEX capable sys.getwindowsversion(),
578 # or help from the registry, we cannot properly identify
579 # non-workstation versions.
Christian Heimes02781dc2008-03-21 01:11:52 +0000580 try:
Brian Curtin6e2824d2010-05-06 03:05:50 +0000581 key = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey)
582 name, type = RegQueryValueEx(key, "ProductName")
583 # Discard any type that isn't REG_SZ
584 if type == REG_SZ and name.find("Server") != -1:
585 product_type = VER_NT_SERVER
Andrew Svetlov2606a6f2012-12-19 14:33:35 +0200586 except OSError:
Brian Curtin6e2824d2010-05-06 03:05:50 +0000587 # Use default of VER_NT_WORKSTATION
588 pass
589
590 if min == 0:
591 if product_type == VER_NT_WORKSTATION:
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000592 release = 'Vista'
593 else:
Brian Curtin6e2824d2010-05-06 03:05:50 +0000594 release = '2008Server'
595 elif min == 1:
596 if product_type == VER_NT_WORKSTATION:
597 release = '7'
598 else:
599 release = '2008ServerR2'
Brian Curtin0b960f52012-10-11 16:07:52 -0500600 elif min == 2:
601 if product_type == VER_NT_WORKSTATION:
602 release = '8'
603 else:
604 release = '2012Server'
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000605 else:
Brian Curtin0b960f52012-10-11 16:07:52 -0500606 release = 'post2012Server'
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000607
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000608 else:
609 if not release:
610 # E.g. Win3.1 with win32s
Victor Stinnerced39362013-12-09 00:14:52 +0100611 release = '%i.%i' % (maj, min)
612 return release, version, csd, ptype
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000613
614 # Open the registry key
615 try:
Christian Heimes02781dc2008-03-21 01:11:52 +0000616 keyCurVer = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000617 # Get a value to make sure the key exists...
Christian Heimes02781dc2008-03-21 01:11:52 +0000618 RegQueryValueEx(keyCurVer, 'SystemRoot')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000619 except:
Victor Stinnerced39362013-12-09 00:14:52 +0100620 return release, version, csd, ptype
Tim Peters0eadaac2003-04-24 16:02:54 +0000621
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000622 # Parse values
623 #subversion = _win32_getvalue(keyCurVer,
624 # 'SubVersionNumber',
625 # ('',1))[0]
626 #if subversion:
627 # release = release + subversion # 95a, 95b, etc.
628 build = _win32_getvalue(keyCurVer,
629 'CurrentBuildNumber',
Victor Stinnerced39362013-12-09 00:14:52 +0100630 ('', 1))[0]
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000631 ptype = _win32_getvalue(keyCurVer,
632 'CurrentType',
Victor Stinnerced39362013-12-09 00:14:52 +0100633 (ptype, 1))[0]
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000634
635 # Normalize version
Victor Stinnerced39362013-12-09 00:14:52 +0100636 version = _norm_version(version, build)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000637
638 # Close key
639 RegCloseKey(keyCurVer)
Victor Stinnerced39362013-12-09 00:14:52 +0100640 return release, version, csd, ptype
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000641
Ronald Oussorene186e382010-07-23 11:54:59 +0000642def _mac_ver_xml():
643 fn = '/System/Library/CoreServices/SystemVersion.plist'
644 if not os.path.exists(fn):
645 return None
646
647 try:
648 import plistlib
Brett Cannoncd171c82013-07-04 17:43:24 -0400649 except ImportError:
Ronald Oussorene186e382010-07-23 11:54:59 +0000650 return None
651
Ned Deily936dfae2014-01-13 11:34:19 -0800652 with open(fn, 'rb') as f:
653 pl = plistlib.load(f)
Ronald Oussorene186e382010-07-23 11:54:59 +0000654 release = pl['ProductVersion']
Victor Stinnerced39362013-12-09 00:14:52 +0100655 versioninfo = ('', '', '')
Larry Hastings605a62d2012-06-24 04:33:36 -0700656 machine = os.uname().machine
Ronald Oussorenfcd77012010-08-03 07:42:42 +0000657 if machine in ('ppc', 'Power Macintosh'):
Ezio Melotti9a3777e2013-08-17 15:53:55 +0300658 # Canonical name
Ronald Oussorene186e382010-07-23 11:54:59 +0000659 machine = 'PowerPC'
660
Victor Stinnerced39362013-12-09 00:14:52 +0100661 return release, versioninfo, machine
Ronald Oussorene186e382010-07-23 11:54:59 +0000662
663
Victor Stinnerced39362013-12-09 00:14:52 +0100664def mac_ver(release='', versioninfo=('', '', ''), machine=''):
Ronald Oussorene186e382010-07-23 11:54:59 +0000665
666 """ Get MacOS version information and return it as tuple (release,
667 versioninfo, machine) with versioninfo being a tuple (version,
668 dev_stage, non_release_version).
669
Ezio Melotti30b9d5d2013-08-17 15:50:46 +0300670 Entries which cannot be determined are set to the parameter values
Ronald Oussorene186e382010-07-23 11:54:59 +0000671 which default to ''. All tuple entries are strings.
672 """
673
674 # First try reading the information from an XML file which should
675 # always be present
676 info = _mac_ver_xml()
677 if info is not None:
678 return info
679
Ronald Oussorene186e382010-07-23 11:54:59 +0000680 # If that also doesn't work return the default values
Victor Stinnerced39362013-12-09 00:14:52 +0100681 return release, versioninfo, machine
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000682
Victor Stinnerced39362013-12-09 00:14:52 +0100683def _java_getprop(name, default):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000684
685 from java.lang import System
686 try:
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000687 value = System.getProperty(name)
688 if value is None:
689 return default
690 return value
691 except AttributeError:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000692 return default
693
Victor Stinnerced39362013-12-09 00:14:52 +0100694def java_ver(release='', vendor='', vminfo=('', '', ''), osinfo=('', '', '')):
Tim Peters0eadaac2003-04-24 16:02:54 +0000695
Brett Cannon8ab27df2003-08-05 03:52:04 +0000696 """ Version interface for Jython.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000697
Victor Stinnerced39362013-12-09 00:14:52 +0100698 Returns a tuple (release, vendor, vminfo, osinfo) with vminfo being
699 a tuple (vm_name, vm_release, vm_vendor) and osinfo being a
700 tuple (os_name, os_version, os_arch).
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000701
702 Values which cannot be determined are set to the defaults
703 given as parameters (which all default to '').
704
705 """
706 # Import the needed APIs
707 try:
708 import java.lang
Brett Cannoncd171c82013-07-04 17:43:24 -0400709 except ImportError:
Victor Stinnerced39362013-12-09 00:14:52 +0100710 return release, vendor, vminfo, osinfo
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000711
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000712 vendor = _java_getprop('java.vendor', vendor)
713 release = _java_getprop('java.version', release)
714 vm_name, vm_release, vm_vendor = vminfo
715 vm_name = _java_getprop('java.vm.name', vm_name)
716 vm_vendor = _java_getprop('java.vm.vendor', vm_vendor)
717 vm_release = _java_getprop('java.vm.version', vm_release)
718 vminfo = vm_name, vm_release, vm_vendor
719 os_name, os_version, os_arch = osinfo
720 os_arch = _java_getprop('java.os.arch', os_arch)
721 os_name = _java_getprop('java.os.name', os_name)
722 os_version = _java_getprop('java.os.version', os_version)
723 osinfo = os_name, os_version, os_arch
Tim Peters0eadaac2003-04-24 16:02:54 +0000724
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000725 return release, vendor, vminfo, osinfo
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000726
727### System name aliasing
728
Victor Stinnerced39362013-12-09 00:14:52 +0100729def system_alias(system, release, version):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000730
Victor Stinnerced39362013-12-09 00:14:52 +0100731 """ Returns (system, release, version) aliased to common
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000732 marketing names used for some systems.
733
734 It also does some reordering of the information in some cases
735 where it would otherwise cause confusion.
736
737 """
738 if system == 'Rhapsody':
739 # Apple's BSD derivative
740 # XXX How can we determine the marketing release number ?
Victor Stinnerced39362013-12-09 00:14:52 +0100741 return 'MacOS X Server', system+release, version
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000742
743 elif system == 'SunOS':
744 # Sun's OS
745 if release < '5':
746 # These releases use the old name SunOS
Victor Stinnerced39362013-12-09 00:14:52 +0100747 return system, release, version
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000748 # Modify release (marketing release = SunOS release - 3)
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000749 l = release.split('.')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000750 if l:
751 try:
752 major = int(l[0])
753 except ValueError:
754 pass
755 else:
756 major = major - 3
757 l[0] = str(major)
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000758 release = '.'.join(l)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000759 if release < '6':
760 system = 'Solaris'
761 else:
762 # XXX Whatever the new SunOS marketing name is...
763 system = 'Solaris'
764
765 elif system == 'IRIX64':
766 # IRIX reports IRIX64 on platforms with 64-bit support; yet it
767 # is really a version and not a different platform, since 32-bit
768 # apps are also supported..
769 system = 'IRIX'
770 if version:
771 version = version + ' (64bit)'
772 else:
773 version = '64bit'
774
Victor Stinnerced39362013-12-09 00:14:52 +0100775 elif system in ('win32', 'win16'):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000776 # In case one of the other tricks
777 system = 'Windows'
778
Victor Stinnerced39362013-12-09 00:14:52 +0100779 return system, release, version
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000780
781### Various internal helpers
782
783def _platform(*args):
784
785 """ Helper to format the platform string in a filename
786 compatible format e.g. "system-version-machine".
787 """
788 # Format the platform string
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000789 platform = '-'.join(x.strip() for x in filter(len, args))
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000790
791 # Cleanup some possible filename obstacles...
Victor Stinnerced39362013-12-09 00:14:52 +0100792 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('(', '-')
799 platform = platform.replace(')', '-')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000800
801 # No need to report 'unknown' information...
Victor Stinnerced39362013-12-09 00:14:52 +0100802 platform = platform.replace('unknown', '')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000803
804 # Fold '--'s and remove trailing '-'
805 while 1:
Victor Stinnerced39362013-12-09 00:14:52 +0100806 cleaned = platform.replace('--', '-')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000807 if cleaned == platform:
808 break
809 platform = cleaned
810 while platform[-1] == '-':
811 platform = platform[:-1]
812
813 return platform
814
815def _node(default=''):
816
817 """ Helper to determine the node name of this machine.
818 """
819 try:
820 import socket
Brett Cannoncd171c82013-07-04 17:43:24 -0400821 except ImportError:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000822 # No sockets...
823 return default
824 try:
825 return socket.gethostname()
Andrew Svetlov0832af62012-12-18 23:10:48 +0200826 except OSError:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000827 # Still not working...
828 return default
829
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000830def _follow_symlinks(filepath):
831
832 """ In case filepath is a symlink, follow it until a
833 real file is reached.
834 """
Georg Brandl673f7ef2008-01-05 21:20:19 +0000835 filepath = os.path.abspath(filepath)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000836 while os.path.islink(filepath):
837 filepath = os.path.normpath(
Victor Stinnerced39362013-12-09 00:14:52 +0100838 os.path.join(os.path.dirname(filepath), os.readlink(filepath)))
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000839 return filepath
840
Victor Stinnerced39362013-12-09 00:14:52 +0100841def _syscmd_uname(option, default=''):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000842
843 """ Interface to the system's uname command.
844 """
Victor Stinnerced39362013-12-09 00:14:52 +0100845 if sys.platform in ('dos', 'win32', 'win16'):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000846 # XXX Others too ?
847 return default
848 try:
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000849 f = os.popen('uname %s 2> %s' % (option, DEV_NULL))
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200850 except (AttributeError, OSError):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000851 return default
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000852 output = f.read().strip()
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000853 rc = f.close()
854 if not output or rc:
855 return default
856 else:
857 return output
858
Victor Stinnerced39362013-12-09 00:14:52 +0100859def _syscmd_file(target, default=''):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000860
861 """ Interface to the system's file command.
862
863 The function uses the -b option of the file command to have it
Victor Stinnerddfb2c32010-08-13 16:30:15 +0000864 omit the filename in its output. Follow the symlinks. It returns
865 default in case the command should fail.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000866
867 """
Victor Stinnerced39362013-12-09 00:14:52 +0100868 if sys.platform in ('dos', 'win32', 'win16'):
Hirokazu Yamamotod26782e2008-09-01 14:35:47 +0000869 # XXX Others too ?
870 return default
Jesus Ceafc990e92012-10-04 13:51:43 +0200871 target = _follow_symlinks(target)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000872 try:
Jesus Cea685fffa2012-10-05 05:21:42 +0200873 proc = subprocess.Popen(['file', target],
874 stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
Jesus Ceae8801e22012-10-04 13:56:23 +0200875
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200876 except (AttributeError, OSError):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000877 return default
Jesus Ceacb959962012-10-05 05:31:31 +0200878 output = proc.communicate()[0].decode('latin-1')
Jesus Ceafc990e92012-10-04 13:51:43 +0200879 rc = proc.wait()
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000880 if not output or rc:
881 return default
882 else:
883 return output
884
885### Information about the used architecture
886
887# Default values for architecture; non-empty strings override the
888# defaults given as parameters
889_default_architecture = {
Victor Stinnerced39362013-12-09 00:14:52 +0100890 'win32': ('', 'WindowsPE'),
891 'win16': ('', 'Windows'),
892 'dos': ('', 'MSDOS'),
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000893}
894
Victor Stinnerced39362013-12-09 00:14:52 +0100895def architecture(executable=sys.executable, bits='', linkage=''):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000896
897 """ Queries the given executable (defaults to the Python interpreter
Brett Cannon8ab27df2003-08-05 03:52:04 +0000898 binary) for various architecture information.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000899
Victor Stinnerced39362013-12-09 00:14:52 +0100900 Returns a tuple (bits, linkage) which contains information about
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000901 the bit architecture and the linkage format used for the
902 executable. Both values are returned as strings.
903
904 Values that cannot be determined are returned as given by the
905 parameter presets. If bits is given as '', the sizeof(pointer)
906 (or sizeof(long) on Python version < 1.5.2) is used as
907 indicator for the supported pointer size.
908
909 The function relies on the system's "file" command to do the
910 actual work. This is available on most if not all Unix
Brett Cannon8ab27df2003-08-05 03:52:04 +0000911 platforms. On some non-Unix platforms where the "file" command
912 does not exist and the executable is set to the Python interpreter
913 binary defaults from _default_architecture are used.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000914
915 """
916 # Use the sizeof(pointer) as default number of bits if nothing
917 # else is given as default.
918 if not bits:
919 import struct
920 try:
921 size = struct.calcsize('P')
922 except struct.error:
923 # Older installations can only query longs
924 size = struct.calcsize('l')
925 bits = str(size*8) + 'bit'
Tim Peters0eadaac2003-04-24 16:02:54 +0000926
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000927 # Get data from the 'file' system command
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000928 if executable:
Victor Stinnerddfb2c32010-08-13 16:30:15 +0000929 fileout = _syscmd_file(executable, '')
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000930 else:
Victor Stinnerddfb2c32010-08-13 16:30:15 +0000931 fileout = ''
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000932
Victor Stinnerddfb2c32010-08-13 16:30:15 +0000933 if not fileout and \
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000934 executable == sys.executable:
935 # "file" command did not return anything; we'll try to provide
Tim Peters0eadaac2003-04-24 16:02:54 +0000936 # some sensible defaults then...
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000937 if sys.platform in _default_architecture:
Victor Stinnerced39362013-12-09 00:14:52 +0100938 b, l = _default_architecture[sys.platform]
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000939 if b:
940 bits = b
941 if l:
942 linkage = l
Victor Stinnerced39362013-12-09 00:14:52 +0100943 return bits, linkage
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000944
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000945 if 'executable' not in fileout:
946 # Format not supported
Victor Stinnerced39362013-12-09 00:14:52 +0100947 return bits, linkage
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000948
949 # Bits
950 if '32-bit' in fileout:
951 bits = '32bit'
952 elif 'N32' in fileout:
953 # On Irix only
954 bits = 'n32bit'
955 elif '64-bit' in fileout:
956 bits = '64bit'
957
958 # Linkage
959 if 'ELF' in fileout:
960 linkage = 'ELF'
961 elif 'PE' in fileout:
962 # E.g. Windows uses this format
963 if 'Windows' in fileout:
964 linkage = 'WindowsPE'
965 else:
966 linkage = 'PE'
967 elif 'COFF' in fileout:
968 linkage = 'COFF'
969 elif 'MS-DOS' in fileout:
970 linkage = 'MSDOS'
971 else:
972 # XXX the A.OUT format also falls under this class...
973 pass
974
Victor Stinnerced39362013-12-09 00:14:52 +0100975 return bits, linkage
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000976
977### Portable uname() interface
Tim Peters0eadaac2003-04-24 16:02:54 +0000978
Larry Hastings68386bc2012-06-24 14:30:41 -0700979uname_result = collections.namedtuple("uname_result",
980 "system node release version machine processor")
981
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000982_uname_cache = None
983
984def uname():
985
986 """ Fairly portable uname interface. Returns a tuple
Victor Stinnerced39362013-12-09 00:14:52 +0100987 of strings (system, node, release, version, machine, processor)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000988 identifying the underlying platform.
989
990 Note that unlike the os.uname function this also returns
Brett Cannon8ab27df2003-08-05 03:52:04 +0000991 possible processor information as an additional tuple entry.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000992
993 Entries which cannot be determined are set to ''.
994
995 """
996 global _uname_cache
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +0000997 no_os_uname = 0
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000998
999 if _uname_cache is not None:
1000 return _uname_cache
1001
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001002 processor = ''
1003
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001004 # Get some infos from the builtin os.uname API...
1005 try:
Victor Stinnerced39362013-12-09 00:14:52 +01001006 system, node, release, version, machine = os.uname()
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001007 except AttributeError:
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001008 no_os_uname = 1
1009
Georg Brandl62e2ca22010-07-31 21:54:24 +00001010 if no_os_uname or not list(filter(None, (system, node, release, version, machine))):
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001011 # Hmm, no there is either no uname or uname has returned
1012 #'unknowns'... we'll have to poke around the system then.
1013 if no_os_uname:
1014 system = sys.platform
1015 release = ''
1016 version = ''
1017 node = _node()
1018 machine = ''
1019
Amaury Forgeot d'Arc7a019842008-06-17 21:42:46 +00001020 use_syscmd_ver = 1
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001021
1022 # Try win32_ver() on win32 platforms
1023 if system == 'win32':
Victor Stinnerced39362013-12-09 00:14:52 +01001024 release, version, csd, ptype = win32_ver()
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001025 if release and version:
1026 use_syscmd_ver = 0
Christian Heimes02781dc2008-03-21 01:11:52 +00001027 # Try to use the PROCESSOR_* environment variables
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001028 # available on Win XP and later; see
1029 # http://support.microsoft.com/kb/888731 and
1030 # http://www.geocities.com/rick_lively/MANUALS/ENV/MSWIN/PROCESSI.HTM
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001031 if not machine:
R. David Murrayca2edce2010-03-22 17:48:48 +00001032 # WOW64 processes mask the native architecture
1033 if "PROCESSOR_ARCHITEW6432" in os.environ:
1034 machine = os.environ.get("PROCESSOR_ARCHITEW6432", '')
1035 else:
1036 machine = os.environ.get('PROCESSOR_ARCHITECTURE', '')
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001037 if not processor:
1038 processor = os.environ.get('PROCESSOR_IDENTIFIER', machine)
Tim Peters0eadaac2003-04-24 16:02:54 +00001039
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001040 # Try the 'ver' system command available on some
1041 # platforms
1042 if use_syscmd_ver:
Victor Stinnerced39362013-12-09 00:14:52 +01001043 system, release, version = _syscmd_ver(system)
Marc-André Lemburgcdc79232004-06-19 17:17:00 +00001044 # Normalize system to what win32_ver() normally returns
1045 # (_syscmd_ver() tends to return the vendor name as well)
1046 if system == 'Microsoft Windows':
1047 system = 'Windows'
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001048 elif system == 'Microsoft' and release == 'Windows':
1049 # Under Windows Vista and Windows Server 2008,
1050 # Microsoft changed the output of the ver command. The
1051 # release is no longer printed. This causes the
1052 # system and release to be misidentified.
1053 system = 'Windows'
1054 if '6.0' == version[:3]:
1055 release = 'Vista'
1056 else:
1057 release = ''
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001058
1059 # In case we still don't know anything useful, we'll try to
1060 # help ourselves
Victor Stinnerced39362013-12-09 00:14:52 +01001061 if system in ('win32', 'win16'):
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001062 if not version:
1063 if system == 'win32':
1064 version = '32bit'
1065 else:
1066 version = '16bit'
1067 system = 'Windows'
1068
1069 elif system[:4] == 'java':
Victor Stinnerced39362013-12-09 00:14:52 +01001070 release, vendor, vminfo, osinfo = java_ver()
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001071 system = 'Java'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001072 version = ', '.join(vminfo)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001073 if not version:
1074 version = vendor
1075
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001076 # System specific extensions
1077 if system == 'OpenVMS':
1078 # OpenVMS seems to have release and version mixed up
1079 if not release or release == '0':
1080 release = version
1081 version = ''
1082 # Get processor information
1083 try:
1084 import vms_lib
Brett Cannoncd171c82013-07-04 17:43:24 -04001085 except ImportError:
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001086 pass
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001087 else:
Victor Stinnerced39362013-12-09 00:14:52 +01001088 csid, cpu_number = vms_lib.getsyi('SYI$_CPU', 0)
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001089 if (cpu_number >= 128):
1090 processor = 'Alpha'
1091 else:
1092 processor = 'VAX'
1093 if not processor:
1094 # Get processor information from the uname system command
Victor Stinnerced39362013-12-09 00:14:52 +01001095 processor = _syscmd_uname('-p', '')
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001096
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001097 #If any unknowns still exist, replace them with ''s, which are more portable
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001098 if system == 'unknown':
1099 system = ''
1100 if node == 'unknown':
1101 node = ''
1102 if release == 'unknown':
1103 release = ''
1104 if version == 'unknown':
1105 version = ''
1106 if machine == 'unknown':
1107 machine = ''
1108 if processor == 'unknown':
1109 processor = ''
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001110
1111 # normalize name
1112 if system == 'Microsoft' and release == 'Windows':
1113 system = 'Windows'
1114 release = 'Vista'
1115
Victor Stinnerced39362013-12-09 00:14:52 +01001116 _uname_cache = uname_result(system, node, release, version,
1117 machine, processor)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001118 return _uname_cache
1119
1120### Direct interfaces to some of the uname() return values
1121
1122def system():
1123
1124 """ Returns the system/OS name, e.g. 'Linux', 'Windows' or 'Java'.
1125
1126 An empty string is returned if the value cannot be determined.
1127
1128 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001129 return uname().system
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001130
1131def node():
1132
Brett Cannon8ab27df2003-08-05 03:52:04 +00001133 """ Returns the computer's network name (which may not be fully
1134 qualified)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001135
1136 An empty string is returned if the value cannot be determined.
1137
1138 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001139 return uname().node
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001140
1141def release():
1142
1143 """ Returns the system's release, e.g. '2.2.0' or 'NT'
1144
1145 An empty string is returned if the value cannot be determined.
1146
1147 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001148 return uname().release
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001149
1150def version():
1151
1152 """ Returns the system's release version, e.g. '#3 on degas'
1153
1154 An empty string is returned if the value cannot be determined.
1155
1156 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001157 return uname().version
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001158
1159def machine():
1160
1161 """ Returns the machine type, e.g. 'i386'
1162
1163 An empty string is returned if the value cannot be determined.
1164
1165 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001166 return uname().machine
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001167
1168def processor():
1169
1170 """ Returns the (true) processor name, e.g. 'amdk6'
1171
1172 An empty string is returned if the value cannot be
1173 determined. Note that many platforms do not provide this
1174 information or simply return the same value as for machine(),
1175 e.g. NetBSD does this.
1176
1177 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001178 return uname().processor
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001179
1180### Various APIs for extracting information from sys.version
1181
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001182_sys_version_parser = re.compile(
1183 r'([\w.+]+)\s*'
1184 '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
Antoine Pitroufd036452008-08-19 17:56:33 +00001185 '\[([^\]]+)\]?', re.ASCII)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001186
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001187_ironpython_sys_version_parser = re.compile(
1188 r'IronPython\s*'
1189 '([\d\.]+)'
1190 '(?: \(([\d\.]+)\))?'
Antoine Pitroufd036452008-08-19 17:56:33 +00001191 ' on (.NET [\d\.]+)', re.ASCII)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001192
Ezio Melottif076f532013-10-21 03:03:32 +03001193# IronPython covering 2.6 and 2.7
1194_ironpython26_sys_version_parser = re.compile(
1195 r'([\d.]+)\s*'
1196 '\(IronPython\s*'
1197 '[\d.]+\s*'
1198 '\(([\d.]+)\) on ([\w.]+ [\d.]+(?: \(\d+-bit\))?)\)'
1199)
1200
Benjamin Petersone549ead2009-03-28 21:42:05 +00001201_pypy_sys_version_parser = re.compile(
1202 r'([\w.+]+)\s*'
1203 '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
1204 '\[PyPy [^\]]+\]?')
1205
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001206_sys_version_cache = {}
1207
1208def _sys_version(sys_version=None):
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001209
1210 """ Returns a parsed version of Python's sys.version as tuple
Benjamin Peterson5f28b7b2009-03-26 21:49:58 +00001211 (name, version, branch, revision, buildno, builddate, compiler)
1212 referring to the Python implementation name, version, branch,
1213 revision, build number, build date/time as string and the compiler
1214 identification string.
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001215
1216 Note that unlike the Python sys.version, the returned value
1217 for the Python version will always include the patchlevel (it
1218 defaults to '.0').
1219
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001220 The function returns empty strings for tuple entries that
1221 cannot be determined.
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001222
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001223 sys_version may be given to parse an alternative version
1224 string, e.g. if the version was read from a different Python
1225 interpreter.
1226
1227 """
1228 # Get the Python version
1229 if sys_version is None:
1230 sys_version = sys.version
1231
1232 # Try the cache first
1233 result = _sys_version_cache.get(sys_version, None)
1234 if result is not None:
1235 return result
1236
1237 # Parse it
Ezio Melottif076f532013-10-21 03:03:32 +03001238 if 'IronPython' in sys_version:
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001239 # IronPython
1240 name = 'IronPython'
Ezio Melottif076f532013-10-21 03:03:32 +03001241 if sys_version.startswith('IronPython'):
1242 match = _ironpython_sys_version_parser.match(sys_version)
1243 else:
1244 match = _ironpython26_sys_version_parser.match(sys_version)
1245
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001246 if match is None:
1247 raise ValueError(
1248 'failed to parse IronPython sys.version: %s' %
1249 repr(sys_version))
Ezio Melottif076f532013-10-21 03:03:32 +03001250
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001251 version, alt_version, compiler = match.groups()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001252 buildno = ''
1253 builddate = ''
1254
Ezio Melottif076f532013-10-21 03:03:32 +03001255 elif sys.platform.startswith('java'):
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001256 # Jython
1257 name = 'Jython'
Benjamin Petersone549ead2009-03-28 21:42:05 +00001258 match = _sys_version_parser.match(sys_version)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001259 if match is None:
1260 raise ValueError(
1261 'failed to parse Jython sys.version: %s' %
1262 repr(sys_version))
Benjamin Petersone549ead2009-03-28 21:42:05 +00001263 version, buildno, builddate, buildtime, _ = match.groups()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001264 compiler = sys.platform
Benjamin Petersone549ead2009-03-28 21:42:05 +00001265
1266 elif "PyPy" in sys_version:
1267 # PyPy
1268 name = "PyPy"
1269 match = _pypy_sys_version_parser.match(sys_version)
1270 if match is None:
1271 raise ValueError("failed to parse PyPy sys.version: %s" %
1272 repr(sys_version))
1273 version, buildno, builddate, buildtime = match.groups()
1274 compiler = ""
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001275
1276 else:
1277 # CPython
1278 match = _sys_version_parser.match(sys_version)
1279 if match is None:
1280 raise ValueError(
1281 'failed to parse CPython sys.version: %s' %
1282 repr(sys_version))
1283 version, buildno, builddate, buildtime, compiler = \
1284 match.groups()
Benjamin Petersone549ead2009-03-28 21:42:05 +00001285 name = 'CPython'
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001286 builddate = builddate + ' ' + buildtime
1287
Georg Brandl82562422011-03-05 21:09:22 +01001288 if hasattr(sys, '_mercurial'):
1289 _, branch, revision = sys._mercurial
1290 elif hasattr(sys, 'subversion'):
Benjamin Petersone549ead2009-03-28 21:42:05 +00001291 # sys.subversion was added in Python 2.5
1292 _, branch, revision = sys.subversion
1293 else:
1294 branch = ''
1295 revision = ''
1296
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001297 # Add the patchlevel version if missing
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001298 l = version.split('.')
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001299 if len(l) == 2:
1300 l.append('0')
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001301 version = '.'.join(l)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001302
1303 # Build and cache the result
1304 result = (name, version, branch, revision, buildno, builddate, compiler)
1305 _sys_version_cache[sys_version] = result
1306 return result
1307
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001308def python_implementation():
1309
1310 """ Returns a string identifying the Python implementation.
1311
1312 Currently, the following implementations are identified:
Ezio Melottif16898b2011-05-04 18:37:50 +03001313 'CPython' (C implementation of Python),
1314 'IronPython' (.NET implementation of Python),
1315 'Jython' (Java implementation of Python),
1316 'PyPy' (Python implementation of Python).
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001317
1318 """
1319 return _sys_version()[0]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001320
1321def python_version():
1322
1323 """ Returns the Python version as string 'major.minor.patchlevel'
1324
1325 Note that unlike the Python sys.version, the returned value
1326 will always include the patchlevel (it defaults to 0).
1327
1328 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001329 return _sys_version()[1]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001330
1331def python_version_tuple():
1332
1333 """ Returns the Python version as tuple (major, minor, patchlevel)
1334 of strings.
1335
1336 Note that unlike the Python sys.version, the returned value
1337 will always include the patchlevel (it defaults to 0).
1338
1339 """
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001340 return tuple(_sys_version()[1].split('.'))
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001341
1342def python_branch():
1343
1344 """ Returns a string identifying the Python implementation
1345 branch.
1346
1347 For CPython this is the Subversion branch from which the
1348 Python binary was built.
1349
1350 If not available, an empty string is returned.
1351
1352 """
Thomas Wouters9fe394c2007-02-05 01:24:16 +00001353
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001354 return _sys_version()[2]
1355
1356def python_revision():
1357
1358 """ Returns a string identifying the Python implementation
1359 revision.
1360
1361 For CPython this is the Subversion revision from which the
1362 Python binary was built.
1363
1364 If not available, an empty string is returned.
1365
1366 """
1367 return _sys_version()[3]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001368
1369def python_build():
1370
1371 """ Returns a tuple (buildno, builddate) stating the Python
1372 build number and date as strings.
1373
1374 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001375 return _sys_version()[4:6]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001376
1377def python_compiler():
1378
1379 """ Returns a string identifying the compiler used for compiling
1380 Python.
1381
1382 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001383 return _sys_version()[6]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001384
1385### The Opus Magnum of platform strings :-)
1386
Marc-André Lemburg91e83e22004-03-25 18:35:12 +00001387_platform_cache = {}
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001388
1389def platform(aliased=0, terse=0):
1390
1391 """ Returns a single string identifying the underlying platform
1392 with as much useful information as possible (but no more :).
Tim Peters0eadaac2003-04-24 16:02:54 +00001393
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001394 The output is intended to be human readable rather than
1395 machine parseable. It may look different on different
1396 platforms and this is intended.
1397
1398 If "aliased" is true, the function will use aliases for
1399 various platforms that report system names which differ from
1400 their common names, e.g. SunOS will be reported as
1401 Solaris. The system_alias() function is used to implement
1402 this.
1403
1404 Setting terse to true causes the function to return only the
1405 absolute minimum information needed to identify the platform.
1406
1407 """
Marc-André Lemburg91e83e22004-03-25 18:35:12 +00001408 result = _platform_cache.get((aliased, terse), None)
1409 if result is not None:
1410 return result
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001411
1412 # Get uname information and then apply platform specific cosmetics
1413 # to it...
Victor Stinnerced39362013-12-09 00:14:52 +01001414 system, node, release, version, machine, processor = uname()
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001415 if machine == processor:
1416 processor = ''
1417 if aliased:
Victor Stinnerced39362013-12-09 00:14:52 +01001418 system, release, version = system_alias(system, release, version)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001419
1420 if system == 'Windows':
1421 # MS platforms
Victor Stinnerced39362013-12-09 00:14:52 +01001422 rel, vers, csd, ptype = win32_ver(version)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001423 if terse:
Victor Stinnerced39362013-12-09 00:14:52 +01001424 platform = _platform(system, release)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001425 else:
Victor Stinnerced39362013-12-09 00:14:52 +01001426 platform = _platform(system, release, version, csd)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001427
1428 elif system in ('Linux',):
1429 # Linux based systems
Victor Stinnerced39362013-12-09 00:14:52 +01001430 distname, distversion, distid = dist('')
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001431 if distname and not terse:
Victor Stinnerced39362013-12-09 00:14:52 +01001432 platform = _platform(system, release, machine, processor,
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001433 'with',
Victor Stinnerced39362013-12-09 00:14:52 +01001434 distname, distversion, distid)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001435 else:
1436 # If the distribution name is unknown check for libc vs. glibc
Victor Stinnerced39362013-12-09 00:14:52 +01001437 libcname, libcversion = libc_ver(sys.executable)
1438 platform = _platform(system, release, machine, processor,
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001439 'with',
1440 libcname+libcversion)
1441 elif system == 'Java':
1442 # Java platforms
Victor Stinnerced39362013-12-09 00:14:52 +01001443 r, v, vminfo, (os_name, os_version, os_arch) = java_ver()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001444 if terse or not os_name:
Victor Stinnerced39362013-12-09 00:14:52 +01001445 platform = _platform(system, release, version)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001446 else:
Victor Stinnerced39362013-12-09 00:14:52 +01001447 platform = _platform(system, release, version,
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001448 'on',
Victor Stinnerced39362013-12-09 00:14:52 +01001449 os_name, os_version, os_arch)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001450
1451 elif system == 'MacOS':
1452 # MacOS platforms
1453 if terse:
Victor Stinnerced39362013-12-09 00:14:52 +01001454 platform = _platform(system, release)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001455 else:
Victor Stinnerced39362013-12-09 00:14:52 +01001456 platform = _platform(system, release, machine)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001457
1458 else:
1459 # Generic handler
1460 if terse:
Victor Stinnerced39362013-12-09 00:14:52 +01001461 platform = _platform(system, release)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001462 else:
Victor Stinnerced39362013-12-09 00:14:52 +01001463 bits, linkage = architecture(sys.executable)
1464 platform = _platform(system, release, machine,
1465 processor, bits, linkage)
Tim Peters0eadaac2003-04-24 16:02:54 +00001466
Marc-André Lemburg91e83e22004-03-25 18:35:12 +00001467 _platform_cache[(aliased, terse)] = platform
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001468 return platform
1469
1470### Command line interface
1471
1472if __name__ == '__main__':
1473 # Default is to print the aliased verbose platform string
Tim Peters0eadaac2003-04-24 16:02:54 +00001474 terse = ('terse' in sys.argv or '--terse' in sys.argv)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001475 aliased = (not 'nonaliased' in sys.argv and not '--nonaliased' in sys.argv)
Victor Stinnerced39362013-12-09 00:14:52 +01001476 print(platform(aliased, terse))
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001477 sys.exit(0)