blob: c54f7687ba5e74447ed1ed4b2e42f29f969ffd1a [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
Jesus Cea4791a242012-10-05 03:15:39 +0200125 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
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000132### Platform specific APIs
133
Antoine Pitrouba7c2262011-10-07 13:26:59 +0200134_libc_search = re.compile(b'(__libc_init)'
135 b'|'
136 b'(GLIBC_([0-9.]+))'
137 b'|'
138 br'(libc(_\w+)?\.so(?:\.(\d[0-9.]*))?)', re.ASCII)
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000139
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000140def libc_ver(executable=sys.executable,lib='',version='',
141
Antoine Pitrouba7c2262011-10-07 13:26:59 +0200142 chunksize=16384):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000143
Brett Cannon8ab27df2003-08-05 03:52:04 +0000144 """ Tries to determine the libc version that the file executable
145 (which defaults to the Python interpreter) is linked against.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000146
147 Returns a tuple of strings (lib,version) which default to the
148 given parameters in case the lookup fails.
149
150 Note that the function has intimate knowledge of how different
Brett Cannon8ab27df2003-08-05 03:52:04 +0000151 libc versions add symbols to the executable and thus is probably
152 only useable for executables compiled using gcc.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000153
154 The file is read and scanned in chunks of chunksize bytes.
155
156 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000157 if hasattr(os.path, 'realpath'):
158 # Python 2.2 introduced os.path.realpath(); it is used
159 # here to work around problems with Cygwin not being
160 # able to open symlinks for reading
161 executable = os.path.realpath(executable)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000162 f = open(executable,'rb')
Antoine Pitrouba7c2262011-10-07 13:26:59 +0200163 binary = f.read(chunksize)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000164 pos = 0
165 while 1:
Antoine Pitrouba7c2262011-10-07 13:26:59 +0200166 if b'libc' in binary or b'GLIBC' in binary:
167 m = _libc_search.search(binary,pos)
168 else:
169 m = None
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000170 if not m:
Antoine Pitrouba7c2262011-10-07 13:26:59 +0200171 binary = f.read(chunksize)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000172 if not binary:
173 break
174 pos = 0
175 continue
Antoine Pitrouba7c2262011-10-07 13:26:59 +0200176 libcinit,glibc,glibcversion,so,threads,soversion = [
177 s.decode('latin1') if s is not None else s
178 for s in m.groups()]
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000179 if libcinit and not lib:
180 lib = 'libc'
181 elif glibc:
182 if lib != 'glibc':
183 lib = 'glibc'
184 version = glibcversion
185 elif glibcversion > version:
186 version = glibcversion
187 elif so:
188 if lib != 'glibc':
189 lib = 'libc'
Victor Stinner87448812011-12-15 21:42:03 +0100190 if soversion and soversion > version:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000191 version = soversion
192 if threads and version[-len(threads):] != threads:
193 version = version + threads
194 pos = m.end()
195 f.close()
196 return lib,version
197
198def _dist_try_harder(distname,version,id):
199
Tim Peters0eadaac2003-04-24 16:02:54 +0000200 """ Tries some special tricks to get the distribution
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000201 information in case the default method fails.
202
203 Currently supports older SuSE Linux, Caldera OpenLinux and
204 Slackware Linux distributions.
205
206 """
207 if os.path.exists('/var/adm/inst-log/info'):
208 # SuSE Linux stores distribution information in that file
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000209 distname = 'SuSE'
Florent Xicluna7dde7922010-09-03 19:52:03 +0000210 for line in open('/var/adm/inst-log/info'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000211 tv = line.split()
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000212 if len(tv) == 2:
213 tag,value = tv
214 else:
215 continue
216 if tag == 'MIN_DIST_VERSION':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000217 version = value.strip()
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000218 elif tag == 'DIST_IDENT':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000219 values = value.split('-')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000220 id = values[2]
221 return distname,version,id
222
223 if os.path.exists('/etc/.installed'):
224 # Caldera OpenLinux has some infos in that file (thanks to Colin Kong)
Florent Xicluna7dde7922010-09-03 19:52:03 +0000225 for line in open('/etc/.installed'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000226 pkg = line.split('-')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000227 if len(pkg) >= 2 and pkg[0] == 'OpenLinux':
228 # XXX does Caldera support non Intel platforms ? If yes,
229 # where can we find the needed id ?
230 return 'OpenLinux',pkg[1],id
231
232 if os.path.isdir('/usr/lib/setup'):
233 # Check for slackware verson tag file (thanks to Greg Andruk)
234 verfiles = os.listdir('/usr/lib/setup')
Guido van Rossum843c7342004-05-04 18:18:59 +0000235 for n in range(len(verfiles)-1, -1, -1):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000236 if verfiles[n][:14] != 'slack-version-':
237 del verfiles[n]
238 if verfiles:
239 verfiles.sort()
240 distname = 'slackware'
241 version = verfiles[-1][14:]
242 return distname,version,id
243
244 return distname,version,id
245
Antoine Pitroufd036452008-08-19 17:56:33 +0000246_release_filename = re.compile(r'(\w+)[-_](release|version)', re.ASCII)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000247_lsb_release_version = re.compile(r'(.+)'
248 ' release '
249 '([\d.]+)'
Antoine Pitroufd036452008-08-19 17:56:33 +0000250 '[^(]*(?:\((.+)\))?', re.ASCII)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000251_release_version = re.compile(r'([^0-9]+)'
252 '(?: release )?'
253 '([\d.]+)'
Antoine Pitroufd036452008-08-19 17:56:33 +0000254 '[^(]*(?:\((.+)\))?', re.ASCII)
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000255
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000256# See also http://www.novell.com/coolsolutions/feature/11251.html
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000257# and http://linuxmafia.com/faq/Admin/release-files.html
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000258# and http://data.linux-ntfs.org/rpm/whichrpm
259# and http://www.die.net/doc/linux/man/man1/lsb_release.1.html
Marc-André Lemburg380f4172005-11-07 16:11:02 +0000260
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000261_supported_dists = (
262 'SuSE', 'debian', 'fedora', 'redhat', 'centos',
263 'mandrake', 'mandriva', 'rocks', 'slackware', 'yellowdog', 'gentoo',
Antoine Pitrouab888032012-06-24 22:20:18 +0200264 'UnitedLinux', 'turbolinux', 'arch', 'mageia')
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000265
266def _parse_release_file(firstline):
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000267
Benjamin Peterson25001472010-01-25 03:37:42 +0000268 # Default to empty 'version' and 'id' strings. Both defaults are used
269 # when 'firstline' is empty. 'id' defaults to empty when an id can not
270 # be deduced.
271 version = ''
272 id = ''
273
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000274 # Parse the first line
275 m = _lsb_release_version.match(firstline)
276 if m is not None:
277 # LSB format: "distro release x.x (codename)"
278 return tuple(m.groups())
279
280 # Pre-LSB format: "distro x.x (codename)"
281 m = _release_version.match(firstline)
282 if m is not None:
283 return tuple(m.groups())
284
285 # Unkown format... take the first two words
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000286 l = firstline.strip().split()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000287 if l:
288 version = l[0]
289 if len(l) > 1:
290 id = l[1]
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000291 return '', version, id
292
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000293def linux_distribution(distname='', version='', id='',
294
295 supported_dists=_supported_dists,
296 full_distribution_name=1):
297
298 """ Tries to determine the name of the Linux OS distribution name.
299
300 The function first looks for a distribution release file in
301 /etc and then reverts to _dist_try_harder() in case no
302 suitable files are found.
303
304 supported_dists may be given to define the set of Linux
305 distributions to look for. It defaults to a list of currently
306 supported Linux distributions identified by their release file
307 name.
308
309 If full_distribution_name is true (default), the full
310 distribution read from the OS is returned. Otherwise the short
311 name taken from supported_dists is used.
312
313 Returns a tuple (distname,version,id) which default to the
314 args given as parameters.
315
316 """
317 try:
318 etc = os.listdir('/etc')
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200319 except OSError:
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000320 # Probably not a Unix system
321 return distname,version,id
322 etc.sort()
323 for file in etc:
324 m = _release_filename.match(file)
325 if m is not None:
326 _distname,dummy = m.groups()
327 if _distname in supported_dists:
328 distname = _distname
329 break
330 else:
331 return _dist_try_harder(distname,version,id)
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000332
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000333 # Read the first line
Florent Xicluna7dde7922010-09-03 19:52:03 +0000334 with open('/etc/'+file, 'r') as f:
335 firstline = f.readline()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000336 _distname, _version, _id = _parse_release_file(firstline)
337
338 if _distname and full_distribution_name:
339 distname = _distname
340 if _version:
341 version = _version
342 if _id:
343 id = _id
344 return distname, version, id
345
346# To maintain backwards compatibility:
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000347
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000348def dist(distname='',version='',id='',
349
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000350 supported_dists=_supported_dists):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000351
Brett Cannon8ab27df2003-08-05 03:52:04 +0000352 """ Tries to determine the name of the Linux OS distribution name.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000353
354 The function first looks for a distribution release file in
355 /etc and then reverts to _dist_try_harder() in case no
356 suitable files are found.
357
Brett Cannon8ab27df2003-08-05 03:52:04 +0000358 Returns a tuple (distname,version,id) which default to the
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000359 args given as parameters.
360
361 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000362 return linux_distribution(distname, version, id,
363 supported_dists=supported_dists,
364 full_distribution_name=0)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000365
Antoine Pitrou877766d2011-03-19 17:00:37 +0100366def popen(cmd, mode='r', bufsize=-1):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000367
368 """ Portable popen() interface.
369 """
Victor Stinner25000d42011-05-24 00:16:16 +0200370 import warnings
371 warnings.warn('use os.popen instead', DeprecationWarning, stacklevel=2)
Victor Stinner1dfd3802011-03-03 12:54:07 +0000372 return os.popen(cmd, mode, bufsize)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000373
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000374def _norm_version(version, build=''):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000375
Brett Cannon8ab27df2003-08-05 03:52:04 +0000376 """ Normalize the version and build strings and return a single
Walter Dörwalde5a7fad2005-11-21 17:01:27 +0000377 version string using the format major.minor.build (or patchlevel).
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000378 """
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000379 l = version.split('.')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000380 if build:
381 l.append(build)
382 try:
383 ints = map(int,l)
384 except ValueError:
385 strings = l
386 else:
Neal Norwitz78a70bd2007-08-30 06:16:26 +0000387 strings = list(map(str,ints))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000388 version = '.'.join(strings[:3])
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000389 return version
390
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000391_ver_output = re.compile(r'(?:([\w ]+) ([\w.]+) '
392 '.*'
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000393 '\[.* ([\d.]+)\])')
394
395# Examples of VER command output:
396#
397# Windows 2000: Microsoft Windows 2000 [Version 5.00.2195]
398# Windows XP: Microsoft Windows XP [Version 5.1.2600]
399# Windows Vista: Microsoft Windows [Version 6.0.6002]
400#
401# Note that the "Version" string gets localized on different
402# Windows versions.
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000403
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000404def _syscmd_ver(system='', release='', version='',
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000405
Jesus Ceaf1af7052012-10-05 02:48:46 +0200406 supported_platforms=('win32','win16','dos')):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000407
408 """ Tries to figure out the OS version used and returns
409 a tuple (system,release,version).
Tim Peters0eadaac2003-04-24 16:02:54 +0000410
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000411 It uses the "ver" shell command for this which is known
Jesus Ceaf1af7052012-10-05 02:48:46 +0200412 to exists on Windows, DOS. XXX Others too ?
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000413
414 In case this fails, the given parameters are used as
415 defaults.
416
417 """
418 if sys.platform not in supported_platforms:
419 return system,release,version
420
421 # Try some common cmd strings
422 for cmd in ('ver','command /c ver','cmd /c ver'):
423 try:
424 pipe = popen(cmd)
425 info = pipe.read()
426 if pipe.close():
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200427 raise OSError('command failed')
Ezio Melotti13925002011-03-16 11:05:33 +0200428 # XXX How can I suppress shell errors from being written
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000429 # to stderr ?
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200430 except OSError as why:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000431 #print 'Command %s failed: %s' % (cmd,why)
432 continue
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000433 else:
434 break
435 else:
436 return system,release,version
437
438 # Parse the output
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000439 info = info.strip()
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000440 m = _ver_output.match(info)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000441 if m is not None:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000442 system,release,version = m.groups()
443 # Strip trailing dots from version and release
444 if release[-1] == '.':
445 release = release[:-1]
446 if version[-1] == '.':
447 version = version[:-1]
448 # Normalize the version and build strings (eliminating additional
449 # zeros)
450 version = _norm_version(version)
451 return system,release,version
452
453def _win32_getvalue(key,name,default=''):
454
455 """ Read a value for name from the registry key.
456
457 In case this fails, default is returned.
458
459 """
Christian Heimes02781dc2008-03-21 01:11:52 +0000460 try:
461 # Use win32api if available
462 from win32api import RegQueryValueEx
463 except ImportError:
Georg Brandl38feaf02008-05-25 07:45:51 +0000464 # On Python 2.0 and later, emulate using winreg
465 import winreg
466 RegQueryValueEx = winreg.QueryValueEx
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000467 try:
468 return RegQueryValueEx(key,name)
469 except:
470 return default
471
472def win32_ver(release='',version='',csd='',ptype=''):
473
474 """ Get additional version information from the Windows Registry
475 and return a tuple (version,csd,ptype) referring to version
Brian Curtin10dda6e2012-02-01 15:14:00 -0600476 number, CSD level (service pack), and OS type (multi/single
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000477 processor).
478
479 As a hint: ptype returns 'Uniprocessor Free' on single
480 processor NT machines and 'Multiprocessor Free' on multi
481 processor machines. The 'Free' refers to the OS version being
482 free of debugging code. It could also state 'Checked' which
483 means the OS version uses debugging code, i.e. code that
484 checks arguments, ranges, etc. (Thomas Heller).
485
Christian Heimes02781dc2008-03-21 01:11:52 +0000486 Note: this function works best with Mark Hammond's win32
487 package installed, but also on Python 2.3 and later. It
488 obviously only runs on Win32 compatible platforms.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000489
490 """
491 # XXX Is there any way to find out the processor type on WinXX ?
492 # XXX Is win32 available on Windows CE ?
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000493 #
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000494 # Adapted from code posted by Karl Putland to comp.lang.python.
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000495 #
496 # The mappings between reg. values and release names can be found
497 # here: http://msdn.microsoft.com/library/en-us/sysinfo/base/osversioninfo_str.asp
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000498
499 # Import the needed APIs
500 try:
501 import win32api
Christian Heimes02781dc2008-03-21 01:11:52 +0000502 from win32api import RegQueryValueEx, RegOpenKeyEx, \
503 RegCloseKey, GetVersionEx
504 from win32con import HKEY_LOCAL_MACHINE, VER_PLATFORM_WIN32_NT, \
505 VER_PLATFORM_WIN32_WINDOWS, VER_NT_WORKSTATION
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000506 except ImportError:
Christian Heimes02781dc2008-03-21 01:11:52 +0000507 # Emulate the win32api module using Python APIs
508 try:
509 sys.getwindowsversion
510 except AttributeError:
511 # No emulation possible, so return the defaults...
512 return release,version,csd,ptype
513 else:
Georg Brandl38feaf02008-05-25 07:45:51 +0000514 # Emulation using winreg (added in Python 2.0) and
Christian Heimes02781dc2008-03-21 01:11:52 +0000515 # sys.getwindowsversion() (added in Python 2.3)
Georg Brandl38feaf02008-05-25 07:45:51 +0000516 import winreg
Christian Heimes02781dc2008-03-21 01:11:52 +0000517 GetVersionEx = sys.getwindowsversion
Georg Brandl38feaf02008-05-25 07:45:51 +0000518 RegQueryValueEx = winreg.QueryValueEx
519 RegOpenKeyEx = winreg.OpenKeyEx
520 RegCloseKey = winreg.CloseKey
521 HKEY_LOCAL_MACHINE = winreg.HKEY_LOCAL_MACHINE
Christian Heimes02781dc2008-03-21 01:11:52 +0000522 VER_PLATFORM_WIN32_WINDOWS = 1
523 VER_PLATFORM_WIN32_NT = 2
524 VER_NT_WORKSTATION = 1
Brian Curtin6e2824d2010-05-06 03:05:50 +0000525 VER_NT_SERVER = 3
526 REG_SZ = 1
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000527
528 # Find out the registry key and some general version infos
Brian Curtin6e2824d2010-05-06 03:05:50 +0000529 winver = GetVersionEx()
530 maj,min,buildno,plat,csd = winver
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000531 version = '%i.%i.%i' % (maj,min,buildno & 0xFFFF)
Brian Curtin6e2824d2010-05-06 03:05:50 +0000532 if hasattr(winver, "service_pack"):
533 if winver.service_pack != "":
534 csd = 'SP%s' % winver.service_pack_major
535 else:
536 if csd[:13] == 'Service Pack ':
537 csd = 'SP' + csd[13:]
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000538
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000539 if plat == VER_PLATFORM_WIN32_WINDOWS:
540 regkey = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion'
541 # Try to guess the release name
542 if maj == 4:
543 if min == 0:
544 release = '95'
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000545 elif min == 10:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000546 release = '98'
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000547 elif min == 90:
548 release = 'Me'
549 else:
550 release = 'postMe'
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000551 elif maj == 5:
552 release = '2000'
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000553
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000554 elif plat == VER_PLATFORM_WIN32_NT:
555 regkey = 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion'
556 if maj <= 4:
557 release = 'NT'
558 elif maj == 5:
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000559 if min == 0:
560 release = '2000'
561 elif min == 1:
562 release = 'XP'
563 elif min == 2:
564 release = '2003Server'
565 else:
566 release = 'post2003'
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000567 elif maj == 6:
Brian Curtin6e2824d2010-05-06 03:05:50 +0000568 if hasattr(winver, "product_type"):
569 product_type = winver.product_type
570 else:
571 product_type = VER_NT_WORKSTATION
572 # Without an OSVERSIONINFOEX capable sys.getwindowsversion(),
573 # or help from the registry, we cannot properly identify
574 # non-workstation versions.
Christian Heimes02781dc2008-03-21 01:11:52 +0000575 try:
Brian Curtin6e2824d2010-05-06 03:05:50 +0000576 key = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey)
577 name, type = RegQueryValueEx(key, "ProductName")
578 # Discard any type that isn't REG_SZ
579 if type == REG_SZ and name.find("Server") != -1:
580 product_type = VER_NT_SERVER
Andrew Svetlov2606a6f2012-12-19 14:33:35 +0200581 except OSError:
Brian Curtin6e2824d2010-05-06 03:05:50 +0000582 # Use default of VER_NT_WORKSTATION
583 pass
584
585 if min == 0:
586 if product_type == VER_NT_WORKSTATION:
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000587 release = 'Vista'
588 else:
Brian Curtin6e2824d2010-05-06 03:05:50 +0000589 release = '2008Server'
590 elif min == 1:
591 if product_type == VER_NT_WORKSTATION:
592 release = '7'
593 else:
594 release = '2008ServerR2'
Brian Curtin0b960f52012-10-11 16:07:52 -0500595 elif min == 2:
596 if product_type == VER_NT_WORKSTATION:
597 release = '8'
598 else:
599 release = '2012Server'
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000600 else:
Brian Curtin0b960f52012-10-11 16:07:52 -0500601 release = 'post2012Server'
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000602
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000603 else:
604 if not release:
605 # E.g. Win3.1 with win32s
606 release = '%i.%i' % (maj,min)
607 return release,version,csd,ptype
608
609 # Open the registry key
610 try:
Christian Heimes02781dc2008-03-21 01:11:52 +0000611 keyCurVer = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000612 # Get a value to make sure the key exists...
Christian Heimes02781dc2008-03-21 01:11:52 +0000613 RegQueryValueEx(keyCurVer, 'SystemRoot')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000614 except:
615 return release,version,csd,ptype
Tim Peters0eadaac2003-04-24 16:02:54 +0000616
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000617 # Parse values
618 #subversion = _win32_getvalue(keyCurVer,
619 # 'SubVersionNumber',
620 # ('',1))[0]
621 #if subversion:
622 # release = release + subversion # 95a, 95b, etc.
623 build = _win32_getvalue(keyCurVer,
624 'CurrentBuildNumber',
625 ('',1))[0]
626 ptype = _win32_getvalue(keyCurVer,
627 'CurrentType',
628 (ptype,1))[0]
629
630 # Normalize version
631 version = _norm_version(version,build)
632
633 # Close key
634 RegCloseKey(keyCurVer)
635 return release,version,csd,ptype
636
637def _mac_ver_lookup(selectors,default=None):
638
Benjamin Petersonebacd262008-05-29 21:09:51 +0000639 from _gestalt import gestalt
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000640 l = []
641 append = l.append
642 for selector in selectors:
643 try:
644 append(gestalt(selector))
Benjamin Petersonebacd262008-05-29 21:09:51 +0000645 except (RuntimeError, OSError):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000646 append(default)
647 return l
648
649def _bcd2str(bcd):
650
651 return hex(bcd)[2:]
652
Ronald Oussorene186e382010-07-23 11:54:59 +0000653def _mac_ver_gestalt():
654 """
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000655 Thanks to Mark R. Levinson for mailing documentation links and
656 code examples for this function. Documentation for the
657 gestalt() API is available online at:
658
659 http://www.rgaros.nl/gestalt/
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000660 """
661 # Check whether the version info module is available
662 try:
Benjamin Petersonebacd262008-05-29 21:09:51 +0000663 import _gestalt
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000664 except ImportError:
Ronald Oussorene186e382010-07-23 11:54:59 +0000665 return None
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000666 # Get the infos
Ronald Oussoren19258d52010-02-07 11:33:33 +0000667 sysv, sysa = _mac_ver_lookup(('sysv','sysa'))
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000668 # Decode the infos
669 if sysv:
670 major = (sysv & 0xFF00) >> 8
671 minor = (sysv & 0x00F0) >> 4
672 patch = (sysv & 0x000F)
Christian Heimese4ca8152008-05-08 17:18:53 +0000673
674 if (major, minor) >= (10, 4):
675 # the 'sysv' gestald cannot return patchlevels
676 # higher than 9. Apple introduced 3 new
677 # gestalt codes in 10.4 to deal with this
678 # issue (needed because patch levels can
679 # run higher than 9, such as 10.4.11)
680 major,minor,patch = _mac_ver_lookup(('sys1','sys2','sys3'))
681 release = '%i.%i.%i' %(major, minor, patch)
682 else:
683 release = '%s.%i.%i' % (_bcd2str(major),minor,patch)
Benjamin Peterson856ff5f2008-05-29 21:22:40 +0000684
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000685 if sysa:
Tim Peters0eadaac2003-04-24 16:02:54 +0000686 machine = {0x1: '68k',
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000687 0x2: 'PowerPC',
688 0xa: 'i386'}.get(sysa,'')
Ronald Oussorene186e382010-07-23 11:54:59 +0000689
Ned Deily58e33502011-07-13 15:07:04 -0700690 versioninfo=('', '', '')
Ronald Oussorene186e382010-07-23 11:54:59 +0000691 return release,versioninfo,machine
692
693def _mac_ver_xml():
694 fn = '/System/Library/CoreServices/SystemVersion.plist'
695 if not os.path.exists(fn):
696 return None
697
698 try:
699 import plistlib
700 except ImportError:
701 return None
702
703 pl = plistlib.readPlist(fn)
704 release = pl['ProductVersion']
705 versioninfo=('', '', '')
Larry Hastings605a62d2012-06-24 04:33:36 -0700706 machine = os.uname().machine
Ronald Oussorenfcd77012010-08-03 07:42:42 +0000707 if machine in ('ppc', 'Power Macintosh'):
Ronald Oussorene186e382010-07-23 11:54:59 +0000708 # for compatibility with the gestalt based code
709 machine = 'PowerPC'
710
711 return release,versioninfo,machine
712
713
714def mac_ver(release='',versioninfo=('','',''),machine=''):
715
716 """ Get MacOS version information and return it as tuple (release,
717 versioninfo, machine) with versioninfo being a tuple (version,
718 dev_stage, non_release_version).
719
720 Entries which cannot be determined are set to the paramter values
721 which default to ''. All tuple entries are strings.
722 """
723
724 # First try reading the information from an XML file which should
725 # always be present
726 info = _mac_ver_xml()
727 if info is not None:
728 return info
729
730 # If that doesn't work for some reason fall back to reading the
731 # information using gestalt calls.
732 info = _mac_ver_gestalt()
733 if info is not None:
734 return info
735
736 # If that also doesn't work return the default values
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000737 return release,versioninfo,machine
738
Neal Norwitz9b924c62003-06-29 04:17:45 +0000739def _java_getprop(name,default):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000740
741 from java.lang import System
742 try:
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000743 value = System.getProperty(name)
744 if value is None:
745 return default
746 return value
747 except AttributeError:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000748 return default
749
750def java_ver(release='',vendor='',vminfo=('','',''),osinfo=('','','')):
Tim Peters0eadaac2003-04-24 16:02:54 +0000751
Brett Cannon8ab27df2003-08-05 03:52:04 +0000752 """ Version interface for Jython.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000753
754 Returns a tuple (release,vendor,vminfo,osinfo) with vminfo being
755 a tuple (vm_name,vm_release,vm_vendor) and osinfo being a
756 tuple (os_name,os_version,os_arch).
757
758 Values which cannot be determined are set to the defaults
759 given as parameters (which all default to '').
760
761 """
762 # Import the needed APIs
763 try:
764 import java.lang
765 except ImportError:
766 return release,vendor,vminfo,osinfo
767
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000768 vendor = _java_getprop('java.vendor', vendor)
769 release = _java_getprop('java.version', release)
770 vm_name, vm_release, vm_vendor = vminfo
771 vm_name = _java_getprop('java.vm.name', vm_name)
772 vm_vendor = _java_getprop('java.vm.vendor', vm_vendor)
773 vm_release = _java_getprop('java.vm.version', vm_release)
774 vminfo = vm_name, vm_release, vm_vendor
775 os_name, os_version, os_arch = osinfo
776 os_arch = _java_getprop('java.os.arch', os_arch)
777 os_name = _java_getprop('java.os.name', os_name)
778 os_version = _java_getprop('java.os.version', os_version)
779 osinfo = os_name, os_version, os_arch
Tim Peters0eadaac2003-04-24 16:02:54 +0000780
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000781 return release, vendor, vminfo, osinfo
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000782
783### System name aliasing
784
785def system_alias(system,release,version):
786
787 """ Returns (system,release,version) aliased to common
788 marketing names used for some systems.
789
790 It also does some reordering of the information in some cases
791 where it would otherwise cause confusion.
792
793 """
794 if system == 'Rhapsody':
795 # Apple's BSD derivative
796 # XXX How can we determine the marketing release number ?
797 return 'MacOS X Server',system+release,version
798
799 elif system == 'SunOS':
800 # Sun's OS
801 if release < '5':
802 # These releases use the old name SunOS
803 return system,release,version
804 # Modify release (marketing release = SunOS release - 3)
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000805 l = release.split('.')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000806 if l:
807 try:
808 major = int(l[0])
809 except ValueError:
810 pass
811 else:
812 major = major - 3
813 l[0] = str(major)
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000814 release = '.'.join(l)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000815 if release < '6':
816 system = 'Solaris'
817 else:
818 # XXX Whatever the new SunOS marketing name is...
819 system = 'Solaris'
820
821 elif system == 'IRIX64':
822 # IRIX reports IRIX64 on platforms with 64-bit support; yet it
823 # is really a version and not a different platform, since 32-bit
824 # apps are also supported..
825 system = 'IRIX'
826 if version:
827 version = version + ' (64bit)'
828 else:
829 version = '64bit'
830
831 elif system in ('win32','win16'):
832 # In case one of the other tricks
833 system = 'Windows'
834
835 return system,release,version
836
837### Various internal helpers
838
839def _platform(*args):
840
841 """ Helper to format the platform string in a filename
842 compatible format e.g. "system-version-machine".
843 """
844 # Format the platform string
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000845 platform = '-'.join(x.strip() for x in filter(len, args))
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000846
847 # Cleanup some possible filename obstacles...
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000848 platform = platform.replace(' ','_')
849 platform = platform.replace('/','-')
850 platform = platform.replace('\\','-')
851 platform = platform.replace(':','-')
852 platform = platform.replace(';','-')
853 platform = platform.replace('"','-')
854 platform = platform.replace('(','-')
855 platform = platform.replace(')','-')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000856
857 # No need to report 'unknown' information...
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000858 platform = platform.replace('unknown','')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000859
860 # Fold '--'s and remove trailing '-'
861 while 1:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000862 cleaned = platform.replace('--','-')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000863 if cleaned == platform:
864 break
865 platform = cleaned
866 while platform[-1] == '-':
867 platform = platform[:-1]
868
869 return platform
870
871def _node(default=''):
872
873 """ Helper to determine the node name of this machine.
874 """
875 try:
876 import socket
877 except ImportError:
878 # No sockets...
879 return default
880 try:
881 return socket.gethostname()
Andrew Svetlov0832af62012-12-18 23:10:48 +0200882 except OSError:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000883 # Still not working...
884 return default
885
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000886def _follow_symlinks(filepath):
887
888 """ In case filepath is a symlink, follow it until a
889 real file is reached.
890 """
Georg Brandl673f7ef2008-01-05 21:20:19 +0000891 filepath = os.path.abspath(filepath)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000892 while os.path.islink(filepath):
893 filepath = os.path.normpath(
Hirokazu Yamamotob12716b2008-09-04 11:24:53 +0000894 os.path.join(os.path.dirname(filepath),os.readlink(filepath)))
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000895 return filepath
896
897def _syscmd_uname(option,default=''):
898
899 """ Interface to the system's uname command.
900 """
Jesus Cea4791a242012-10-05 03:15:39 +0200901 if sys.platform in ('dos','win32','win16'):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000902 # XXX Others too ?
903 return default
904 try:
Alexandre Vassalottie52e3782009-07-17 09:18:18 +0000905 f = os.popen('uname %s 2> %s' % (option, DEV_NULL))
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200906 except (AttributeError, OSError):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000907 return default
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000908 output = f.read().strip()
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000909 rc = f.close()
910 if not output or rc:
911 return default
912 else:
913 return output
914
915def _syscmd_file(target,default=''):
916
917 """ Interface to the system's file command.
918
919 The function uses the -b option of the file command to have it
Victor Stinnerddfb2c32010-08-13 16:30:15 +0000920 omit the filename in its output. Follow the symlinks. It returns
921 default in case the command should fail.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000922
923 """
Jesus Cea4791a242012-10-05 03:15:39 +0200924 if sys.platform in ('dos','win32','win16'):
Hirokazu Yamamotod26782e2008-09-01 14:35:47 +0000925 # XXX Others too ?
926 return default
Jesus Ceafc990e92012-10-04 13:51:43 +0200927 target = _follow_symlinks(target)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000928 try:
Jesus Cea685fffa2012-10-05 05:21:42 +0200929 proc = subprocess.Popen(['file', target],
930 stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
Jesus Ceae8801e22012-10-04 13:56:23 +0200931
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200932 except (AttributeError, OSError):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000933 return default
Jesus Ceacb959962012-10-05 05:31:31 +0200934 output = proc.communicate()[0].decode('latin-1')
Jesus Ceafc990e92012-10-04 13:51:43 +0200935 rc = proc.wait()
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000936 if not output or rc:
937 return default
938 else:
939 return output
940
941### Information about the used architecture
942
943# Default values for architecture; non-empty strings override the
944# defaults given as parameters
945_default_architecture = {
946 'win32': ('','WindowsPE'),
947 'win16': ('','Windows'),
948 'dos': ('','MSDOS'),
949}
950
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000951def architecture(executable=sys.executable,bits='',linkage=''):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000952
953 """ Queries the given executable (defaults to the Python interpreter
Brett Cannon8ab27df2003-08-05 03:52:04 +0000954 binary) for various architecture information.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000955
Brett Cannon8ab27df2003-08-05 03:52:04 +0000956 Returns a tuple (bits,linkage) which contains information about
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000957 the bit architecture and the linkage format used for the
958 executable. Both values are returned as strings.
959
960 Values that cannot be determined are returned as given by the
961 parameter presets. If bits is given as '', the sizeof(pointer)
962 (or sizeof(long) on Python version < 1.5.2) is used as
963 indicator for the supported pointer size.
964
965 The function relies on the system's "file" command to do the
966 actual work. This is available on most if not all Unix
Brett Cannon8ab27df2003-08-05 03:52:04 +0000967 platforms. On some non-Unix platforms where the "file" command
968 does not exist and the executable is set to the Python interpreter
969 binary defaults from _default_architecture are used.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000970
971 """
972 # Use the sizeof(pointer) as default number of bits if nothing
973 # else is given as default.
974 if not bits:
975 import struct
976 try:
977 size = struct.calcsize('P')
978 except struct.error:
979 # Older installations can only query longs
980 size = struct.calcsize('l')
981 bits = str(size*8) + 'bit'
Tim Peters0eadaac2003-04-24 16:02:54 +0000982
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000983 # Get data from the 'file' system command
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000984 if executable:
Victor Stinnerddfb2c32010-08-13 16:30:15 +0000985 fileout = _syscmd_file(executable, '')
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000986 else:
Victor Stinnerddfb2c32010-08-13 16:30:15 +0000987 fileout = ''
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000988
Victor Stinnerddfb2c32010-08-13 16:30:15 +0000989 if not fileout and \
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000990 executable == sys.executable:
991 # "file" command did not return anything; we'll try to provide
Tim Peters0eadaac2003-04-24 16:02:54 +0000992 # some sensible defaults then...
Guido van Rossume2b70bc2006-08-18 22:13:04 +0000993 if sys.platform in _default_architecture:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000994 b,l = _default_architecture[sys.platform]
995 if b:
996 bits = b
997 if l:
998 linkage = l
999 return bits,linkage
1000
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001001 if 'executable' not in fileout:
1002 # Format not supported
1003 return bits,linkage
1004
1005 # Bits
1006 if '32-bit' in fileout:
1007 bits = '32bit'
1008 elif 'N32' in fileout:
1009 # On Irix only
1010 bits = 'n32bit'
1011 elif '64-bit' in fileout:
1012 bits = '64bit'
1013
1014 # Linkage
1015 if 'ELF' in fileout:
1016 linkage = 'ELF'
1017 elif 'PE' in fileout:
1018 # E.g. Windows uses this format
1019 if 'Windows' in fileout:
1020 linkage = 'WindowsPE'
1021 else:
1022 linkage = 'PE'
1023 elif 'COFF' in fileout:
1024 linkage = 'COFF'
1025 elif 'MS-DOS' in fileout:
1026 linkage = 'MSDOS'
1027 else:
1028 # XXX the A.OUT format also falls under this class...
1029 pass
1030
1031 return bits,linkage
1032
1033### Portable uname() interface
Tim Peters0eadaac2003-04-24 16:02:54 +00001034
Larry Hastings68386bc2012-06-24 14:30:41 -07001035uname_result = collections.namedtuple("uname_result",
1036 "system node release version machine processor")
1037
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001038_uname_cache = None
1039
1040def uname():
1041
1042 """ Fairly portable uname interface. Returns a tuple
1043 of strings (system,node,release,version,machine,processor)
1044 identifying the underlying platform.
1045
1046 Note that unlike the os.uname function this also returns
Brett Cannon8ab27df2003-08-05 03:52:04 +00001047 possible processor information as an additional tuple entry.
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001048
1049 Entries which cannot be determined are set to ''.
1050
1051 """
1052 global _uname_cache
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001053 no_os_uname = 0
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001054
1055 if _uname_cache is not None:
1056 return _uname_cache
1057
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001058 processor = ''
1059
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001060 # Get some infos from the builtin os.uname API...
1061 try:
1062 system,node,release,version,machine = os.uname()
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001063 except AttributeError:
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001064 no_os_uname = 1
1065
Georg Brandl62e2ca22010-07-31 21:54:24 +00001066 if no_os_uname or not list(filter(None, (system, node, release, version, machine))):
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001067 # Hmm, no there is either no uname or uname has returned
1068 #'unknowns'... we'll have to poke around the system then.
1069 if no_os_uname:
1070 system = sys.platform
1071 release = ''
1072 version = ''
1073 node = _node()
1074 machine = ''
1075
Amaury Forgeot d'Arc7a019842008-06-17 21:42:46 +00001076 use_syscmd_ver = 1
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001077
1078 # Try win32_ver() on win32 platforms
1079 if system == 'win32':
1080 release,version,csd,ptype = win32_ver()
1081 if release and version:
1082 use_syscmd_ver = 0
Christian Heimes02781dc2008-03-21 01:11:52 +00001083 # Try to use the PROCESSOR_* environment variables
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001084 # available on Win XP and later; see
1085 # http://support.microsoft.com/kb/888731 and
1086 # http://www.geocities.com/rick_lively/MANUALS/ENV/MSWIN/PROCESSI.HTM
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001087 if not machine:
R. David Murrayca2edce2010-03-22 17:48:48 +00001088 # WOW64 processes mask the native architecture
1089 if "PROCESSOR_ARCHITEW6432" in os.environ:
1090 machine = os.environ.get("PROCESSOR_ARCHITEW6432", '')
1091 else:
1092 machine = os.environ.get('PROCESSOR_ARCHITECTURE', '')
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001093 if not processor:
1094 processor = os.environ.get('PROCESSOR_IDENTIFIER', machine)
Tim Peters0eadaac2003-04-24 16:02:54 +00001095
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001096 # Try the 'ver' system command available on some
1097 # platforms
1098 if use_syscmd_ver:
1099 system,release,version = _syscmd_ver(system)
Marc-André Lemburgcdc79232004-06-19 17:17:00 +00001100 # Normalize system to what win32_ver() normally returns
1101 # (_syscmd_ver() tends to return the vendor name as well)
1102 if system == 'Microsoft Windows':
1103 system = 'Windows'
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001104 elif system == 'Microsoft' and release == 'Windows':
1105 # Under Windows Vista and Windows Server 2008,
1106 # Microsoft changed the output of the ver command. The
1107 # release is no longer printed. This causes the
1108 # system and release to be misidentified.
1109 system = 'Windows'
1110 if '6.0' == version[:3]:
1111 release = 'Vista'
1112 else:
1113 release = ''
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001114
1115 # In case we still don't know anything useful, we'll try to
1116 # help ourselves
1117 if system in ('win32','win16'):
1118 if not version:
1119 if system == 'win32':
1120 version = '32bit'
1121 else:
1122 version = '16bit'
1123 system = 'Windows'
1124
1125 elif system[:4] == 'java':
1126 release,vendor,vminfo,osinfo = java_ver()
1127 system = 'Java'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001128 version = ', '.join(vminfo)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001129 if not version:
1130 version = vendor
1131
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001132 # System specific extensions
1133 if system == 'OpenVMS':
1134 # OpenVMS seems to have release and version mixed up
1135 if not release or release == '0':
1136 release = version
1137 version = ''
1138 # Get processor information
1139 try:
1140 import vms_lib
1141 except ImportError:
1142 pass
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001143 else:
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001144 csid, cpu_number = vms_lib.getsyi('SYI$_CPU',0)
1145 if (cpu_number >= 128):
1146 processor = 'Alpha'
1147 else:
1148 processor = 'VAX'
1149 if not processor:
1150 # Get processor information from the uname system command
1151 processor = _syscmd_uname('-p','')
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001152
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001153 #If any unknowns still exist, replace them with ''s, which are more portable
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001154 if system == 'unknown':
1155 system = ''
1156 if node == 'unknown':
1157 node = ''
1158 if release == 'unknown':
1159 release = ''
1160 if version == 'unknown':
1161 version = ''
1162 if machine == 'unknown':
1163 machine = ''
1164 if processor == 'unknown':
1165 processor = ''
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001166
1167 # normalize name
1168 if system == 'Microsoft' and release == 'Windows':
1169 system = 'Windows'
1170 release = 'Vista'
1171
Larry Hastings68386bc2012-06-24 14:30:41 -07001172 _uname_cache = uname_result(system,node,release,version,machine,processor)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001173 return _uname_cache
1174
1175### Direct interfaces to some of the uname() return values
1176
1177def system():
1178
1179 """ Returns the system/OS name, e.g. 'Linux', 'Windows' or 'Java'.
1180
1181 An empty string is returned if the value cannot be determined.
1182
1183 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001184 return uname().system
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001185
1186def node():
1187
Brett Cannon8ab27df2003-08-05 03:52:04 +00001188 """ Returns the computer's network name (which may not be fully
1189 qualified)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001190
1191 An empty string is returned if the value cannot be determined.
1192
1193 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001194 return uname().node
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001195
1196def release():
1197
1198 """ Returns the system's release, e.g. '2.2.0' or 'NT'
1199
1200 An empty string is returned if the value cannot be determined.
1201
1202 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001203 return uname().release
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001204
1205def version():
1206
1207 """ Returns the system's release version, e.g. '#3 on degas'
1208
1209 An empty string is returned if the value cannot be determined.
1210
1211 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001212 return uname().version
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001213
1214def machine():
1215
1216 """ Returns the machine type, e.g. 'i386'
1217
1218 An empty string is returned if the value cannot be determined.
1219
1220 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001221 return uname().machine
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001222
1223def processor():
1224
1225 """ Returns the (true) processor name, e.g. 'amdk6'
1226
1227 An empty string is returned if the value cannot be
1228 determined. Note that many platforms do not provide this
1229 information or simply return the same value as for machine(),
1230 e.g. NetBSD does this.
1231
1232 """
Larry Hastings68386bc2012-06-24 14:30:41 -07001233 return uname().processor
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001234
1235### Various APIs for extracting information from sys.version
1236
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001237_sys_version_parser = re.compile(
1238 r'([\w.+]+)\s*'
1239 '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
Antoine Pitroufd036452008-08-19 17:56:33 +00001240 '\[([^\]]+)\]?', re.ASCII)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001241
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001242_ironpython_sys_version_parser = re.compile(
1243 r'IronPython\s*'
1244 '([\d\.]+)'
1245 '(?: \(([\d\.]+)\))?'
Antoine Pitroufd036452008-08-19 17:56:33 +00001246 ' on (.NET [\d\.]+)', re.ASCII)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001247
Benjamin Petersone549ead2009-03-28 21:42:05 +00001248_pypy_sys_version_parser = re.compile(
1249 r'([\w.+]+)\s*'
1250 '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
1251 '\[PyPy [^\]]+\]?')
1252
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001253_sys_version_cache = {}
1254
1255def _sys_version(sys_version=None):
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001256
1257 """ Returns a parsed version of Python's sys.version as tuple
Benjamin Peterson5f28b7b2009-03-26 21:49:58 +00001258 (name, version, branch, revision, buildno, builddate, compiler)
1259 referring to the Python implementation name, version, branch,
1260 revision, build number, build date/time as string and the compiler
1261 identification string.
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001262
1263 Note that unlike the Python sys.version, the returned value
1264 for the Python version will always include the patchlevel (it
1265 defaults to '.0').
1266
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001267 The function returns empty strings for tuple entries that
1268 cannot be determined.
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001269
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001270 sys_version may be given to parse an alternative version
1271 string, e.g. if the version was read from a different Python
1272 interpreter.
1273
1274 """
1275 # Get the Python version
1276 if sys_version is None:
1277 sys_version = sys.version
1278
1279 # Try the cache first
1280 result = _sys_version_cache.get(sys_version, None)
1281 if result is not None:
1282 return result
1283
1284 # Parse it
1285 if sys_version[:10] == 'IronPython':
1286 # IronPython
1287 name = 'IronPython'
1288 match = _ironpython_sys_version_parser.match(sys_version)
1289 if match is None:
1290 raise ValueError(
1291 'failed to parse IronPython sys.version: %s' %
1292 repr(sys_version))
1293 version, alt_version, compiler = match.groups()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001294 buildno = ''
1295 builddate = ''
1296
1297 elif sys.platform[:4] == 'java':
1298 # Jython
1299 name = 'Jython'
Benjamin Petersone549ead2009-03-28 21:42:05 +00001300 match = _sys_version_parser.match(sys_version)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001301 if match is None:
1302 raise ValueError(
1303 'failed to parse Jython sys.version: %s' %
1304 repr(sys_version))
Benjamin Petersone549ead2009-03-28 21:42:05 +00001305 version, buildno, builddate, buildtime, _ = match.groups()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001306 compiler = sys.platform
Benjamin Petersone549ead2009-03-28 21:42:05 +00001307
1308 elif "PyPy" in sys_version:
1309 # PyPy
1310 name = "PyPy"
1311 match = _pypy_sys_version_parser.match(sys_version)
1312 if match is None:
1313 raise ValueError("failed to parse PyPy sys.version: %s" %
1314 repr(sys_version))
1315 version, buildno, builddate, buildtime = match.groups()
1316 compiler = ""
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001317
1318 else:
1319 # CPython
1320 match = _sys_version_parser.match(sys_version)
1321 if match is None:
1322 raise ValueError(
1323 'failed to parse CPython sys.version: %s' %
1324 repr(sys_version))
1325 version, buildno, builddate, buildtime, compiler = \
1326 match.groups()
Benjamin Petersone549ead2009-03-28 21:42:05 +00001327 name = 'CPython'
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001328 builddate = builddate + ' ' + buildtime
1329
Georg Brandl82562422011-03-05 21:09:22 +01001330 if hasattr(sys, '_mercurial'):
1331 _, branch, revision = sys._mercurial
1332 elif hasattr(sys, 'subversion'):
Benjamin Petersone549ead2009-03-28 21:42:05 +00001333 # sys.subversion was added in Python 2.5
1334 _, branch, revision = sys.subversion
1335 else:
1336 branch = ''
1337 revision = ''
1338
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001339 # Add the patchlevel version if missing
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001340 l = version.split('.')
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001341 if len(l) == 2:
1342 l.append('0')
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001343 version = '.'.join(l)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001344
1345 # Build and cache the result
1346 result = (name, version, branch, revision, buildno, builddate, compiler)
1347 _sys_version_cache[sys_version] = result
1348 return result
1349
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001350def python_implementation():
1351
1352 """ Returns a string identifying the Python implementation.
1353
1354 Currently, the following implementations are identified:
Ezio Melottif16898b2011-05-04 18:37:50 +03001355 'CPython' (C implementation of Python),
1356 'IronPython' (.NET implementation of Python),
1357 'Jython' (Java implementation of Python),
1358 'PyPy' (Python implementation of Python).
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001359
1360 """
1361 return _sys_version()[0]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001362
1363def python_version():
1364
1365 """ Returns the Python version as string 'major.minor.patchlevel'
1366
1367 Note that unlike the Python sys.version, the returned value
1368 will always include the patchlevel (it defaults to 0).
1369
1370 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001371 return _sys_version()[1]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001372
1373def python_version_tuple():
1374
1375 """ Returns the Python version as tuple (major, minor, patchlevel)
1376 of strings.
1377
1378 Note that unlike the Python sys.version, the returned value
1379 will always include the patchlevel (it defaults to 0).
1380
1381 """
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001382 return tuple(_sys_version()[1].split('.'))
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001383
1384def python_branch():
1385
1386 """ Returns a string identifying the Python implementation
1387 branch.
1388
1389 For CPython this is the Subversion branch from which the
1390 Python binary was built.
1391
1392 If not available, an empty string is returned.
1393
1394 """
Thomas Wouters9fe394c2007-02-05 01:24:16 +00001395
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001396 return _sys_version()[2]
1397
1398def python_revision():
1399
1400 """ Returns a string identifying the Python implementation
1401 revision.
1402
1403 For CPython this is the Subversion revision from which the
1404 Python binary was built.
1405
1406 If not available, an empty string is returned.
1407
1408 """
1409 return _sys_version()[3]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001410
1411def python_build():
1412
1413 """ Returns a tuple (buildno, builddate) stating the Python
1414 build number and date as strings.
1415
1416 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001417 return _sys_version()[4:6]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001418
1419def python_compiler():
1420
1421 """ Returns a string identifying the compiler used for compiling
1422 Python.
1423
1424 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001425 return _sys_version()[6]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001426
1427### The Opus Magnum of platform strings :-)
1428
Marc-André Lemburg91e83e22004-03-25 18:35:12 +00001429_platform_cache = {}
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001430
1431def platform(aliased=0, terse=0):
1432
1433 """ Returns a single string identifying the underlying platform
1434 with as much useful information as possible (but no more :).
Tim Peters0eadaac2003-04-24 16:02:54 +00001435
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001436 The output is intended to be human readable rather than
1437 machine parseable. It may look different on different
1438 platforms and this is intended.
1439
1440 If "aliased" is true, the function will use aliases for
1441 various platforms that report system names which differ from
1442 their common names, e.g. SunOS will be reported as
1443 Solaris. The system_alias() function is used to implement
1444 this.
1445
1446 Setting terse to true causes the function to return only the
1447 absolute minimum information needed to identify the platform.
1448
1449 """
Marc-André Lemburg91e83e22004-03-25 18:35:12 +00001450 result = _platform_cache.get((aliased, terse), None)
1451 if result is not None:
1452 return result
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001453
1454 # Get uname information and then apply platform specific cosmetics
1455 # to it...
1456 system,node,release,version,machine,processor = uname()
1457 if machine == processor:
1458 processor = ''
1459 if aliased:
1460 system,release,version = system_alias(system,release,version)
1461
1462 if system == 'Windows':
1463 # MS platforms
1464 rel,vers,csd,ptype = win32_ver(version)
1465 if terse:
1466 platform = _platform(system,release)
1467 else:
1468 platform = _platform(system,release,version,csd)
1469
1470 elif system in ('Linux',):
1471 # Linux based systems
1472 distname,distversion,distid = dist('')
1473 if distname and not terse:
1474 platform = _platform(system,release,machine,processor,
1475 'with',
1476 distname,distversion,distid)
1477 else:
1478 # If the distribution name is unknown check for libc vs. glibc
1479 libcname,libcversion = libc_ver(sys.executable)
1480 platform = _platform(system,release,machine,processor,
1481 'with',
1482 libcname+libcversion)
1483 elif system == 'Java':
1484 # Java platforms
1485 r,v,vminfo,(os_name,os_version,os_arch) = java_ver()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001486 if terse or not os_name:
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001487 platform = _platform(system,release,version)
1488 else:
1489 platform = _platform(system,release,version,
1490 'on',
1491 os_name,os_version,os_arch)
1492
1493 elif system == 'MacOS':
1494 # MacOS platforms
1495 if terse:
1496 platform = _platform(system,release)
1497 else:
1498 platform = _platform(system,release,machine)
1499
1500 else:
1501 # Generic handler
1502 if terse:
1503 platform = _platform(system,release)
1504 else:
1505 bits,linkage = architecture(sys.executable)
1506 platform = _platform(system,release,machine,processor,bits,linkage)
Tim Peters0eadaac2003-04-24 16:02:54 +00001507
Marc-André Lemburg91e83e22004-03-25 18:35:12 +00001508 _platform_cache[(aliased, terse)] = platform
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001509 return platform
1510
1511### Command line interface
1512
1513if __name__ == '__main__':
1514 # Default is to print the aliased verbose platform string
Tim Peters0eadaac2003-04-24 16:02:54 +00001515 terse = ('terse' in sys.argv or '--terse' in sys.argv)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001516 aliased = (not 'nonaliased' in sys.argv and not '--nonaliased' in sys.argv)
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001517 print(platform(aliased,terse))
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001518 sys.exit(0)