blob: 780301d264fa0c6ff44e5d0de6cddbdcfdb2299d [file] [log] [blame]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001#!/usr/bin/env python
2
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 Petersonf3d7dbe2009-10-04 14:54:52 +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#
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +000035# 1.0.6 - added linux_distribution()
36# 1.0.5 - fixed Java support to allow running the module on Jython
37# 1.0.4 - added IronPython support
Marc-André Lemburgcdc79232004-06-19 17:17:00 +000038# 1.0.3 - added normalization of Windows system name
Marc-André Lemburg91e83e22004-03-25 18:35:12 +000039# 1.0.2 - added more Windows support
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +000040# 1.0.1 - reformatted to make doc.py happy
Marc-André Lemburg246d8472003-04-24 11:36:11 +000041# 1.0.0 - reformatted a bit and checked into Python CVS
42# 0.8.0 - added sys.version parser and various new access
43# APIs (python_version(), python_compiler(), etc.)
44# 0.7.2 - fixed architecture() to use sizeof(pointer) where available
45# 0.7.1 - added support for Caldera OpenLinux
46# 0.7.0 - some fixes for WinCE; untabified the source file
47# 0.6.2 - support for OpenVMS - requires version 1.5.2-V006 or higher and
48# vms_lib.getsyi() configured
49# 0.6.1 - added code to prevent 'uname -p' on platforms which are
50# known not to support it
51# 0.6.0 - fixed win32_ver() to hopefully work on Win95,98,NT and Win2k;
52# did some cleanup of the interfaces - some APIs have changed
53# 0.5.5 - fixed another type in the MacOS code... should have
54# used more coffee today ;-)
55# 0.5.4 - fixed a few typos in the MacOS code
56# 0.5.3 - added experimental MacOS support; added better popen()
57# workarounds in _syscmd_ver() -- still not 100% elegant
58# though
59# 0.5.2 - fixed uname() to return '' instead of 'unknown' in all
60# return values (the system uname command tends to return
61# 'unknown' instead of just leaving the field emtpy)
62# 0.5.1 - included code for slackware dist; added exception handlers
63# to cover up situations where platforms don't have os.popen
64# (e.g. Mac) or fail on socket.gethostname(); fixed libc
65# detection RE
66# 0.5.0 - changed the API names referring to system commands to *syscmd*;
67# added java_ver(); made syscmd_ver() a private
68# API (was system_ver() in previous versions) -- use uname()
69# instead; extended the win32_ver() to also return processor
70# type information
71# 0.4.0 - added win32_ver() and modified the platform() output for WinXX
72# 0.3.4 - fixed a bug in _follow_symlinks()
73# 0.3.3 - fixed popen() and "file" command invokation bugs
74# 0.3.2 - added architecture() API and support for it in platform()
75# 0.3.1 - fixed syscmd_ver() RE to support Windows NT
76# 0.3.0 - added system alias support
77# 0.2.3 - removed 'wince' again... oh well.
78# 0.2.2 - added 'wince' to syscmd_ver() supported platforms
79# 0.2.1 - added cache logic and changed the platform string format
80# 0.2.0 - changed the API to use functions instead of module globals
81# since some action take too long to be run on module import
82# 0.1.0 - first release
83#
84# You can always get the latest version of this module at:
85#
86# http://www.egenix.com/files/python/platform.py
87#
88# If that URL should fail, try contacting the author.
89
90__copyright__ = """
91 Copyright (c) 1999-2000, Marc-Andre Lemburg; mailto:mal@lemburg.com
Benjamin Petersonffeda292010-01-09 18:48:46 +000092 Copyright (c) 2000-2010, eGenix.com Software GmbH; mailto:info@egenix.com
Marc-André Lemburg246d8472003-04-24 11:36:11 +000093
94 Permission to use, copy, modify, and distribute this software and its
95 documentation for any purpose and without fee or royalty is hereby granted,
96 provided that the above copyright notice appear in all copies and that
97 both that copyright notice and this permission notice appear in
98 supporting documentation or portions thereof, including modifications,
99 that you make.
100
101 EGENIX.COM SOFTWARE GMBH DISCLAIMS ALL WARRANTIES WITH REGARD TO
102 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
103 FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
104 INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
105 FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
106 NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
107 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE !
108
109"""
110
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000111__version__ = '1.0.6'
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000112
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000113import sys, os, re
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000114
115### Platform specific APIs
116
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000117_libc_search = re.compile(r'(__libc_init)'
118 '|'
Tim Peters0eadaac2003-04-24 16:02:54 +0000119 '(GLIBC_([0-9.]+))'
120 '|'
Antoine Pitroufd036452008-08-19 17:56:33 +0000121 '(libc(_\w+)?\.so(?:\.(\d[0-9.]*))?)', re.ASCII)
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000122
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000123def libc_ver(executable=sys.executable,lib='',version='',
124
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000125 chunksize=2048):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000126
Brett Cannon8ab27df2003-08-05 03:52:04 +0000127 """ Tries to determine the libc version that the file executable
128 (which defaults to the Python interpreter) is linked against.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000129
130 Returns a tuple of strings (lib,version) which default to the
131 given parameters in case the lookup fails.
132
133 Note that the function has intimate knowledge of how different
Brett Cannon8ab27df2003-08-05 03:52:04 +0000134 libc versions add symbols to the executable and thus is probably
135 only useable for executables compiled using gcc.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000136
137 The file is read and scanned in chunks of chunksize bytes.
138
139 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000140 if hasattr(os.path, 'realpath'):
141 # Python 2.2 introduced os.path.realpath(); it is used
142 # here to work around problems with Cygwin not being
143 # able to open symlinks for reading
144 executable = os.path.realpath(executable)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000145 f = open(executable,'rb')
Walter Dörwaldc3b6ac72007-06-07 19:26:24 +0000146 binary = f.read(chunksize).decode('latin-1')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000147 pos = 0
148 while 1:
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000149 m = _libc_search.search(binary,pos)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000150 if not m:
Walter Dörwaldc3b6ac72007-06-07 19:26:24 +0000151 binary = f.read(chunksize).decode('latin-1')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000152 if not binary:
153 break
154 pos = 0
155 continue
156 libcinit,glibc,glibcversion,so,threads,soversion = m.groups()
157 if libcinit and not lib:
158 lib = 'libc'
159 elif glibc:
160 if lib != 'glibc':
161 lib = 'glibc'
162 version = glibcversion
163 elif glibcversion > version:
164 version = glibcversion
165 elif so:
166 if lib != 'glibc':
167 lib = 'libc'
168 if soversion > version:
169 version = soversion
170 if threads and version[-len(threads):] != threads:
171 version = version + threads
172 pos = m.end()
173 f.close()
174 return lib,version
175
176def _dist_try_harder(distname,version,id):
177
Tim Peters0eadaac2003-04-24 16:02:54 +0000178 """ Tries some special tricks to get the distribution
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000179 information in case the default method fails.
180
181 Currently supports older SuSE Linux, Caldera OpenLinux and
182 Slackware Linux distributions.
183
184 """
185 if os.path.exists('/var/adm/inst-log/info'):
186 # SuSE Linux stores distribution information in that file
187 info = open('/var/adm/inst-log/info').readlines()
188 distname = 'SuSE'
189 for line in info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000190 tv = line.split()
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000191 if len(tv) == 2:
192 tag,value = tv
193 else:
194 continue
195 if tag == 'MIN_DIST_VERSION':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000196 version = value.strip()
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000197 elif tag == 'DIST_IDENT':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000198 values = value.split('-')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000199 id = values[2]
200 return distname,version,id
201
202 if os.path.exists('/etc/.installed'):
203 # Caldera OpenLinux has some infos in that file (thanks to Colin Kong)
204 info = open('/etc/.installed').readlines()
205 for line in info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000206 pkg = line.split('-')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000207 if len(pkg) >= 2 and pkg[0] == 'OpenLinux':
208 # XXX does Caldera support non Intel platforms ? If yes,
209 # where can we find the needed id ?
210 return 'OpenLinux',pkg[1],id
211
212 if os.path.isdir('/usr/lib/setup'):
213 # Check for slackware verson tag file (thanks to Greg Andruk)
214 verfiles = os.listdir('/usr/lib/setup')
Guido van Rossum843c7342004-05-04 18:18:59 +0000215 for n in range(len(verfiles)-1, -1, -1):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000216 if verfiles[n][:14] != 'slack-version-':
217 del verfiles[n]
218 if verfiles:
219 verfiles.sort()
220 distname = 'slackware'
221 version = verfiles[-1][14:]
222 return distname,version,id
223
224 return distname,version,id
225
Antoine Pitroufd036452008-08-19 17:56:33 +0000226_release_filename = re.compile(r'(\w+)[-_](release|version)', re.ASCII)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000227_lsb_release_version = re.compile(r'(.+)'
228 ' release '
229 '([\d.]+)'
Antoine Pitroufd036452008-08-19 17:56:33 +0000230 '[^(]*(?:\((.+)\))?', re.ASCII)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000231_release_version = re.compile(r'([^0-9]+)'
232 '(?: release )?'
233 '([\d.]+)'
Antoine Pitroufd036452008-08-19 17:56:33 +0000234 '[^(]*(?:\((.+)\))?', re.ASCII)
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000235
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000236# See also http://www.novell.com/coolsolutions/feature/11251.html
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000237# and http://linuxmafia.com/faq/Admin/release-files.html
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000238# and http://data.linux-ntfs.org/rpm/whichrpm
239# and http://www.die.net/doc/linux/man/man1/lsb_release.1.html
Marc-André Lemburg380f4172005-11-07 16:11:02 +0000240
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000241_supported_dists = (
242 'SuSE', 'debian', 'fedora', 'redhat', 'centos',
243 'mandrake', 'mandriva', 'rocks', 'slackware', 'yellowdog', 'gentoo',
244 'UnitedLinux', 'turbolinux')
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000245
246def _parse_release_file(firstline):
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000247
Benjamin Peterson79e0b812010-01-25 03:40:53 +0000248 # Default to empty 'version' and 'id' strings. Both defaults are used
249 # when 'firstline' is empty. 'id' defaults to empty when an id can not
250 # be deduced.
251 version = ''
252 id = ''
253
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000254 # Parse the first line
255 m = _lsb_release_version.match(firstline)
256 if m is not None:
257 # LSB format: "distro release x.x (codename)"
258 return tuple(m.groups())
259
260 # Pre-LSB format: "distro x.x (codename)"
261 m = _release_version.match(firstline)
262 if m is not None:
263 return tuple(m.groups())
264
265 # Unkown format... take the first two words
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000266 l = firstline.strip().split()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000267 if l:
268 version = l[0]
269 if len(l) > 1:
270 id = l[1]
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000271 return '', version, id
272
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000273def linux_distribution(distname='', version='', id='',
274
275 supported_dists=_supported_dists,
276 full_distribution_name=1):
277
278 """ Tries to determine the name of the Linux OS distribution name.
279
280 The function first looks for a distribution release file in
281 /etc and then reverts to _dist_try_harder() in case no
282 suitable files are found.
283
284 supported_dists may be given to define the set of Linux
285 distributions to look for. It defaults to a list of currently
286 supported Linux distributions identified by their release file
287 name.
288
289 If full_distribution_name is true (default), the full
290 distribution read from the OS is returned. Otherwise the short
291 name taken from supported_dists is used.
292
293 Returns a tuple (distname,version,id) which default to the
294 args given as parameters.
295
296 """
297 try:
298 etc = os.listdir('/etc')
299 except os.error:
300 # Probably not a Unix system
301 return distname,version,id
302 etc.sort()
303 for file in etc:
304 m = _release_filename.match(file)
305 if m is not None:
306 _distname,dummy = m.groups()
307 if _distname in supported_dists:
308 distname = _distname
309 break
310 else:
311 return _dist_try_harder(distname,version,id)
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000312
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000313 # Read the first line
314 f = open('/etc/'+file, 'r')
315 firstline = f.readline()
316 f.close()
317 _distname, _version, _id = _parse_release_file(firstline)
318
319 if _distname and full_distribution_name:
320 distname = _distname
321 if _version:
322 version = _version
323 if _id:
324 id = _id
325 return distname, version, id
326
327# To maintain backwards compatibility:
Thomas Wouters9fe394c2007-02-05 01:24:16 +0000328
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000329def dist(distname='',version='',id='',
330
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000331 supported_dists=_supported_dists):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000332
Brett Cannon8ab27df2003-08-05 03:52:04 +0000333 """ Tries to determine the name of the Linux OS distribution name.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000334
335 The function first looks for a distribution release file in
336 /etc and then reverts to _dist_try_harder() in case no
337 suitable files are found.
338
Brett Cannon8ab27df2003-08-05 03:52:04 +0000339 Returns a tuple (distname,version,id) which default to the
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000340 args given as parameters.
341
342 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000343 return linux_distribution(distname, version, id,
344 supported_dists=supported_dists,
345 full_distribution_name=0)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000346
347class _popen:
348
349 """ Fairly portable (alternative) popen implementation.
350
351 This is mostly needed in case os.popen() is not available, or
352 doesn't work as advertised, e.g. in Win9X GUI programs like
353 PythonWin or IDLE.
354
355 Writing to the pipe is currently not supported.
356
357 """
358 tmpfile = ''
359 pipe = None
360 bufsize = None
361 mode = 'r'
362
363 def __init__(self,cmd,mode='r',bufsize=None):
364
365 if mode != 'r':
Collin Winterce36ad82007-08-30 01:19:48 +0000366 raise ValueError('popen()-emulation only supports read mode')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000367 import tempfile
368 self.tmpfile = tmpfile = tempfile.mktemp()
369 os.system(cmd + ' > %s' % tmpfile)
370 self.pipe = open(tmpfile,'rb')
371 self.bufsize = bufsize
372 self.mode = mode
373
374 def read(self):
375
376 return self.pipe.read()
377
378 def readlines(self):
379
380 if self.bufsize is not None:
381 return self.pipe.readlines()
382
383 def close(self,
384
385 remove=os.unlink,error=os.error):
386
387 if self.pipe:
388 rc = self.pipe.close()
389 else:
390 rc = 255
391 if self.tmpfile:
392 try:
393 remove(self.tmpfile)
394 except error:
395 pass
396 return rc
397
398 # Alias
399 __del__ = close
400
401def popen(cmd, mode='r', bufsize=None):
402
403 """ Portable popen() interface.
404 """
405 # Find a working popen implementation preferring win32pipe.popen
406 # over os.popen over _popen
407 popen = None
408 if os.environ.get('OS','') == 'Windows_NT':
409 # On NT win32pipe should work; on Win9x it hangs due to bugs
410 # in the MS C lib (see MS KnowledgeBase article Q150956)
411 try:
412 import win32pipe
413 except ImportError:
414 pass
415 else:
416 popen = win32pipe.popen
417 if popen is None:
418 if hasattr(os,'popen'):
419 popen = os.popen
420 # Check whether it works... it doesn't in GUI programs
421 # on Windows platforms
422 if sys.platform == 'win32': # XXX Others too ?
423 try:
424 popen('')
425 except os.error:
426 popen = _popen
427 else:
428 popen = _popen
429 if bufsize is None:
430 return popen(cmd,mode)
431 else:
432 return popen(cmd,mode,bufsize)
433
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000434def _norm_version(version, build=''):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000435
Brett Cannon8ab27df2003-08-05 03:52:04 +0000436 """ Normalize the version and build strings and return a single
Walter Dörwalde5a7fad2005-11-21 17:01:27 +0000437 version string using the format major.minor.build (or patchlevel).
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000438 """
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000439 l = version.split('.')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000440 if build:
441 l.append(build)
442 try:
443 ints = map(int,l)
444 except ValueError:
445 strings = l
446 else:
Neal Norwitz78a70bd2007-08-30 06:16:26 +0000447 strings = list(map(str,ints))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000448 version = '.'.join(strings[:3])
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000449 return version
450
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000451_ver_output = re.compile(r'(?:([\w ]+) ([\w.]+) '
452 '.*'
Antoine Pitroufd036452008-08-19 17:56:33 +0000453 'Version ([\d.]+))', re.ASCII)
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000454
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000455def _syscmd_ver(system='', release='', version='',
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000456
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000457 supported_platforms=('win32','win16','dos','os2')):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000458
459 """ Tries to figure out the OS version used and returns
460 a tuple (system,release,version).
Tim Peters0eadaac2003-04-24 16:02:54 +0000461
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000462 It uses the "ver" shell command for this which is known
463 to exists on Windows, DOS and OS/2. XXX Others too ?
464
465 In case this fails, the given parameters are used as
466 defaults.
467
468 """
469 if sys.platform not in supported_platforms:
470 return system,release,version
471
472 # Try some common cmd strings
473 for cmd in ('ver','command /c ver','cmd /c ver'):
474 try:
475 pipe = popen(cmd)
476 info = pipe.read()
477 if pipe.close():
Collin Winterce36ad82007-08-30 01:19:48 +0000478 raise os.error('command failed')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000479 # XXX How can I supress shell errors from being written
480 # to stderr ?
Guido van Rossumb940e112007-01-10 16:19:56 +0000481 except os.error as why:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000482 #print 'Command %s failed: %s' % (cmd,why)
483 continue
Guido van Rossumb940e112007-01-10 16:19:56 +0000484 except IOError as why:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000485 #print 'Command %s failed: %s' % (cmd,why)
486 continue
487 else:
488 break
489 else:
490 return system,release,version
491
492 # Parse the output
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000493 info = info.strip()
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000494 m = _ver_output.match(info)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000495 if m is not None:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000496 system,release,version = m.groups()
497 # Strip trailing dots from version and release
498 if release[-1] == '.':
499 release = release[:-1]
500 if version[-1] == '.':
501 version = version[:-1]
502 # Normalize the version and build strings (eliminating additional
503 # zeros)
504 version = _norm_version(version)
505 return system,release,version
506
507def _win32_getvalue(key,name,default=''):
508
509 """ Read a value for name from the registry key.
510
511 In case this fails, default is returned.
512
513 """
Christian Heimes02781dc2008-03-21 01:11:52 +0000514 try:
515 # Use win32api if available
516 from win32api import RegQueryValueEx
517 except ImportError:
Georg Brandl38feaf02008-05-25 07:45:51 +0000518 # On Python 2.0 and later, emulate using winreg
519 import winreg
520 RegQueryValueEx = winreg.QueryValueEx
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000521 try:
522 return RegQueryValueEx(key,name)
523 except:
524 return default
525
526def win32_ver(release='',version='',csd='',ptype=''):
527
528 """ Get additional version information from the Windows Registry
529 and return a tuple (version,csd,ptype) referring to version
530 number, CSD level and OS type (multi/single
531 processor).
532
533 As a hint: ptype returns 'Uniprocessor Free' on single
534 processor NT machines and 'Multiprocessor Free' on multi
535 processor machines. The 'Free' refers to the OS version being
536 free of debugging code. It could also state 'Checked' which
537 means the OS version uses debugging code, i.e. code that
538 checks arguments, ranges, etc. (Thomas Heller).
539
Christian Heimes02781dc2008-03-21 01:11:52 +0000540 Note: this function works best with Mark Hammond's win32
541 package installed, but also on Python 2.3 and later. It
542 obviously only runs on Win32 compatible platforms.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000543
544 """
545 # XXX Is there any way to find out the processor type on WinXX ?
546 # XXX Is win32 available on Windows CE ?
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000547 #
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000548 # Adapted from code posted by Karl Putland to comp.lang.python.
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000549 #
550 # The mappings between reg. values and release names can be found
551 # here: http://msdn.microsoft.com/library/en-us/sysinfo/base/osversioninfo_str.asp
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000552
553 # Import the needed APIs
554 try:
555 import win32api
Christian Heimes02781dc2008-03-21 01:11:52 +0000556 from win32api import RegQueryValueEx, RegOpenKeyEx, \
557 RegCloseKey, GetVersionEx
558 from win32con import HKEY_LOCAL_MACHINE, VER_PLATFORM_WIN32_NT, \
559 VER_PLATFORM_WIN32_WINDOWS, VER_NT_WORKSTATION
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000560 except ImportError:
Christian Heimes02781dc2008-03-21 01:11:52 +0000561 # Emulate the win32api module using Python APIs
562 try:
563 sys.getwindowsversion
564 except AttributeError:
565 # No emulation possible, so return the defaults...
566 return release,version,csd,ptype
567 else:
Georg Brandl38feaf02008-05-25 07:45:51 +0000568 # Emulation using winreg (added in Python 2.0) and
Christian Heimes02781dc2008-03-21 01:11:52 +0000569 # sys.getwindowsversion() (added in Python 2.3)
Georg Brandl38feaf02008-05-25 07:45:51 +0000570 import winreg
Christian Heimes02781dc2008-03-21 01:11:52 +0000571 GetVersionEx = sys.getwindowsversion
Georg Brandl38feaf02008-05-25 07:45:51 +0000572 RegQueryValueEx = winreg.QueryValueEx
573 RegOpenKeyEx = winreg.OpenKeyEx
574 RegCloseKey = winreg.CloseKey
575 HKEY_LOCAL_MACHINE = winreg.HKEY_LOCAL_MACHINE
Christian Heimes02781dc2008-03-21 01:11:52 +0000576 VER_PLATFORM_WIN32_WINDOWS = 1
577 VER_PLATFORM_WIN32_NT = 2
578 VER_NT_WORKSTATION = 1
Brian Curtine7837352010-05-06 03:09:10 +0000579 VER_NT_SERVER = 3
580 REG_SZ = 1
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000581
582 # Find out the registry key and some general version infos
Brian Curtine7837352010-05-06 03:09:10 +0000583 winver = GetVersionEx()
584 maj,min,buildno,plat,csd = winver
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000585 version = '%i.%i.%i' % (maj,min,buildno & 0xFFFF)
Brian Curtine7837352010-05-06 03:09:10 +0000586 if hasattr(winver, "service_pack"):
587 if winver.service_pack != "":
588 csd = 'SP%s' % winver.service_pack_major
589 else:
590 if csd[:13] == 'Service Pack ':
591 csd = 'SP' + csd[13:]
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000592 if plat == VER_PLATFORM_WIN32_WINDOWS:
593 regkey = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion'
594 # Try to guess the release name
595 if maj == 4:
596 if min == 0:
597 release = '95'
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000598 elif min == 10:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000599 release = '98'
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000600 elif min == 90:
601 release = 'Me'
602 else:
603 release = 'postMe'
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000604 elif maj == 5:
605 release = '2000'
606 elif plat == VER_PLATFORM_WIN32_NT:
607 regkey = 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion'
608 if maj <= 4:
609 release = 'NT'
610 elif maj == 5:
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000611 if min == 0:
612 release = '2000'
613 elif min == 1:
614 release = 'XP'
615 elif min == 2:
616 release = '2003Server'
617 else:
618 release = 'post2003'
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000619 elif maj == 6:
Brian Curtine7837352010-05-06 03:09:10 +0000620 if hasattr(winver, "product_type"):
621 product_type = winver.product_type
622 else:
623 product_type = VER_NT_WORKSTATION
624 # Without an OSVERSIONINFOEX capable sys.getwindowsversion(),
625 # or help from the registry, we cannot properly identify
626 # non-workstation versions.
Christian Heimes02781dc2008-03-21 01:11:52 +0000627 try:
Brian Curtine7837352010-05-06 03:09:10 +0000628 key = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey)
629 name, type = RegQueryValueEx(key, "ProductName")
630 # Discard any type that isn't REG_SZ
631 if type == REG_SZ and name.find("Server") != -1:
632 product_type = VER_NT_SERVER
633 except WindowsError:
634 # Use default of VER_NT_WORKSTATION
635 pass
636
637 if min == 0:
638 if product_type == VER_NT_WORKSTATION:
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000639 release = 'Vista'
640 else:
Brian Curtine7837352010-05-06 03:09:10 +0000641 release = '2008Server'
642 elif min == 1:
643 if product_type == VER_NT_WORKSTATION:
644 release = '7'
645 else:
646 release = '2008ServerR2'
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000647 else:
648 release = 'post2008Server'
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000649 else:
650 if not release:
651 # E.g. Win3.1 with win32s
652 release = '%i.%i' % (maj,min)
653 return release,version,csd,ptype
654
655 # Open the registry key
656 try:
Christian Heimes02781dc2008-03-21 01:11:52 +0000657 keyCurVer = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000658 # Get a value to make sure the key exists...
Christian Heimes02781dc2008-03-21 01:11:52 +0000659 RegQueryValueEx(keyCurVer, 'SystemRoot')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000660 except:
661 return release,version,csd,ptype
Tim Peters0eadaac2003-04-24 16:02:54 +0000662
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000663 # Parse values
664 #subversion = _win32_getvalue(keyCurVer,
665 # 'SubVersionNumber',
666 # ('',1))[0]
667 #if subversion:
668 # release = release + subversion # 95a, 95b, etc.
669 build = _win32_getvalue(keyCurVer,
670 'CurrentBuildNumber',
671 ('',1))[0]
672 ptype = _win32_getvalue(keyCurVer,
673 'CurrentType',
674 (ptype,1))[0]
675
676 # Normalize version
677 version = _norm_version(version,build)
678
679 # Close key
680 RegCloseKey(keyCurVer)
681 return release,version,csd,ptype
682
683def _mac_ver_lookup(selectors,default=None):
684
Benjamin Petersonebacd262008-05-29 21:09:51 +0000685 from _gestalt import gestalt
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000686 l = []
687 append = l.append
688 for selector in selectors:
689 try:
690 append(gestalt(selector))
Benjamin Petersonebacd262008-05-29 21:09:51 +0000691 except (RuntimeError, OSError):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000692 append(default)
693 return l
694
695def _bcd2str(bcd):
696
697 return hex(bcd)[2:]
698
Ronald Oussoren7180d482010-07-23 12:36:59 +0000699def _mac_ver_gestalt():
700 """
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000701 Thanks to Mark R. Levinson for mailing documentation links and
702 code examples for this function. Documentation for the
703 gestalt() API is available online at:
704
705 http://www.rgaros.nl/gestalt/
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000706 """
707 # Check whether the version info module is available
708 try:
Benjamin Petersonebacd262008-05-29 21:09:51 +0000709 import _gestalt
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000710 except ImportError:
Ronald Oussoren7180d482010-07-23 12:36:59 +0000711 return None
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000712 # Get the infos
Ronald Oussorene61b21e2010-02-07 11:34:48 +0000713 sysv, sysa = _mac_ver_lookup(('sysv','sysa'))
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000714 # Decode the infos
715 if sysv:
716 major = (sysv & 0xFF00) >> 8
717 minor = (sysv & 0x00F0) >> 4
718 patch = (sysv & 0x000F)
Christian Heimese4ca8152008-05-08 17:18:53 +0000719
720 if (major, minor) >= (10, 4):
721 # the 'sysv' gestald cannot return patchlevels
722 # higher than 9. Apple introduced 3 new
723 # gestalt codes in 10.4 to deal with this
724 # issue (needed because patch levels can
725 # run higher than 9, such as 10.4.11)
726 major,minor,patch = _mac_ver_lookup(('sys1','sys2','sys3'))
727 release = '%i.%i.%i' %(major, minor, patch)
728 else:
729 release = '%s.%i.%i' % (_bcd2str(major),minor,patch)
Benjamin Peterson856ff5f2008-05-29 21:22:40 +0000730
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000731 if sysa:
Tim Peters0eadaac2003-04-24 16:02:54 +0000732 machine = {0x1: '68k',
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000733 0x2: 'PowerPC',
734 0xa: 'i386'}.get(sysa,'')
Ronald Oussoren7180d482010-07-23 12:36:59 +0000735
736 return release,versioninfo,machine
737
738def _mac_ver_xml():
739 fn = '/System/Library/CoreServices/SystemVersion.plist'
740 if not os.path.exists(fn):
741 return None
742
743 try:
744 import plistlib
745 except ImportError:
746 return None
747
748 pl = plistlib.readPlist(fn)
749 release = pl['ProductVersion']
750 versioninfo=('', '', '')
751 machine = os.uname()[4]
Ronald Oussoren8f5a5122010-08-03 07:43:36 +0000752 if machine in ('ppc', 'Power Macintosh'):
Ronald Oussoren7180d482010-07-23 12:36:59 +0000753 # for compatibility with the gestalt based code
754 machine = 'PowerPC'
755
756 return release,versioninfo,machine
757
758
759def mac_ver(release='',versioninfo=('','',''),machine=''):
760
761 """ Get MacOS version information and return it as tuple (release,
762 versioninfo, machine) with versioninfo being a tuple (version,
763 dev_stage, non_release_version).
764
765 Entries which cannot be determined are set to the paramter values
766 which default to ''. All tuple entries are strings.
767 """
768
769 # First try reading the information from an XML file which should
770 # always be present
771 info = _mac_ver_xml()
772 if info is not None:
773 return info
774
775 # If that doesn't work for some reason fall back to reading the
776 # information using gestalt calls.
777 info = _mac_ver_gestalt()
778 if info is not None:
779 return info
780
781 # If that also doesn't work return the default values
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000782 return release,versioninfo,machine
783
Neal Norwitz9b924c62003-06-29 04:17:45 +0000784def _java_getprop(name,default):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000785
786 from java.lang import System
787 try:
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000788 value = System.getProperty(name)
789 if value is None:
790 return default
791 return value
792 except AttributeError:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000793 return default
794
795def java_ver(release='',vendor='',vminfo=('','',''),osinfo=('','','')):
Tim Peters0eadaac2003-04-24 16:02:54 +0000796
Brett Cannon8ab27df2003-08-05 03:52:04 +0000797 """ Version interface for Jython.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000798
799 Returns a tuple (release,vendor,vminfo,osinfo) with vminfo being
800 a tuple (vm_name,vm_release,vm_vendor) and osinfo being a
801 tuple (os_name,os_version,os_arch).
802
803 Values which cannot be determined are set to the defaults
804 given as parameters (which all default to '').
805
806 """
807 # Import the needed APIs
808 try:
809 import java.lang
810 except ImportError:
811 return release,vendor,vminfo,osinfo
812
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000813 vendor = _java_getprop('java.vendor', vendor)
814 release = _java_getprop('java.version', release)
815 vm_name, vm_release, vm_vendor = vminfo
816 vm_name = _java_getprop('java.vm.name', vm_name)
817 vm_vendor = _java_getprop('java.vm.vendor', vm_vendor)
818 vm_release = _java_getprop('java.vm.version', vm_release)
819 vminfo = vm_name, vm_release, vm_vendor
820 os_name, os_version, os_arch = osinfo
821 os_arch = _java_getprop('java.os.arch', os_arch)
822 os_name = _java_getprop('java.os.name', os_name)
823 os_version = _java_getprop('java.os.version', os_version)
824 osinfo = os_name, os_version, os_arch
Tim Peters0eadaac2003-04-24 16:02:54 +0000825
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000826 return release, vendor, vminfo, osinfo
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000827
828### System name aliasing
829
830def system_alias(system,release,version):
831
832 """ Returns (system,release,version) aliased to common
833 marketing names used for some systems.
834
835 It also does some reordering of the information in some cases
836 where it would otherwise cause confusion.
837
838 """
839 if system == 'Rhapsody':
840 # Apple's BSD derivative
841 # XXX How can we determine the marketing release number ?
842 return 'MacOS X Server',system+release,version
843
844 elif system == 'SunOS':
845 # Sun's OS
846 if release < '5':
847 # These releases use the old name SunOS
848 return system,release,version
849 # Modify release (marketing release = SunOS release - 3)
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000850 l = release.split('.')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000851 if l:
852 try:
853 major = int(l[0])
854 except ValueError:
855 pass
856 else:
857 major = major - 3
858 l[0] = str(major)
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000859 release = '.'.join(l)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000860 if release < '6':
861 system = 'Solaris'
862 else:
863 # XXX Whatever the new SunOS marketing name is...
864 system = 'Solaris'
865
866 elif system == 'IRIX64':
867 # IRIX reports IRIX64 on platforms with 64-bit support; yet it
868 # is really a version and not a different platform, since 32-bit
869 # apps are also supported..
870 system = 'IRIX'
871 if version:
872 version = version + ' (64bit)'
873 else:
874 version = '64bit'
875
876 elif system in ('win32','win16'):
877 # In case one of the other tricks
878 system = 'Windows'
879
880 return system,release,version
881
882### Various internal helpers
883
884def _platform(*args):
885
886 """ Helper to format the platform string in a filename
887 compatible format e.g. "system-version-machine".
888 """
889 # Format the platform string
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000890 platform = '-'.join(x.strip() for x in filter(len, args))
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000891
892 # Cleanup some possible filename obstacles...
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000893 platform = platform.replace(' ','_')
894 platform = platform.replace('/','-')
895 platform = platform.replace('\\','-')
896 platform = platform.replace(':','-')
897 platform = platform.replace(';','-')
898 platform = platform.replace('"','-')
899 platform = platform.replace('(','-')
900 platform = platform.replace(')','-')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000901
902 # No need to report 'unknown' information...
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000903 platform = platform.replace('unknown','')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000904
905 # Fold '--'s and remove trailing '-'
906 while 1:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000907 cleaned = platform.replace('--','-')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000908 if cleaned == platform:
909 break
910 platform = cleaned
911 while platform[-1] == '-':
912 platform = platform[:-1]
913
914 return platform
915
916def _node(default=''):
917
918 """ Helper to determine the node name of this machine.
919 """
920 try:
921 import socket
922 except ImportError:
923 # No sockets...
924 return default
925 try:
926 return socket.gethostname()
927 except socket.error:
928 # Still not working...
929 return default
930
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000931def _follow_symlinks(filepath):
932
933 """ In case filepath is a symlink, follow it until a
934 real file is reached.
935 """
Georg Brandl673f7ef2008-01-05 21:20:19 +0000936 filepath = os.path.abspath(filepath)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000937 while os.path.islink(filepath):
938 filepath = os.path.normpath(
Hirokazu Yamamotob12716b2008-09-04 11:24:53 +0000939 os.path.join(os.path.dirname(filepath),os.readlink(filepath)))
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000940 return filepath
941
942def _syscmd_uname(option,default=''):
943
944 """ Interface to the system's uname command.
945 """
946 if sys.platform in ('dos','win32','win16','os2'):
947 # XXX Others too ?
948 return default
949 try:
950 f = os.popen('uname %s 2> /dev/null' % option)
951 except (AttributeError,os.error):
952 return default
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000953 output = f.read().strip()
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000954 rc = f.close()
955 if not output or rc:
956 return default
957 else:
958 return output
959
960def _syscmd_file(target,default=''):
961
962 """ Interface to the system's file command.
963
964 The function uses the -b option of the file command to have it
965 ommit the filename in its output and if possible the -L option
966 to have the command follow symlinks. It returns default in
967 case the command should fail.
968
969 """
Hirokazu Yamamotod26782e2008-09-01 14:35:47 +0000970 if sys.platform in ('dos','win32','win16','os2'):
971 # XXX Others too ?
972 return default
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000973 target = _follow_symlinks(target)
974 try:
Marc-André Lemburg40779852008-09-02 10:33:55 +0000975 f = os.popen('file "%s" 2> /dev/null' % target)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000976 except (AttributeError,os.error):
977 return default
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000978 output = f.read().strip()
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000979 rc = f.close()
980 if not output or rc:
981 return default
982 else:
983 return output
984
985### Information about the used architecture
986
987# Default values for architecture; non-empty strings override the
988# defaults given as parameters
989_default_architecture = {
990 'win32': ('','WindowsPE'),
991 'win16': ('','Windows'),
992 'dos': ('','MSDOS'),
993}
994
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000995_architecture_split = re.compile(r'[\s,]').split
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000996
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000997def architecture(executable=sys.executable,bits='',linkage=''):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000998
999 """ Queries the given executable (defaults to the Python interpreter
Brett Cannon8ab27df2003-08-05 03:52:04 +00001000 binary) for various architecture information.
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001001
Brett Cannon8ab27df2003-08-05 03:52:04 +00001002 Returns a tuple (bits,linkage) which contains information about
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001003 the bit architecture and the linkage format used for the
1004 executable. Both values are returned as strings.
1005
1006 Values that cannot be determined are returned as given by the
1007 parameter presets. If bits is given as '', the sizeof(pointer)
1008 (or sizeof(long) on Python version < 1.5.2) is used as
1009 indicator for the supported pointer size.
1010
1011 The function relies on the system's "file" command to do the
1012 actual work. This is available on most if not all Unix
Brett Cannon8ab27df2003-08-05 03:52:04 +00001013 platforms. On some non-Unix platforms where the "file" command
1014 does not exist and the executable is set to the Python interpreter
1015 binary defaults from _default_architecture are used.
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001016
1017 """
1018 # Use the sizeof(pointer) as default number of bits if nothing
1019 # else is given as default.
1020 if not bits:
1021 import struct
1022 try:
1023 size = struct.calcsize('P')
1024 except struct.error:
1025 # Older installations can only query longs
1026 size = struct.calcsize('l')
1027 bits = str(size*8) + 'bit'
Tim Peters0eadaac2003-04-24 16:02:54 +00001028
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001029 # Get data from the 'file' system command
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001030 if executable:
1031 output = _syscmd_file(executable, '')
1032 else:
1033 output = ''
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001034
1035 if not output and \
1036 executable == sys.executable:
1037 # "file" command did not return anything; we'll try to provide
Tim Peters0eadaac2003-04-24 16:02:54 +00001038 # some sensible defaults then...
Guido van Rossume2b70bc2006-08-18 22:13:04 +00001039 if sys.platform in _default_architecture:
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001040 b,l = _default_architecture[sys.platform]
1041 if b:
1042 bits = b
1043 if l:
1044 linkage = l
1045 return bits,linkage
1046
1047 # Split the output into a list of strings omitting the filename
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +00001048 fileout = _architecture_split(output)[1:]
Tim Peters0eadaac2003-04-24 16:02:54 +00001049
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001050 if 'executable' not in fileout:
1051 # Format not supported
1052 return bits,linkage
1053
1054 # Bits
1055 if '32-bit' in fileout:
1056 bits = '32bit'
1057 elif 'N32' in fileout:
1058 # On Irix only
1059 bits = 'n32bit'
1060 elif '64-bit' in fileout:
1061 bits = '64bit'
1062
1063 # Linkage
1064 if 'ELF' in fileout:
1065 linkage = 'ELF'
1066 elif 'PE' in fileout:
1067 # E.g. Windows uses this format
1068 if 'Windows' in fileout:
1069 linkage = 'WindowsPE'
1070 else:
1071 linkage = 'PE'
1072 elif 'COFF' in fileout:
1073 linkage = 'COFF'
1074 elif 'MS-DOS' in fileout:
1075 linkage = 'MSDOS'
1076 else:
1077 # XXX the A.OUT format also falls under this class...
1078 pass
1079
1080 return bits,linkage
1081
1082### Portable uname() interface
Tim Peters0eadaac2003-04-24 16:02:54 +00001083
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001084_uname_cache = None
1085
1086def uname():
1087
1088 """ Fairly portable uname interface. Returns a tuple
1089 of strings (system,node,release,version,machine,processor)
1090 identifying the underlying platform.
1091
1092 Note that unlike the os.uname function this also returns
Brett Cannon8ab27df2003-08-05 03:52:04 +00001093 possible processor information as an additional tuple entry.
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001094
1095 Entries which cannot be determined are set to ''.
1096
1097 """
1098 global _uname_cache
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001099 no_os_uname = 0
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001100
1101 if _uname_cache is not None:
1102 return _uname_cache
1103
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001104 processor = ''
1105
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001106 # Get some infos from the builtin os.uname API...
1107 try:
1108 system,node,release,version,machine = os.uname()
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001109 except AttributeError:
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001110 no_os_uname = 1
1111
Georg Brandlcaa78fe2010-08-01 19:07:28 +00001112 if no_os_uname or not list(filter(None, (system, node, release, version, machine))):
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001113 # Hmm, no there is either no uname or uname has returned
1114 #'unknowns'... we'll have to poke around the system then.
1115 if no_os_uname:
1116 system = sys.platform
1117 release = ''
1118 version = ''
1119 node = _node()
1120 machine = ''
1121
Amaury Forgeot d'Arc7a019842008-06-17 21:42:46 +00001122 use_syscmd_ver = 1
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001123
1124 # Try win32_ver() on win32 platforms
1125 if system == 'win32':
1126 release,version,csd,ptype = win32_ver()
1127 if release and version:
1128 use_syscmd_ver = 0
Christian Heimes02781dc2008-03-21 01:11:52 +00001129 # Try to use the PROCESSOR_* environment variables
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001130 # available on Win XP and later; see
1131 # http://support.microsoft.com/kb/888731 and
1132 # http://www.geocities.com/rick_lively/MANUALS/ENV/MSWIN/PROCESSI.HTM
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001133 if not machine:
1134 machine = os.environ.get('PROCESSOR_ARCHITECTURE', '')
1135 if not processor:
1136 processor = os.environ.get('PROCESSOR_IDENTIFIER', machine)
Tim Peters0eadaac2003-04-24 16:02:54 +00001137
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001138 # Try the 'ver' system command available on some
1139 # platforms
1140 if use_syscmd_ver:
1141 system,release,version = _syscmd_ver(system)
Marc-André Lemburgcdc79232004-06-19 17:17:00 +00001142 # Normalize system to what win32_ver() normally returns
1143 # (_syscmd_ver() tends to return the vendor name as well)
1144 if system == 'Microsoft Windows':
1145 system = 'Windows'
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001146 elif system == 'Microsoft' and release == 'Windows':
1147 # Under Windows Vista and Windows Server 2008,
1148 # Microsoft changed the output of the ver command. The
1149 # release is no longer printed. This causes the
1150 # system and release to be misidentified.
1151 system = 'Windows'
1152 if '6.0' == version[:3]:
1153 release = 'Vista'
1154 else:
1155 release = ''
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001156
1157 # In case we still don't know anything useful, we'll try to
1158 # help ourselves
1159 if system in ('win32','win16'):
1160 if not version:
1161 if system == 'win32':
1162 version = '32bit'
1163 else:
1164 version = '16bit'
1165 system = 'Windows'
1166
1167 elif system[:4] == 'java':
1168 release,vendor,vminfo,osinfo = java_ver()
1169 system = 'Java'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001170 version = ', '.join(vminfo)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001171 if not version:
1172 version = vendor
1173
1174 elif os.name == 'mac':
1175 release,(version,stage,nonrel),machine = mac_ver()
1176 system = 'MacOS'
1177
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001178 # System specific extensions
1179 if system == 'OpenVMS':
1180 # OpenVMS seems to have release and version mixed up
1181 if not release or release == '0':
1182 release = version
1183 version = ''
1184 # Get processor information
1185 try:
1186 import vms_lib
1187 except ImportError:
1188 pass
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001189 else:
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001190 csid, cpu_number = vms_lib.getsyi('SYI$_CPU',0)
1191 if (cpu_number >= 128):
1192 processor = 'Alpha'
1193 else:
1194 processor = 'VAX'
1195 if not processor:
1196 # Get processor information from the uname system command
1197 processor = _syscmd_uname('-p','')
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001198
Amaury Forgeot d'Arc35c86582008-06-17 21:11:29 +00001199 #If any unknowns still exist, replace them with ''s, which are more portable
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001200 if system == 'unknown':
1201 system = ''
1202 if node == 'unknown':
1203 node = ''
1204 if release == 'unknown':
1205 release = ''
1206 if version == 'unknown':
1207 version = ''
1208 if machine == 'unknown':
1209 machine = ''
1210 if processor == 'unknown':
1211 processor = ''
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001212
1213 # normalize name
1214 if system == 'Microsoft' and release == 'Windows':
1215 system = 'Windows'
1216 release = 'Vista'
1217
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001218 _uname_cache = system,node,release,version,machine,processor
1219 return _uname_cache
1220
1221### Direct interfaces to some of the uname() return values
1222
1223def system():
1224
1225 """ Returns the system/OS name, e.g. 'Linux', 'Windows' or 'Java'.
1226
1227 An empty string is returned if the value cannot be determined.
1228
1229 """
1230 return uname()[0]
1231
1232def node():
1233
Brett Cannon8ab27df2003-08-05 03:52:04 +00001234 """ Returns the computer's network name (which may not be fully
1235 qualified)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001236
1237 An empty string is returned if the value cannot be determined.
1238
1239 """
1240 return uname()[1]
1241
1242def release():
1243
1244 """ Returns the system's release, e.g. '2.2.0' or 'NT'
1245
1246 An empty string is returned if the value cannot be determined.
1247
1248 """
1249 return uname()[2]
1250
1251def version():
1252
1253 """ Returns the system's release version, e.g. '#3 on degas'
1254
1255 An empty string is returned if the value cannot be determined.
1256
1257 """
1258 return uname()[3]
1259
1260def machine():
1261
1262 """ Returns the machine type, e.g. 'i386'
1263
1264 An empty string is returned if the value cannot be determined.
1265
1266 """
1267 return uname()[4]
1268
1269def processor():
1270
1271 """ Returns the (true) processor name, e.g. 'amdk6'
1272
1273 An empty string is returned if the value cannot be
1274 determined. Note that many platforms do not provide this
1275 information or simply return the same value as for machine(),
1276 e.g. NetBSD does this.
1277
1278 """
1279 return uname()[5]
1280
1281### Various APIs for extracting information from sys.version
1282
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001283_sys_version_parser = re.compile(
1284 r'([\w.+]+)\s*'
1285 '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
Antoine Pitroufd036452008-08-19 17:56:33 +00001286 '\[([^\]]+)\]?', re.ASCII)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001287
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001288_ironpython_sys_version_parser = re.compile(
1289 r'IronPython\s*'
1290 '([\d\.]+)'
1291 '(?: \(([\d\.]+)\))?'
Antoine Pitroufd036452008-08-19 17:56:33 +00001292 ' on (.NET [\d\.]+)', re.ASCII)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001293
Benjamin Petersone549ead2009-03-28 21:42:05 +00001294_pypy_sys_version_parser = re.compile(
1295 r'([\w.+]+)\s*'
1296 '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
1297 '\[PyPy [^\]]+\]?')
1298
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001299_sys_version_cache = {}
1300
1301def _sys_version(sys_version=None):
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001302
1303 """ Returns a parsed version of Python's sys.version as tuple
Benjamin Peterson5f28b7b2009-03-26 21:49:58 +00001304 (name, version, branch, revision, buildno, builddate, compiler)
1305 referring to the Python implementation name, version, branch,
1306 revision, build number, build date/time as string and the compiler
1307 identification string.
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001308
1309 Note that unlike the Python sys.version, the returned value
1310 for the Python version will always include the patchlevel (it
1311 defaults to '.0').
1312
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001313 The function returns empty strings for tuple entries that
1314 cannot be determined.
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001315
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001316 sys_version may be given to parse an alternative version
1317 string, e.g. if the version was read from a different Python
1318 interpreter.
1319
1320 """
1321 # Get the Python version
1322 if sys_version is None:
1323 sys_version = sys.version
1324
1325 # Try the cache first
1326 result = _sys_version_cache.get(sys_version, None)
1327 if result is not None:
1328 return result
1329
1330 # Parse it
1331 if sys_version[:10] == 'IronPython':
1332 # IronPython
1333 name = 'IronPython'
1334 match = _ironpython_sys_version_parser.match(sys_version)
1335 if match is None:
1336 raise ValueError(
1337 'failed to parse IronPython sys.version: %s' %
1338 repr(sys_version))
1339 version, alt_version, compiler = match.groups()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001340 buildno = ''
1341 builddate = ''
1342
1343 elif sys.platform[:4] == 'java':
1344 # Jython
1345 name = 'Jython'
Benjamin Petersone549ead2009-03-28 21:42:05 +00001346 match = _sys_version_parser.match(sys_version)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001347 if match is None:
1348 raise ValueError(
1349 'failed to parse Jython sys.version: %s' %
1350 repr(sys_version))
Benjamin Petersone549ead2009-03-28 21:42:05 +00001351 version, buildno, builddate, buildtime, _ = match.groups()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001352 compiler = sys.platform
Benjamin Petersone549ead2009-03-28 21:42:05 +00001353
1354 elif "PyPy" in sys_version:
1355 # PyPy
1356 name = "PyPy"
1357 match = _pypy_sys_version_parser.match(sys_version)
1358 if match is None:
1359 raise ValueError("failed to parse PyPy sys.version: %s" %
1360 repr(sys_version))
1361 version, buildno, builddate, buildtime = match.groups()
1362 compiler = ""
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001363
1364 else:
1365 # CPython
1366 match = _sys_version_parser.match(sys_version)
1367 if match is None:
1368 raise ValueError(
1369 'failed to parse CPython sys.version: %s' %
1370 repr(sys_version))
1371 version, buildno, builddate, buildtime, compiler = \
1372 match.groups()
Benjamin Petersone549ead2009-03-28 21:42:05 +00001373 name = 'CPython'
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001374 builddate = builddate + ' ' + buildtime
1375
Georg Brandl82562422011-03-05 21:09:22 +01001376 if hasattr(sys, '_mercurial'):
1377 _, branch, revision = sys._mercurial
1378 elif hasattr(sys, 'subversion'):
Benjamin Petersone549ead2009-03-28 21:42:05 +00001379 # sys.subversion was added in Python 2.5
1380 _, branch, revision = sys.subversion
1381 else:
1382 branch = ''
1383 revision = ''
1384
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001385 # Add the patchlevel version if missing
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001386 l = version.split('.')
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001387 if len(l) == 2:
1388 l.append('0')
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001389 version = '.'.join(l)
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001390
1391 # Build and cache the result
1392 result = (name, version, branch, revision, buildno, builddate, compiler)
1393 _sys_version_cache[sys_version] = result
1394 return result
1395
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001396def python_implementation():
1397
1398 """ Returns a string identifying the Python implementation.
1399
1400 Currently, the following implementations are identified:
1401 'CPython' (C implementation of Python),
1402 'IronPython' (.NET implementation of Python),
1403 'Jython' (Java implementation of Python).
1404
1405 """
1406 return _sys_version()[0]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001407
1408def python_version():
1409
1410 """ Returns the Python version as string 'major.minor.patchlevel'
1411
1412 Note that unlike the Python sys.version, the returned value
1413 will always include the patchlevel (it defaults to 0).
1414
1415 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001416 return _sys_version()[1]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001417
1418def python_version_tuple():
1419
1420 """ Returns the Python version as tuple (major, minor, patchlevel)
1421 of strings.
1422
1423 Note that unlike the Python sys.version, the returned value
1424 will always include the patchlevel (it defaults to 0).
1425
1426 """
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001427 return tuple(_sys_version()[1].split('.'))
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001428
1429def python_branch():
1430
1431 """ Returns a string identifying the Python implementation
1432 branch.
1433
1434 For CPython this is the Subversion branch from which the
1435 Python binary was built.
1436
1437 If not available, an empty string is returned.
1438
1439 """
Thomas Wouters9fe394c2007-02-05 01:24:16 +00001440
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001441 return _sys_version()[2]
1442
1443def python_revision():
1444
1445 """ Returns a string identifying the Python implementation
1446 revision.
1447
1448 For CPython this is the Subversion revision from which the
1449 Python binary was built.
1450
1451 If not available, an empty string is returned.
1452
1453 """
1454 return _sys_version()[3]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001455
1456def python_build():
1457
1458 """ Returns a tuple (buildno, builddate) stating the Python
1459 build number and date as strings.
1460
1461 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001462 return _sys_version()[4:6]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001463
1464def python_compiler():
1465
1466 """ Returns a string identifying the compiler used for compiling
1467 Python.
1468
1469 """
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001470 return _sys_version()[6]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001471
1472### The Opus Magnum of platform strings :-)
1473
Marc-André Lemburg91e83e22004-03-25 18:35:12 +00001474_platform_cache = {}
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001475
1476def platform(aliased=0, terse=0):
1477
1478 """ Returns a single string identifying the underlying platform
1479 with as much useful information as possible (but no more :).
Tim Peters0eadaac2003-04-24 16:02:54 +00001480
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001481 The output is intended to be human readable rather than
1482 machine parseable. It may look different on different
1483 platforms and this is intended.
1484
1485 If "aliased" is true, the function will use aliases for
1486 various platforms that report system names which differ from
1487 their common names, e.g. SunOS will be reported as
1488 Solaris. The system_alias() function is used to implement
1489 this.
1490
1491 Setting terse to true causes the function to return only the
1492 absolute minimum information needed to identify the platform.
1493
1494 """
Marc-André Lemburg91e83e22004-03-25 18:35:12 +00001495 result = _platform_cache.get((aliased, terse), None)
1496 if result is not None:
1497 return result
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001498
1499 # Get uname information and then apply platform specific cosmetics
1500 # to it...
1501 system,node,release,version,machine,processor = uname()
1502 if machine == processor:
1503 processor = ''
1504 if aliased:
1505 system,release,version = system_alias(system,release,version)
1506
1507 if system == 'Windows':
1508 # MS platforms
1509 rel,vers,csd,ptype = win32_ver(version)
1510 if terse:
1511 platform = _platform(system,release)
1512 else:
1513 platform = _platform(system,release,version,csd)
1514
1515 elif system in ('Linux',):
1516 # Linux based systems
1517 distname,distversion,distid = dist('')
1518 if distname and not terse:
1519 platform = _platform(system,release,machine,processor,
1520 'with',
1521 distname,distversion,distid)
1522 else:
1523 # If the distribution name is unknown check for libc vs. glibc
1524 libcname,libcversion = libc_ver(sys.executable)
1525 platform = _platform(system,release,machine,processor,
1526 'with',
1527 libcname+libcversion)
1528 elif system == 'Java':
1529 # Java platforms
1530 r,v,vminfo,(os_name,os_version,os_arch) = java_ver()
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001531 if terse or not os_name:
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001532 platform = _platform(system,release,version)
1533 else:
1534 platform = _platform(system,release,version,
1535 'on',
1536 os_name,os_version,os_arch)
1537
1538 elif system == 'MacOS':
1539 # MacOS platforms
1540 if terse:
1541 platform = _platform(system,release)
1542 else:
1543 platform = _platform(system,release,machine)
1544
1545 else:
1546 # Generic handler
1547 if terse:
1548 platform = _platform(system,release)
1549 else:
1550 bits,linkage = architecture(sys.executable)
1551 platform = _platform(system,release,machine,processor,bits,linkage)
Tim Peters0eadaac2003-04-24 16:02:54 +00001552
Marc-André Lemburg91e83e22004-03-25 18:35:12 +00001553 _platform_cache[(aliased, terse)] = platform
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001554 return platform
1555
1556### Command line interface
1557
1558if __name__ == '__main__':
1559 # Default is to print the aliased verbose platform string
Tim Peters0eadaac2003-04-24 16:02:54 +00001560 terse = ('terse' in sys.argv or '--terse' in sys.argv)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001561 aliased = (not 'nonaliased' in sys.argv and not '--nonaliased' in sys.argv)
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001562 print(platform(aliased,terse))
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001563 sys.exit(0)