|
From: <fwi...@us...> - 2011-03-23 05:03:36
|
Revision: 7262
http://jython.svn.sourceforge.net/jython/?rev=7262&view=rev
Author: fwierzbicki
Date: 2011-03-23 05:03:29 +0000 (Wed, 23 Mar 2011)
Log Message:
-----------
Update to 2.6 platform.py.
Modified Paths:
--------------
trunk/jython/Lib/platform.py
Modified: trunk/jython/Lib/platform.py
===================================================================
--- trunk/jython/Lib/platform.py 2011-03-22 02:38:16 UTC (rev 7261)
+++ trunk/jython/Lib/platform.py 2011-03-23 05:03:29 UTC (rev 7262)
@@ -10,7 +10,7 @@
"""
# This module is maintained by Marc-Andre Lemburg <ma...@eg...>.
# If you find problems, please submit bug reports/patches via the
-# Python SourceForge Project Page and assign them to "lemburg".
+# Python bug tracker (http://bugs.python.org) and assign them to "lemburg".
#
# Note: Please keep this module compatible to Python 1.5.2.
#
@@ -28,12 +28,15 @@
# Betancourt, Randall Hopper, Karl Putland, John Farrell, Greg
# Andruk, Just van Rossum, Thomas Heller, Mark R. Levinson, Mark
# Hammond, Bill Tutt, Hans Nowak, Uwe Zessin (OpenVMS support),
-# Colin Kong, Trent Mick, Guido van Rossum
+# Colin Kong, Trent Mick, Guido van Rossum, Anthony Baxter
#
# History:
#
# <see CVS and SVN checkin messages for history>
#
+# 1.0.6 - added linux_distribution()
+# 1.0.5 - fixed Java support to allow running the module on Jython
+# 1.0.4 - added IronPython support
# 1.0.3 - added normalization of Windows system name
# 1.0.2 - added more Windows support
# 1.0.1 - reformatted to make doc.py happy
@@ -88,7 +91,7 @@
__copyright__ = """
Copyright (c) 1999-2000, Marc-Andre Lemburg; mailto:ma...@le...
- Copyright (c) 2000-2003, eGenix.com Software GmbH; mailto:in...@eg...
+ Copyright (c) 2000-2010, eGenix.com Software GmbH; mailto:in...@eg...
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee or royalty is hereby granted,
@@ -107,7 +110,7 @@
"""
-__version__ = '1.0.4'
+__version__ = '1.0.6'
import sys,string,os,re
@@ -136,6 +139,11 @@
The file is read and scanned in chunks of chunksize bytes.
"""
+ if hasattr(os.path, 'realpath'):
+ # Python 2.2 introduced os.path.realpath(); it is used
+ # here to work around problems with Cygwin not being
+ # able to open symlinks for reading
+ executable = os.path.realpath(executable)
f = open(executable,'rb')
binary = f.read(chunksize)
pos = 0
@@ -218,21 +226,90 @@
return distname,version,id
_release_filename = re.compile(r'(\w+)[-_](release|version)')
-_release_version = re.compile(r'([\d.]+)[^(]*(?:\((.+)\))?')
+_lsb_release_version = re.compile(r'(.+)'
+ ' release '
+ '([\d.]+)'
+ '[^(]*(?:\((.+)\))?')
+_release_version = re.compile(r'([^0-9]+)'
+ '(?: release )?'
+ '([\d.]+)'
+ '[^(]*(?:\((.+)\))?')
-# Note:In supported_dists below we need 'fedora' before 'redhat' as in
-# Fedora redhat-release is a link to fedora-release.
+# See also http://www.novell.com/coolsolutions/feature/11251.html
+# and http://linuxmafia.com/faq/Admin/release-files.html
+# and http://data.linux-ntfs.org/rpm/whichrpm
+# and http://www.die.net/doc/linux/man/man1/lsb_release.1.html
-def dist(distname='',version='',id='',
+_supported_dists = (
+ 'SuSE', 'debian', 'fedora', 'redhat', 'centos',
+ 'mandrake', 'mandriva', 'rocks', 'slackware', 'yellowdog', 'gentoo',
+ 'UnitedLinux', 'turbolinux')
- supported_dists=('SuSE', 'debian', 'fedora', 'redhat', 'mandrake')):
+def _parse_release_file(firstline):
+ # Default to empty 'version' and 'id' strings. Both defaults are used
+ # when 'firstline' is empty. 'id' defaults to empty when an id can not
+ # be deduced.
+ version = ''
+ id = ''
+
+ # Parse the first line
+ m = _lsb_release_version.match(firstline)
+ if m is not None:
+ # LSB format: "distro release x.x (codename)"
+ return tuple(m.groups())
+
+ # Pre-LSB format: "distro x.x (codename)"
+ m = _release_version.match(firstline)
+ if m is not None:
+ return tuple(m.groups())
+
+ # Unkown format... take the first two words
+ l = string.split(string.strip(firstline))
+ if l:
+ version = l[0]
+ if len(l) > 1:
+ id = l[1]
+ return '', version, id
+
+def _test_parse_release_file():
+
+ for input, output in (
+ # Examples of release file contents:
+ ('SuSE Linux 9.3 (x86-64)', ('SuSE Linux ', '9.3', 'x86-64'))
+ ('SUSE LINUX 10.1 (X86-64)', ('SUSE LINUX ', '10.1', 'X86-64'))
+ ('SUSE LINUX 10.1 (i586)', ('SUSE LINUX ', '10.1', 'i586'))
+ ('Fedora Core release 5 (Bordeaux)', ('Fedora Core', '5', 'Bordeaux'))
+ ('Red Hat Linux release 8.0 (Psyche)', ('Red Hat Linux', '8.0', 'Psyche'))
+ ('Red Hat Linux release 9 (Shrike)', ('Red Hat Linux', '9', 'Shrike'))
+ ('Red Hat Enterprise Linux release 4 (Nahant)', ('Red Hat Enterprise Linux', '4', 'Nahant'))
+ ('CentOS release 4', ('CentOS', '4', None))
+ ('Rocks release 4.2.1 (Cydonia)', ('Rocks', '4.2.1', 'Cydonia'))
+ ):
+ parsed = _parse_release_file(input)
+ if parsed != output:
+ print (input, parsed)
+
+def linux_distribution(distname='', version='', id='',
+
+ supported_dists=_supported_dists,
+ full_distribution_name=1):
+
""" Tries to determine the name of the Linux OS distribution name.
The function first looks for a distribution release file in
/etc and then reverts to _dist_try_harder() in case no
suitable files are found.
+ supported_dists may be given to define the set of Linux
+ distributions to look for. It defaults to a list of currently
+ supported Linux distributions identified by their release file
+ name.
+
+ If full_distribution_name is true (default), the full
+ distribution read from the OS is returned. Otherwise the short
+ name taken from supported_dists is used.
+
Returns a tuple (distname,version,id) which default to the
args given as parameters.
@@ -242,34 +319,51 @@
except os.error:
# Probably not a Unix system
return distname,version,id
+ etc.sort()
for file in etc:
m = _release_filename.match(file)
- if m:
+ if m is not None:
_distname,dummy = m.groups()
if _distname in supported_dists:
distname = _distname
break
else:
return _dist_try_harder(distname,version,id)
- f = open('/etc/'+file,'r')
+
+ # Read the first line
+ f = open('/etc/'+file, 'r')
firstline = f.readline()
f.close()
- m = _release_version.search(firstline)
- if m:
- _version,_id = m.groups()
- if _version:
- version = _version
- if _id:
- id = _id
- else:
- # Unkown format... take the first two words
- l = string.split(string.strip(firstline))
- if l:
- version = l[0]
- if len(l) > 1:
- id = l[1]
- return distname,version,id
+ _distname, _version, _id = _parse_release_file(firstline)
+ if _distname and full_distribution_name:
+ distname = _distname
+ if _version:
+ version = _version
+ if _id:
+ id = _id
+ return distname, version, id
+
+# To maintain backwards compatibility:
+
+def dist(distname='',version='',id='',
+
+ supported_dists=_supported_dists):
+
+ """ Tries to determine the name of the Linux OS distribution name.
+
+ The function first looks for a distribution release file in
+ /etc and then reverts to _dist_try_harder() in case no
+ suitable files are found.
+
+ Returns a tuple (distname,version,id) which default to the
+ args given as parameters.
+
+ """
+ return linux_distribution(distname, version, id,
+ supported_dists=supported_dists,
+ full_distribution_name=0)
+
class _popen:
""" Fairly portable (alternative) popen implementation.
@@ -357,7 +451,7 @@
else:
return popen(cmd,mode,bufsize)
-def _norm_version(version,build=''):
+def _norm_version(version, build=''):
""" Normalize the version and build strings and return a single
version string using the format major.minor.build (or patchlevel).
@@ -378,7 +472,7 @@
'.*'
'Version ([\d.]+))')
-def _syscmd_ver(system='',release='',version='',
+def _syscmd_ver(system='', release='', version='',
supported_platforms=('win32','win16','dos','os2')):
@@ -418,7 +512,7 @@
# Parse the output
info = string.strip(info)
m = _ver_output.match(info)
- if m:
+ if m is not None:
system,release,version = m.groups()
# Strip trailing dots from version and release
if release[-1] == '.':
@@ -437,8 +531,14 @@
In case this fails, default is returned.
"""
- from win32api import RegQueryValueEx
try:
+ # Use win32api if available
+ from win32api import RegQueryValueEx
+ except ImportError:
+ # On Python 2.0 and later, emulate using _winreg
+ import _winreg
+ RegQueryValueEx = _winreg.QueryValueEx
+ try:
return RegQueryValueEx(key,name)
except:
return default
@@ -457,9 +557,9 @@
means the OS version uses debugging code, i.e. code that
checks arguments, ranges, etc. (Thomas Heller).
- Note: this function only works if Mark Hammond's win32
- package is installed and obviously only runs on Win32
- compatible platforms.
+ Note: this function works best with Mark Hammond's win32
+ package installed, but also on Python 2.3 and later. It
+ obviously only runs on Win32 compatible platforms.
"""
# XXX Is there any way to find out the processor type on WinXX ?
@@ -473,17 +573,42 @@
# Import the needed APIs
try:
import win32api
+ from win32api import RegQueryValueEx, RegOpenKeyEx, \
+ RegCloseKey, GetVersionEx
+ from win32con import HKEY_LOCAL_MACHINE, VER_PLATFORM_WIN32_NT, \
+ VER_PLATFORM_WIN32_WINDOWS, VER_NT_WORKSTATION
except ImportError:
- return release,version,csd,ptype
- from win32api import RegQueryValueEx,RegOpenKeyEx,RegCloseKey,GetVersionEx
- from win32con import HKEY_LOCAL_MACHINE,VER_PLATFORM_WIN32_NT,\
- VER_PLATFORM_WIN32_WINDOWS
+ # Emulate the win32api module using Python APIs
+ try:
+ sys.getwindowsversion
+ except AttributeError:
+ # No emulation possible, so return the defaults...
+ return release,version,csd,ptype
+ else:
+ # Emulation using _winreg (added in Python 2.0) and
+ # sys.getwindowsversion() (added in Python 2.3)
+ import _winreg
+ GetVersionEx = sys.getwindowsversion
+ RegQueryValueEx = _winreg.QueryValueEx
+ RegOpenKeyEx = _winreg.OpenKeyEx
+ RegCloseKey = _winreg.CloseKey
+ HKEY_LOCAL_MACHINE = _winreg.HKEY_LOCAL_MACHINE
+ VER_PLATFORM_WIN32_WINDOWS = 1
+ VER_PLATFORM_WIN32_NT = 2
+ VER_NT_WORKSTATION = 1
+ VER_NT_SERVER = 3
+ REG_SZ = 1
# Find out the registry key and some general version infos
- maj,min,buildno,plat,csd = GetVersionEx()
+ winver = GetVersionEx()
+ maj,min,buildno,plat,csd = winver
version = '%i.%i.%i' % (maj,min,buildno & 0xFFFF)
- if csd[:13] == 'Service Pack ':
- csd = 'SP' + csd[13:]
+ if hasattr(winver, "service_pack"):
+ if winver.service_pack != "":
+ csd = 'SP%s' % winver.service_pack_major
+ else:
+ if csd[:13] == 'Service Pack ':
+ csd = 'SP' + csd[13:]
if plat == VER_PLATFORM_WIN32_WINDOWS:
regkey = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion'
# Try to guess the release name
@@ -511,6 +636,36 @@
release = '2003Server'
else:
release = 'post2003'
+ elif maj == 6:
+ if hasattr(winver, "product_type"):
+ product_type = winver.product_type
+ else:
+ product_type = VER_NT_WORKSTATION
+ # Without an OSVERSIONINFOEX capable sys.getwindowsversion(),
+ # or help from the registry, we cannot properly identify
+ # non-workstation versions.
+ try:
+ key = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey)
+ name, type = RegQueryValueEx(key, "ProductName")
+ # Discard any type that isn't REG_SZ
+ if type == REG_SZ and name.find("Server") != -1:
+ product_type = VER_NT_SERVER
+ except WindowsError:
+ # Use default of VER_NT_WORKSTATION
+ pass
+
+ if min == 0:
+ if product_type == VER_NT_WORKSTATION:
+ release = 'Vista'
+ else:
+ release = '2008Server'
+ elif min == 1:
+ if product_type == VER_NT_WORKSTATION:
+ release = '7'
+ else:
+ release = '2008ServerR2'
+ else:
+ release = 'post2008Server'
else:
if not release:
# E.g. Win3.1 with win32s
@@ -519,9 +674,9 @@
# Open the registry key
try:
- keyCurVer = RegOpenKeyEx(HKEY_LOCAL_MACHINE,regkey)
+ keyCurVer = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey)
# Get a value to make sure the key exists...
- RegQueryValueEx(keyCurVer,'SystemRoot')
+ RegQueryValueEx(keyCurVer, 'SystemRoot')
except:
return release,version,csd,ptype
@@ -562,30 +717,22 @@
return hex(bcd)[2:]
-def mac_ver(release='',versioninfo=('','',''),machine=''):
-
- """ Get MacOS version information and return it as tuple (release,
- versioninfo, machine) with versioninfo being a tuple (version,
- dev_stage, non_release_version).
-
- Entries which cannot be determined are set to the paramter values
- which default to ''. All tuple entries are strings.
-
+def _mac_ver_gestalt():
+ """
Thanks to Mark R. Levinson for mailing documentation links and
code examples for this function. Documentation for the
gestalt() API is available online at:
http://www.rgaros.nl/gestalt/
-
"""
# Check whether the version info module is available
try:
import gestalt
import MacOS
except ImportError:
- return release,versioninfo,machine
+ return None
# Get the infos
- sysv,sysu,sysa = _mac_ver_lookup(('sysv','sysu','sysa'))
+ sysv,sysa = _mac_ver_lookup(('sysv','sysa'))
# Decode the infos
if sysv:
major = (sysv & 0xFF00) >> 8
@@ -602,32 +749,70 @@
release = '%i.%i.%i' %(major, minor, patch)
else:
release = '%s.%i.%i' % (_bcd2str(major),minor,patch)
- if sysu:
- major = int((sysu & 0xFF000000L) >> 24)
- minor = (sysu & 0x00F00000) >> 20
- bugfix = (sysu & 0x000F0000) >> 16
- stage = (sysu & 0x0000FF00) >> 8
- nonrel = (sysu & 0x000000FF)
- version = '%s.%i.%i' % (_bcd2str(major),minor,bugfix)
- nonrel = _bcd2str(nonrel)
- stage = {0x20:'development',
- 0x40:'alpha',
- 0x60:'beta',
- 0x80:'final'}.get(stage,'')
- versioninfo = (version,stage,nonrel)
+
if sysa:
machine = {0x1: '68k',
0x2: 'PowerPC',
0xa: 'i386'}.get(sysa,'')
+
return release,versioninfo,machine
+def _mac_ver_xml():
+ fn = '/System/Library/CoreServices/SystemVersion.plist'
+ if not os.path.exists(fn):
+ return None
+
+ try:
+ import plistlib
+ except ImportError:
+ return None
+
+ pl = plistlib.readPlist(fn)
+ release = pl['ProductVersion']
+ versioninfo=('', '', '')
+ machine = os.uname()[4]
+ if machine in ('ppc', 'Power Macintosh'):
+ # for compatibility with the gestalt based code
+ machine = 'PowerPC'
+
+ return release,versioninfo,machine
+
+
+def mac_ver(release='',versioninfo=('','',''),machine=''):
+
+ """ Get MacOS version information and return it as tuple (release,
+ versioninfo, machine) with versioninfo being a tuple (version,
+ dev_stage, non_release_version).
+
+ Entries which cannot be determined are set to the paramter values
+ which default to ''. All tuple entries are strings.
+ """
+
+ # First try reading the information from an XML file which should
+ # always be present
+ info = _mac_ver_xml()
+ if info is not None:
+ return info
+
+ # If that doesn't work for some reason fall back to reading the
+ # information using gestalt calls.
+ info = _mac_ver_gestalt()
+ if info is not None:
+ return info
+
+ # If that also doesn't work return the default values
+ return release,versioninfo,machine
+
def _java_getprop(name,default):
from java.lang import System
from org.python.core.Py import newString
try:
- return newString(System.getProperty(name))
- except:
+ value = System.getProperty(name)
+ if value is None:
+ return default
+ return newString(value)
+ except AttributeError:
return default
def java_ver(release='',vendor='',vminfo=('','',''),osinfo=('','','')):
@@ -648,20 +833,20 @@
except ImportError:
return release,vendor,vminfo,osinfo
- vendor = _java_getprop('java.vendor',vendor)
- release = _java_getprop('java.version',release)
- vm_name,vm_release,vm_vendor = vminfo
- vm_name = _java_getprop('java.vm.name',vm_name)
- vm_vendor = _java_getprop('java.vm.vendor',vm_vendor)
- vm_release = _java_getprop('java.vm.version',vm_release)
- vminfo = vm_name,vm_release,vm_vendor
- os_name,os_version,os_arch = osinfo
- os_arch = _java_getprop('os.arch',os_arch)
- os_name = _java_getprop('os.name',os_name)
- os_version = _java_getprop('os.version',os_version)
- osinfo = os_name,os_version,os_arch
+ vendor = _java_getprop('java.vendor', vendor)
+ release = _java_getprop('java.version', release)
+ vm_name, vm_release, vm_vendor = vminfo
+ vm_name = _java_getprop('java.vm.name', vm_name)
+ vm_vendor = _java_getprop('java.vm.vendor', vm_vendor)
+ vm_release = _java_getprop('java.vm.version', vm_release)
+ vminfo = vm_name, vm_release, vm_vendor
+ os_name, os_version, os_arch = osinfo
+ os_arch = _java_getprop('os.arch', os_arch)
+ os_name = _java_getprop('os.name', os_name)
+ os_version = _java_getprop('os.version', os_version)
+ osinfo = os_name, os_version, os_arch
- return release,vendor,vminfo,osinfo
+ return release, vendor, vminfo, osinfo
### System name aliasing
@@ -727,7 +912,7 @@
# Format the platform string
platform = string.join(
map(string.strip,
- filter(len,args)),
+ filter(len, args)),
'-')
# Cleanup some possible filename obstacles...
@@ -825,9 +1010,12 @@
case the command should fail.
"""
- target = _follow_symlinks(target)
+ if sys.platform in ('dos','win32','win16','os2'):
+ # XXX Others too ?
+ return default
+ target = _follow_symlinks(target).replace('"', '\\"')
try:
- f = os.popen('file %s 2> /dev/null' % target)
+ f = os.popen('file "%s" 2> /dev/null' % target)
except (AttributeError,os.error):
return default
output = string.strip(f.read())
@@ -882,19 +1070,22 @@
bits = str(size*8) + 'bit'
# Get data from the 'file' system command
- output = _syscmd_file(executable,'')
+ if executable:
+ output = _syscmd_file(executable, '')
+ else:
+ output = ''
if not output and \
executable == sys.executable:
# "file" command did not return anything; we'll try to provide
# some sensible defaults then...
- if _default_architecture.has_key(sys.platform):
- b,l = _default_architecture[sys.platform]
+ if sys.platform in _default_architecture:
+ b, l = _default_architecture[sys.platform]
if b:
bits = b
if l:
linkage = l
- return bits,linkage
+ return bits, linkage
# Split the output into a list of strings omitting the filename
fileout = _architecture_split(output)[1:]
@@ -948,29 +1139,44 @@
"""
global _uname_cache
+ no_os_uname = 0
if _uname_cache is not None:
return _uname_cache
+ processor = ''
+
# Get some infos from the builtin os.uname API...
try:
system,node,release,version,machine = os.uname()
-
except AttributeError:
- # Hmm, no uname... we'll have to poke around the system then.
- system = sys.platform
- release = ''
- version = ''
- node = _node()
- machine = ''
- processor = ''
- use_syscmd_ver = 1
+ no_os_uname = 1
+ if no_os_uname or not filter(None, (system, node, release, version, machine)):
+ # Hmm, no there is either no uname or uname has returned
+ #'unknowns'... we'll have to poke around the system then.
+ if no_os_uname:
+ system = sys.platform
+ release = ''
+ version = ''
+ node = _node()
+ machine = ''
+
+ use_syscmd_ver = 01
+
# Try win32_ver() on win32 platforms
if system == 'win32':
release,version,csd,ptype = win32_ver()
if release and version:
use_syscmd_ver = 0
+ # Try to use the PROCESSOR_* environment variables
+ # available on Win XP and later; see
+ # http://support.microsoft.com/kb/888731 and
+ # http://www.geocities.com/rick_lively/MANUALS/ENV/MSWIN/PROCESSI.HTM
+ if not machine:
+ machine = os.environ.get('PROCESSOR_ARCHITECTURE', '')
+ if not processor:
+ processor = os.environ.get('PROCESSOR_IDENTIFIER', machine)
# Try the 'ver' system command available on some
# platforms
@@ -980,6 +1186,16 @@
# (_syscmd_ver() tends to return the vendor name as well)
if system == 'Microsoft Windows':
system = 'Windows'
+ elif system == 'Microsoft' and release == 'Windows':
+ # Under Windows Vista and Windows Server 2008,
+ # Microsoft changed the output of the ver command. The
+ # release is no longer printed. This causes the
+ # system and release to be misidentified.
+ system = 'Windows'
+ if '6.0' == version[:3]:
+ release = 'Vista'
+ else:
+ release = ''
# In case we still don't know anything useful, we'll try to
# help ourselves
@@ -1002,30 +1218,28 @@
release,(version,stage,nonrel),machine = mac_ver()
system = 'MacOS'
- else:
- # System specific extensions
- if system == 'OpenVMS':
- # OpenVMS seems to have release and version mixed up
- if not release or release == '0':
- release = version
- version = ''
- # Get processor information
- try:
- import vms_lib
- except ImportError:
- pass
+ # System specific extensions
+ if system == 'OpenVMS':
+ # OpenVMS seems to have release and version mixed up
+ if not release or release == '0':
+ release = version
+ version = ''
+ # Get processor information
+ try:
+ import vms_lib
+ except ImportError:
+ pass
+ else:
+ csid, cpu_number = vms_lib.getsyi('SYI$_CPU',0)
+ if (cpu_number >= 128):
+ processor = 'Alpha'
else:
- csid, cpu_number = vms_lib.getsyi('SYI$_CPU',0)
- if (cpu_number >= 128):
- processor = 'Alpha'
- else:
- processor = 'VAX'
- else:
- # Get processor information from the uname system command
- processor = _syscmd_uname('-p','')
+ processor = 'VAX'
+ if not processor:
+ # Get processor information from the uname system command
+ processor = _syscmd_uname('-p','')
- # 'unknown' is not really any useful as information; we'll convert
- # it to '' which is more portable
+ #If any unknowns still exist, replace them with ''s, which are more portable
if system == 'unknown':
system = ''
if node == 'unknown':
@@ -1109,37 +1323,137 @@
### Various APIs for extracting information from sys.version
-_sys_version_parser = re.compile(r'([\w.+]+)\s*'
- '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
- '\[([^\]]+)\]?')
-_sys_version_cache = None
+_sys_version_parser = re.compile(
+ r'([\w.+]+)\s*'
+ '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
+ '\[([^\]]+)\]?')
-def _sys_version():
+_jython_sys_version_parser = re.compile(
+ r'([\d\.]+)')
+_ironpython_sys_version_parser = re.compile(
+ r'IronPython\s*'
+ '([\d\.]+)'
+ '(?: \(([\d\.]+)\))?'
+ ' on (.NET [\d\.]+)')
+
+_sys_version_cache = {}
+
+def _sys_version(sys_version=None):
+
""" Returns a parsed version of Python's sys.version as tuple
- (version, buildno, builddate, compiler) referring to the Python
- version, build number, build date/time as string and the compiler
+ (name, version, branch, revision, buildno, builddate, compiler)
+ referring to the Python implementation name, version, branch,
+ revision, build number, build date/time as string and the compiler
identification string.
Note that unlike the Python sys.version, the returned value
for the Python version will always include the patchlevel (it
defaults to '.0').
+ The function returns empty strings for tuple entries that
+ cannot be determined.
+
+ sys_version may be given to parse an alternative version
+ string, e.g. if the version was read from a different Python
+ interpreter.
+
"""
- global _sys_version_cache
+ # Get the Python version
+ if sys_version is None:
+ sys_version = sys.version
- if _sys_version_cache is not None:
- return _sys_version_cache
- version, buildno, builddate, buildtime, compiler = \
- _sys_version_parser.match(sys.version).groups()
- builddate = builddate + ' ' + buildtime
+ # Try the cache first
+ result = _sys_version_cache.get(sys_version, None)
+ if result is not None:
+ return result
+
+ # Parse it
+ if sys_version[:10] == 'IronPython':
+ # IronPython
+ name = 'IronPython'
+ match = _ironpython_sys_version_parser.match(sys_version)
+ if match is None:
+ raise ValueError(
+ 'failed to parse IronPython sys.version: %s' %
+ repr(sys_version))
+ version, alt_version, compiler = match.groups()
+ branch = ''
+ revision = ''
+ buildno = ''
+ builddate = ''
+
+ elif sys.platform[:4] == 'java':
+ # Jython
+ name = 'Jython'
+ match = _jython_sys_version_parser.match(sys_version)
+ if match is None:
+ raise ValueError(
+ 'failed to parse Jython sys.version: %s' %
+ repr(sys_version))
+ version, = match.groups()
+ branch = ''
+ revision = ''
+ compiler = sys.platform
+ buildno = ''
+ builddate = ''
+
+ else:
+ # CPython
+ match = _sys_version_parser.match(sys_version)
+ if match is None:
+ raise ValueError(
+ 'failed to parse CPython sys.version: %s' %
+ repr(sys_version))
+ version, buildno, builddate, buildtime, compiler = \
+ match.groups()
+ if hasattr(sys, 'subversion'):
+ # sys.subversion was added in Python 2.5
+ name, branch, revision = sys.subversion
+ else:
+ name = 'CPython'
+ branch = ''
+ revision = ''
+ builddate = builddate + ' ' + buildtime
+
+ # Add the patchlevel version if missing
l = string.split(version, '.')
if len(l) == 2:
l.append('0')
version = string.join(l, '.')
- _sys_version_cache = (version, buildno, builddate, compiler)
- return _sys_version_cache
+ # Build and cache the result
+ result = (name, version, branch, revision, buildno, builddate, compiler)
+ _sys_version_cache[sys_version] = result
+ return result
+
+def _test_sys_version():
+
+ _sys_version_cache.clear()
+ for input, output in (
+ ('2.4.3 (#1, Jun 21 2006, 13:54:21) \n[GCC 3.3.4 (pre 3.3.5 20040809)]',
+ ('CPython', '2.4.3', '', '', '1', 'Jun 21 2006 13:54:21', 'GCC 3.3.4 (pre 3.3.5 20040809)')),
+ ('IronPython 1.0.60816 on .NET 2.0.50727.42',
+ ('IronPython', '1.0.60816', '', '', '', '', '.NET 2.0.50727.42')),
+ ('IronPython 1.0 (1.0.61005.1977) on .NET 2.0.50727.42',
+ ('IronPython', '1.0.0', '', '', '', '', '.NET 2.0.50727.42')),
+ ):
+ parsed = _sys_version(input)
+ if parsed != output:
+ print (input, parsed)
+
+def python_implementation():
+
+ """ Returns a string identifying the Python implementation.
+
+ Currently, the following implementations are identified:
+ 'CPython' (C implementation of Python),
+ 'IronPython' (.NET implementation of Python),
+ 'Jython' (Java implementation of Python).
+
+ """
+ return _sys_version()[0]
+
def python_version():
""" Returns the Python version as string 'major.minor.patchlevel'
@@ -1148,7 +1462,7 @@
will always include the patchlevel (it defaults to 0).
"""
- return _sys_version()[0]
+ return _sys_version()[1]
def python_version_tuple():
@@ -1159,15 +1473,42 @@
will always include the patchlevel (it defaults to 0).
"""
- return string.split(_sys_version()[0], '.')
+ return tuple(string.split(_sys_version()[1], '.'))
+def python_branch():
+
+ """ Returns a string identifying the Python implementation
+ branch.
+
+ For CPython this is the Subversion branch from which the
+ Python binary was built.
+
+ If not available, an empty string is returned.
+
+ """
+
+ return _sys_version()[2]
+
+def python_revision():
+
+ """ Returns a string identifying the Python implementation
+ revision.
+
+ For CPython this is the Subversion revision from which the
+ Python binary was built.
+
+ If not available, an empty string is returned.
+
+ """
+ return _sys_version()[3]
+
def python_build():
""" Returns a tuple (buildno, builddate) stating the Python
build number and date as strings.
"""
- return _sys_version()[1:3]
+ return _sys_version()[4:6]
def python_compiler():
@@ -1175,7 +1516,7 @@
Python.
"""
- return _sys_version()[3]
+ return _sys_version()[6]
### The Opus Magnum of platform strings :-)
@@ -1236,7 +1577,7 @@
elif system == 'Java':
# Java platforms
r,v,vminfo,(os_name,os_version,os_arch) = java_ver()
- if terse:
+ if terse or not os_name:
platform = _platform(system,release,version)
else:
platform = _platform(system,release,version,
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|