diff options
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/BaseHTTPServer.py | 4 | ||||
-rw-r--r-- | Lib/ctypes/__init__.py | 30 | ||||
-rw-r--r-- | Lib/ctypes/test/test_win32.py | 24 | ||||
-rw-r--r-- | Lib/ctypes/util.py | 78 | ||||
-rw-r--r-- | Lib/ctypes/wintypes.py | 12 | ||||
-rw-r--r-- | Lib/idlelib/EditorWindow.py | 2 | ||||
-rw-r--r-- | Lib/logging/__init__.py | 27 | ||||
-rw-r--r-- | Lib/logging/handlers.py | 49 | ||||
-rwxr-xr-x | Lib/platform.py | 370 | ||||
-rwxr-xr-x | Lib/pydoc.py | 19 | ||||
-rw-r--r-- | Lib/sqlite3/dbapi2.py | 2 | ||||
-rw-r--r-- | Lib/sqlite3/test/factory.py | 23 | ||||
-rw-r--r-- | Lib/sqlite3/test/regression.py | 10 | ||||
-rw-r--r-- | Lib/sqlite3/test/types.py | 27 | ||||
-rw-r--r-- | Lib/subprocess.py | 2 | ||||
-rw-r--r-- | Lib/test/test___all__.py | 1 | ||||
-rw-r--r-- | Lib/test/test_optparse.py | 12 | ||||
-rw-r--r-- | Lib/test/test_set.py | 11 | ||||
-rw-r--r-- | Lib/test/test_subprocess.py | 2 |
19 files changed, 573 insertions, 132 deletions
diff --git a/Lib/BaseHTTPServer.py b/Lib/BaseHTTPServer.py index 396e4d6..e4e1a14 100644 --- a/Lib/BaseHTTPServer.py +++ b/Lib/BaseHTTPServer.py @@ -396,7 +396,7 @@ class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler): self.log_message('"%s" %s %s', self.requestline, str(code), str(size)) - def log_error(self, *args): + def log_error(self, format, *args): """Log an error. This is called when a request cannot be fulfilled. By @@ -408,7 +408,7 @@ class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler): """ - self.log_message(*args) + self.log_message(format, *args) def log_message(self, format, *args): """Log an arbitrary message. diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py index eb5d97e..efb0c5c 100644 --- a/Lib/ctypes/__init__.py +++ b/Lib/ctypes/__init__.py @@ -5,7 +5,7 @@ import os as _os, sys as _sys -__version__ = "1.0.1" +__version__ = "1.1.0" from _ctypes import Union, Structure, Array from _ctypes import _Pointer @@ -133,6 +133,18 @@ elif _os.name == "posix": from _ctypes import sizeof, byref, addressof, alignment, resize from _ctypes import _SimpleCData +def _check_size(typ, typecode=None): + # Check if sizeof(ctypes_type) against struct.calcsize. This + # should protect somewhat against a misconfigured libffi. + from struct import calcsize + if typecode is None: + # Most _type_ codes are the same as used in struct + typecode = typ._type_ + actual, required = sizeof(typ), calcsize(typecode) + if actual != required: + raise SystemError("sizeof(%s) wrong: %d instead of %d" % \ + (typ, actual, required)) + class py_object(_SimpleCData): _type_ = "O" def __repr__(self): @@ -140,18 +152,23 @@ class py_object(_SimpleCData): return super(py_object, self).__repr__() except ValueError: return "%s(<NULL>)" % type(self).__name__ +_check_size(py_object, "P") class c_short(_SimpleCData): _type_ = "h" +_check_size(c_short) class c_ushort(_SimpleCData): _type_ = "H" +_check_size(c_ushort) class c_long(_SimpleCData): _type_ = "l" +_check_size(c_long) class c_ulong(_SimpleCData): _type_ = "L" +_check_size(c_ulong) if _calcsize("i") == _calcsize("l"): # if int and long have the same size, make c_int an alias for c_long @@ -160,15 +177,19 @@ if _calcsize("i") == _calcsize("l"): else: class c_int(_SimpleCData): _type_ = "i" + _check_size(c_int) class c_uint(_SimpleCData): _type_ = "I" + _check_size(c_uint) class c_float(_SimpleCData): _type_ = "f" +_check_size(c_float) class c_double(_SimpleCData): _type_ = "d" +_check_size(c_double) if _calcsize("l") == _calcsize("q"): # if long and long long have the same size, make c_longlong an alias for c_long @@ -177,33 +198,40 @@ if _calcsize("l") == _calcsize("q"): else: class c_longlong(_SimpleCData): _type_ = "q" + _check_size(c_longlong) class c_ulonglong(_SimpleCData): _type_ = "Q" ## def from_param(cls, val): ## return ('d', float(val), val) ## from_param = classmethod(from_param) + _check_size(c_ulonglong) class c_ubyte(_SimpleCData): _type_ = "B" c_ubyte.__ctype_le__ = c_ubyte.__ctype_be__ = c_ubyte # backward compatibility: ##c_uchar = c_ubyte +_check_size(c_ubyte) class c_byte(_SimpleCData): _type_ = "b" c_byte.__ctype_le__ = c_byte.__ctype_be__ = c_byte +_check_size(c_byte) class c_char(_SimpleCData): _type_ = "c" c_char.__ctype_le__ = c_char.__ctype_be__ = c_char +_check_size(c_char) class c_char_p(_SimpleCData): _type_ = "z" +_check_size(c_char_p, "P") class c_void_p(_SimpleCData): _type_ = "P" c_voidp = c_void_p # backwards compatibility (to a bug) +_check_size(c_void_p) # This cache maps types to pointers to them. _pointer_type_cache = {} diff --git a/Lib/ctypes/test/test_win32.py b/Lib/ctypes/test/test_win32.py index 10deaca..057873c 100644 --- a/Lib/ctypes/test/test_win32.py +++ b/Lib/ctypes/test/test_win32.py @@ -32,12 +32,32 @@ if sys.platform == "win32" and sizeof(c_void_p) == sizeof(c_int): # or wrong calling convention self.assertRaises(ValueError, IsWindow, None) +if sys.platform == "win32": + class FunctionCallTestCase(unittest.TestCase): + if is_resource_enabled("SEH"): def test_SEH(self): - # Call functions with invalid arguments, and make sure that access violations - # are trapped and raise an exception. + # Call functions with invalid arguments, and make sure + # that access violations are trapped and raise an + # exception. self.assertRaises(WindowsError, windll.kernel32.GetModuleHandleA, 32) + def test_noargs(self): + # This is a special case on win32 x64 + windll.user32.GetDesktopWindow() + + class TestWintypes(unittest.TestCase): + def test_HWND(self): + from ctypes import wintypes + self.failUnlessEqual(sizeof(wintypes.HWND), sizeof(c_void_p)) + + def test_PARAM(self): + from ctypes import wintypes + self.failUnlessEqual(sizeof(wintypes.WPARAM), + sizeof(c_void_p)) + self.failUnlessEqual(sizeof(wintypes.LPARAM), + sizeof(c_void_p)) + class Structures(unittest.TestCase): def test_struct_by_value(self): diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py index e65646a..46f4c55 100644 --- a/Lib/ctypes/util.py +++ b/Lib/ctypes/util.py @@ -46,24 +46,17 @@ elif os.name == "posix": import re, tempfile, errno def _findLib_gcc(name): - expr = '[^\(\)\s]*lib%s\.[^\(\)\s]*' % name + expr = r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name) fdout, ccout = tempfile.mkstemp() os.close(fdout) - cmd = 'if type gcc &>/dev/null; then CC=gcc; else CC=cc; fi;' \ + cmd = 'if type gcc >/dev/null 2>&1; then CC=gcc; else CC=cc; fi;' \ '$CC -Wl,-t -o ' + ccout + ' 2>&1 -l' + name try: - fdout, outfile = tempfile.mkstemp() - os.close(fdout) - fd = os.popen(cmd) - trace = fd.read() - err = fd.close() + f = os.popen(cmd) + trace = f.read() + f.close() finally: try: - os.unlink(outfile) - except OSError as e: - if e.errno != errno.ENOENT: - raise - try: os.unlink(ccout) except OSError as e: if e.errno != errno.ENOENT: @@ -73,29 +66,58 @@ elif os.name == "posix": return None return res.group(0) - def _findLib_ld(name): - expr = '/[^\(\)\s]*lib%s\.[^\(\)\s]*' % name - res = re.search(expr, os.popen('/sbin/ldconfig -p 2>/dev/null').read()) - if not res: - # Hm, this works only for libs needed by the python executable. - cmd = 'ldd %s 2>/dev/null' % sys.executable - res = re.search(expr, os.popen(cmd).read()) - if not res: - return None - return res.group(0) - def _get_soname(f): + # assuming GNU binutils / ELF + if not f: + return None cmd = "objdump -p -j .dynamic 2>/dev/null " + f res = re.search(r'\sSONAME\s+([^\s]+)', os.popen(cmd).read()) if not res: return None return res.group(1) - def find_library(name): - lib = _findLib_ld(name) or _findLib_gcc(name) - if not lib: - return None - return _get_soname(lib) + if (sys.platform.startswith("freebsd") + or sys.platform.startswith("openbsd") + or sys.platform.startswith("dragonfly")): + + def _num_version(libname): + # "libxyz.so.MAJOR.MINOR" => [ MAJOR, MINOR ] + parts = libname.split(".") + nums = [] + try: + while parts: + nums.insert(0, int(parts.pop())) + except ValueError: + pass + return nums or [ sys.maxint ] + + def find_library(name): + ename = re.escape(name) + expr = r':-l%s\.\S+ => \S*/(lib%s\.\S+)' % (ename, ename) + res = re.findall(expr, + os.popen('/sbin/ldconfig -r 2>/dev/null').read()) + if not res: + return _get_soname(_findLib_gcc(name)) + res.sort(cmp= lambda x,y: cmp(_num_version(x), _num_version(y))) + return res[-1] + + else: + + def _findLib_ldconfig(name): + # XXX assuming GLIBC's ldconfig (with option -p) + expr = r'/[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name) + res = re.search(expr, + os.popen('/sbin/ldconfig -p 2>/dev/null').read()) + if not res: + # Hm, this works only for libs needed by the python executable. + cmd = 'ldd %s 2>/dev/null' % sys.executable + res = re.search(expr, os.popen(cmd).read()) + if not res: + return None + return res.group(0) + + def find_library(name): + return _get_soname(_findLib_ldconfig(name) or _findLib_gcc(name)) ################################################################ # test code diff --git a/Lib/ctypes/wintypes.py b/Lib/ctypes/wintypes.py index 9768233..a0fc0bb 100644 --- a/Lib/ctypes/wintypes.py +++ b/Lib/ctypes/wintypes.py @@ -34,8 +34,14 @@ LPCOLESTR = LPOLESTR = OLESTR = c_wchar_p LPCWSTR = LPWSTR = c_wchar_p LPCSTR = LPSTR = c_char_p -WPARAM = c_uint -LPARAM = c_long +# WPARAM is defined as UINT_PTR (unsigned type) +# LPARAM is defined as LONG_PTR (signed type) +if sizeof(c_long) == sizeof(c_void_p): + WPARAM = c_ulong + LPARAM = c_long +elif sizeof(c_longlong) == sizeof(c_void_p): + WPARAM = c_ulonglong + LPARAM = c_longlong ATOM = WORD LANGID = WORD @@ -48,7 +54,7 @@ LCID = DWORD ################################################################ # HANDLE types -HANDLE = c_ulong # in the header files: void * +HANDLE = c_void_p # in the header files: void * HACCEL = HANDLE HBITMAP = HANDLE diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py index 400c31c..396e2bd 100644 --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -819,7 +819,7 @@ class EditorWindow(object): def close(self): reply = self.maybesave() - if reply != "cancel": + if str(reply) != "cancel": self._close() return reply diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index 615dcc7..1415226 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -41,8 +41,8 @@ except ImportError: __author__ = "Vinay Sajip <vinay_sajip@red-dove.com>" __status__ = "production" -__version__ = "0.5.0.0" -__date__ = "08 January 2007" +__version__ = "0.5.0.1" +__date__ = "09 January 2007" #--------------------------------------------------------------------------- # Miscellaneous module data @@ -764,17 +764,15 @@ class FileHandler(StreamHandler): """ Open the specified file and use it as the stream for logging. """ - if codecs is None: - encoding = None - if encoding is None: - stream = open(filename, mode) - else: - stream = codecs.open(filename, mode, encoding) - StreamHandler.__init__(self, stream) #keep the absolute path, otherwise derived classes which use this #may come a cropper when the current directory changes + if codecs is None: + encoding = None self.baseFilename = os.path.abspath(filename) self.mode = mode + self.encoding = encoding + stream = self._open() + StreamHandler.__init__(self, stream) def close(self): """ @@ -784,6 +782,17 @@ class FileHandler(StreamHandler): self.stream.close() StreamHandler.close(self) + def _open(self): + """ + Open the current base file with the (original) mode and encoding. + Return the resulting stream. + """ + if self.encoding is None: + stream = open(self.baseFilename, self.mode) + else: + stream = codecs.open(self.baseFilename, self.mode, self.encoding) + return stream + #--------------------------------------------------------------------------- # Manager classes and functions #--------------------------------------------------------------------------- diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py index 82896ad..41cbca1 100644 --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -32,6 +32,7 @@ try: import cPickle as pickle except ImportError: import pickle +from stat import ST_DEV, ST_INO try: import codecs @@ -286,6 +287,54 @@ class TimedRotatingFileHandler(BaseRotatingHandler): self.stream = open(self.baseFilename, 'w') self.rolloverAt = self.rolloverAt + self.interval +class WatchedFileHandler(logging.FileHandler): + """ + A handler for logging to a file, which watches the file + to see if it has changed while in use. This can happen because of + usage of programs such as newsyslog and logrotate which perform + log file rotation. This handler, intended for use under Unix, + watches the file to see if it has changed since the last emit. + (A file has changed if its device or inode have changed.) + If it has changed, the old file stream is closed, and the file + opened to get a new stream. + + This handler is not appropriate for use under Windows, because + under Windows open files cannot be moved or renamed - logging + opens the files with exclusive locks - and so there is no need + for such a handler. Furthermore, ST_INO is not supported under + Windows; stat always returns zero for this value. + + This handler is based on a suggestion and patch by Chad J. + Schroeder. + """ + def __init__(self, filename, mode='a', encoding=None): + logging.FileHandler.__init__(self, filename, mode, encoding) + stat = os.stat(self.baseFilename) + self.dev, self.ino = stat[ST_DEV], stat[ST_INO] + + def emit(self, record): + """ + Emit a record. + + First check if the underlying file has changed, and if it + has, close the old stream and reopen the file to get the + current stream. + """ + if not os.path.exists(self.baseFilename): + stat = None + changed = 1 + else: + stat = os.stat(self.baseFilename) + changed = (stat[ST_DEV] != self.dev) or (stat[ST_INO] != self.ino) + if changed: + self.stream.flush() + self.stream.close() + self.stream = self._open() + if stat is None: + stat = os.stat(self.baseFilename) + self.dev, self.ino = stat[ST_DEV], stat[ST_INO] + logging.FileHandler.emit(self, record) + class SocketHandler(logging.Handler): """ A handler class which writes logging records, in pickle format, to diff --git a/Lib/platform.py b/Lib/platform.py index cf58819..ba24b28 100755 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -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:mal@lemburg.com - Copyright (c) 2000-2003, eGenix.com Software GmbH; mailto:info@egenix.com + Copyright (c) 2000-2007, eGenix.com Software GmbH; mailto:info@egenix.com 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 @@ __copyright__ = """ """ -__version__ = '1.0.4' +__version__ = '1.0.6' import sys,string,os,re @@ -136,6 +139,11 @@ def libc_ver(executable=sys.executable,lib='',version='', 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,14 +226,69 @@ def _dist_try_harder(distname,version,id): return distname,version,id _release_filename = re.compile(r'(\w+)[-_](release|version)') -_release_version = re.compile(r'([\d.]+)[^(]*(?:\((.+)\))?') - -# Note:In supported_dists below we need 'fedora' before 'redhat' as in -# Fedora redhat-release is a link to fedora-release. - -def dist(distname='',version='',id='', - - supported_dists=('SuSE', 'debian', 'fedora', 'redhat', 'mandrake')): +_lsb_release_version = re.compile(r'(.+)' + ' release ' + '([\d.]+)' + '[^(]*(?:\((.+)\))?') +_release_version = re.compile(r'([^0-9]+)' + '(?: release )?' + '([\d.]+)' + '[^(]*(?:\((.+)\))?') + +# 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 + +_supported_dists = ('SuSE', 'debian', 'fedora', 'redhat', 'centos', + 'mandrake', 'rocks', 'slackware', 'yellowdog', + 'gentoo', 'UnitedLinux') + +def _parse_release_file(firstline): + + # 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] + else: + id = '' + 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. @@ -233,6 +296,15 @@ def dist(distname='',version='',id='', /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,33 +314,50 @@ def dist(distname='',version='',id='', 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: @@ -357,7 +446,7 @@ def popen(cmd, mode='r', bufsize=None): 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 +467,7 @@ _ver_output = re.compile(r'(?:([\w ]+) ([\w.]+) ' '.*' 'Version ([\d.]+))') -def _syscmd_ver(system='',release='',version='', +def _syscmd_ver(system='', release='', version='', supported_platforms=('win32','win16','dos','os2')): @@ -418,7 +507,7 @@ def _syscmd_ver(system='',release='',version='', # 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] == '.': @@ -615,8 +704,11 @@ def _java_getprop(name,default): from java.lang import System try: - return System.getProperty(name) - except: + value = System.getProperty(name) + if value is None: + return default + return value + except AttributeError: return default def java_ver(release='',vendor='',vminfo=('','',''),osinfo=('','','')): @@ -637,20 +729,20 @@ def java_ver(release='',vendor='',vminfo=('','',''),osinfo=('','','')): 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('java.os.arch',os_arch) - os_name = _java_getprop('java.os.name',os_name) - os_version = _java_getprop('java.os.version',os_version) - osinfo = os_name,os_version,os_arch - - 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('java.os.arch', os_arch) + os_name = _java_getprop('java.os.name', os_name) + os_version = _java_getprop('java.os.version', os_version) + osinfo = os_name, os_version, os_arch + + return release, vendor, vminfo, osinfo ### System name aliasing @@ -716,7 +808,7 @@ def _platform(*args): # Format the platform string platform = string.join( map(string.strip, - filter(len,args)), + filter(len, args)), '-') # Cleanup some possible filename obstacles... @@ -871,7 +963,10 @@ def architecture(executable=sys.executable,bits='',linkage=''): 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: @@ -960,6 +1055,10 @@ def uname(): release,version,csd,ptype = win32_ver() if release and version: use_syscmd_ver = 0 + # XXX Should try to parse 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 # Try the 'ver' system command available on some # platforms @@ -1092,36 +1191,136 @@ def processor(): ### 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*' + '\[([^\]]+)\]?') + +_jython_sys_version_parser = re.compile( + r'([\d\.]+)') + +_ironpython_sys_version_parser = re.compile( + r'IronPython\s*' + '([\d\.]+)' + '(?: \(([\d\.]+)\))?' + ' on (.NET [\d\.]+)') -def _sys_version(): +_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 - identification string. + (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(): @@ -1131,7 +1330,9 @@ def python_version(): will always include the patchlevel (it defaults to 0). """ - return _sys_version()[0] + if hasattr(sys, 'version_info'): + return '%i.%i.%i' % sys.version_info[:3] + return _sys_version()[1] def python_version_tuple(): @@ -1142,7 +1343,36 @@ def python_version_tuple(): will always include the patchlevel (it defaults to 0). """ - return string.split(_sys_version()[0], '.') + if hasattr(sys, 'version_info'): + return sys.version_info[:3] + 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(): @@ -1150,7 +1380,7 @@ def python_build(): build number and date as strings. """ - return _sys_version()[1:3] + return _sys_version()[4:6] def python_compiler(): @@ -1158,7 +1388,7 @@ def python_compiler(): Python. """ - return _sys_version()[3] + return _sys_version()[6] ### The Opus Magnum of platform strings :-) @@ -1219,7 +1449,7 @@ def platform(aliased=0, terse=0): 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, diff --git a/Lib/pydoc.py b/Lib/pydoc.py index 892e278..dd10334 100755 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1448,6 +1448,9 @@ def locate(path, forceload=0): text = TextDoc() html = HTMLDoc() +class _OldStyleClass: pass +_OLD_INSTANCE_TYPE = type(_OldStyleClass()) + def resolve(thing, forceload=0): """Given an object or a path to an object, get the object and its name.""" if isinstance(thing, str): @@ -1468,12 +1471,16 @@ def doc(thing, title='Python Library Documentation: %s', forceload=0): desc += ' in ' + name[:name.rfind('.')] elif module and module is not object: desc += ' in module ' + module.__name__ - if not (inspect.ismodule(object) or - inspect.isclass(object) or - inspect.isroutine(object) or - inspect.isgetsetdescriptor(object) or - inspect.ismemberdescriptor(object) or - isinstance(object, property)): + if type(object) is _OLD_INSTANCE_TYPE: + # If the passed object is an instance of an old-style class, + # document its available methods instead of its value. + object = object.__class__ + elif not (inspect.ismodule(object) or + inspect.isclass(object) or + inspect.isroutine(object) or + inspect.isgetsetdescriptor(object) or + inspect.ismemberdescriptor(object) or + isinstance(object, property)): # If the passed object is a piece of data or an instance, # document its available methods instead of its value. object = type(object) diff --git a/Lib/sqlite3/dbapi2.py b/Lib/sqlite3/dbapi2.py index 9b7d56d..7eb28e8 100644 --- a/Lib/sqlite3/dbapi2.py +++ b/Lib/sqlite3/dbapi2.py @@ -68,7 +68,7 @@ def register_adapters_and_converters(): timepart_full = timepart.split(".") hours, minutes, seconds = map(int, timepart_full[0].split(":")) if len(timepart_full) == 2: - microseconds = int(float("0." + timepart_full[1]) * 1000000) + microseconds = int(timepart_full[1]) else: microseconds = 0 diff --git a/Lib/sqlite3/test/factory.py b/Lib/sqlite3/test/factory.py index 8778056..8a77d5d 100644 --- a/Lib/sqlite3/test/factory.py +++ b/Lib/sqlite3/test/factory.py @@ -91,7 +91,7 @@ class RowFactoryTests(unittest.TestCase): list), "row is not instance of list") - def CheckSqliteRow(self): + def CheckSqliteRowIndex(self): self.con.row_factory = sqlite.Row row = self.con.execute("select 1 as a, 2 as b").fetchone() self.failUnless(isinstance(row, @@ -110,6 +110,27 @@ class RowFactoryTests(unittest.TestCase): self.failUnless(col1 == 1, "by index: wrong result for column 0") self.failUnless(col2 == 2, "by index: wrong result for column 1") + def CheckSqliteRowIter(self): + """Checks if the row object is iterable""" + self.con.row_factory = sqlite.Row + row = self.con.execute("select 1 as a, 2 as b").fetchone() + for col in row: + pass + + def CheckSqliteRowAsTuple(self): + """Checks if the row object can be converted to a tuple""" + self.con.row_factory = sqlite.Row + row = self.con.execute("select 1 as a, 2 as b").fetchone() + t = tuple(row) + + def CheckSqliteRowAsDict(self): + """Checks if the row object can be correctly converted to a dictionary""" + self.con.row_factory = sqlite.Row + row = self.con.execute("select 1 as a, 2 as b").fetchone() + d = dict(row) + self.failUnlessEqual(d["a"], row["a"]) + self.failUnlessEqual(d["b"], row["b"]) + def tearDown(self): self.con.close() diff --git a/Lib/sqlite3/test/regression.py b/Lib/sqlite3/test/regression.py index c8733b9..addedb1 100644 --- a/Lib/sqlite3/test/regression.py +++ b/Lib/sqlite3/test/regression.py @@ -69,6 +69,16 @@ class RegressionTests(unittest.TestCase): cur.execute('select 1 as "foo baz"') self.failUnlessEqual(cur.description[0][0], "foo baz") + def CheckStatementAvailable(self): + # pysqlite up to 2.3.2 crashed on this, because the active statement handle was not checked + # before trying to fetch data from it. close() destroys the active statement ... + con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES) + cur = con.cursor() + cur.execute("select 4 union select 5") + cur.close() + cur.fetchone() + cur.fetchone() + def suite(): regression_suite = unittest.makeSuite(RegressionTests, "Check") return unittest.TestSuite((regression_suite,)) diff --git a/Lib/sqlite3/test/types.py b/Lib/sqlite3/test/types.py index 9a11f5c..a357b2e 100644 --- a/Lib/sqlite3/test/types.py +++ b/Lib/sqlite3/test/types.py @@ -112,6 +112,7 @@ class DeclTypesTests(unittest.TestCase): # and implement two custom ones sqlite.converters["BOOL"] = lambda x: bool(int(x)) sqlite.converters["FOO"] = DeclTypesTests.Foo + sqlite.converters["WRONG"] = lambda x: "WRONG" def tearDown(self): del sqlite.converters["FLOAT"] @@ -123,7 +124,7 @@ class DeclTypesTests(unittest.TestCase): def CheckString(self): # default self.cur.execute("insert into test(s) values (?)", ("foo",)) - self.cur.execute("select s from test") + self.cur.execute('select s as "s [WRONG]" from test') row = self.cur.fetchone() self.failUnlessEqual(row[0], "foo") @@ -210,26 +211,32 @@ class DeclTypesTests(unittest.TestCase): class ColNamesTests(unittest.TestCase): def setUp(self): - self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_COLNAMES|sqlite.PARSE_DECLTYPES) + self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_COLNAMES) self.cur = self.con.cursor() self.cur.execute("create table test(x foo)") sqlite.converters["FOO"] = lambda x: "[%s]" % x sqlite.converters["BAR"] = lambda x: "<%s>" % x sqlite.converters["EXC"] = lambda x: 5/0 + sqlite.converters["B1B1"] = lambda x: "MARKER" def tearDown(self): del sqlite.converters["FOO"] del sqlite.converters["BAR"] del sqlite.converters["EXC"] + del sqlite.converters["B1B1"] self.cur.close() self.con.close() - def CheckDeclType(self): + def CheckDeclTypeNotUsed(self): + """ + Assures that the declared type is not used when PARSE_DECLTYPES + is not set. + """ self.cur.execute("insert into test(x) values (?)", ("xxx",)) self.cur.execute("select x from test") val = self.cur.fetchone()[0] - self.failUnlessEqual(val, "[xxx]") + self.failUnlessEqual(val, "xxx") def CheckNone(self): self.cur.execute("insert into test(x) values (?)", (None,)) @@ -247,6 +254,11 @@ class ColNamesTests(unittest.TestCase): # whitespace should be stripped. self.failUnlessEqual(self.cur.description[0][0], "x") + def CheckCaseInConverterName(self): + self.cur.execute("""select 'other' as "x [b1b1]\"""") + val = self.cur.fetchone()[0] + self.failUnlessEqual(val, "MARKER") + def CheckCursorDescriptionNoRow(self): """ cursor.description should at least provide the column name(s), even if @@ -340,6 +352,13 @@ class DateTimeTests(unittest.TestCase): ts2 = self.cur.fetchone()[0] self.failUnlessEqual(ts, ts2) + def CheckDateTimeSubSecondsFloatingPoint(self): + ts = sqlite.Timestamp(2004, 2, 14, 7, 15, 0, 510241) + self.cur.execute("insert into test(ts) values (?)", (ts,)) + self.cur.execute("select ts from test") + ts2 = self.cur.fetchone()[0] + self.failUnlessEqual(ts, ts2) + def suite(): sqlite_type_suite = unittest.makeSuite(SqliteTypeTests, "Check") decltypes_type_suite = unittest.makeSuite(DeclTypesTests, "Check") diff --git a/Lib/subprocess.py b/Lib/subprocess.py index f5800fb..6656890 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -500,7 +500,7 @@ def list2cmdline(seq): if result: result.append(' ') - needquote = (" " in arg) or ("\t" in arg) + needquote = (" " in arg) or ("\t" in arg) or arg == "" if needquote: result.append('"') diff --git a/Lib/test/test___all__.py b/Lib/test/test___all__.py index e4f0f44..d8e850a 100644 --- a/Lib/test/test___all__.py +++ b/Lib/test/test___all__.py @@ -132,7 +132,6 @@ class AllTest(unittest.TestCase): self.check_all("rlcompleter") self.check_all("robotparser") self.check_all("sched") - self.check_all("sets") self.check_all("sgmllib") self.check_all("shelve") self.check_all("shlex") diff --git a/Lib/test/test_optparse.py b/Lib/test/test_optparse.py index aa6525e..e05fbc6 100644 --- a/Lib/test/test_optparse.py +++ b/Lib/test/test_optparse.py @@ -1500,8 +1500,16 @@ class TestHelp(BaseTest): self.assertHelpEquals(_expected_help_long_opts_first) def test_help_title_formatter(self): - self.parser.formatter = TitledHelpFormatter() - self.assertHelpEquals(_expected_help_title_formatter) + save = os.environ.get("COLUMNS") + try: + os.environ["COLUMNS"] = "80" + self.parser.formatter = TitledHelpFormatter() + self.assertHelpEquals(_expected_help_title_formatter) + finally: + if save is not None: + os.environ["COLUMNS"] = save + else: + del os.environ["COLUMNS"] def test_wrap_columns(self): # Ensure that wrapping respects $COLUMNS environment variable. diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py index 0d08b79..a1c797c 100644 --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -476,6 +476,16 @@ class SetSubclass(set): class TestSetSubclass(TestSet): thetype = SetSubclass +class SetSubclassWithKeywordArgs(set): + def __init__(self, iterable=[], newarg=None): + set.__init__(self, iterable) + +class TestSetSubclassWithKeywordArgs(TestSet): + + def test_keywords_in_subclass(self): + 'SF bug #1486663 -- this used to erroneously raise a TypeError' + SetSubclassWithKeywordArgs(newarg=1) + class TestFrozenSet(TestJointOps): thetype = frozenset @@ -1454,6 +1464,7 @@ def test_main(verbose=None): test_classes = ( TestSet, TestSetSubclass, + TestSetSubclassWithKeywordArgs, TestFrozenSet, TestFrozenSetSubclass, TestSetOfSets, diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index fcc0f45..1b34d61 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -430,6 +430,8 @@ class ProcessTestCase(unittest.TestCase): '"a\\\\b c" d e') self.assertEqual(subprocess.list2cmdline(['a\\\\b\\ c', 'd', 'e']), '"a\\\\b\\ c" d e') + self.assertEqual(subprocess.list2cmdline(['ab', '']), + 'ab ""') def test_poll(self): |