blob: 030ef2a3a4b61232530f5127a0ada55ed4b5aebb [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
125 if sys.platform in ('dos','win32','win16','os2'):
126 # 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
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000144def libc_ver(executable=sys.executable,lib='',version='',
145
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)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000166 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:
171 m = _libc_search.search(binary,pos)
172 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
Antoine Pitrouba7c2262011-10-07 13:26:59 +0200180 libcinit,glibc,glibcversion,so,threads,soversion = [
181 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()
200 return lib,version
201
202def _dist_try_harder(distname,version,id):
203
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:
217 tag,value = tv
218 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]
225 return distname,version,id
226
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 ?
234 return 'OpenLinux',pkg[1],id
235
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:]
246 return distname,version,id
247
248 return distname,version,id
249
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
317 Returns a tuple (distname,version,id) which default to the
318 args given as parameters.
319
320 """
321 try:
Victor Stinner620c48b2013-12-09 00:01:27 +0100322 etc = os.listdir(_UNIXCONFDIR)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000323 except os.error:
324 # Probably not a Unix system
325 return distname,version,id
326 etc.sort()
327 for file in etc:
328 m = _release_filename.match(file)
329 if m is not None:
330 _distname,dummy = m.groups()
331 if _distname in supported_dists:
332 distname = _distname
333 break
334 else:
335 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
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000353def dist(distname='',version='',id='',
354
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
Brett Cannon8ab27df2003-08-05 03:52:04 +0000363 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:
388 ints = map(int,l)
389 except ValueError:
390 strings = l
391 else:
Neal Norwitz78a70bd2007-08-30 06:16:26 +0000392 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
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000411 supported_platforms=('win32','win16','dos','os2')):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000412
413 """ Tries to figure out the OS version used and returns
414 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
417 to exists on Windows, DOS and OS/2. XXX Others too ?
418
419 In case this fails, the given parameters are used as
420 defaults.
421
422 """
423 if sys.platform not in supported_platforms:
424 return system,release,version
425
426 # Try some common cmd strings
427 for cmd in ('ver','command /c ver','cmd /c ver'):
428 try:
429 pipe = popen(cmd)
430 info = pipe.read()
431 if pipe.close():
Collin Winterce36ad82007-08-30 01:19:48 +0000432 raise os.error('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 ?
Guido van Rossumb940e112007-01-10 16:19:56 +0000435 except os.error as why:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000436 #print 'Command %s failed: %s' % (cmd,why)
437 continue
Guido van Rossumb940e112007-01-10 16:19:56 +0000438 except IOError as why:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000439 #print 'Command %s failed: %s' % (cmd,why)
440 continue
441 else:
442 break
443 else:
444 return system,release,version
445
446 # Parse the output
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000447 info = info.strip()
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000448 m = _ver_output.match(info)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000449 if m is not None:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000450 system,release,version = m.groups()
451 # Strip trailing dots from version and release
452 if release[-1] == '.':
453 release = release[:-1]
454 if version[-1] == '.':
455 version = version[:-1]
456 # Normalize the version and build strings (eliminating additional
457 # zeros)
458 version = _norm_version(version)
459 return system,release,version
460
461def _win32_getvalue(key,name,default=''):
462
463 """ Read a value for name from the registry key.
464
465 In case this fails, default is returned.
466
467 """
Christian Heimes02781dc2008-03-21 01:11:52 +0000468 try:
469 # Use win32api if available
470 from win32api import RegQueryValueEx
471 except ImportError:
Georg Brandl38feaf02008-05-25 07:45:51 +0000472 # On Python 2.0 and later, emulate using winreg
473 import winreg
474 RegQueryValueEx = winreg.QueryValueEx
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000475 try:
476 return RegQueryValueEx(key,name)
477 except:
478 return default
479
480def win32_ver(release='',version='',csd='',ptype=''):
481
482 """ Get additional version information from the Windows Registry
483 and return a tuple (version,csd,ptype) referring to version
Brian Curtin10dda6e2012-02-01 15:14:00 -0600484 number, CSD level (service pack), and OS type (multi/single
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000485 processor).
486
487 As a hint: ptype returns 'Uniprocessor Free' on single
488 processor NT machines and 'Multiprocessor Free' on multi
489 processor machines. The 'Free' refers to the OS version being
490 free of debugging code. It could also state 'Checked' which
491 means the OS version uses debugging code, i.e. code that
492 checks arguments, ranges, etc. (Thomas Heller).
493
Christian Heimes02781dc2008-03-21 01:11:52 +0000494 Note: this function works best with Mark Hammond's win32
495 package installed, but also on Python 2.3 and later. It
496 obviously only runs on Win32 compatible platforms.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000497
498 """
499 # XXX Is there any way to find out the processor type on WinXX ?
500 # XXX Is win32 available on Windows CE ?
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000501 #
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000502 # Adapted from code posted by Karl Putland to comp.lang.python.
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000503 #
504 # The mappings between reg. values and release names can be found
505 # here: http://msdn.microsoft.com/library/en-us/sysinfo/base/osversioninfo_str.asp
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000506
507 # Import the needed APIs
508 try:
509 import win32api
Christian Heimes02781dc2008-03-21 01:11:52 +0000510 from win32api import RegQueryValueEx, RegOpenKeyEx, \
511 RegCloseKey, GetVersionEx
512 from win32con import HKEY_LOCAL_MACHINE, VER_PLATFORM_WIN32_NT, \
513 VER_PLATFORM_WIN32_WINDOWS, VER_NT_WORKSTATION
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000514 except ImportError:
Christian Heimes02781dc2008-03-21 01:11:52 +0000515 # Emulate the win32api module using Python APIs
516 try:
517 sys.getwindowsversion
518 except AttributeError:
519 # No emulation possible, so return the defaults...
520 return release,version,csd,ptype
521 else:
Georg Brandl38feaf02008-05-25 07:45:51 +0000522 # Emulation using winreg (added in Python 2.0) and
Christian Heimes02781dc2008-03-21 01:11:52 +0000523 # sys.getwindowsversion() (added in Python 2.3)
Georg Brandl38feaf02008-05-25 07:45:51 +0000524 import winreg
Christian Heimes02781dc2008-03-21 01:11:52 +0000525 GetVersionEx = sys.getwindowsversion
Georg Brandl38feaf02008-05-25 07:45:51 +0000526 RegQueryValueEx = winreg.QueryValueEx
527 RegOpenKeyEx = winreg.OpenKeyEx
528 RegCloseKey = winreg.CloseKey
529 HKEY_LOCAL_MACHINE = winreg.HKEY_LOCAL_MACHINE
Christian Heimes02781dc2008-03-21 01:11:52 +0000530 VER_PLATFORM_WIN32_WINDOWS = 1
531 VER_PLATFORM_WIN32_NT = 2
532 VER_NT_WORKSTATION = 1
Brian Curtin6e2824d2010-05-06 03:05:50 +0000533 VER_NT_SERVER = 3
534 REG_SZ = 1
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000535
536 # Find out the registry key and some general version infos
Brian Curtin6e2824d2010-05-06 03:05:50 +0000537 winver = GetVersionEx()
538 maj,min,buildno,plat,csd = winver
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000539 version = '%i.%i.%i' % (maj,min,buildno & 0xFFFF)
Brian Curtin6e2824d2010-05-06 03:05:50 +0000540 if hasattr(winver, "service_pack"):
541 if winver.service_pack != "":
542 csd = 'SP%s' % winver.service_pack_major
543 else:
544 if csd[:13] == 'Service Pack ':
545 csd = 'SP' + csd[13:]
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000546
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000547 if plat == VER_PLATFORM_WIN32_WINDOWS:
548 regkey = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion'
549 # Try to guess the release name
550 if maj == 4:
551 if min == 0:
552 release = '95'
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000553 elif min == 10:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000554 release = '98'
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000555 elif min == 90:
556 release = 'Me'
557 else:
558 release = 'postMe'
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000559 elif maj == 5:
560 release = '2000'
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000561
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000562 elif plat == VER_PLATFORM_WIN32_NT:
563 regkey = 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion'
564 if maj <= 4:
565 release = 'NT'
566 elif maj == 5:
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000567 if min == 0:
568 release = '2000'
569 elif min == 1:
570 release = 'XP'
571 elif min == 2:
572 release = '2003Server'
573 else:
574 release = 'post2003'
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000575 elif maj == 6:
Brian Curtin6e2824d2010-05-06 03:05:50 +0000576 if hasattr(winver, "product_type"):
577 product_type = winver.product_type
578 else:
579 product_type = VER_NT_WORKSTATION
580 # Without an OSVERSIONINFOEX capable sys.getwindowsversion(),
581 # or help from the registry, we cannot properly identify
582 # non-workstation versions.
Christian Heimes02781dc2008-03-21 01:11:52 +0000583 try:
Brian Curtin6e2824d2010-05-06 03:05:50 +0000584 key = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey)
585 name, type = RegQueryValueEx(key, "ProductName")
586 # Discard any type that isn't REG_SZ
587 if type == REG_SZ and name.find("Server") != -1:
588 product_type = VER_NT_SERVER
589 except WindowsError:
590 # Use default of VER_NT_WORKSTATION
591 pass
592
593 if min == 0:
594 if product_type == VER_NT_WORKSTATION:
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000595 release = 'Vista'
596 else:
Brian Curtin6e2824d2010-05-06 03:05:50 +0000597 release = '2008Server'
598 elif min == 1:
599 if product_type == VER_NT_WORKSTATION:
600 release = '7'
601 else:
602 release = '2008ServerR2'
Brian Curtin0b960f52012-10-11 16:07:52 -0500603 elif min == 2:
604 if product_type == VER_NT_WORKSTATION:
605 release = '8'
606 else:
607 release = '2012Server'
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000608 else:
Brian Curtin0b960f52012-10-11 16:07:52 -0500609 release = 'post2012Server'
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000610
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000611 else:
612 if not release:
613 # E.g. Win3.1 with win32s
614 release = '%i.%i' % (maj,min)
615 return release,version,csd,ptype
616
617 # Open the registry key
618 try:
Christian Heimes02781dc2008-03-21 01:11:52 +0000619 keyCurVer = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000620 # Get a value to make sure the key exists...
Christian Heimes02781dc2008-03-21 01:11:52 +0000621 RegQueryValueEx(keyCurVer, 'SystemRoot')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000622 except:
623 return release,version,csd,ptype
Tim Peters0eadaac2003-04-24 16:02:54 +0000624
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000625 # Parse values
626 #subversion = _win32_getvalue(keyCurVer,
627 # 'SubVersionNumber',
628 # ('',1))[0]
629 #if subversion:
630 # release = release + subversion # 95a, 95b, etc.
631 build = _win32_getvalue(keyCurVer,
632 'CurrentBuildNumber',
633 ('',1))[0]
634 ptype = _win32_getvalue(keyCurVer,
635 'CurrentType',
636 (ptype,1))[0]
637
638 # Normalize version
639 version = _norm_version(version,build)
640
641 # Close key
642 RegCloseKey(keyCurVer)
643 return release,version,csd,ptype
644
645def _mac_ver_lookup(selectors,default=None):
646
Benjamin Petersonebacd262008-05-29 21:09:51 +0000647 from _gestalt import gestalt
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000648 l = []
649 append = l.append
650 for selector in selectors:
651 try:
652 append(gestalt(selector))
Benjamin Petersonebacd262008-05-29 21:09:51 +0000653 except (RuntimeError, OSError):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000654 append(default)
655 return l
656
657def _bcd2str(bcd):
658
659 return hex(bcd)[2:]
660
Ronald Oussorene186e382010-07-23 11:54:59 +0000661def _mac_ver_gestalt():
662 """
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000663 Thanks to Mark R. Levinson for mailing documentation links and
664 code examples for this function. Documentation for the
665 gestalt() API is available online at:
666
667 http://www.rgaros.nl/gestalt/
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000668 """
669 # Check whether the version info module is available
670 try:
Benjamin Petersonebacd262008-05-29 21:09:51 +0000671 import _gestalt
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000672 except ImportError:
Ronald Oussorene186e382010-07-23 11:54:59 +0000673 return None
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000674 # Get the infos
Ronald Oussoren19258d52010-02-07 11:33:33 +0000675 sysv, sysa = _mac_ver_lookup(('sysv','sysa'))
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000676 # Decode the infos
677 if sysv:
678 major = (sysv & 0xFF00) >> 8
679 minor = (sysv & 0x00F0) >> 4
680 patch = (sysv & 0x000F)
Christian Heimese4ca8152008-05-08 17:18:53 +0000681
682 if (major, minor) >= (10, 4):
683 # the 'sysv' gestald cannot return patchlevels
684 # higher than 9. Apple introduced 3 new
685 # gestalt codes in 10.4 to deal with this
686 # issue (needed because patch levels can
687 # run higher than 9, such as 10.4.11)
688 major,minor,patch = _mac_ver_lookup(('sys1','sys2','sys3'))
689 release = '%i.%i.%i' %(major, minor, patch)
690 else:
691 release = '%s.%i.%i' % (_bcd2str(major),minor,patch)
Benjamin Peterson856ff5f2008-05-29 21:22:40 +0000692
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000693 if sysa:
Tim Peters0eadaac2003-04-24 16:02:54 +0000694 machine = {0x1: '68k',
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000695 0x2: 'PowerPC',
696 0xa: 'i386'}.get(sysa,'')
Ronald Oussorene186e382010-07-23 11:54:59 +0000697
Ned Deily58e33502011-07-13 15:07:04 -0700698 versioninfo=('', '', '')
Ronald Oussorene186e382010-07-23 11:54:59 +0000699 return release,versioninfo,machine
700
701def _mac_ver_xml():
702 fn = '/System/Library/CoreServices/SystemVersion.plist'
703 if not os.path.exists(fn):
704 return None
705
706 try:
707 import plistlib
708 except ImportError:
709 return None
710
711 pl = plistlib.readPlist(fn)
712 release = pl['ProductVersion']
713 versioninfo=('', '', '')
Larry Hastings605a62d2012-06-24 04:33:36 -0700714 machine = os.uname().machine
Ronald Oussorenfcd77012010-08-03 07:42:42 +0000715 if machine in ('ppc', 'Power Macintosh'):
Ronald Oussorene186e382010-07-23 11:54:59 +0000716 # for compatibility with the gestalt based code
717 machine = 'PowerPC'
718
719 return release,versioninfo,machine
720
721
722def mac_ver(release='',versioninfo=('','',''),machine=''):
723
724 """ Get MacOS version information and return it as tuple (release,
725 versioninfo, machine) with versioninfo being a tuple (version,
726 dev_stage, non_release_version).
727
Ezio Melotti30b9d5d2013-08-17 15:50:46 +0300728 Entries which cannot be determined are set to the parameter values
Ronald Oussorene186e382010-07-23 11:54:59 +0000729 which default to ''. All tuple entries are strings.
730 """
731
732 # First try reading the information from an XML file which should
733 # always be present
734 info = _mac_ver_xml()
735 if info is not None:
736 return info
737
738 # If that doesn't work for some reason fall back to reading the
739 # information using gestalt calls.
740 info = _mac_ver_gestalt()
741 if info is not None:
742 return info
743
744 # If that also doesn't work return the default values
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000745 return release,versioninfo,machine
746
Neal Norwitz9b924c62003-06-29 04:17:45 +0000747def _java_getprop(name,default):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000748
749 from java.lang import System
750 try:
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000751 value = System.getProperty(name)
752 if value is None:
753 return default
754 return value
755 except AttributeError:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000756 return default
757
758def java_ver(release='',vendor='',vminfo=('','',''),osinfo=('','','')):
Tim Peters0eadaac2003-04-24 16:02:54 +0000759
Brett Cannon8ab27df2003-08-05 03:52:04 +0000760 """ Version interface for Jython.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000761
762 Returns a tuple (release,vendor,vminfo,osinfo) with vminfo being
763 a tuple (vm_name,vm_release,vm_vendor) and osinfo being a
764 tuple (os_name,os_version,os_arch).
765
766 Values which cannot be determined are set to the defaults
767 given as parameters (which all default to '').
768
769 """
770 # Import the needed APIs
771 try:
772 import java.lang
773 except ImportError:
774 return release,vendor,vminfo,osinfo
775
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000776 vendor = _java_getprop('java.vendor', vendor)
777 release = _java_getprop('java.version', release)
778 vm_name, vm_release, vm_vendor = vminfo
779 vm_name = _java_getprop('java.vm.name', vm_name)
780 vm_vendor = _java_getprop('java.vm.vendor', vm_vendor)
781 vm_release = _java_getprop('java.vm.version', vm_release)
782 vminfo = vm_name, vm_release, vm_vendor
783 os_name, os_version, os_arch = osinfo
784 os_arch = _java_getprop('java.os.arch', os_arch)
785 os_name = _java_getprop('java.os.name', os_name)
786 os_version = _java_getprop('java.os.version', os_version)
787 osinfo = os_name, os_version, os_arch
Tim Peters0eadaac2003-04-24 16:02:54 +0000788
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000789 return release, vendor, vminfo, osinfo
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000790
791### System name aliasing
792
793def system_alias(system,release,version):
794
795 """ Returns (system,release,version) aliased to common
796 marketing names used for some systems.
797
798 It also does some reordering of the information in some cases
799 where it would otherwise cause confusion.
800
801 """
802 if system == 'Rhapsody':
803 # Apple's BSD derivative
804 # XXX How can we determine the marketing release number ?
805 return 'MacOS X Server',system+release,version
806
807 elif system == 'SunOS':
808 # Sun's OS
809 if release < '5':
810 # These releases use the old name SunOS
811 return system,release,version
812 # Modify release (marketing release = SunOS release - 3)
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000813 l = release.split('.')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000814 if l:
815 try:
816 major = int(l[0])
817 except ValueError:
818 pass
819 else:
820 major = major - 3
821 l[0] = str(major)
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000822 release = '.'.join(l)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000823 if release < '6':
824 system = 'Solaris'
825 else:
826 # XXX Whatever the new SunOS marketing name is...
827 system = 'Solaris'
828
829 elif system == 'IRIX64':
830 # IRIX reports IRIX64 on platforms with 64-bit support; yet it
831 # is really a version and not a different platform, since 32-bit
832 # apps are also supported..
833 system = 'IRIX'
834 if version:
835 version = version + ' (64bit)'
836 else:
837 version = '64bit'
838
839 elif system in ('win32','win16'):
840 # In case one of the other tricks
841 system = 'Windows'
842
843 return system,release,version
844
845### Various internal helpers
846
847def _platform(*args):
848
849 """ Helper to format the platform string in a filename
850 compatible format e.g. "system-version-machine".
851 """
852 # Format the platform string
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000853 platform = '-'.join(x.strip() for x in filter(len, args))
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000854
855 # Cleanup some possible filename obstacles...
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000856 platform = platform.replace(' ','_')
857 platform = platform.replace('/','-')
858 platform = platform.replace('\\','-')
859 platform = platform.replace(':','-')
860 platform = platform.replace(';','-')
861 platform = platform.replace('"','-')
862 platform = platform.replace('(','-')
863 platform = platform.replace(')','-')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000864
865 # No need to report 'unknown' information...
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000866 platform = platform.replace('unknown','')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000867
868 # Fold '--'s and remove trailing '-'
869 while 1:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000870 cleaned = platform.replace('--','-')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000871 if cleaned == platform:
872 break
873 platform = cleaned
874 while platform[-1] == '-':
875 platform = platform[:-1]
876
877 return platform
878
879def _node(default=''):
880
881 """ Helper to determine the node name of this machine.
882 """
883 try:
884 import socket
885 except ImportError:
886 # No sockets...
887 return default
888 try:
889 return socket.gethostname()
890 except socket.error:
891 # Still not working...
892 return default
893
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000894def _follow_symlinks(filepath):
895
896 """ In case filepath is a symlink, follow it until a
897 real file is reached.
898 """
Georg Brandl673f7ef2008-01-05 21:20:19 +0000899 filepath = os.path.abspath(filepath)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000900 while os.path.islink(filepath):
901 filepath = os.path.normpath(
Hirokazu Yamamotob12716b2008-09-04 11:24:53 +0000902 os.path.join(os.path.dirname(filepath),os.readlink(filepath)))
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000903 return filepath
904
905def _syscmd_uname(option,default=''):
906
907 """ Interface to the system's uname command.
908 """
909 if sys.platform in ('dos','win32','win16','os2'):
910 # XXX Others too ?
911 return default
912 try:
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000913 f = os.popen('uname %s 2> %s' % (option, DEV_NULL))
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000914 except (AttributeError,os.error):
915 return default
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000916 output = f.read().strip()
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000917 rc = f.close()
918 if not output or rc:
919 return default
920 else:
921 return output
922
923def _syscmd_file(target,default=''):
924
925 """ Interface to the system's file command.
926
927 The function uses the -b option of the file command to have it
Victor Stinnerddfb2c32010-08-13 16:30:15 +0000928 omit the filename in its output. Follow the symlinks. It returns
929 default in case the command should fail.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000930
931 """
Hirokazu Yamamotod26782e2008-09-01 14:35:47 +0000932 if sys.platform in ('dos','win32','win16','os2'):
933 # XXX Others too ?
934 return default
Jesus Ceafc990e92012-10-04 13:51:43 +0200935 target = _follow_symlinks(target)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000936 try:
Jesus Cea685fffa2012-10-05 05:21:42 +0200937 proc = subprocess.Popen(['file', target],
938 stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
Jesus Ceae8801e22012-10-04 13:56:23 +0200939
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000940 except (AttributeError,os.error):
941 return default
Jesus Ceacb959962012-10-05 05:31:31 +0200942 output = proc.communicate()[0].decode('latin-1')
Jesus Ceafc990e92012-10-04 13:51:43 +0200943 rc = proc.wait()
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000944 if not output or rc:
945 return default
946 else:
947 return output
948
949### Information about the used architecture
950
951# Default values for architecture; non-empty strings override the
952# defaults given as parameters
953_default_architecture = {
954 'win32': ('','WindowsPE'),
955 'win16': ('','Windows'),
956 'dos': ('','MSDOS'),
957}
958
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000959def architecture(executable=sys.executable,bits='',linkage=''):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000960
961 """ Queries the given executable (defaults to the Python interpreter
Brett Cannon8ab27df2003-08-05 03:52:04 +0000962 binary) for various architecture information.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000963
Brett Cannon8ab27df2003-08-05 03:52:04 +0000964 Returns a tuple (bits,linkage) which contains information about
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000965 the bit architecture and the linkage format used for the
966 executable. Both values are returned as strings.
967
968 Values that cannot be determined are returned as given by the
969 parameter presets. If bits is given as '', the sizeof(pointer)
970 (or sizeof(long) on Python version < 1.5.2) is used as
971 indicator for the supported pointer size.
972
973 The function relies on the system's "file" command to do the
974 actual work. This is available on most if not all Unix
Brett Cannon8ab27df2003-08-05 03:52:04 +0000975 platforms. On some non-Unix platforms where the "file" command
976 does not exist and the executable is set to the Python interpreter
977 binary defaults from _default_architecture are used.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000978
979 """
980 # Use the sizeof(pointer) as default number of bits if nothing
981 # else is given as default.
982 if not bits:
983 import struct
984 try:
985 size = struct.calcsize('P')
986 except struct.error:
987 # Older installations can only query longs
988 size = struct.calcsize('l')
989 bits = str(size*8) + 'bit'
Tim Peters0eadaac2003-04-24 16:02:54 +0000990
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000991 # Get data from the 'file' system command
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000992 if executable:
Victor Stinnerddfb2c32010-08-13 16:30:15 +0000993 fileout = _syscmd_file(executable, '')
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000994 else:
Victor Stinnerddfb2c32010-08-13 16:30:15 +0000995 fileout = ''
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000996
Victor Stinnerddfb2c32010-08-13 16:30:15 +0000997 if not fileout and \
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000998 executable == sys.executable:
999 # "file" command did not return anything; we'll try to provide
Tim Peters0eadaac2003-04-24 16:02:54 +00001000 # some sensible defaults then...
Guido van Rossume2b70bc2006-08-18 22:13:04 +00001001 if sys.platform in _default_architecture:
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001002 b,l = _default_architecture[sys.platform]
1003 if b:
1004 bits = b
1005 if l:
1006 linkage = l
1007 return bits,linkage
1008
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001009 if 'executable' not in fileout:
1010 # Format not supported
1011 return bits,linkage
1012
1013 # Bits
1014 if '32-bit' in fileout:
1015 bits = '32bit'
1016 elif 'N32' in fileout:
1017 # On Irix only
1018 bits = 'n32bit'
1019 elif '64-bit' in fileout:
1020 bits = '64bit'
1021
1022 # Linkage
1023 if 'ELF' in fileout:
1024 linkage = 'ELF'
1025 elif 'PE' in fileout:
1026 # E.g. Windows uses this format
1027 if 'Windows' in fileout:
1028 linkage = 'WindowsPE'
1029 else:
1030 linkage = 'PE'
1031 elif 'COFF' in fileout:
1032 linkage = 'COFF'
1033 elif 'MS-DOS' in fileout:
1034 linkage = 'MSDOS'
1035 else:
1036 # XXX the A.OUT format also falls under this class...
1037 pass
1038
1039 return bits,linkage
1040
1041### Portable uname() interface
Tim Peters0eadaac2003-04-24 16:02:54 +00001042
Larry Hastings68386bc2012-06-24 14:30:41 -07001043uname_result = collections.namedtuple("uname_result",
1044 "system node release version machine processor")
1045
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001046_uname_cache = None
1047
1048def uname():
1049
1050 """ Fairly portable uname interface. Returns a tuple
1051 of strings (system,node,release,version,machine,processor)
1052 identifying the underlying platform.
1053
1054 Note that unlike the os.uname function this also returns
Brett Cannon8ab27df2003-08-05 03:52:04 +00001055 possible processor information as an additional tuple entry.
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001056
1057 Entries which cannot be determined are set to ''.
1058
1059 """
1060 global _uname_cache
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001061 no_os_uname = 0
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001062
1063 if _uname_cache is not None:
1064 return _uname_cache
1065
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001066 processor = ''
1067
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001068 # Get some infos from the builtin os.uname API...
1069 try:
1070 system,node,release,version,machine = os.uname()
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001071 except AttributeError:
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001072 no_os_uname = 1
1073
Georg Brandl62e2ca22010-07-31 21:54:24 +00001074 if no_os_uname or not list(filter(None, (system, node, release, version, machine))):
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001075 # Hmm, no there is either no uname or uname has returned
1076 #'unknowns'... we'll have to poke around the system then.
1077 if no_os_uname:
1078 system = sys.platform
1079 release = ''
1080 version = ''
1081 node = _node()
1082 machine = ''
1083
Amaury Forgeot d'Arc7a019842008-06-17 21:42:46 +00001084 use_syscmd_ver = 1
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001085
1086 # Try win32_ver() on win32 platforms
1087 if system == 'win32':
1088 release,version,csd,ptype = win32_ver()
1089 if release and version:
1090 use_syscmd_ver = 0
Christian Heimes02781dc2008-03-21 01:11:52 +00001091 # Try to use the PROCESSOR_* environment variables
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001092 # available on Win XP and later; see
1093 # http://support.microsoft.com/kb/888731 and
1094 # http://www.geocities.com/rick_lively/MANUALS/ENV/MSWIN/PROCESSI.HTM
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001095 if not machine:
R. David Murrayca2edce2010-03-22 17:48:48 +00001096 # WOW64 processes mask the native architecture
1097 if "PROCESSOR_ARCHITEW6432" in os.environ:
1098 machine = os.environ.get("PROCESSOR_ARCHITEW6432", '')
1099 else:
1100 machine = os.environ.get('PROCESSOR_ARCHITECTURE', '')
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001101 if not processor:
1102 processor = os.environ.get('PROCESSOR_IDENTIFIER', machine)
Tim Peters0eadaac2003-04-24 16:02:54 +00001103
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001104 # Try the 'ver' system command available on some
1105 # platforms
1106 if use_syscmd_ver:
1107 system,release,version = _syscmd_ver(system)
Marc-André Lemburgcdc79232004-06-19 17:17:00 +00001108 # Normalize system to what win32_ver() normally returns
1109 # (_syscmd_ver() tends to return the vendor name as well)
1110 if system == 'Microsoft Windows':
1111 system = 'Windows'
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001112 elif system == 'Microsoft' and release == 'Windows':
1113 # Under Windows Vista and Windows Server 2008,
1114 # Microsoft changed the output of the ver command. The
1115 # release is no longer printed. This causes the
1116 # system and release to be misidentified.
1117 system = 'Windows'
1118 if '6.0' == version[:3]:
1119 release = 'Vista'
1120 else:
1121 release = ''
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001122
1123 # In case we still don't know anything useful, we'll try to
1124 # help ourselves
1125 if system in ('win32','win16'):
1126 if not version:
1127 if system == 'win32':
1128 version = '32bit'
1129 else:
1130 version = '16bit'
1131 system = 'Windows'
1132
1133 elif system[:4] == 'java':
1134 release,vendor,vminfo,osinfo = java_ver()
1135 system = 'Java'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001136 version = ', '.join(vminfo)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001137 if not version:
1138 version = vendor
1139
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001140 # System specific extensions
1141 if system == 'OpenVMS':
1142 # OpenVMS seems to have release and version mixed up
1143 if not release or release == '0':
1144 release = version
1145 version = ''
1146 # Get processor information
1147 try:
1148 import vms_lib
1149 except ImportError:
1150 pass
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001151 else:
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001152 csid, cpu_number = vms_lib.getsyi('SYI$_CPU',0)
1153 if (cpu_number >= 128):
1154 processor = 'Alpha'
1155 else:
1156 processor = 'VAX'
1157 if not processor:
1158 # Get processor information from the uname system command
1159 processor = _syscmd_uname('-p','')
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001160
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001161 #If any unknowns still exist, replace them with ''s, which are more portable
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001162 if system == 'unknown':
1163 system = ''
1164 if node == 'unknown':
1165 node = ''
1166 if release == 'unknown':
1167 release = ''
1168 if version == 'unknown':
1169 version = ''
1170 if machine == 'unknown':
1171 machine = ''
1172 if processor == 'unknown':
1173 processor = ''
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001174
1175 # normalize name
1176 if system == 'Microsoft' and release == 'Windows':
1177 system = 'Windows'
1178 release = 'Vista'
1179
Larry Hastings68386bc2012-06-24 14:30:41 -07001180 _uname_cache = uname_result(system,node,release,version,machine,processor)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001181 return _uname_cache
1182
1183### Direct interfaces to some of the uname() return values
1184
1185def system():
1186
1187 """ Returns the system/OS name, e.g. 'Linux', 'Windows' or 'Java'.
1188
1189 An empty string is returned if the value cannot be determined.
1190
1191 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001192 return uname().system
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001193
1194def node():
1195
Brett Cannon8ab27df2003-08-05 03:52:04 +00001196 """ Returns the computer's network name (which may not be fully
1197 qualified)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001198
1199 An empty string is returned if the value cannot be determined.
1200
1201 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001202 return uname().node
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001203
1204def release():
1205
1206 """ Returns the system's release, e.g. '2.2.0' or 'NT'
1207
1208 An empty string is returned if the value cannot be determined.
1209
1210 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001211 return uname().release
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001212
1213def version():
1214
1215 """ Returns the system's release version, e.g. '#3 on degas'
1216
1217 An empty string is returned if the value cannot be determined.
1218
1219 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001220 return uname().version
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001221
1222def machine():
1223
1224 """ Returns the machine type, e.g. 'i386'
1225
1226 An empty string is returned if the value cannot be determined.
1227
1228 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001229 return uname().machine
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001230
1231def processor():
1232
1233 """ Returns the (true) processor name, e.g. 'amdk6'
1234
1235 An empty string is returned if the value cannot be
1236 determined. Note that many platforms do not provide this
1237 information or simply return the same value as for machine(),
1238 e.g. NetBSD does this.
1239
1240 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001241 return uname().processor
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001242
1243### Various APIs for extracting information from sys.version
1244
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001245_sys_version_parser = re.compile(
1246 r'([\w.+]+)\s*'
1247 '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
Antoine Pitroufd036452008-08-19 17:56:33 +00001248 '\[([^\]]+)\]?', re.ASCII)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001249
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001250_ironpython_sys_version_parser = re.compile(
1251 r'IronPython\s*'
1252 '([\d\.]+)'
1253 '(?: \(([\d\.]+)\))?'
Antoine Pitroufd036452008-08-19 17:56:33 +00001254 ' on (.NET [\d\.]+)', re.ASCII)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001255
Ezio Melottif076f532013-10-21 03:03:32 +03001256# IronPython covering 2.6 and 2.7
1257_ironpython26_sys_version_parser = re.compile(
1258 r'([\d.]+)\s*'
1259 '\(IronPython\s*'
1260 '[\d.]+\s*'
1261 '\(([\d.]+)\) on ([\w.]+ [\d.]+(?: \(\d+-bit\))?)\)'
1262)
1263
Benjamin Petersone549ead2009-03-28 21:42:05 +00001264_pypy_sys_version_parser = re.compile(
1265 r'([\w.+]+)\s*'
1266 '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
1267 '\[PyPy [^\]]+\]?')
1268
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001269_sys_version_cache = {}
1270
1271def _sys_version(sys_version=None):
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001272
1273 """ Returns a parsed version of Python's sys.version as tuple
Benjamin Peterson5f28b7b2009-03-26 21:49:58 +00001274 (name, version, branch, revision, buildno, builddate, compiler)
1275 referring to the Python implementation name, version, branch,
1276 revision, build number, build date/time as string and the compiler
1277 identification string.
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001278
1279 Note that unlike the Python sys.version, the returned value
1280 for the Python version will always include the patchlevel (it
1281 defaults to '.0').
1282
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001283 The function returns empty strings for tuple entries that
1284 cannot be determined.
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001285
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001286 sys_version may be given to parse an alternative version
1287 string, e.g. if the version was read from a different Python
1288 interpreter.
1289
1290 """
1291 # Get the Python version
1292 if sys_version is None:
1293 sys_version = sys.version
1294
1295 # Try the cache first
1296 result = _sys_version_cache.get(sys_version, None)
1297 if result is not None:
1298 return result
1299
1300 # Parse it
Ezio Melottif076f532013-10-21 03:03:32 +03001301 if 'IronPython' in sys_version:
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001302 # IronPython
1303 name = 'IronPython'
Ezio Melottif076f532013-10-21 03:03:32 +03001304 if sys_version.startswith('IronPython'):
1305 match = _ironpython_sys_version_parser.match(sys_version)
1306 else:
1307 match = _ironpython26_sys_version_parser.match(sys_version)
1308
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001309 if match is None:
1310 raise ValueError(
1311 'failed to parse IronPython sys.version: %s' %
1312 repr(sys_version))
Ezio Melottif076f532013-10-21 03:03:32 +03001313
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001314 version, alt_version, compiler = match.groups()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001315 buildno = ''
1316 builddate = ''
1317
Ezio Melottif076f532013-10-21 03:03:32 +03001318 elif sys.platform.startswith('java'):
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001319 # Jython
1320 name = 'Jython'
Benjamin Petersone549ead2009-03-28 21:42:05 +00001321 match = _sys_version_parser.match(sys_version)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001322 if match is None:
1323 raise ValueError(
1324 'failed to parse Jython sys.version: %s' %
1325 repr(sys_version))
Benjamin Petersone549ead2009-03-28 21:42:05 +00001326 version, buildno, builddate, buildtime, _ = match.groups()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001327 compiler = sys.platform
Benjamin Petersone549ead2009-03-28 21:42:05 +00001328
1329 elif "PyPy" in sys_version:
1330 # PyPy
1331 name = "PyPy"
1332 match = _pypy_sys_version_parser.match(sys_version)
1333 if match is None:
1334 raise ValueError("failed to parse PyPy sys.version: %s" %
1335 repr(sys_version))
1336 version, buildno, builddate, buildtime = match.groups()
1337 compiler = ""
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001338
1339 else:
1340 # CPython
1341 match = _sys_version_parser.match(sys_version)
1342 if match is None:
1343 raise ValueError(
1344 'failed to parse CPython sys.version: %s' %
1345 repr(sys_version))
1346 version, buildno, builddate, buildtime, compiler = \
1347 match.groups()
Benjamin Petersone549ead2009-03-28 21:42:05 +00001348 name = 'CPython'
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001349 builddate = builddate + ' ' + buildtime
1350
Georg Brandl82562422011-03-05 21:09:22 +01001351 if hasattr(sys, '_mercurial'):
1352 _, branch, revision = sys._mercurial
1353 elif hasattr(sys, 'subversion'):
Benjamin Petersone549ead2009-03-28 21:42:05 +00001354 # sys.subversion was added in Python 2.5
1355 _, branch, revision = sys.subversion
1356 else:
1357 branch = ''
1358 revision = ''
1359
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001360 # Add the patchlevel version if missing
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001361 l = version.split('.')
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001362 if len(l) == 2:
1363 l.append('0')
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001364 version = '.'.join(l)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001365
1366 # Build and cache the result
1367 result = (name, version, branch, revision, buildno, builddate, compiler)
1368 _sys_version_cache[sys_version] = result
1369 return result
1370
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001371def python_implementation():
1372
1373 """ Returns a string identifying the Python implementation.
1374
1375 Currently, the following implementations are identified:
Ezio Melottif16898b2011-05-04 18:37:50 +03001376 'CPython' (C implementation of Python),
1377 'IronPython' (.NET implementation of Python),
1378 'Jython' (Java implementation of Python),
1379 'PyPy' (Python implementation of Python).
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001380
1381 """
1382 return _sys_version()[0]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001383
1384def python_version():
1385
1386 """ Returns the Python version as string 'major.minor.patchlevel'
1387
1388 Note that unlike the Python sys.version, the returned value
1389 will always include the patchlevel (it defaults to 0).
1390
1391 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001392 return _sys_version()[1]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001393
1394def python_version_tuple():
1395
1396 """ Returns the Python version as tuple (major, minor, patchlevel)
1397 of strings.
1398
1399 Note that unlike the Python sys.version, the returned value
1400 will always include the patchlevel (it defaults to 0).
1401
1402 """
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001403 return tuple(_sys_version()[1].split('.'))
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001404
1405def python_branch():
1406
1407 """ Returns a string identifying the Python implementation
1408 branch.
1409
1410 For CPython this is the Subversion branch from which the
1411 Python binary was built.
1412
1413 If not available, an empty string is returned.
1414
1415 """
Thomas Wouters9fe394c2007-02-05 01:24:16 +00001416
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001417 return _sys_version()[2]
1418
1419def python_revision():
1420
1421 """ Returns a string identifying the Python implementation
1422 revision.
1423
1424 For CPython this is the Subversion revision from which the
1425 Python binary was built.
1426
1427 If not available, an empty string is returned.
1428
1429 """
1430 return _sys_version()[3]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001431
1432def python_build():
1433
1434 """ Returns a tuple (buildno, builddate) stating the Python
1435 build number and date as strings.
1436
1437 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001438 return _sys_version()[4:6]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001439
1440def python_compiler():
1441
1442 """ Returns a string identifying the compiler used for compiling
1443 Python.
1444
1445 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001446 return _sys_version()[6]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001447
1448### The Opus Magnum of platform strings :-)
1449
Marc-André Lemburg91e83e22004-03-25 18:35:12 +00001450_platform_cache = {}
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001451
1452def platform(aliased=0, terse=0):
1453
1454 """ Returns a single string identifying the underlying platform
1455 with as much useful information as possible (but no more :).
Tim Peters0eadaac2003-04-24 16:02:54 +00001456
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001457 The output is intended to be human readable rather than
1458 machine parseable. It may look different on different
1459 platforms and this is intended.
1460
1461 If "aliased" is true, the function will use aliases for
1462 various platforms that report system names which differ from
1463 their common names, e.g. SunOS will be reported as
1464 Solaris. The system_alias() function is used to implement
1465 this.
1466
1467 Setting terse to true causes the function to return only the
1468 absolute minimum information needed to identify the platform.
1469
1470 """
Marc-André Lemburg91e83e22004-03-25 18:35:12 +00001471 result = _platform_cache.get((aliased, terse), None)
1472 if result is not None:
1473 return result
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001474
1475 # Get uname information and then apply platform specific cosmetics
1476 # to it...
1477 system,node,release,version,machine,processor = uname()
1478 if machine == processor:
1479 processor = ''
1480 if aliased:
1481 system,release,version = system_alias(system,release,version)
1482
1483 if system == 'Windows':
1484 # MS platforms
1485 rel,vers,csd,ptype = win32_ver(version)
1486 if terse:
1487 platform = _platform(system,release)
1488 else:
1489 platform = _platform(system,release,version,csd)
1490
1491 elif system in ('Linux',):
1492 # Linux based systems
1493 distname,distversion,distid = dist('')
1494 if distname and not terse:
1495 platform = _platform(system,release,machine,processor,
1496 'with',
1497 distname,distversion,distid)
1498 else:
1499 # If the distribution name is unknown check for libc vs. glibc
1500 libcname,libcversion = libc_ver(sys.executable)
1501 platform = _platform(system,release,machine,processor,
1502 'with',
1503 libcname+libcversion)
1504 elif system == 'Java':
1505 # Java platforms
1506 r,v,vminfo,(os_name,os_version,os_arch) = java_ver()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001507 if terse or not os_name:
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001508 platform = _platform(system,release,version)
1509 else:
1510 platform = _platform(system,release,version,
1511 'on',
1512 os_name,os_version,os_arch)
1513
1514 elif system == 'MacOS':
1515 # MacOS platforms
1516 if terse:
1517 platform = _platform(system,release)
1518 else:
1519 platform = _platform(system,release,machine)
1520
1521 else:
1522 # Generic handler
1523 if terse:
1524 platform = _platform(system,release)
1525 else:
1526 bits,linkage = architecture(sys.executable)
1527 platform = _platform(system,release,machine,processor,bits,linkage)
Tim Peters0eadaac2003-04-24 16:02:54 +00001528
Marc-André Lemburg91e83e22004-03-25 18:35:12 +00001529 _platform_cache[(aliased, terse)] = platform
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001530 return platform
1531
1532### Command line interface
1533
1534if __name__ == '__main__':
1535 # Default is to print the aliased verbose platform string
Tim Peters0eadaac2003-04-24 16:02:54 +00001536 terse = ('terse' in sys.argv or '--terse' in sys.argv)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001537 aliased = (not 'nonaliased' in sys.argv and not '--nonaliased' in sys.argv)
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001538 print(platform(aliased,terse))
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001539 sys.exit(0)