3 """ This module tries to retrieve as much platform identifying data as
4 possible. It makes this information available via function APIs.
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.
11 # This module is maintained by Marc-Andre Lemburg <mal@egenix.com>.
12 # If you find problems, please submit bug reports/patches via the
13 # Python SourceForge Project Page and assign them to "lemburg".
15 # Note: Please keep this module compatible to Python 1.5.2.
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
23 # Many thanks to all those who helped adding platform specific
24 # checks (in no particular order):
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),
31 # Colin Kong, Trent Mick
34 # 1.0.1 - reformatted to make doc.py happy
35 # 1.0.0 - reformatted a bit and checked into Python CVS
36 # 0.8.0 - added sys.version parser and various new access
37 # APIs (python_version(), python_compiler(), etc.)
38 # 0.7.2 - fixed architecture() to use sizeof(pointer) where available
39 # 0.7.1 - added support for Caldera OpenLinux
40 # 0.7.0 - some fixes for WinCE; untabified the source file
41 # 0.6.2 - support for OpenVMS - requires version 1.5.2-V006 or higher and
42 # vms_lib.getsyi() configured
43 # 0.6.1 - added code to prevent 'uname -p' on platforms which are
44 # known not to support it
45 # 0.6.0 - fixed win32_ver() to hopefully work on Win95,98,NT and Win2k;
46 # did some cleanup of the interfaces - some APIs have changed
47 # 0.5.5 - fixed another type in the MacOS code... should have
48 # used more coffee today ;-)
49 # 0.5.4 - fixed a few typos in the MacOS code
50 # 0.5.3 - added experimental MacOS support; added better popen()
51 # workarounds in _syscmd_ver() -- still not 100% elegant
53 # 0.5.2 - fixed uname() to return '' instead of 'unknown' in all
54 # return values (the system uname command tends to return
55 # 'unknown' instead of just leaving the field emtpy)
56 # 0.5.1 - included code for slackware dist; added exception handlers
57 # to cover up situations where platforms don't have os.popen
58 # (e.g. Mac) or fail on socket.gethostname(); fixed libc
60 # 0.5.0 - changed the API names referring to system commands to *syscmd*;
61 # added java_ver(); made syscmd_ver() a private
62 # API (was system_ver() in previous versions) -- use uname()
63 # instead; extended the win32_ver() to also return processor
65 # 0.4.0 - added win32_ver() and modified the platform() output for WinXX
66 # 0.3.4 - fixed a bug in _follow_symlinks()
67 # 0.3.3 - fixed popen() and "file" command invokation bugs
68 # 0.3.2 - added architecture() API and support for it in platform()
69 # 0.3.1 - fixed syscmd_ver() RE to support Windows NT
70 # 0.3.0 - added system alias support
71 # 0.2.3 - removed 'wince' again... oh well.
72 # 0.2.2 - added 'wince' to syscmd_ver() supported platforms
73 # 0.2.1 - added cache logic and changed the platform string format
74 # 0.2.0 - changed the API to use functions instead of module globals
75 # since some action take too long to be run on module import
76 # 0.1.0 - first release
78 # You can always get the latest version of this module at:
80 # http://www.egenix.com/files/python/platform.py
82 # If that URL should fail, try contacting the author.
85 Copyright (c) 1999-2000, Marc-Andre Lemburg; mailto:mal@lemburg.com
86 Copyright (c) 2000-2003, eGenix.com Software GmbH; mailto:info@egenix.com
88 Permission to use, copy, modify, and distribute this software and its
89 documentation for any purpose and without fee or royalty is hereby granted,
90 provided that the above copyright notice appear in all copies and that
91 both that copyright notice and this permission notice appear in
92 supporting documentation or portions thereof, including modifications,
95 EGENIX.COM SOFTWARE GMBH DISCLAIMS ALL WARRANTIES WITH REGARD TO
96 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
97 FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
98 INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
99 FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
100 NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
101 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE !
105 __version__
= '1.0.1'
107 import sys
,string
,os
,re
109 ### Platform specific APIs
111 _libc_search
= re
.compile(r
'(__libc_init)'
115 '(libc(_\w+)?\.so(?:\.(\d[0-9.]*))?)')
117 def libc_ver(executable
=sys
.executable
,lib
='',version
='',
121 """ Tries to determine the libc version against which the
122 file executable (defaults to the Python interpreter) is linked.
124 Returns a tuple of strings (lib,version) which default to the
125 given parameters in case the lookup fails.
127 Note that the function has intimate knowledge of how different
128 libc versions add symbols to the executable is probably only
129 useable for executables compiled using gcc.
131 The file is read and scanned in chunks of chunksize bytes.
134 f
= open(executable
,'rb')
135 binary
= f
.read(chunksize
)
138 m
= _libc_search
.search(binary
,pos
)
140 binary
= f
.read(chunksize
)
145 libcinit
,glibc
,glibcversion
,so
,threads
,soversion
= m
.groups()
146 if libcinit
and not lib
:
151 version
= glibcversion
152 elif glibcversion
> version
:
153 version
= glibcversion
157 if soversion
> version
:
159 if threads
and version
[-len(threads
):] != threads
:
160 version
= version
+ threads
165 def _dist_try_harder(distname
,version
,id):
167 """ Tries some special tricks to get the distribution
168 information in case the default method fails.
170 Currently supports older SuSE Linux, Caldera OpenLinux and
171 Slackware Linux distributions.
174 if os
.path
.exists('/var/adm/inst-log/info'):
175 # SuSE Linux stores distribution information in that file
176 info
= open('/var/adm/inst-log/info').readlines()
179 tv
= string
.split(line
)
184 if tag
== 'MIN_DIST_VERSION':
185 version
= string
.strip(value
)
186 elif tag
== 'DIST_IDENT':
187 values
= string
.split(value
,'-')
189 return distname
,version
,id
191 if os
.path
.exists('/etc/.installed'):
192 # Caldera OpenLinux has some infos in that file (thanks to Colin Kong)
193 info
= open('/etc/.installed').readlines()
195 pkg
= string
.split(line
,'-')
196 if len(pkg
) >= 2 and pkg
[0] == 'OpenLinux':
197 # XXX does Caldera support non Intel platforms ? If yes,
198 # where can we find the needed id ?
199 return 'OpenLinux',pkg
[1],id
201 if os
.path
.isdir('/usr/lib/setup'):
202 # Check for slackware verson tag file (thanks to Greg Andruk)
203 verfiles
= os
.listdir('/usr/lib/setup')
204 for n
in range(len(verfiles
)-1, -1, -1):
205 if verfiles
[n
][:14] != 'slack-version-':
209 distname
= 'slackware'
210 version
= verfiles
[-1][14:]
211 return distname
,version
,id
213 return distname
,version
,id
215 _release_filename
= re
.compile(r
'(\w+)[-_](release|version)')
216 _release_version
= re
.compile(r
'([\d.]+)[^(]*(?:\((.+)\))?')
218 def dist(distname
='',version
='',id='',
220 supported_dists
=('SuSE','debian','redhat','mandrake')):
222 """ Tries to determine the name of the OS distribution name
224 The function first looks for a distribution release file in
225 /etc and then reverts to _dist_try_harder() in case no
226 suitable files are found.
228 Returns a tuple distname,version,id which default to the
229 args given as parameters.
233 etc
= os
.listdir('/etc')
235 # Probably not a Unix system
236 return distname
,version
,id
238 m
= _release_filename
.match(file)
240 _distname
,dummy
= m
.groups()
241 if _distname
in supported_dists
:
245 return _dist_try_harder(distname
,version
,id)
246 f
= open('/etc/'+file,'r')
247 firstline
= f
.readline()
249 m
= _release_version
.search(firstline
)
251 _version
,_id
= m
.groups()
257 # Unkown format... take the first two words
258 l
= string
.split(string
.strip(firstline
))
263 return distname
,version
,id
267 """ Fairly portable (alternative) popen implementation.
269 This is mostly needed in case os.popen() is not available, or
270 doesn't work as advertised, e.g. in Win9X GUI programs like
273 Writing to the pipe is currently not supported.
281 def __init__(self
,cmd
,mode
='r',bufsize
=None):
284 raise ValueError,'popen()-emulation only supports read mode'
286 self
.tmpfile
= tmpfile
= tempfile
.mktemp()
287 os
.system(cmd
+ ' > %s' % tmpfile
)
288 self
.pipe
= open(tmpfile
,'rb')
289 self
.bufsize
= bufsize
294 return self
.pipe
.read()
298 if self
.bufsize
is not None:
299 return self
.pipe
.readlines()
303 remove
=os
.unlink
,error
=os
.error
):
306 rc
= self
.pipe
.close()
319 def popen(cmd
, mode
='r', bufsize
=None):
321 """ Portable popen() interface.
323 # Find a working popen implementation preferring win32pipe.popen
324 # over os.popen over _popen
326 if os
.environ
.get('OS','') == 'Windows_NT':
327 # On NT win32pipe should work; on Win9x it hangs due to bugs
328 # in the MS C lib (see MS KnowledgeBase article Q150956)
334 popen
= win32pipe
.popen
336 if hasattr(os
,'popen'):
338 # Check whether it works... it doesn't in GUI programs
339 # on Windows platforms
340 if sys
.platform
== 'win32': # XXX Others too ?
348 return popen(cmd
,mode
)
350 return popen(cmd
,mode
,bufsize
)
352 def _norm_version(version
,build
=''):
354 """ Normalize the version and build strings and return a sinlge
355 vesion string using the format major.minor.build (or patchlevel).
357 l
= string
.split(version
,'.')
365 strings
= map(str,ints
)
366 version
= string
.join(strings
[:3],'.')
369 _ver_output
= re
.compile(r
'(?:([\w ]+) ([\w.]+) '
373 def _syscmd_ver(system
='',release
='',version
='',
375 supported_platforms
=('win32','win16','dos','os2')):
377 """ Tries to figure out the OS version used and returns
378 a tuple (system,release,version).
380 It uses the "ver" shell command for this which is known
381 to exists on Windows, DOS and OS/2. XXX Others too ?
383 In case this fails, the given parameters are used as
387 if sys
.platform
not in supported_platforms
:
388 return system
,release
,version
390 # Try some common cmd strings
391 for cmd
in ('ver','command /c ver','cmd /c ver'):
396 raise os
.error
,'command failed'
397 # XXX How can I supress shell errors from being written
400 #print 'Command %s failed: %s' % (cmd,why)
403 #print 'Command %s failed: %s' % (cmd,why)
408 return system
,release
,version
411 info
= string
.strip(info
)
412 m
= _ver_output
.match(info
)
414 system
,release
,version
= m
.groups()
415 # Strip trailing dots from version and release
416 if release
[-1] == '.':
417 release
= release
[:-1]
418 if version
[-1] == '.':
419 version
= version
[:-1]
420 # Normalize the version and build strings (eliminating additional
422 version
= _norm_version(version
)
423 return system
,release
,version
425 def _win32_getvalue(key
,name
,default
=''):
427 """ Read a value for name from the registry key.
429 In case this fails, default is returned.
432 from win32api
import RegQueryValueEx
434 return RegQueryValueEx(key
,name
)
438 def win32_ver(release
='',version
='',csd
='',ptype
=''):
440 """ Get additional version information from the Windows Registry
441 and return a tuple (version,csd,ptype) referring to version
442 number, CSD level and OS type (multi/single
445 As a hint: ptype returns 'Uniprocessor Free' on single
446 processor NT machines and 'Multiprocessor Free' on multi
447 processor machines. The 'Free' refers to the OS version being
448 free of debugging code. It could also state 'Checked' which
449 means the OS version uses debugging code, i.e. code that
450 checks arguments, ranges, etc. (Thomas Heller).
452 Note: this function only works if Mark Hammond's win32
453 package is installed and obviously only runs on Win32
454 compatible platforms.
457 # XXX Is there any way to find out the processor type on WinXX ?
458 # XXX Is win32 available on Windows CE ?
459 # Adapted from code posted by Karl Putland to comp.lang.python.
461 # Import the needed APIs
465 return release
,version
,csd
,ptype
466 from win32api
import RegQueryValueEx
,RegOpenKeyEx
,RegCloseKey
,GetVersionEx
467 from win32con
import HKEY_LOCAL_MACHINE
,VER_PLATFORM_WIN32_NT
,\
468 VER_PLATFORM_WIN32_WINDOWS
470 # Find out the registry key and some general version infos
471 maj
,min,buildno
,plat
,csd
= GetVersionEx()
472 version
= '%i.%i.%i' % (maj
,min,buildno
& 0xFFFF)
473 if csd
[:13] == 'Service Pack ':
474 csd
= 'SP' + csd
[13:]
475 if plat
== VER_PLATFORM_WIN32_WINDOWS
:
476 regkey
= 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion'
477 # Try to guess the release name
485 elif plat
== VER_PLATFORM_WIN32_NT
:
486 regkey
= 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion'
493 # E.g. Win3.1 with win32s
494 release
= '%i.%i' % (maj
,min)
495 return release
,version
,csd
,ptype
497 # Open the registry key
499 keyCurVer
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
,regkey
)
500 # Get a value to make sure the key exists...
501 RegQueryValueEx(keyCurVer
,'SystemRoot')
503 return release
,version
,csd
,ptype
506 #subversion = _win32_getvalue(keyCurVer,
507 # 'SubVersionNumber',
510 # release = release + subversion # 95a, 95b, etc.
511 build
= _win32_getvalue(keyCurVer
,
512 'CurrentBuildNumber',
514 ptype
= _win32_getvalue(keyCurVer
,
519 version
= _norm_version(version
,build
)
522 RegCloseKey(keyCurVer
)
523 return release
,version
,csd
,ptype
525 def _mac_ver_lookup(selectors
,default
=None):
527 from gestalt
import gestalt
530 for selector
in selectors
:
532 append(gestalt(selector
))
541 def mac_ver(release
='',versioninfo
=('','',''),machine
=''):
543 """ Get MacOS version information and return it as tuple (release,
544 versioninfo, machine) with versioninfo being a tuple (version,
545 dev_stage, non_release_version).
547 Entries which cannot be determined are set to ''. All tuple
550 Thanks to Mark R. Levinson for mailing documentation links and
551 code examples for this function. Documentation for the
552 gestalt() API is available online at:
554 http://www.rgaros.nl/gestalt/
557 # Check whether the version info module is available
561 return release
,versioninfo
,machine
563 sysv
,sysu
,sysa
= _mac_ver_lookup(('sysv','sysu','sysa'))
566 major
= (sysv
& 0xFF00) >> 8
567 minor
= (sysv
& 0x00F0) >> 4
568 patch
= (sysv
& 0x000F)
569 release
= '%s.%i.%i' % (_bcd2str(major
),minor
,patch
)
571 major
= int((sysu
& 0xFF000000L
) >> 24)
572 minor
= (sysu
& 0x00F00000) >> 20
573 bugfix
= (sysu
& 0x000F0000) >> 16
574 stage
= (sysu
& 0x0000FF00) >> 8
575 nonrel
= (sysu
& 0x000000FF)
576 version
= '%s.%i.%i' % (_bcd2str(major
),minor
,bugfix
)
577 nonrel
= _bcd2str(nonrel
)
578 stage
= {0x20:'development',
581 0x80:'final'}.get(stage
,'')
582 versioninfo
= (version
,stage
,nonrel
)
584 machine
= {0x1: '68k',
585 0x2: 'PowerPC'}.get(sysa
,'')
586 return release
,versioninfo
,machine
588 def _java_getprop(name
,default
):
590 from java
.lang
import System
592 return System
.getProperty(name
)
596 def java_ver(release
='',vendor
='',vminfo
=('','',''),osinfo
=('','','')):
598 """ Version interface for JPython.
600 Returns a tuple (release,vendor,vminfo,osinfo) with vminfo being
601 a tuple (vm_name,vm_release,vm_vendor) and osinfo being a
602 tuple (os_name,os_version,os_arch).
604 Values which cannot be determined are set to the defaults
605 given as parameters (which all default to '').
608 # Import the needed APIs
612 return release
,vendor
,vminfo
,osinfo
614 vendor
= _java_getprop('java.vendor',vendor
)
615 release
= _java_getprop('java.version',release
)
616 vm_name
,vm_release
,vm_vendor
= vminfo
617 vm_name
= _java_getprop('java.vm.name',vm_name
)
618 vm_vendor
= _java_getprop('java.vm.vendor',vm_vendor
)
619 vm_release
= _java_getprop('java.vm.version',vm_release
)
620 vminfo
= vm_name
,vm_release
,vm_vendor
621 os_name
,os_version
,os_arch
= osinfo
622 os_arch
= _java_getprop('java.os.arch',os_arch
)
623 os_name
= _java_getprop('java.os.name',os_name
)
624 os_version
= _java_getprop('java.os.version',os_version
)
625 osinfo
= os_name
,os_version
,os_arch
627 return release
,vendor
,vminfo
,osinfo
629 ### System name aliasing
631 def system_alias(system
,release
,version
):
633 """ Returns (system,release,version) aliased to common
634 marketing names used for some systems.
636 It also does some reordering of the information in some cases
637 where it would otherwise cause confusion.
640 if system
== 'Rhapsody':
641 # Apple's BSD derivative
642 # XXX How can we determine the marketing release number ?
643 return 'MacOS X Server',system
+release
,version
645 elif system
== 'SunOS':
648 # These releases use the old name SunOS
649 return system
,release
,version
650 # Modify release (marketing release = SunOS release - 3)
651 l
= string
.split(release
,'.')
660 release
= string
.join(l
,'.')
664 # XXX Whatever the new SunOS marketing name is...
667 elif system
== 'IRIX64':
668 # IRIX reports IRIX64 on platforms with 64-bit support; yet it
669 # is really a version and not a different platform, since 32-bit
670 # apps are also supported..
673 version
= version
+ ' (64bit)'
677 elif system
in ('win32','win16'):
678 # In case one of the other tricks
681 return system
,release
,version
683 ### Various internal helpers
685 def _platform(*args
):
687 """ Helper to format the platform string in a filename
688 compatible format e.g. "system-version-machine".
690 # Format the platform string
691 platform
= string
.join(
696 # Cleanup some possible filename obstacles...
697 replace
= string
.replace
698 platform
= replace(platform
,' ','_')
699 platform
= replace(platform
,'/','-')
700 platform
= replace(platform
,'\\','-')
701 platform
= replace(platform
,':','-')
702 platform
= replace(platform
,';','-')
703 platform
= replace(platform
,'"','-')
704 platform
= replace(platform
,'(','-')
705 platform
= replace(platform
,')','-')
707 # No need to report 'unknown' information...
708 platform
= replace(platform
,'unknown','')
710 # Fold '--'s and remove trailing '-'
712 cleaned
= replace(platform
,'--','-')
713 if cleaned
== platform
:
716 while platform
[-1] == '-':
717 platform
= platform
[:-1]
721 def _node(default
=''):
723 """ Helper to determine the node name of this machine.
731 return socket
.gethostname()
733 # Still not working...
736 # os.path.abspath is new in Python 1.5.2:
737 if not hasattr(os
.path
,'abspath'):
741 isabs
=os
.path
.isabs
,join
=os
.path
.join
,getcwd
=os
.getcwd
,
742 normpath
=os
.path
.normpath
):
745 path
= join(getcwd(), path
)
746 return normpath(path
)
750 _abspath
= os
.path
.abspath
752 def _follow_symlinks(filepath
):
754 """ In case filepath is a symlink, follow it until a
755 real file is reached.
757 filepath
= _abspath(filepath
)
758 while os
.path
.islink(filepath
):
759 filepath
= os
.path
.normpath(
760 os
.path
.join(filepath
,os
.readlink(filepath
)))
763 def _syscmd_uname(option
,default
=''):
765 """ Interface to the system's uname command.
767 if sys
.platform
in ('dos','win32','win16','os2'):
771 f
= os
.popen('uname %s 2> /dev/null' % option
)
772 except (AttributeError,os
.error
):
774 output
= string
.strip(f
.read())
781 def _syscmd_file(target
,default
=''):
783 """ Interface to the system's file command.
785 The function uses the -b option of the file command to have it
786 ommit the filename in its output and if possible the -L option
787 to have the command follow symlinks. It returns default in
788 case the command should fail.
791 target
= _follow_symlinks(target
)
793 f
= os
.popen('file %s 2> /dev/null' % target
)
794 except (AttributeError,os
.error
):
796 output
= string
.strip(f
.read())
803 ### Information about the used architecture
805 # Default values for architecture; non-empty strings override the
806 # defaults given as parameters
807 _default_architecture
= {
808 'win32': ('','WindowsPE'),
809 'win16': ('','Windows'),
813 _architecture_split
= re
.compile(r
'[\s,]').split
815 def architecture(executable
=sys
.executable
,bits
='',linkage
=''):
817 """ Queries the given executable (defaults to the Python interpreter
818 binary) for various architecture informations.
820 Returns a tuple (bits,linkage) which contain information about
821 the bit architecture and the linkage format used for the
822 executable. Both values are returned as strings.
824 Values that cannot be determined are returned as given by the
825 parameter presets. If bits is given as '', the sizeof(pointer)
826 (or sizeof(long) on Python version < 1.5.2) is used as
827 indicator for the supported pointer size.
829 The function relies on the system's "file" command to do the
830 actual work. This is available on most if not all Unix
831 platforms. On some non-Unix platforms and then only if the
832 executable points to the Python interpreter defaults from
833 _default_architecture are used.
836 # Use the sizeof(pointer) as default number of bits if nothing
837 # else is given as default.
841 size
= struct
.calcsize('P')
843 # Older installations can only query longs
844 size
= struct
.calcsize('l')
845 bits
= str(size
*8) + 'bit'
847 # Get data from the 'file' system command
848 output
= _syscmd_file(executable
,'')
851 executable
== sys
.executable
:
852 # "file" command did not return anything; we'll try to provide
853 # some sensible defaults then...
854 if _default_architecture
.has_key(sys
.platform
):
855 b
,l
= _default_architecture
[sys
.platform
]
862 # Split the output into a list of strings omitting the filename
863 fileout
= _architecture_split(output
)[1:]
865 if 'executable' not in fileout
:
866 # Format not supported
870 if '32-bit' in fileout
:
872 elif 'N32' in fileout
:
875 elif '64-bit' in fileout
:
881 elif 'PE' in fileout
:
882 # E.g. Windows uses this format
883 if 'Windows' in fileout
:
884 linkage
= 'WindowsPE'
887 elif 'COFF' in fileout
:
889 elif 'MS-DOS' in fileout
:
892 # XXX the A.OUT format also falls under this class...
897 ### Portable uname() interface
903 """ Fairly portable uname interface. Returns a tuple
904 of strings (system,node,release,version,machine,processor)
905 identifying the underlying platform.
907 Note that unlike the os.uname function this also returns
908 possible processor information as additional tuple entry.
910 Entries which cannot be determined are set to ''.
915 if _uname_cache
is not None:
918 # Get some infos from the builtin os.uname API...
920 system
,node
,release
,version
,machine
= os
.uname()
922 except AttributeError:
923 # Hmm, no uname... we'll have to poke around the system then.
924 system
= sys
.platform
932 # Try win32_ver() on win32 platforms
933 if system
== 'win32':
934 release
,version
,csd
,ptype
= win32_ver()
935 if release
and version
:
938 # Try the 'ver' system command available on some
941 system
,release
,version
= _syscmd_ver(system
)
943 # In case we still don't know anything useful, we'll try to
945 if system
in ('win32','win16'):
947 if system
== 'win32':
953 elif system
[:4] == 'java':
954 release
,vendor
,vminfo
,osinfo
= java_ver()
956 version
= string
.join(vminfo
,', ')
960 elif os
.name
== 'mac':
961 release
,(version
,stage
,nonrel
),machine
= mac_ver()
965 # System specific extensions
966 if system
== 'OpenVMS':
967 # OpenVMS seems to have release and version mixed up
968 if not release
or release
== '0':
971 # Get processor information
977 csid
, cpu_number
= vms_lib
.getsyi('SYI$_CPU',0)
978 if (cpu_number
>= 128):
983 # Get processor information from the uname system command
984 processor
= _syscmd_uname('-p','')
986 # 'unknown' is not really any useful as information; we'll convert
987 # it to '' which is more portable
988 if system
== 'unknown':
990 if node
== 'unknown':
992 if release
== 'unknown':
994 if version
== 'unknown':
996 if machine
== 'unknown':
998 if processor
== 'unknown':
1000 _uname_cache
= system
,node
,release
,version
,machine
,processor
1003 ### Direct interfaces to some of the uname() return values
1007 """ Returns the system/OS name, e.g. 'Linux', 'Windows' or 'Java'.
1009 An empty string is returned if the value cannot be determined.
1016 """ Returns the computer's network name (may not be fully qualified !)
1018 An empty string is returned if the value cannot be determined.
1025 """ Returns the system's release, e.g. '2.2.0' or 'NT'
1027 An empty string is returned if the value cannot be determined.
1034 """ Returns the system's release version, e.g. '#3 on degas'
1036 An empty string is returned if the value cannot be determined.
1043 """ Returns the machine type, e.g. 'i386'
1045 An empty string is returned if the value cannot be determined.
1052 """ Returns the (true) processor name, e.g. 'amdk6'
1054 An empty string is returned if the value cannot be
1055 determined. Note that many platforms do not provide this
1056 information or simply return the same value as for machine(),
1057 e.g. NetBSD does this.
1062 ### Various APIs for extracting information from sys.version
1064 _sys_version_parser
= re
.compile(r
'([\w.+]+)\s*'
1065 '\(#(\d+),\s*([\w ]+),\s*([\w :]+)\)\s*'
1067 _sys_version_cache
= None
1071 """ Returns a parsed version of Python's sys.version as tuple
1072 (version, buildno, builddate, compiler) referring to the Python
1073 version, build number, build date/time as string and the compiler
1074 identification string.
1076 Note that unlike the Python sys.version, the returned value
1077 for the Python version will always include the patchlevel (it
1081 global _sys_version_cache
1084 if _sys_version_cache
is not None:
1085 return _sys_version_cache
1086 version
, buildno
, builddate
, buildtime
, compiler
= \
1087 _sys_version_parser
.match(sys
.version
).groups()
1088 buildno
= int(buildno
)
1089 builddate
= builddate
+ ' ' + buildtime
1090 l
= string
.split(version
, '.')
1093 version
= string
.join(l
, '.')
1094 _sys_version_cache
= (version
, buildno
, builddate
, compiler
)
1095 return _sys_version_cache
1097 def python_version():
1099 """ Returns the Python version as string 'major.minor.patchlevel'
1101 Note that unlike the Python sys.version, the returned value
1102 will always include the patchlevel (it defaults to 0).
1105 return _sys_version()[0]
1107 def python_version_tuple():
1109 """ Returns the Python version as tuple (major, minor, patchlevel)
1112 Note that unlike the Python sys.version, the returned value
1113 will always include the patchlevel (it defaults to 0).
1116 return string
.split(_sys_version()[0], '.')
1120 """ Returns a tuple (buildno, builddate) stating the Python
1121 build number and date as strings.
1124 return _sys_version()[1:3]
1126 def python_compiler():
1128 """ Returns a string identifying the compiler used for compiling
1132 return _sys_version()[3]
1134 ### The Opus Magnum of platform strings :-)
1136 _platform_cache
= None
1137 _platform_aliased_cache
= None
1139 def platform(aliased
=0, terse
=0):
1141 """ Returns a single string identifying the underlying platform
1142 with as much useful information as possible (but no more :).
1144 The output is intended to be human readable rather than
1145 machine parseable. It may look different on different
1146 platforms and this is intended.
1148 If "aliased" is true, the function will use aliases for
1149 various platforms that report system names which differ from
1150 their common names, e.g. SunOS will be reported as
1151 Solaris. The system_alias() function is used to implement
1154 Setting terse to true causes the function to return only the
1155 absolute minimum information needed to identify the platform.
1158 global _platform_cache
,_platform_aliased_cache
1160 if not aliased
and (_platform_cache
is not None):
1161 return _platform_cache
1162 elif _platform_aliased_cache
is not None:
1163 return _platform_aliased_cache
1165 # Get uname information and then apply platform specific cosmetics
1167 system
,node
,release
,version
,machine
,processor
= uname()
1168 if machine
== processor
:
1171 system
,release
,version
= system_alias(system
,release
,version
)
1173 if system
== 'Windows':
1175 rel
,vers
,csd
,ptype
= win32_ver(version
)
1177 platform
= _platform(system
,release
)
1179 platform
= _platform(system
,release
,version
,csd
)
1181 elif system
in ('Linux',):
1182 # Linux based systems
1183 distname
,distversion
,distid
= dist('')
1184 if distname
and not terse
:
1185 platform
= _platform(system
,release
,machine
,processor
,
1187 distname
,distversion
,distid
)
1189 # If the distribution name is unknown check for libc vs. glibc
1190 libcname
,libcversion
= libc_ver(sys
.executable
)
1191 platform
= _platform(system
,release
,machine
,processor
,
1193 libcname
+libcversion
)
1194 elif system
== 'Java':
1196 r
,v
,vminfo
,(os_name
,os_version
,os_arch
) = java_ver()
1198 platform
= _platform(system
,release
,version
)
1200 platform
= _platform(system
,release
,version
,
1202 os_name
,os_version
,os_arch
)
1204 elif system
== 'MacOS':
1207 platform
= _platform(system
,release
)
1209 platform
= _platform(system
,release
,machine
)
1214 platform
= _platform(system
,release
)
1216 bits
,linkage
= architecture(sys
.executable
)
1217 platform
= _platform(system
,release
,machine
,processor
,bits
,linkage
)
1220 _platform_aliased_cache
= platform
1224 _platform_cache
= platform
1227 ### Command line interface
1229 if __name__
== '__main__':
1230 # Default is to print the aliased verbose platform string
1231 terse
= ('terse' in sys
.argv
or '--terse' in sys
.argv
)
1232 aliased
= (not 'nonaliased' in sys
.argv
and not '--nonaliased' in sys
.argv
)
1233 print platform(aliased
,terse
)