blob: 10b04bde95ef3646d5fd0785f08de221f3361244 [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
Georg Brandl52c17942009-09-19 08:43:16 +000013# Python bug tracker (http://bugs.python.org) and assign them to "lemburg".
Marc-André Lemburg246d8472003-04-24 11:36:11 +000014#
15# Note: Please keep this module compatible to Python 1.5.2.
16#
17# Still needed:
18# * more support for WinCE
19# * support for MS-DOS (PythonDX ?)
20# * support for Amiga and other still unsupported platforms running Python
21# * support for additional Linux distributions
22#
Brett Cannon8ab27df2003-08-05 03:52:04 +000023# Many thanks to all those who helped adding platform-specific
Marc-André Lemburg246d8472003-04-24 11:36:11 +000024# checks (in no particular order):
25#
26# Charles G Waldman, David Arnold, Gordon McMillan, Ben Darnell,
27# Jeff Bauer, Cliff Crawford, Ivan Van Laningham, Josef
28# Betancourt, Randall Hopper, Karl Putland, John Farrell, Greg
29# Andruk, Just van Rossum, Thomas Heller, Mark R. Levinson, Mark
30# Hammond, Bill Tutt, Hans Nowak, Uwe Zessin (OpenVMS support),
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +000031# Colin Kong, Trent Mick, Guido van Rossum, Anthony Baxter
Marc-André Lemburg246d8472003-04-24 11:36:11 +000032#
33# History:
Marc-André Lemburg380f4172005-11-07 16:11:02 +000034#
35# <see CVS and SVN checkin messages for history>
36#
Marc-André Lemburg19e5b3f2009-07-13 20:23:49 +000037# 1.0.7 - added DEV_NULL
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +000038# 1.0.6 - added linux_distribution()
39# 1.0.5 - fixed Java support to allow running the module on Jython
40# 1.0.4 - added IronPython support
Marc-André Lemburgcdc79232004-06-19 17:17:00 +000041# 1.0.3 - added normalization of Windows system name
Marc-André Lemburg91e83e22004-03-25 18:35:12 +000042# 1.0.2 - added more Windows support
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +000043# 1.0.1 - reformatted to make doc.py happy
Marc-André Lemburg246d8472003-04-24 11:36:11 +000044# 1.0.0 - reformatted a bit and checked into Python CVS
45# 0.8.0 - added sys.version parser and various new access
46# APIs (python_version(), python_compiler(), etc.)
47# 0.7.2 - fixed architecture() to use sizeof(pointer) where available
48# 0.7.1 - added support for Caldera OpenLinux
49# 0.7.0 - some fixes for WinCE; untabified the source file
50# 0.6.2 - support for OpenVMS - requires version 1.5.2-V006 or higher and
51# vms_lib.getsyi() configured
52# 0.6.1 - added code to prevent 'uname -p' on platforms which are
53# known not to support it
54# 0.6.0 - fixed win32_ver() to hopefully work on Win95,98,NT and Win2k;
55# did some cleanup of the interfaces - some APIs have changed
56# 0.5.5 - fixed another type in the MacOS code... should have
57# used more coffee today ;-)
58# 0.5.4 - fixed a few typos in the MacOS code
59# 0.5.3 - added experimental MacOS support; added better popen()
60# workarounds in _syscmd_ver() -- still not 100% elegant
61# though
62# 0.5.2 - fixed uname() to return '' instead of 'unknown' in all
63# return values (the system uname command tends to return
64# 'unknown' instead of just leaving the field emtpy)
65# 0.5.1 - included code for slackware dist; added exception handlers
66# to cover up situations where platforms don't have os.popen
67# (e.g. Mac) or fail on socket.gethostname(); fixed libc
68# detection RE
69# 0.5.0 - changed the API names referring to system commands to *syscmd*;
70# added java_ver(); made syscmd_ver() a private
71# API (was system_ver() in previous versions) -- use uname()
72# instead; extended the win32_ver() to also return processor
73# type information
74# 0.4.0 - added win32_ver() and modified the platform() output for WinXX
75# 0.3.4 - fixed a bug in _follow_symlinks()
76# 0.3.3 - fixed popen() and "file" command invokation bugs
77# 0.3.2 - added architecture() API and support for it in platform()
78# 0.3.1 - fixed syscmd_ver() RE to support Windows NT
79# 0.3.0 - added system alias support
80# 0.2.3 - removed 'wince' again... oh well.
81# 0.2.2 - added 'wince' to syscmd_ver() supported platforms
82# 0.2.1 - added cache logic and changed the platform string format
83# 0.2.0 - changed the API to use functions instead of module globals
84# since some action take too long to be run on module import
85# 0.1.0 - first release
86#
87# You can always get the latest version of this module at:
88#
89# http://www.egenix.com/files/python/platform.py
90#
91# If that URL should fail, try contacting the author.
92
93__copyright__ = """
94 Copyright (c) 1999-2000, Marc-Andre Lemburg; mailto:mal@lemburg.com
Georg Brandl8cdc9bc2010-01-01 13:07:05 +000095 Copyright (c) 2000-2010, eGenix.com Software GmbH; mailto:info@egenix.com
Marc-André Lemburg246d8472003-04-24 11:36:11 +000096
97 Permission to use, copy, modify, and distribute this software and its
98 documentation for any purpose and without fee or royalty is hereby granted,
99 provided that the above copyright notice appear in all copies and that
100 both that copyright notice and this permission notice appear in
101 supporting documentation or portions thereof, including modifications,
102 that you make.
103
104 EGENIX.COM SOFTWARE GMBH DISCLAIMS ALL WARRANTIES WITH REGARD TO
105 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
106 FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
107 INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
108 FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
109 NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
110 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE !
111
112"""
113
Marc-André Lemburg19e5b3f2009-07-13 20:23:49 +0000114__version__ = '1.0.7'
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000115
Jesus Ceadebda5d2012-10-04 15:14:56 +0200116import sys,string,os,re
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000117
Marc-André Lemburg19e5b3f2009-07-13 20:23:49 +0000118### Globals & Constants
119
120# Determine the platform's /dev/null device
121try:
122 DEV_NULL = os.devnull
123except AttributeError:
124 # os.devnull was added in Python 2.4, so emulate it for earlier
125 # Python versions
126 if sys.platform in ('dos','win32','win16','os2'):
127 # Use the old CP/M NUL as device name
128 DEV_NULL = 'NUL'
129 else:
130 # Standard Unix uses /dev/null
131 DEV_NULL = '/dev/null'
132
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000133### Platform specific APIs
134
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000135_libc_search = re.compile(r'(__libc_init)'
136 '|'
Tim Peters0eadaac2003-04-24 16:02:54 +0000137 '(GLIBC_([0-9.]+))'
138 '|'
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000139 '(libc(_\w+)?\.so(?:\.(\d[0-9.]*))?)')
140
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000141def libc_ver(executable=sys.executable,lib='',version='',
142
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000143 chunksize=2048):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000144
Brett Cannon8ab27df2003-08-05 03:52:04 +0000145 """ Tries to determine the libc version that the file executable
146 (which defaults to the Python interpreter) is linked against.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000147
148 Returns a tuple of strings (lib,version) which default to the
149 given parameters in case the lookup fails.
150
151 Note that the function has intimate knowledge of how different
Brett Cannon8ab27df2003-08-05 03:52:04 +0000152 libc versions add symbols to the executable and thus is probably
153 only useable for executables compiled using gcc.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000154
155 The file is read and scanned in chunks of chunksize bytes.
156
157 """
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +0000158 if hasattr(os.path, 'realpath'):
159 # Python 2.2 introduced os.path.realpath(); it is used
160 # here to work around problems with Cygwin not being
161 # able to open symlinks for reading
162 executable = os.path.realpath(executable)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000163 f = open(executable,'rb')
164 binary = f.read(chunksize)
165 pos = 0
166 while 1:
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000167 m = _libc_search.search(binary,pos)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000168 if not m:
169 binary = f.read(chunksize)
170 if not binary:
171 break
172 pos = 0
173 continue
174 libcinit,glibc,glibcversion,so,threads,soversion = m.groups()
175 if libcinit and not lib:
176 lib = 'libc'
177 elif glibc:
178 if lib != 'glibc':
179 lib = 'glibc'
180 version = glibcversion
181 elif glibcversion > version:
182 version = glibcversion
183 elif so:
184 if lib != 'glibc':
185 lib = 'libc'
Victor Stinner429a12b2011-12-15 21:42:03 +0100186 if soversion and soversion > version:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000187 version = soversion
188 if threads and version[-len(threads):] != threads:
189 version = version + threads
190 pos = m.end()
191 f.close()
192 return lib,version
193
194def _dist_try_harder(distname,version,id):
195
Tim Peters0eadaac2003-04-24 16:02:54 +0000196 """ Tries some special tricks to get the distribution
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000197 information in case the default method fails.
198
199 Currently supports older SuSE Linux, Caldera OpenLinux and
200 Slackware Linux distributions.
201
202 """
203 if os.path.exists('/var/adm/inst-log/info'):
204 # SuSE Linux stores distribution information in that file
205 info = open('/var/adm/inst-log/info').readlines()
206 distname = 'SuSE'
207 for line in info:
208 tv = string.split(line)
209 if len(tv) == 2:
210 tag,value = tv
211 else:
212 continue
213 if tag == 'MIN_DIST_VERSION':
214 version = string.strip(value)
215 elif tag == 'DIST_IDENT':
216 values = string.split(value,'-')
217 id = values[2]
218 return distname,version,id
219
220 if os.path.exists('/etc/.installed'):
221 # Caldera OpenLinux has some infos in that file (thanks to Colin Kong)
222 info = open('/etc/.installed').readlines()
223 for line in info:
224 pkg = string.split(line,'-')
225 if len(pkg) >= 2 and pkg[0] == 'OpenLinux':
226 # XXX does Caldera support non Intel platforms ? If yes,
227 # where can we find the needed id ?
228 return 'OpenLinux',pkg[1],id
229
230 if os.path.isdir('/usr/lib/setup'):
231 # Check for slackware verson tag file (thanks to Greg Andruk)
232 verfiles = os.listdir('/usr/lib/setup')
Guido van Rossum843c7342004-05-04 18:18:59 +0000233 for n in range(len(verfiles)-1, -1, -1):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000234 if verfiles[n][:14] != 'slack-version-':
235 del verfiles[n]
236 if verfiles:
237 verfiles.sort()
238 distname = 'slackware'
239 version = verfiles[-1][14:]
240 return distname,version,id
241
242 return distname,version,id
243
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000244_release_filename = re.compile(r'(\w+)[-_](release|version)')
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +0000245_lsb_release_version = re.compile(r'(.+)'
246 ' release '
247 '([\d.]+)'
248 '[^(]*(?:\((.+)\))?')
249_release_version = re.compile(r'([^0-9]+)'
250 '(?: release )?'
251 '([\d.]+)'
252 '[^(]*(?:\((.+)\))?')
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000253
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +0000254# See also http://www.novell.com/coolsolutions/feature/11251.html
Tim Petersf733abb72007-01-30 03:03:46 +0000255# and http://linuxmafia.com/faq/Admin/release-files.html
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +0000256# and http://data.linux-ntfs.org/rpm/whichrpm
257# and http://www.die.net/doc/linux/man/man1/lsb_release.1.html
Marc-André Lemburg380f4172005-11-07 16:11:02 +0000258
Marc-André Lemburg50967bd2008-03-08 10:01:43 +0000259_supported_dists = (
260 'SuSE', 'debian', 'fedora', 'redhat', 'centos',
261 'mandrake', 'mandriva', 'rocks', 'slackware', 'yellowdog', 'gentoo',
262 'UnitedLinux', 'turbolinux')
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +0000263
264def _parse_release_file(firstline):
Tim Petersf733abb72007-01-30 03:03:46 +0000265
Benjamin Petersona43f34c2010-01-25 03:31:13 +0000266 # Default to empty 'version' and 'id' strings. Both defaults are used
267 # when 'firstline' is empty. 'id' defaults to empty when an id can not
268 # be deduced.
269 version = ''
270 id = ''
271
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +0000272 # Parse the first line
273 m = _lsb_release_version.match(firstline)
274 if m is not None:
275 # LSB format: "distro release x.x (codename)"
276 return tuple(m.groups())
277
278 # Pre-LSB format: "distro x.x (codename)"
279 m = _release_version.match(firstline)
280 if m is not None:
281 return tuple(m.groups())
282
283 # Unkown format... take the first two words
284 l = string.split(string.strip(firstline))
285 if l:
286 version = l[0]
287 if len(l) > 1:
288 id = l[1]
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +0000289 return '', version, id
290
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +0000291def linux_distribution(distname='', version='', id='',
292
293 supported_dists=_supported_dists,
294 full_distribution_name=1):
295
296 """ Tries to determine the name of the Linux OS distribution name.
297
298 The function first looks for a distribution release file in
299 /etc and then reverts to _dist_try_harder() in case no
300 suitable files are found.
301
302 supported_dists may be given to define the set of Linux
303 distributions to look for. It defaults to a list of currently
304 supported Linux distributions identified by their release file
305 name.
306
307 If full_distribution_name is true (default), the full
308 distribution read from the OS is returned. Otherwise the short
309 name taken from supported_dists is used.
310
311 Returns a tuple (distname,version,id) which default to the
312 args given as parameters.
313
314 """
315 try:
316 etc = os.listdir('/etc')
317 except os.error:
318 # Probably not a Unix system
319 return distname,version,id
320 etc.sort()
321 for file in etc:
322 m = _release_filename.match(file)
323 if m is not None:
324 _distname,dummy = m.groups()
325 if _distname in supported_dists:
326 distname = _distname
327 break
328 else:
329 return _dist_try_harder(distname,version,id)
Tim Petersf733abb72007-01-30 03:03:46 +0000330
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +0000331 # Read the first line
332 f = open('/etc/'+file, 'r')
333 firstline = f.readline()
334 f.close()
335 _distname, _version, _id = _parse_release_file(firstline)
336
337 if _distname and full_distribution_name:
338 distname = _distname
339 if _version:
340 version = _version
341 if _id:
342 id = _id
343 return distname, version, id
344
345# To maintain backwards compatibility:
Tim Petersf733abb72007-01-30 03:03:46 +0000346
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000347def dist(distname='',version='',id='',
348
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +0000349 supported_dists=_supported_dists):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000350
Brett Cannon8ab27df2003-08-05 03:52:04 +0000351 """ Tries to determine the name of the Linux OS distribution name.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000352
353 The function first looks for a distribution release file in
354 /etc and then reverts to _dist_try_harder() in case no
355 suitable files are found.
356
Brett Cannon8ab27df2003-08-05 03:52:04 +0000357 Returns a tuple (distname,version,id) which default to the
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000358 args given as parameters.
359
360 """
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +0000361 return linux_distribution(distname, version, id,
362 supported_dists=supported_dists,
363 full_distribution_name=0)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000364
365class _popen:
366
367 """ Fairly portable (alternative) popen implementation.
368
369 This is mostly needed in case os.popen() is not available, or
370 doesn't work as advertised, e.g. in Win9X GUI programs like
371 PythonWin or IDLE.
372
373 Writing to the pipe is currently not supported.
374
375 """
376 tmpfile = ''
377 pipe = None
378 bufsize = None
379 mode = 'r'
380
381 def __init__(self,cmd,mode='r',bufsize=None):
382
383 if mode != 'r':
384 raise ValueError,'popen()-emulation only supports read mode'
385 import tempfile
386 self.tmpfile = tmpfile = tempfile.mktemp()
387 os.system(cmd + ' > %s' % tmpfile)
388 self.pipe = open(tmpfile,'rb')
389 self.bufsize = bufsize
390 self.mode = mode
391
392 def read(self):
393
394 return self.pipe.read()
395
396 def readlines(self):
397
398 if self.bufsize is not None:
399 return self.pipe.readlines()
400
401 def close(self,
402
403 remove=os.unlink,error=os.error):
404
405 if self.pipe:
406 rc = self.pipe.close()
407 else:
408 rc = 255
409 if self.tmpfile:
410 try:
411 remove(self.tmpfile)
412 except error:
413 pass
414 return rc
415
416 # Alias
417 __del__ = close
418
419def popen(cmd, mode='r', bufsize=None):
420
421 """ Portable popen() interface.
422 """
423 # Find a working popen implementation preferring win32pipe.popen
424 # over os.popen over _popen
425 popen = None
426 if os.environ.get('OS','') == 'Windows_NT':
427 # On NT win32pipe should work; on Win9x it hangs due to bugs
428 # in the MS C lib (see MS KnowledgeBase article Q150956)
429 try:
430 import win32pipe
431 except ImportError:
432 pass
433 else:
434 popen = win32pipe.popen
435 if popen is None:
436 if hasattr(os,'popen'):
437 popen = os.popen
438 # Check whether it works... it doesn't in GUI programs
439 # on Windows platforms
440 if sys.platform == 'win32': # XXX Others too ?
441 try:
442 popen('')
443 except os.error:
444 popen = _popen
445 else:
446 popen = _popen
447 if bufsize is None:
448 return popen(cmd,mode)
449 else:
450 return popen(cmd,mode,bufsize)
451
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +0000452def _norm_version(version, build=''):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000453
Brett Cannon8ab27df2003-08-05 03:52:04 +0000454 """ Normalize the version and build strings and return a single
Walter Dörwalde5a7fad2005-11-21 17:01:27 +0000455 version string using the format major.minor.build (or patchlevel).
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000456 """
457 l = string.split(version,'.')
458 if build:
459 l.append(build)
460 try:
461 ints = map(int,l)
462 except ValueError:
463 strings = l
464 else:
465 strings = map(str,ints)
466 version = string.join(strings[:3],'.')
467 return version
468
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000469_ver_output = re.compile(r'(?:([\w ]+) ([\w.]+) '
470 '.*'
Marc-André Lemburgcecaa652009-07-13 21:28:33 +0000471 '\[.* ([\d.]+)\])')
472
473# Examples of VER command output:
474#
475# Windows 2000: Microsoft Windows 2000 [Version 5.00.2195]
476# Windows XP: Microsoft Windows XP [Version 5.1.2600]
477# Windows Vista: Microsoft Windows [Version 6.0.6002]
478#
479# Note that the "Version" string gets localized on different
480# Windows versions.
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000481
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +0000482def _syscmd_ver(system='', release='', version='',
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000483
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000484 supported_platforms=('win32','win16','dos','os2')):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000485
486 """ Tries to figure out the OS version used and returns
487 a tuple (system,release,version).
Tim Peters0eadaac2003-04-24 16:02:54 +0000488
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000489 It uses the "ver" shell command for this which is known
490 to exists on Windows, DOS and OS/2. XXX Others too ?
491
492 In case this fails, the given parameters are used as
493 defaults.
494
495 """
496 if sys.platform not in supported_platforms:
497 return system,release,version
498
499 # Try some common cmd strings
500 for cmd in ('ver','command /c ver','cmd /c ver'):
501 try:
502 pipe = popen(cmd)
503 info = pipe.read()
504 if pipe.close():
505 raise os.error,'command failed'
Ezio Melottic2077b02011-03-16 12:34:31 +0200506 # XXX How can I suppress shell errors from being written
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000507 # to stderr ?
508 except os.error,why:
509 #print 'Command %s failed: %s' % (cmd,why)
510 continue
511 except IOError,why:
512 #print 'Command %s failed: %s' % (cmd,why)
513 continue
514 else:
515 break
516 else:
517 return system,release,version
518
519 # Parse the output
520 info = string.strip(info)
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +0000521 m = _ver_output.match(info)
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +0000522 if m is not None:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000523 system,release,version = m.groups()
524 # Strip trailing dots from version and release
525 if release[-1] == '.':
526 release = release[:-1]
527 if version[-1] == '.':
528 version = version[:-1]
529 # Normalize the version and build strings (eliminating additional
530 # zeros)
531 version = _norm_version(version)
532 return system,release,version
533
534def _win32_getvalue(key,name,default=''):
535
536 """ Read a value for name from the registry key.
537
538 In case this fails, default is returned.
539
540 """
Marc-André Lemburgdbd61a22008-03-20 17:31:36 +0000541 try:
542 # Use win32api if available
543 from win32api import RegQueryValueEx
544 except ImportError:
545 # On Python 2.0 and later, emulate using _winreg
546 import _winreg
547 RegQueryValueEx = _winreg.QueryValueEx
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000548 try:
549 return RegQueryValueEx(key,name)
550 except:
551 return default
552
553def win32_ver(release='',version='',csd='',ptype=''):
554
555 """ Get additional version information from the Windows Registry
556 and return a tuple (version,csd,ptype) referring to version
Brian Curtinb4bef302012-02-01 15:17:39 -0600557 number, CSD level (service pack), and OS type (multi/single
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000558 processor).
559
560 As a hint: ptype returns 'Uniprocessor Free' on single
561 processor NT machines and 'Multiprocessor Free' on multi
562 processor machines. The 'Free' refers to the OS version being
563 free of debugging code. It could also state 'Checked' which
564 means the OS version uses debugging code, i.e. code that
565 checks arguments, ranges, etc. (Thomas Heller).
566
Marc-André Lemburgdbd61a22008-03-20 17:31:36 +0000567 Note: this function works best with Mark Hammond's win32
568 package installed, but also on Python 2.3 and later. It
569 obviously only runs on Win32 compatible platforms.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000570
571 """
572 # XXX Is there any way to find out the processor type on WinXX ?
573 # XXX Is win32 available on Windows CE ?
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000574 #
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000575 # Adapted from code posted by Karl Putland to comp.lang.python.
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000576 #
577 # The mappings between reg. values and release names can be found
578 # here: http://msdn.microsoft.com/library/en-us/sysinfo/base/osversioninfo_str.asp
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000579
580 # Import the needed APIs
581 try:
582 import win32api
Marc-André Lemburgdbd61a22008-03-20 17:31:36 +0000583 from win32api import RegQueryValueEx, RegOpenKeyEx, \
584 RegCloseKey, GetVersionEx
585 from win32con import HKEY_LOCAL_MACHINE, VER_PLATFORM_WIN32_NT, \
586 VER_PLATFORM_WIN32_WINDOWS, VER_NT_WORKSTATION
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000587 except ImportError:
Marc-André Lemburgdbd61a22008-03-20 17:31:36 +0000588 # Emulate the win32api module using Python APIs
589 try:
590 sys.getwindowsversion
591 except AttributeError:
592 # No emulation possible, so return the defaults...
593 return release,version,csd,ptype
594 else:
595 # Emulation using _winreg (added in Python 2.0) and
596 # sys.getwindowsversion() (added in Python 2.3)
597 import _winreg
598 GetVersionEx = sys.getwindowsversion
599 RegQueryValueEx = _winreg.QueryValueEx
600 RegOpenKeyEx = _winreg.OpenKeyEx
601 RegCloseKey = _winreg.CloseKey
602 HKEY_LOCAL_MACHINE = _winreg.HKEY_LOCAL_MACHINE
603 VER_PLATFORM_WIN32_WINDOWS = 1
604 VER_PLATFORM_WIN32_NT = 2
605 VER_NT_WORKSTATION = 1
Brian Curtin11f8b9d2010-05-06 02:54:44 +0000606 VER_NT_SERVER = 3
607 REG_SZ = 1
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000608
609 # Find out the registry key and some general version infos
Brian Curtin11f8b9d2010-05-06 02:54:44 +0000610 winver = GetVersionEx()
611 maj,min,buildno,plat,csd = winver
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000612 version = '%i.%i.%i' % (maj,min,buildno & 0xFFFF)
Brian Curtin11f8b9d2010-05-06 02:54:44 +0000613 if hasattr(winver, "service_pack"):
614 if winver.service_pack != "":
615 csd = 'SP%s' % winver.service_pack_major
616 else:
617 if csd[:13] == 'Service Pack ':
618 csd = 'SP' + csd[13:]
Marc-André Lemburgcecaa652009-07-13 21:28:33 +0000619
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000620 if plat == VER_PLATFORM_WIN32_WINDOWS:
621 regkey = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion'
622 # Try to guess the release name
623 if maj == 4:
624 if min == 0:
625 release = '95'
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000626 elif min == 10:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000627 release = '98'
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000628 elif min == 90:
629 release = 'Me'
630 else:
631 release = 'postMe'
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000632 elif maj == 5:
633 release = '2000'
Marc-André Lemburgcecaa652009-07-13 21:28:33 +0000634
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000635 elif plat == VER_PLATFORM_WIN32_NT:
636 regkey = 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion'
637 if maj <= 4:
638 release = 'NT'
639 elif maj == 5:
Marc-André Lemburg91e83e22004-03-25 18:35:12 +0000640 if min == 0:
641 release = '2000'
642 elif min == 1:
643 release = 'XP'
644 elif min == 2:
645 release = '2003Server'
646 else:
647 release = 'post2003'
Marc-André Lemburgb24cd0f2007-06-12 09:26:49 +0000648 elif maj == 6:
Brian Curtin11f8b9d2010-05-06 02:54:44 +0000649 if hasattr(winver, "product_type"):
650 product_type = winver.product_type
651 else:
652 product_type = VER_NT_WORKSTATION
653 # Without an OSVERSIONINFOEX capable sys.getwindowsversion(),
654 # or help from the registry, we cannot properly identify
655 # non-workstation versions.
Marc-André Lemburgdbd61a22008-03-20 17:31:36 +0000656 try:
Brian Curtin11f8b9d2010-05-06 02:54:44 +0000657 key = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey)
658 name, type = RegQueryValueEx(key, "ProductName")
659 # Discard any type that isn't REG_SZ
660 if type == REG_SZ and name.find("Server") != -1:
661 product_type = VER_NT_SERVER
662 except WindowsError:
663 # Use default of VER_NT_WORKSTATION
664 pass
665
666 if min == 0:
667 if product_type == VER_NT_WORKSTATION:
Marc-André Lemburgb24cd0f2007-06-12 09:26:49 +0000668 release = 'Vista'
669 else:
Brian Curtin11f8b9d2010-05-06 02:54:44 +0000670 release = '2008Server'
671 elif min == 1:
672 if product_type == VER_NT_WORKSTATION:
673 release = '7'
674 else:
675 release = '2008ServerR2'
Marc-André Lemburgb24cd0f2007-06-12 09:26:49 +0000676 else:
677 release = 'post2008Server'
Marc-André Lemburgcecaa652009-07-13 21:28:33 +0000678
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000679 else:
680 if not release:
681 # E.g. Win3.1 with win32s
682 release = '%i.%i' % (maj,min)
683 return release,version,csd,ptype
684
685 # Open the registry key
686 try:
Marc-André Lemburgdbd61a22008-03-20 17:31:36 +0000687 keyCurVer = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey)
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000688 # Get a value to make sure the key exists...
Marc-André Lemburgdbd61a22008-03-20 17:31:36 +0000689 RegQueryValueEx(keyCurVer, 'SystemRoot')
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000690 except:
691 return release,version,csd,ptype
Tim Peters0eadaac2003-04-24 16:02:54 +0000692
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000693 # Parse values
694 #subversion = _win32_getvalue(keyCurVer,
695 # 'SubVersionNumber',
696 # ('',1))[0]
697 #if subversion:
698 # release = release + subversion # 95a, 95b, etc.
699 build = _win32_getvalue(keyCurVer,
700 'CurrentBuildNumber',
701 ('',1))[0]
702 ptype = _win32_getvalue(keyCurVer,
703 'CurrentType',
704 (ptype,1))[0]
705
706 # Normalize version
707 version = _norm_version(version,build)
708
709 # Close key
710 RegCloseKey(keyCurVer)
711 return release,version,csd,ptype
712
713def _mac_ver_lookup(selectors,default=None):
714
715 from gestalt import gestalt
Jack Jansena290e3d2003-08-11 11:08:49 +0000716 import MacOS
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000717 l = []
718 append = l.append
719 for selector in selectors:
720 try:
721 append(gestalt(selector))
Jack Jansena290e3d2003-08-11 11:08:49 +0000722 except (RuntimeError, MacOS.Error):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000723 append(default)
724 return l
725
726def _bcd2str(bcd):
727
728 return hex(bcd)[2:]
729
Ronald Oussoren3a04a252010-07-23 12:41:00 +0000730def _mac_ver_gestalt():
731 """
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000732 Thanks to Mark R. Levinson for mailing documentation links and
733 code examples for this function. Documentation for the
734 gestalt() API is available online at:
735
736 http://www.rgaros.nl/gestalt/
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000737 """
738 # Check whether the version info module is available
739 try:
740 import gestalt
Jack Jansena290e3d2003-08-11 11:08:49 +0000741 import MacOS
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000742 except ImportError:
Ronald Oussoren3a04a252010-07-23 12:41:00 +0000743 return None
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000744 # Get the infos
Ronald Oussoren9341ad22010-02-07 11:29:31 +0000745 sysv,sysa = _mac_ver_lookup(('sysv','sysa'))
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000746 # Decode the infos
747 if sysv:
748 major = (sysv & 0xFF00) >> 8
749 minor = (sysv & 0x00F0) >> 4
750 patch = (sysv & 0x000F)
Ronald Oussorenc27b8b82008-05-08 10:34:39 +0000751
752 if (major, minor) >= (10, 4):
753 # the 'sysv' gestald cannot return patchlevels
754 # higher than 9. Apple introduced 3 new
755 # gestalt codes in 10.4 to deal with this
756 # issue (needed because patch levels can
757 # run higher than 9, such as 10.4.11)
758 major,minor,patch = _mac_ver_lookup(('sys1','sys2','sys3'))
759 release = '%i.%i.%i' %(major, minor, patch)
760 else:
761 release = '%s.%i.%i' % (_bcd2str(major),minor,patch)
Ronald Oussoren7a0f4c72008-05-18 20:54:47 +0000762
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000763 if sysa:
Tim Peters0eadaac2003-04-24 16:02:54 +0000764 machine = {0x1: '68k',
Ronald Oussoren749d0702006-04-17 13:37:15 +0000765 0x2: 'PowerPC',
766 0xa: 'i386'}.get(sysa,'')
Ronald Oussoren3a04a252010-07-23 12:41:00 +0000767
Ned Deily0ab67ee2011-07-13 15:05:31 -0700768 versioninfo=('', '', '')
Ronald Oussoren3a04a252010-07-23 12:41:00 +0000769 return release,versioninfo,machine
770
771def _mac_ver_xml():
772 fn = '/System/Library/CoreServices/SystemVersion.plist'
773 if not os.path.exists(fn):
774 return None
775
776 try:
777 import plistlib
778 except ImportError:
779 return None
780
781 pl = plistlib.readPlist(fn)
782 release = pl['ProductVersion']
783 versioninfo=('', '', '')
784 machine = os.uname()[4]
Ronald Oussoren22e3e692010-08-03 07:44:35 +0000785 if machine in ('ppc', 'Power Macintosh'):
Ronald Oussoren3a04a252010-07-23 12:41:00 +0000786 # for compatibility with the gestalt based code
787 machine = 'PowerPC'
788
789 return release,versioninfo,machine
790
791
792def mac_ver(release='',versioninfo=('','',''),machine=''):
793
794 """ Get MacOS version information and return it as tuple (release,
795 versioninfo, machine) with versioninfo being a tuple (version,
796 dev_stage, non_release_version).
797
798 Entries which cannot be determined are set to the paramter values
799 which default to ''. All tuple entries are strings.
800 """
801
802 # First try reading the information from an XML file which should
803 # always be present
804 info = _mac_ver_xml()
805 if info is not None:
806 return info
807
808 # If that doesn't work for some reason fall back to reading the
809 # information using gestalt calls.
810 info = _mac_ver_gestalt()
811 if info is not None:
812 return info
813
814 # If that also doesn't work return the default values
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000815 return release,versioninfo,machine
816
Neal Norwitz9b924c62003-06-29 04:17:45 +0000817def _java_getprop(name,default):
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000818
819 from java.lang import System
820 try:
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +0000821 value = System.getProperty(name)
822 if value is None:
823 return default
824 return value
825 except AttributeError:
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000826 return default
827
828def java_ver(release='',vendor='',vminfo=('','',''),osinfo=('','','')):
Tim Peters0eadaac2003-04-24 16:02:54 +0000829
Brett Cannon8ab27df2003-08-05 03:52:04 +0000830 """ Version interface for Jython.
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000831
832 Returns a tuple (release,vendor,vminfo,osinfo) with vminfo being
833 a tuple (vm_name,vm_release,vm_vendor) and osinfo being a
834 tuple (os_name,os_version,os_arch).
835
836 Values which cannot be determined are set to the defaults
837 given as parameters (which all default to '').
838
839 """
840 # Import the needed APIs
841 try:
842 import java.lang
843 except ImportError:
844 return release,vendor,vminfo,osinfo
845
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +0000846 vendor = _java_getprop('java.vendor', vendor)
847 release = _java_getprop('java.version', release)
848 vm_name, vm_release, vm_vendor = vminfo
849 vm_name = _java_getprop('java.vm.name', vm_name)
850 vm_vendor = _java_getprop('java.vm.vendor', vm_vendor)
851 vm_release = _java_getprop('java.vm.version', vm_release)
852 vminfo = vm_name, vm_release, vm_vendor
853 os_name, os_version, os_arch = osinfo
854 os_arch = _java_getprop('java.os.arch', os_arch)
855 os_name = _java_getprop('java.os.name', os_name)
856 os_version = _java_getprop('java.os.version', os_version)
857 osinfo = os_name, os_version, os_arch
Tim Peters0eadaac2003-04-24 16:02:54 +0000858
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +0000859 return release, vendor, vminfo, osinfo
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000860
861### System name aliasing
862
863def system_alias(system,release,version):
864
865 """ Returns (system,release,version) aliased to common
866 marketing names used for some systems.
867
868 It also does some reordering of the information in some cases
869 where it would otherwise cause confusion.
870
871 """
872 if system == 'Rhapsody':
873 # Apple's BSD derivative
874 # XXX How can we determine the marketing release number ?
875 return 'MacOS X Server',system+release,version
876
877 elif system == 'SunOS':
878 # Sun's OS
879 if release < '5':
880 # These releases use the old name SunOS
881 return system,release,version
882 # Modify release (marketing release = SunOS release - 3)
883 l = string.split(release,'.')
884 if l:
885 try:
886 major = int(l[0])
887 except ValueError:
888 pass
889 else:
890 major = major - 3
891 l[0] = str(major)
892 release = string.join(l,'.')
893 if release < '6':
894 system = 'Solaris'
895 else:
896 # XXX Whatever the new SunOS marketing name is...
897 system = 'Solaris'
898
899 elif system == 'IRIX64':
900 # IRIX reports IRIX64 on platforms with 64-bit support; yet it
901 # is really a version and not a different platform, since 32-bit
902 # apps are also supported..
903 system = 'IRIX'
904 if version:
905 version = version + ' (64bit)'
906 else:
907 version = '64bit'
908
909 elif system in ('win32','win16'):
910 # In case one of the other tricks
911 system = 'Windows'
912
913 return system,release,version
914
915### Various internal helpers
916
917def _platform(*args):
918
919 """ Helper to format the platform string in a filename
920 compatible format e.g. "system-version-machine".
921 """
922 # Format the platform string
923 platform = string.join(
924 map(string.strip,
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +0000925 filter(len, args)),
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000926 '-')
927
928 # Cleanup some possible filename obstacles...
929 replace = string.replace
930 platform = replace(platform,' ','_')
931 platform = replace(platform,'/','-')
932 platform = replace(platform,'\\','-')
933 platform = replace(platform,':','-')
934 platform = replace(platform,';','-')
935 platform = replace(platform,'"','-')
936 platform = replace(platform,'(','-')
937 platform = replace(platform,')','-')
938
939 # No need to report 'unknown' information...
940 platform = replace(platform,'unknown','')
941
942 # Fold '--'s and remove trailing '-'
943 while 1:
944 cleaned = replace(platform,'--','-')
945 if cleaned == platform:
946 break
947 platform = cleaned
948 while platform[-1] == '-':
949 platform = platform[:-1]
950
951 return platform
952
953def _node(default=''):
954
955 """ Helper to determine the node name of this machine.
956 """
957 try:
958 import socket
959 except ImportError:
960 # No sockets...
961 return default
962 try:
963 return socket.gethostname()
964 except socket.error:
965 # Still not working...
966 return default
967
968# os.path.abspath is new in Python 1.5.2:
969if not hasattr(os.path,'abspath'):
970
971 def _abspath(path,
972
973 isabs=os.path.isabs,join=os.path.join,getcwd=os.getcwd,
974 normpath=os.path.normpath):
975
976 if not isabs(path):
977 path = join(getcwd(), path)
978 return normpath(path)
979
980else:
981
982 _abspath = os.path.abspath
983
984def _follow_symlinks(filepath):
985
986 """ In case filepath is a symlink, follow it until a
987 real file is reached.
988 """
989 filepath = _abspath(filepath)
990 while os.path.islink(filepath):
991 filepath = os.path.normpath(
Hirokazu Yamamoto171c4aa2008-09-04 11:15:14 +0000992 os.path.join(os.path.dirname(filepath),os.readlink(filepath)))
Marc-André Lemburg246d8472003-04-24 11:36:11 +0000993 return filepath
994
995def _syscmd_uname(option,default=''):
996
997 """ Interface to the system's uname command.
998 """
999 if sys.platform in ('dos','win32','win16','os2'):
1000 # XXX Others too ?
1001 return default
1002 try:
Marc-André Lemburg19e5b3f2009-07-13 20:23:49 +00001003 f = os.popen('uname %s 2> %s' % (option, DEV_NULL))
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001004 except (AttributeError,os.error):
1005 return default
1006 output = string.strip(f.read())
1007 rc = f.close()
1008 if not output or rc:
1009 return default
1010 else:
1011 return output
1012
1013def _syscmd_file(target,default=''):
1014
1015 """ Interface to the system's file command.
1016
1017 The function uses the -b option of the file command to have it
1018 ommit the filename in its output and if possible the -L option
1019 to have the command follow symlinks. It returns default in
1020 case the command should fail.
1021
1022 """
Jesus Ceadebda5d2012-10-04 15:14:56 +02001023
1024 # We do the import here to avoid a bootstrap issue.
1025 # See c73b90b6dadd changeset.
1026 #
1027 # [..]
1028 # ranlib libpython2.7.a
1029 # gcc -o python \
1030 # Modules/python.o \
1031 # libpython2.7.a -lsocket -lnsl -ldl -lm
1032 # Traceback (most recent call last):
1033 # File "./setup.py", line 8, in <module>
1034 # from platform import machine as platform_machine
1035 # File "[..]/build/Lib/platform.py", line 116, in <module>
1036 # import sys,string,os,re,subprocess
1037 # File "[..]/build/Lib/subprocess.py", line 429, in <module>
1038 # import select
1039 # ImportError: No module named select
1040
1041 import subprocess
1042
Hirokazu Yamamotoed8c6442008-09-01 14:32:58 +00001043 if sys.platform in ('dos','win32','win16','os2'):
1044 # XXX Others too ?
1045 return default
Jesus Cea3e94e142012-10-04 15:06:57 +02001046 target = _follow_symlinks(target)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001047 try:
Jesus Cea69e7c9b2012-10-05 04:50:17 +02001048 proc = subprocess.Popen(['file', '-b', '--', target],
1049 stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
Jesus Cea3e94e142012-10-04 15:06:57 +02001050
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001051 except (AttributeError,os.error):
1052 return default
Jesus Cea69e7c9b2012-10-05 04:50:17 +02001053 output = proc.communicate()[0]
Jesus Cea3e94e142012-10-04 15:06:57 +02001054 rc = proc.wait()
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001055 if not output or rc:
1056 return default
1057 else:
1058 return output
1059
1060### Information about the used architecture
1061
1062# Default values for architecture; non-empty strings override the
1063# defaults given as parameters
1064_default_architecture = {
1065 'win32': ('','WindowsPE'),
1066 'win16': ('','Windows'),
1067 'dos': ('','MSDOS'),
1068}
1069
Victor Stinner814b6c22010-04-18 18:22:25 +00001070_architecture_split = re.compile(r'[\s,]').split
1071
Marc-André Lemburg366a0fe2003-04-24 11:46:35 +00001072def architecture(executable=sys.executable,bits='',linkage=''):
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001073
1074 """ Queries the given executable (defaults to the Python interpreter
Brett Cannon8ab27df2003-08-05 03:52:04 +00001075 binary) for various architecture information.
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001076
Brett Cannon8ab27df2003-08-05 03:52:04 +00001077 Returns a tuple (bits,linkage) which contains information about
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001078 the bit architecture and the linkage format used for the
1079 executable. Both values are returned as strings.
1080
1081 Values that cannot be determined are returned as given by the
1082 parameter presets. If bits is given as '', the sizeof(pointer)
1083 (or sizeof(long) on Python version < 1.5.2) is used as
1084 indicator for the supported pointer size.
1085
1086 The function relies on the system's "file" command to do the
1087 actual work. This is available on most if not all Unix
Brett Cannon8ab27df2003-08-05 03:52:04 +00001088 platforms. On some non-Unix platforms where the "file" command
1089 does not exist and the executable is set to the Python interpreter
1090 binary defaults from _default_architecture are used.
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001091
1092 """
1093 # Use the sizeof(pointer) as default number of bits if nothing
1094 # else is given as default.
1095 if not bits:
1096 import struct
1097 try:
1098 size = struct.calcsize('P')
1099 except struct.error:
1100 # Older installations can only query longs
1101 size = struct.calcsize('l')
1102 bits = str(size*8) + 'bit'
Tim Peters0eadaac2003-04-24 16:02:54 +00001103
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001104 # Get data from the 'file' system command
Marc-André Lemburg3b8f60b2007-01-13 23:13:54 +00001105 if executable:
Victor Stinner814b6c22010-04-18 18:22:25 +00001106 output = _syscmd_file(executable, '')
Marc-André Lemburg3b8f60b2007-01-13 23:13:54 +00001107 else:
Victor Stinner814b6c22010-04-18 18:22:25 +00001108 output = ''
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001109
Victor Stinner814b6c22010-04-18 18:22:25 +00001110 if not output and \
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001111 executable == sys.executable:
1112 # "file" command did not return anything; we'll try to provide
Tim Peters0eadaac2003-04-24 16:02:54 +00001113 # some sensible defaults then...
Florent Xicluna8d1da0f2010-04-01 18:17:09 +00001114 if sys.platform in _default_architecture:
1115 b, l = _default_architecture[sys.platform]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001116 if b:
1117 bits = b
1118 if l:
1119 linkage = l
Florent Xicluna8d1da0f2010-04-01 18:17:09 +00001120 return bits, linkage
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001121
Victor Stinner814b6c22010-04-18 18:22:25 +00001122 # Split the output into a list of strings omitting the filename
1123 fileout = _architecture_split(output)[1:]
1124
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001125 if 'executable' not in fileout:
1126 # Format not supported
1127 return bits,linkage
1128
1129 # Bits
1130 if '32-bit' in fileout:
1131 bits = '32bit'
1132 elif 'N32' in fileout:
1133 # On Irix only
1134 bits = 'n32bit'
1135 elif '64-bit' in fileout:
1136 bits = '64bit'
1137
1138 # Linkage
1139 if 'ELF' in fileout:
1140 linkage = 'ELF'
1141 elif 'PE' in fileout:
1142 # E.g. Windows uses this format
1143 if 'Windows' in fileout:
1144 linkage = 'WindowsPE'
1145 else:
1146 linkage = 'PE'
1147 elif 'COFF' in fileout:
1148 linkage = 'COFF'
1149 elif 'MS-DOS' in fileout:
1150 linkage = 'MSDOS'
1151 else:
1152 # XXX the A.OUT format also falls under this class...
1153 pass
1154
1155 return bits,linkage
1156
1157### Portable uname() interface
Tim Peters0eadaac2003-04-24 16:02:54 +00001158
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001159_uname_cache = None
1160
1161def uname():
1162
1163 """ Fairly portable uname interface. Returns a tuple
1164 of strings (system,node,release,version,machine,processor)
1165 identifying the underlying platform.
1166
1167 Note that unlike the os.uname function this also returns
Brett Cannon8ab27df2003-08-05 03:52:04 +00001168 possible processor information as an additional tuple entry.
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001169
1170 Entries which cannot be determined are set to ''.
1171
1172 """
1173 global _uname_cache
Benjamin Peterson5c0be322008-06-13 15:11:50 +00001174 no_os_uname = 0
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001175
1176 if _uname_cache is not None:
1177 return _uname_cache
1178
Benjamin Peterson5c0be322008-06-13 15:11:50 +00001179 processor = ''
1180
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001181 # Get some infos from the builtin os.uname API...
1182 try:
1183 system,node,release,version,machine = os.uname()
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001184 except AttributeError:
Benjamin Peterson5c0be322008-06-13 15:11:50 +00001185 no_os_uname = 1
1186
1187 if no_os_uname or not filter(None, (system, node, release, version, machine)):
1188 # Hmm, no there is either no uname or uname has returned
1189 #'unknowns'... we'll have to poke around the system then.
1190 if no_os_uname:
1191 system = sys.platform
1192 release = ''
1193 version = ''
1194 node = _node()
1195 machine = ''
1196
Marc-André Lemburgcecaa652009-07-13 21:28:33 +00001197 use_syscmd_ver = 1
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001198
1199 # Try win32_ver() on win32 platforms
1200 if system == 'win32':
1201 release,version,csd,ptype = win32_ver()
1202 if release and version:
1203 use_syscmd_ver = 0
Marc-André Lemburgdbd61a22008-03-20 17:31:36 +00001204 # Try to use the PROCESSOR_* environment variables
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001205 # available on Win XP and later; see
1206 # http://support.microsoft.com/kb/888731 and
1207 # http://www.geocities.com/rick_lively/MANUALS/ENV/MSWIN/PROCESSI.HTM
Benjamin Peterson5c0be322008-06-13 15:11:50 +00001208 if not machine:
R. David Murrayc9d1a782010-03-22 15:55:09 +00001209 # WOW64 processes mask the native architecture
1210 if "PROCESSOR_ARCHITEW6432" in os.environ:
1211 machine = os.environ.get("PROCESSOR_ARCHITEW6432", '')
1212 else:
1213 machine = os.environ.get('PROCESSOR_ARCHITECTURE', '')
Benjamin Peterson5c0be322008-06-13 15:11:50 +00001214 if not processor:
1215 processor = os.environ.get('PROCESSOR_IDENTIFIER', machine)
Tim Peters0eadaac2003-04-24 16:02:54 +00001216
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001217 # Try the 'ver' system command available on some
1218 # platforms
1219 if use_syscmd_ver:
1220 system,release,version = _syscmd_ver(system)
Marc-André Lemburgcdc79232004-06-19 17:17:00 +00001221 # Normalize system to what win32_ver() normally returns
1222 # (_syscmd_ver() tends to return the vendor name as well)
1223 if system == 'Microsoft Windows':
1224 system = 'Windows'
Marc-André Lemburgb24cd0f2007-06-12 09:26:49 +00001225 elif system == 'Microsoft' and release == 'Windows':
1226 # Under Windows Vista and Windows Server 2008,
1227 # Microsoft changed the output of the ver command. The
1228 # release is no longer printed. This causes the
1229 # system and release to be misidentified.
1230 system = 'Windows'
1231 if '6.0' == version[:3]:
1232 release = 'Vista'
1233 else:
1234 release = ''
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001235
1236 # In case we still don't know anything useful, we'll try to
1237 # help ourselves
1238 if system in ('win32','win16'):
1239 if not version:
1240 if system == 'win32':
1241 version = '32bit'
1242 else:
1243 version = '16bit'
1244 system = 'Windows'
1245
1246 elif system[:4] == 'java':
1247 release,vendor,vminfo,osinfo = java_ver()
1248 system = 'Java'
1249 version = string.join(vminfo,', ')
1250 if not version:
1251 version = vendor
1252
Benjamin Peterson5c0be322008-06-13 15:11:50 +00001253 # System specific extensions
1254 if system == 'OpenVMS':
1255 # OpenVMS seems to have release and version mixed up
1256 if not release or release == '0':
1257 release = version
1258 version = ''
1259 # Get processor information
1260 try:
1261 import vms_lib
1262 except ImportError:
1263 pass
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001264 else:
Benjamin Peterson5c0be322008-06-13 15:11:50 +00001265 csid, cpu_number = vms_lib.getsyi('SYI$_CPU',0)
1266 if (cpu_number >= 128):
1267 processor = 'Alpha'
1268 else:
1269 processor = 'VAX'
1270 if not processor:
1271 # Get processor information from the uname system command
1272 processor = _syscmd_uname('-p','')
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001273
Benjamin Peterson5c0be322008-06-13 15:11:50 +00001274 #If any unknowns still exist, replace them with ''s, which are more portable
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001275 if system == 'unknown':
1276 system = ''
1277 if node == 'unknown':
1278 node = ''
1279 if release == 'unknown':
1280 release = ''
1281 if version == 'unknown':
1282 version = ''
1283 if machine == 'unknown':
1284 machine = ''
1285 if processor == 'unknown':
1286 processor = ''
Sean Reifscheiderf09597c2007-09-17 20:53:21 +00001287
1288 # normalize name
1289 if system == 'Microsoft' and release == 'Windows':
1290 system = 'Windows'
1291 release = 'Vista'
1292
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001293 _uname_cache = system,node,release,version,machine,processor
1294 return _uname_cache
1295
1296### Direct interfaces to some of the uname() return values
1297
1298def system():
1299
1300 """ Returns the system/OS name, e.g. 'Linux', 'Windows' or 'Java'.
1301
1302 An empty string is returned if the value cannot be determined.
1303
1304 """
1305 return uname()[0]
1306
1307def node():
1308
Brett Cannon8ab27df2003-08-05 03:52:04 +00001309 """ Returns the computer's network name (which may not be fully
1310 qualified)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001311
1312 An empty string is returned if the value cannot be determined.
1313
1314 """
1315 return uname()[1]
1316
1317def release():
1318
1319 """ Returns the system's release, e.g. '2.2.0' or 'NT'
1320
1321 An empty string is returned if the value cannot be determined.
1322
1323 """
1324 return uname()[2]
1325
1326def version():
1327
1328 """ Returns the system's release version, e.g. '#3 on degas'
1329
1330 An empty string is returned if the value cannot be determined.
1331
1332 """
1333 return uname()[3]
1334
1335def machine():
1336
1337 """ Returns the machine type, e.g. 'i386'
1338
1339 An empty string is returned if the value cannot be determined.
1340
1341 """
1342 return uname()[4]
1343
1344def processor():
1345
1346 """ Returns the (true) processor name, e.g. 'amdk6'
1347
1348 An empty string is returned if the value cannot be
1349 determined. Note that many platforms do not provide this
1350 information or simply return the same value as for machine(),
1351 e.g. NetBSD does this.
1352
1353 """
1354 return uname()[5]
1355
1356### Various APIs for extracting information from sys.version
1357
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001358_sys_version_parser = re.compile(
1359 r'([\w.+]+)\s*'
1360 '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
1361 '\[([^\]]+)\]?')
1362
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001363_ironpython_sys_version_parser = re.compile(
1364 r'IronPython\s*'
1365 '([\d\.]+)'
1366 '(?: \(([\d\.]+)\))?'
1367 ' on (.NET [\d\.]+)')
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001368
Benjamin Peterson0ad9b772009-03-26 19:09:21 +00001369_pypy_sys_version_parser = re.compile(
1370 r'([\w.+]+)\s*'
1371 '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
1372 '\[PyPy [^\]]+\]?')
1373
Marc-André Lemburg2be9d432007-01-13 22:32:21 +00001374_sys_version_cache = {}
1375
1376def _sys_version(sys_version=None):
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001377
1378 """ Returns a parsed version of Python's sys.version as tuple
Marc-André Lemburga519cfc2009-03-25 19:44:58 +00001379 (name, version, branch, revision, buildno, builddate, compiler)
1380 referring to the Python implementation name, version, branch,
1381 revision, build number, build date/time as string and the compiler
1382 identification string.
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001383
1384 Note that unlike the Python sys.version, the returned value
1385 for the Python version will always include the patchlevel (it
1386 defaults to '.0').
1387
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001388 The function returns empty strings for tuple entries that
1389 cannot be determined.
1390
Marc-André Lemburg2be9d432007-01-13 22:32:21 +00001391 sys_version may be given to parse an alternative version
1392 string, e.g. if the version was read from a different Python
1393 interpreter.
1394
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001395 """
Marc-André Lemburg2be9d432007-01-13 22:32:21 +00001396 # Get the Python version
1397 if sys_version is None:
1398 sys_version = sys.version
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001399
Marc-André Lemburg2be9d432007-01-13 22:32:21 +00001400 # Try the cache first
1401 result = _sys_version_cache.get(sys_version, None)
1402 if result is not None:
1403 return result
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001404
Marc-André Lemburg2be9d432007-01-13 22:32:21 +00001405 # Parse it
1406 if sys_version[:10] == 'IronPython':
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001407 # IronPython
1408 name = 'IronPython'
Marc-André Lemburg2be9d432007-01-13 22:32:21 +00001409 match = _ironpython_sys_version_parser.match(sys_version)
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001410 if match is None:
1411 raise ValueError(
1412 'failed to parse IronPython sys.version: %s' %
Marc-André Lemburg2be9d432007-01-13 22:32:21 +00001413 repr(sys_version))
1414 version, alt_version, compiler = match.groups()
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001415 buildno = ''
1416 builddate = ''
1417
1418 elif sys.platform[:4] == 'java':
1419 # Jython
1420 name = 'Jython'
Benjamin Petersonf521b8c2009-03-26 18:35:37 +00001421 match = _sys_version_parser.match(sys_version)
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001422 if match is None:
1423 raise ValueError(
1424 'failed to parse Jython sys.version: %s' %
Marc-André Lemburg2be9d432007-01-13 22:32:21 +00001425 repr(sys_version))
Benjamin Petersonf521b8c2009-03-26 18:35:37 +00001426 version, buildno, builddate, buildtime, _ = match.groups()
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001427 compiler = sys.platform
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001428
Benjamin Peterson0ad9b772009-03-26 19:09:21 +00001429 elif "PyPy" in sys_version:
1430 # PyPy
1431 name = "PyPy"
1432 match = _pypy_sys_version_parser.match(sys_version)
1433 if match is None:
1434 raise ValueError("failed to parse PyPy sys.version: %s" %
1435 repr(sys_version))
1436 version, buildno, builddate, buildtime = match.groups()
1437 compiler = ""
1438
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001439 else:
1440 # CPython
Marc-André Lemburg2be9d432007-01-13 22:32:21 +00001441 match = _sys_version_parser.match(sys_version)
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001442 if match is None:
1443 raise ValueError(
1444 'failed to parse CPython sys.version: %s' %
Marc-André Lemburg2be9d432007-01-13 22:32:21 +00001445 repr(sys_version))
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001446 version, buildno, builddate, buildtime, compiler = \
1447 match.groups()
Benjamin Petersonb457b892009-03-26 18:55:48 +00001448 name = 'CPython'
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001449 builddate = builddate + ' ' + buildtime
Marc-André Lemburg2be9d432007-01-13 22:32:21 +00001450
Benjamin Petersonb457b892009-03-26 18:55:48 +00001451 if hasattr(sys, 'subversion'):
1452 # sys.subversion was added in Python 2.5
1453 _, branch, revision = sys.subversion
1454 else:
1455 branch = ''
1456 revision = ''
1457
Marc-André Lemburg2be9d432007-01-13 22:32:21 +00001458 # Add the patchlevel version if missing
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001459 l = string.split(version, '.')
1460 if len(l) == 2:
1461 l.append('0')
1462 version = string.join(l, '.')
Marc-André Lemburg2be9d432007-01-13 22:32:21 +00001463
1464 # Build and cache the result
1465 result = (name, version, branch, revision, buildno, builddate, compiler)
1466 _sys_version_cache[sys_version] = result
1467 return result
1468
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001469def python_implementation():
1470
1471 """ Returns a string identifying the Python implementation.
1472
1473 Currently, the following implementations are identified:
Ezio Melotti6fa09472011-05-04 18:37:50 +03001474 'CPython' (C implementation of Python),
1475 'IronPython' (.NET implementation of Python),
1476 'Jython' (Java implementation of Python),
1477 'PyPy' (Python implementation of Python).
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001478
1479 """
1480 return _sys_version()[0]
1481
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001482def python_version():
1483
1484 """ Returns the Python version as string 'major.minor.patchlevel'
1485
1486 Note that unlike the Python sys.version, the returned value
1487 will always include the patchlevel (it defaults to 0).
1488
1489 """
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001490 return _sys_version()[1]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001491
1492def python_version_tuple():
1493
1494 """ Returns the Python version as tuple (major, minor, patchlevel)
1495 of strings.
1496
1497 Note that unlike the Python sys.version, the returned value
1498 will always include the patchlevel (it defaults to 0).
1499
1500 """
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001501 return tuple(string.split(_sys_version()[1], '.'))
1502
1503def python_branch():
1504
Neal Norwitz4b86f8b2007-01-13 21:22:37 +00001505 """ Returns a string identifying the Python implementation
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001506 branch.
1507
1508 For CPython this is the Subversion branch from which the
1509 Python binary was built.
1510
1511 If not available, an empty string is returned.
1512
1513 """
Tim Petersf733abb72007-01-30 03:03:46 +00001514
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001515 return _sys_version()[2]
1516
1517def python_revision():
1518
Neal Norwitz4b86f8b2007-01-13 21:22:37 +00001519 """ Returns a string identifying the Python implementation
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001520 revision.
1521
1522 For CPython this is the Subversion revision from which the
1523 Python binary was built.
1524
1525 If not available, an empty string is returned.
1526
1527 """
1528 return _sys_version()[3]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001529
1530def python_build():
1531
1532 """ Returns a tuple (buildno, builddate) stating the Python
1533 build number and date as strings.
1534
1535 """
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001536 return _sys_version()[4:6]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001537
1538def python_compiler():
1539
1540 """ Returns a string identifying the compiler used for compiling
1541 Python.
1542
1543 """
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001544 return _sys_version()[6]
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001545
1546### The Opus Magnum of platform strings :-)
1547
Marc-André Lemburg91e83e22004-03-25 18:35:12 +00001548_platform_cache = {}
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001549
1550def platform(aliased=0, terse=0):
1551
1552 """ Returns a single string identifying the underlying platform
1553 with as much useful information as possible (but no more :).
Tim Peters0eadaac2003-04-24 16:02:54 +00001554
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001555 The output is intended to be human readable rather than
1556 machine parseable. It may look different on different
1557 platforms and this is intended.
1558
1559 If "aliased" is true, the function will use aliases for
1560 various platforms that report system names which differ from
1561 their common names, e.g. SunOS will be reported as
1562 Solaris. The system_alias() function is used to implement
1563 this.
1564
1565 Setting terse to true causes the function to return only the
1566 absolute minimum information needed to identify the platform.
1567
1568 """
Marc-André Lemburg91e83e22004-03-25 18:35:12 +00001569 result = _platform_cache.get((aliased, terse), None)
1570 if result is not None:
1571 return result
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001572
1573 # Get uname information and then apply platform specific cosmetics
1574 # to it...
1575 system,node,release,version,machine,processor = uname()
1576 if machine == processor:
1577 processor = ''
1578 if aliased:
1579 system,release,version = system_alias(system,release,version)
1580
1581 if system == 'Windows':
1582 # MS platforms
1583 rel,vers,csd,ptype = win32_ver(version)
1584 if terse:
1585 platform = _platform(system,release)
1586 else:
1587 platform = _platform(system,release,version,csd)
1588
1589 elif system in ('Linux',):
1590 # Linux based systems
1591 distname,distversion,distid = dist('')
1592 if distname and not terse:
1593 platform = _platform(system,release,machine,processor,
1594 'with',
1595 distname,distversion,distid)
1596 else:
1597 # If the distribution name is unknown check for libc vs. glibc
1598 libcname,libcversion = libc_ver(sys.executable)
1599 platform = _platform(system,release,machine,processor,
1600 'with',
1601 libcname+libcversion)
1602 elif system == 'Java':
1603 # Java platforms
1604 r,v,vminfo,(os_name,os_version,os_arch) = java_ver()
Marc-André Lemburg9e0dc962007-01-13 21:00:08 +00001605 if terse or not os_name:
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001606 platform = _platform(system,release,version)
1607 else:
1608 platform = _platform(system,release,version,
1609 'on',
1610 os_name,os_version,os_arch)
1611
1612 elif system == 'MacOS':
1613 # MacOS platforms
1614 if terse:
1615 platform = _platform(system,release)
1616 else:
1617 platform = _platform(system,release,machine)
1618
1619 else:
1620 # Generic handler
1621 if terse:
1622 platform = _platform(system,release)
1623 else:
1624 bits,linkage = architecture(sys.executable)
1625 platform = _platform(system,release,machine,processor,bits,linkage)
Tim Peters0eadaac2003-04-24 16:02:54 +00001626
Marc-André Lemburg91e83e22004-03-25 18:35:12 +00001627 _platform_cache[(aliased, terse)] = platform
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001628 return platform
1629
1630### Command line interface
1631
1632if __name__ == '__main__':
1633 # Default is to print the aliased verbose platform string
Tim Peters0eadaac2003-04-24 16:02:54 +00001634 terse = ('terse' in sys.argv or '--terse' in sys.argv)
Marc-André Lemburg246d8472003-04-24 11:36:11 +00001635 aliased = (not 'nonaliased' in sys.argv and not '--nonaliased' in sys.argv)
1636 print platform(aliased,terse)
1637 sys.exit(0)