summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib')
-rw-r--r--Lib/BaseHTTPServer.py4
-rw-r--r--Lib/ctypes/__init__.py30
-rw-r--r--Lib/ctypes/test/test_win32.py24
-rw-r--r--Lib/ctypes/util.py78
-rw-r--r--Lib/ctypes/wintypes.py12
-rw-r--r--Lib/idlelib/EditorWindow.py2
-rw-r--r--Lib/logging/__init__.py27
-rw-r--r--Lib/logging/handlers.py49
-rwxr-xr-xLib/platform.py370
-rwxr-xr-xLib/pydoc.py19
-rw-r--r--Lib/sqlite3/dbapi2.py2
-rw-r--r--Lib/sqlite3/test/factory.py23
-rw-r--r--Lib/sqlite3/test/regression.py10
-rw-r--r--Lib/sqlite3/test/types.py27
-rw-r--r--Lib/subprocess.py2
-rw-r--r--Lib/test/test___all__.py1
-rw-r--r--Lib/test/test_optparse.py12
-rw-r--r--Lib/test/test_set.py11
-rw-r--r--Lib/test/test_subprocess.py2
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):