summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib')
-rw-r--r--Lib/Cookie.py6
-rwxr-xr-xLib/cgi.py20
-rw-r--r--Lib/compiler/ast.py4
-rw-r--r--Lib/compiler/pycodegen.py19
-rw-r--r--Lib/compiler/symbols.py2
-rw-r--r--Lib/ctypes/__init__.py7
-rw-r--r--Lib/ctypes/test/test_as_parameter.py215
-rw-r--r--Lib/ctypes/test/test_functions.py1
-rw-r--r--Lib/ctypes/test/test_numbers.py15
-rw-r--r--Lib/ctypes/test/test_prototypes.py15
-rw-r--r--Lib/ctypes/test/test_python_api.py5
-rw-r--r--Lib/distutils/__init__.py12
-rw-r--r--Lib/idlelib/Bindings.py4
-rw-r--r--Lib/idlelib/CREDITS.txt4
-rw-r--r--Lib/idlelib/CodeContext.py2
-rw-r--r--Lib/idlelib/NEWS.txt24
-rw-r--r--Lib/idlelib/PyShell.py59
-rw-r--r--Lib/idlelib/idlever.py2
-rw-r--r--Lib/logging/__init__.py4
-rw-r--r--Lib/logging/config.py2
-rw-r--r--Lib/site.py12
-rw-r--r--Lib/string.py1
-rwxr-xr-xLib/tabnanny.py4
-rw-r--r--Lib/tarfile.py3
-rw-r--r--Lib/test/exception_hierarchy.txt1
-rw-r--r--Lib/test/inspect_fodder2.py9
-rw-r--r--Lib/test/output/test_cgi2
-rw-r--r--Lib/test/test_bytes.py8
-rw-r--r--Lib/test/test_bz2.py11
-rw-r--r--Lib/test/test_cgi.py69
-rw-r--r--Lib/test/test_compiler.py7
-rw-r--r--Lib/test/test_format.py8
-rw-r--r--Lib/test/test_index.py182
-rw-r--r--Lib/test/test_inspect.py3
-rw-r--r--Lib/test/test_logging.py4
-rw-r--r--Lib/test/test_mailbox.py13
-rw-r--r--Lib/test/test_signal.py149
-rw-r--r--Lib/test/test_socketserver.py9
-rw-r--r--Lib/test/test_tarfile.py21
-rw-r--r--Lib/test/test_threading.py70
-rw-r--r--Lib/test/test_threadsignals.py2
-rw-r--r--Lib/test/test_urllib2.py77
-rw-r--r--Lib/test/test_uuid.py97
-rw-r--r--Lib/test/test_xml_etree_c.py11
-rw-r--r--Lib/tokenize.py3
-rw-r--r--Lib/trace.py4
-rw-r--r--Lib/urllib2.py28
-rw-r--r--Lib/uuid.py60
48 files changed, 1011 insertions, 279 deletions
diff --git a/Lib/Cookie.py b/Lib/Cookie.py
index 1b84e9f..46ef3ea 100644
--- a/Lib/Cookie.py
+++ b/Lib/Cookie.py
@@ -305,8 +305,10 @@ _Translator = {
'\375' : '\\375', '\376' : '\\376', '\377' : '\\377'
}
+_idmap = ''.join(chr(x) for x in xrange(256))
+
def _quote(str, LegalChars=_LegalChars,
- idmap=string._idmap, translate=string.translate):
+ idmap=_idmap, translate=string.translate):
#
# If the string does not need to be double-quoted,
# then just return the string. Otherwise, surround
@@ -440,7 +442,7 @@ class Morsel(dict):
def set(self, key, val, coded_val,
LegalChars=_LegalChars,
- idmap=string._idmap, translate=string.translate ):
+ idmap=_idmap, translate=string.translate):
# First we verify that the key isn't a reserved word
# Second we make sure it only contains legal characters
if key.lower() in self._reserved:
diff --git a/Lib/cgi.py b/Lib/cgi.py
index 4c617a6..47c0279 100755
--- a/Lib/cgi.py
+++ b/Lib/cgi.py
@@ -251,6 +251,10 @@ def parse_multipart(fp, pdict):
XXX This should really be subsumed by FieldStorage altogether -- no
point in having two implementations of the same parsing algorithm.
+ Also, FieldStorage protects itself better against certain DoS attacks
+ by limiting the size of the data read in one chunk. The API here
+ does not support that kind of protection. This also affects parse()
+ since it can call parse_multipart().
"""
boundary = ""
@@ -691,7 +695,7 @@ class FieldStorage:
def read_lines_to_eof(self):
"""Internal: read lines until EOF."""
while 1:
- line = self.fp.readline()
+ line = self.fp.readline(1<<16)
if not line:
self.done = -1
break
@@ -702,12 +706,13 @@ class FieldStorage:
next = "--" + self.outerboundary
last = next + "--"
delim = ""
+ last_line_lfend = True
while 1:
- line = self.fp.readline()
+ line = self.fp.readline(1<<16)
if not line:
self.done = -1
break
- if line[:2] == "--":
+ if line[:2] == "--" and last_line_lfend:
strippedline = line.strip()
if strippedline == next:
break
@@ -718,11 +723,14 @@ class FieldStorage:
if line[-2:] == "\r\n":
delim = "\r\n"
line = line[:-2]
+ last_line_lfend = True
elif line[-1] == "\n":
delim = "\n"
line = line[:-1]
+ last_line_lfend = True
else:
delim = ""
+ last_line_lfend = False
self.__write(odelim + line)
def skip_lines(self):
@@ -731,18 +739,20 @@ class FieldStorage:
return
next = "--" + self.outerboundary
last = next + "--"
+ last_line_lfend = True
while 1:
- line = self.fp.readline()
+ line = self.fp.readline(1<<16)
if not line:
self.done = -1
break
- if line[:2] == "--":
+ if line[:2] == "--" and last_line_lfend:
strippedline = line.strip()
if strippedline == next:
break
if strippedline == last:
self.done = 1
break
+ last_line_lfend = line.endswith('\n')
def make_file(self, binary=None):
"""Overridable: return a readable & writable file.
diff --git a/Lib/compiler/ast.py b/Lib/compiler/ast.py
index 8dcdf68..93437d6 100644
--- a/Lib/compiler/ast.py
+++ b/Lib/compiler/ast.py
@@ -583,11 +583,9 @@ class GenExpr(Node):
def __init__(self, code, lineno=None):
self.code = code
self.lineno = lineno
- self.argnames = ['[outmost-iterable]']
+ self.argnames = ['.0']
self.varargs = self.kwargs = None
-
-
def getChildren(self):
return self.code,
diff --git a/Lib/compiler/pycodegen.py b/Lib/compiler/pycodegen.py
index c8a9779..db2251e 100644
--- a/Lib/compiler/pycodegen.py
+++ b/Lib/compiler/pycodegen.py
@@ -656,18 +656,19 @@ class CodeGenerator:
stack = []
for i, for_ in zip(range(len(node.quals)), node.quals):
- start, anchor = self.visit(for_)
+ start, anchor, end = self.visit(for_)
cont = None
for if_ in for_.ifs:
if cont is None:
cont = self.newBlock()
self.visit(if_, cont)
- stack.insert(0, (start, cont, anchor))
+ stack.insert(0, (start, cont, anchor, end))
self.visit(node.expr)
self.emit('YIELD_VALUE')
+ self.emit('POP_TOP')
- for start, cont, anchor in stack:
+ for start, cont, anchor, end in stack:
if cont:
skip_one = self.newBlock()
self.emit('JUMP_FORWARD', skip_one)
@@ -676,14 +677,22 @@ class CodeGenerator:
self.nextBlock(skip_one)
self.emit('JUMP_ABSOLUTE', start)
self.startBlock(anchor)
+ self.emit('POP_BLOCK')
+ self.setups.pop()
+ self.startBlock(end)
+
self.emit('LOAD_CONST', None)
def visitGenExprFor(self, node):
start = self.newBlock()
anchor = self.newBlock()
+ end = self.newBlock()
+
+ self.setups.push((LOOP, start))
+ self.emit('SETUP_LOOP', end)
if node.is_outmost:
- self.loadName('[outmost-iterable]')
+ self.loadName('.0')
else:
self.visit(node.iter)
self.emit('GET_ITER')
@@ -693,7 +702,7 @@ class CodeGenerator:
self.emit('FOR_ITER', anchor)
self.nextBlock()
self.visit(node.assign)
- return start, anchor
+ return start, anchor, end
def visitGenExprIf(self, node, branch):
self.set_lineno(node, force=True)
diff --git a/Lib/compiler/symbols.py b/Lib/compiler/symbols.py
index af8e1c9..7ddf42c 100644
--- a/Lib/compiler/symbols.py
+++ b/Lib/compiler/symbols.py
@@ -188,7 +188,7 @@ class GenExprScope(Scope):
i = self.__counter
self.__counter += 1
self.__super_init("generator expression<%d>"%i, module, klass)
- self.add_param('[outmost-iterable]')
+ self.add_param('.0')
def get_names(self):
keys = Scope.get_names(self)
diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py
index 9e91ac6..78a2ab8 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.0"
+__version__ = "1.0.1"
from _ctypes import Union, Structure, Array
from _ctypes import _Pointer
@@ -135,6 +135,11 @@ from _ctypes import _SimpleCData
class py_object(_SimpleCData):
_type_ = "O"
+ def __repr__(self):
+ try:
+ return super(py_object, self).__repr__()
+ except ValueError:
+ return "%s(<NULL>)" % type(self).__name__
class c_short(_SimpleCData):
_type_ = "h"
diff --git a/Lib/ctypes/test/test_as_parameter.py b/Lib/ctypes/test/test_as_parameter.py
new file mode 100644
index 0000000..0581059
--- /dev/null
+++ b/Lib/ctypes/test/test_as_parameter.py
@@ -0,0 +1,215 @@
+import unittest
+from ctypes import *
+import _ctypes_test
+
+dll = CDLL(_ctypes_test.__file__)
+
+try:
+ CALLBACK_FUNCTYPE = WINFUNCTYPE
+except NameError:
+ # fake to enable this test on Linux
+ CALLBACK_FUNCTYPE = CFUNCTYPE
+
+class POINT(Structure):
+ _fields_ = [("x", c_int), ("y", c_int)]
+
+class BasicWrapTestCase(unittest.TestCase):
+ def wrap(self, param):
+ return param
+
+ def test_wchar_parm(self):
+ try:
+ c_wchar
+ except NameError:
+ return
+ f = dll._testfunc_i_bhilfd
+ f.argtypes = [c_byte, c_wchar, c_int, c_long, c_float, c_double]
+ result = f(self.wrap(1), self.wrap(u"x"), self.wrap(3), self.wrap(4), self.wrap(5.0), self.wrap(6.0))
+ self.failUnlessEqual(result, 139)
+ self.failUnless(type(result), int)
+
+ def test_pointers(self):
+ f = dll._testfunc_p_p
+ f.restype = POINTER(c_int)
+ f.argtypes = [POINTER(c_int)]
+
+ # This only works if the value c_int(42) passed to the
+ # function is still alive while the pointer (the result) is
+ # used.
+
+ v = c_int(42)
+
+ self.failUnlessEqual(pointer(v).contents.value, 42)
+ result = f(self.wrap(pointer(v)))
+ self.failUnlessEqual(type(result), POINTER(c_int))
+ self.failUnlessEqual(result.contents.value, 42)
+
+ # This on works...
+ result = f(self.wrap(pointer(v)))
+ self.failUnlessEqual(result.contents.value, v.value)
+
+ p = pointer(c_int(99))
+ result = f(self.wrap(p))
+ self.failUnlessEqual(result.contents.value, 99)
+
+ def test_shorts(self):
+ f = dll._testfunc_callback_i_if
+
+ args = []
+ expected = [262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048,
+ 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1]
+
+ def callback(v):
+ args.append(v)
+ return v
+
+ CallBack = CFUNCTYPE(c_int, c_int)
+
+ cb = CallBack(callback)
+ f(self.wrap(2**18), self.wrap(cb))
+ self.failUnlessEqual(args, expected)
+
+ ################################################################
+
+ def test_callbacks(self):
+ f = dll._testfunc_callback_i_if
+ f.restype = c_int
+
+ MyCallback = CFUNCTYPE(c_int, c_int)
+
+ def callback(value):
+ #print "called back with", value
+ return value
+
+ cb = MyCallback(callback)
+
+ result = f(self.wrap(-10), self.wrap(cb))
+ self.failUnlessEqual(result, -18)
+
+ # test with prototype
+ f.argtypes = [c_int, MyCallback]
+ cb = MyCallback(callback)
+
+ result = f(self.wrap(-10), self.wrap(cb))
+ self.failUnlessEqual(result, -18)
+
+ result = f(self.wrap(-10), self.wrap(cb))
+ self.failUnlessEqual(result, -18)
+
+ AnotherCallback = CALLBACK_FUNCTYPE(c_int, c_int, c_int, c_int, c_int)
+
+ # check that the prototype works: we call f with wrong
+ # argument types
+ cb = AnotherCallback(callback)
+ self.assertRaises(ArgumentError, f, self.wrap(-10), self.wrap(cb))
+
+ def test_callbacks_2(self):
+ # Can also use simple datatypes as argument type specifiers
+ # for the callback function.
+ # In this case the call receives an instance of that type
+ f = dll._testfunc_callback_i_if
+ f.restype = c_int
+
+ MyCallback = CFUNCTYPE(c_int, c_int)
+
+ f.argtypes = [c_int, MyCallback]
+
+ def callback(value):
+ #print "called back with", value
+ self.failUnlessEqual(type(value), int)
+ return value
+
+ cb = MyCallback(callback)
+ result = f(self.wrap(-10), self.wrap(cb))
+ self.failUnlessEqual(result, -18)
+
+ def test_longlong_callbacks(self):
+
+ f = dll._testfunc_callback_q_qf
+ f.restype = c_longlong
+
+ MyCallback = CFUNCTYPE(c_longlong, c_longlong)
+
+ f.argtypes = [c_longlong, MyCallback]
+
+ def callback(value):
+ self.failUnless(isinstance(value, (int, long)))
+ return value & 0x7FFFFFFF
+
+ cb = MyCallback(callback)
+
+ self.failUnlessEqual(13577625587, int(f(self.wrap(1000000000000), self.wrap(cb))))
+
+ def test_byval(self):
+ # without prototype
+ ptin = POINT(1, 2)
+ ptout = POINT()
+ # EXPORT int _testfunc_byval(point in, point *pout)
+ result = dll._testfunc_byval(ptin, byref(ptout))
+ got = result, ptout.x, ptout.y
+ expected = 3, 1, 2
+ self.failUnlessEqual(got, expected)
+
+ # with prototype
+ ptin = POINT(101, 102)
+ ptout = POINT()
+ dll._testfunc_byval.argtypes = (POINT, POINTER(POINT))
+ dll._testfunc_byval.restype = c_int
+ result = dll._testfunc_byval(self.wrap(ptin), byref(ptout))
+ got = result, ptout.x, ptout.y
+ expected = 203, 101, 102
+ self.failUnlessEqual(got, expected)
+
+ def test_struct_return_2H(self):
+ class S2H(Structure):
+ _fields_ = [("x", c_short),
+ ("y", c_short)]
+ dll.ret_2h_func.restype = S2H
+ dll.ret_2h_func.argtypes = [S2H]
+ inp = S2H(99, 88)
+ s2h = dll.ret_2h_func(self.wrap(inp))
+ self.failUnlessEqual((s2h.x, s2h.y), (99*2, 88*3))
+
+ def test_struct_return_8H(self):
+ class S8I(Structure):
+ _fields_ = [("a", c_int),
+ ("b", c_int),
+ ("c", c_int),
+ ("d", c_int),
+ ("e", c_int),
+ ("f", c_int),
+ ("g", c_int),
+ ("h", c_int)]
+ dll.ret_8i_func.restype = S8I
+ dll.ret_8i_func.argtypes = [S8I]
+ inp = S8I(9, 8, 7, 6, 5, 4, 3, 2)
+ s8i = dll.ret_8i_func(self.wrap(inp))
+ self.failUnlessEqual((s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h),
+ (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9))
+
+#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class AsParamWrapper(object):
+ def __init__(self, param):
+ self._as_parameter_ = param
+
+class AsParamWrapperTestCase(BasicWrapTestCase):
+ wrap = AsParamWrapper
+
+#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class AsParamPropertyWrapper(object):
+ def __init__(self, param):
+ self._param = param
+
+ def getParameter(self):
+ return self._param
+ _as_parameter_ = property(getParameter)
+
+class AsParamPropertyWrapperTestCase(BasicWrapTestCase):
+ wrap = AsParamPropertyWrapper
+
+#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/Lib/ctypes/test/test_functions.py b/Lib/ctypes/test/test_functions.py
index bfa0cad..759aea7 100644
--- a/Lib/ctypes/test/test_functions.py
+++ b/Lib/ctypes/test/test_functions.py
@@ -222,6 +222,7 @@ class FunctionTestCase(unittest.TestCase):
def callback(v):
args.append(v)
+ return v
CallBack = CFUNCTYPE(c_int, c_int)
diff --git a/Lib/ctypes/test/test_numbers.py b/Lib/ctypes/test/test_numbers.py
index 83003db..c22688d 100644
--- a/Lib/ctypes/test/test_numbers.py
+++ b/Lib/ctypes/test/test_numbers.py
@@ -19,7 +19,7 @@ def valid_ranges(*types):
result.append((min(a, b, c, d), max(a, b, c, d)))
return result
-ArgType = type(c_int(0)._as_parameter_)
+ArgType = type(byref(c_int(0)))
unsigned_types = [c_ubyte, c_ushort, c_uint, c_ulong]
signed_types = [c_byte, c_short, c_int, c_long, c_longlong]
@@ -80,19 +80,6 @@ class NumberTestCase(unittest.TestCase):
for t in signed_types + unsigned_types + float_types:
self.failUnlessEqual(ArgType, type(t.from_param(0)))
- def test_as_parameter(self):
- # The _as_parameter_ property must also
- # be a PyCArgObject instance
- for t in signed_types + unsigned_types + float_types:
- parm = t()._as_parameter_
- self.failUnlessEqual(ArgType, type(parm))
-
- # _as_parameter_ is readonly!
- #
- # Python 2.3 and 2.4 raise a TypeError when trying to set
- # a readonly attribute, 2.5 raises an AttributeError.
- self.assertRaises((AttributeError, TypeError), setattr, t(), "_as_parameter_", None)
-
def test_byref(self):
# calling byref returns also a PyCArgObject instance
for t in signed_types + unsigned_types + float_types:
diff --git a/Lib/ctypes/test/test_prototypes.py b/Lib/ctypes/test/test_prototypes.py
index aaaa47a..9f02086 100644
--- a/Lib/ctypes/test/test_prototypes.py
+++ b/Lib/ctypes/test/test_prototypes.py
@@ -125,13 +125,18 @@ class CharPointersTestCase(unittest.TestCase):
self.failUnlessEqual(None, func(c_wchar_p(None)))
self.failUnlessEqual(u"123", func(c_wchar_p(u"123")))
-## def test_instance(self):
-## func = testdll._testfunc_p_p
+ def test_instance(self):
+ func = testdll._testfunc_p_p
+ func.restype = c_void_p
+
+ class X:
+ _as_parameter_ = None
-## class X:
-## _as_parameter_ = 0
+ func.argtypes = c_void_p,
+ self.failUnlessEqual(None, func(X()))
-## self.failUnlessEqual(0, func(X()))
+ func.argtypes = None
+ self.failUnlessEqual(None, func(X()))
try:
c_wchar
diff --git a/Lib/ctypes/test/test_python_api.py b/Lib/ctypes/test/test_python_api.py
index 78e0231..9d13474 100644
--- a/Lib/ctypes/test/test_python_api.py
+++ b/Lib/ctypes/test/test_python_api.py
@@ -78,5 +78,10 @@ class PythonAPITestCase(unittest.TestCase):
# not enough arguments
self.failUnlessRaises(TypeError, PyOS_snprintf, buf)
+ def test_pyobject_repr(self):
+ self.failUnlessEqual(repr(py_object()), "py_object(<NULL>)")
+ self.failUnlessEqual(repr(py_object(42)), "py_object(42)")
+ self.failUnlessEqual(repr(py_object(object)), "py_object(%r)" % object)
+
if __name__ == "__main__":
unittest.main()
diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py
index 9c60e54..21d34c7 100644
--- a/Lib/distutils/__init__.py
+++ b/Lib/distutils/__init__.py
@@ -12,6 +12,12 @@ used from a setup script as
__revision__ = "$Id$"
-import sys
-__version__ = "%d.%d.%d" % sys.version_info[:3]
-del sys
+# Distutils version
+#
+# Please coordinate with Marc-Andre Lemburg <mal@egenix.com> when adding
+# new features to distutils that would warrant bumping the version number.
+#
+# In general, major and minor version should loosely follow the Python
+# version number the distutils code was shipped with.
+#
+__version__ = "2.5.0"
diff --git a/Lib/idlelib/Bindings.py b/Lib/idlelib/Bindings.py
index d24be3f..a3c9fc4 100644
--- a/Lib/idlelib/Bindings.py
+++ b/Lib/idlelib/Bindings.py
@@ -22,9 +22,9 @@ menudefs = [
None,
('_Save', '<<save-window>>'),
('Save _As...', '<<save-window-as-file>>'),
- ('Save Co_py As...', '<<save-copy-of-window-as-file>>'),
+ ('Save Cop_y As...', '<<save-copy-of-window-as-file>>'),
None,
- ('_Print Window', '<<print-window>>'),
+ ('Prin_t Window', '<<print-window>>'),
None,
('_Close', '<<close-window>>'),
('E_xit', '<<close-all-windows>>'),
diff --git a/Lib/idlelib/CREDITS.txt b/Lib/idlelib/CREDITS.txt
index e838c03..30561a9 100644
--- a/Lib/idlelib/CREDITS.txt
+++ b/Lib/idlelib/CREDITS.txt
@@ -24,8 +24,8 @@ Noam Raphael (Code Context, Call Tips, many other patches), and Chui Tey (RPC
integration, debugger integration and persistent breakpoints).
Scott David Daniels, Tal Einat, Hernan Foffani, Christos Georgiou,
-Martin v. Löwis, Jason Orendorff, Josh Robb, Nigel Rowe, Bruce Sherwood,
-and Jeff Shute have submitted useful patches. Thanks, guys!
+Jim Jewett, Martin v. Löwis, Jason Orendorff, Josh Robb, Nigel Rowe,
+Bruce Sherwood, and Jeff Shute have submitted useful patches. Thanks, guys!
For additional details refer to NEWS.txt and Changelog.
diff --git a/Lib/idlelib/CodeContext.py b/Lib/idlelib/CodeContext.py
index 63cc82c..74d5b70 100644
--- a/Lib/idlelib/CodeContext.py
+++ b/Lib/idlelib/CodeContext.py
@@ -15,7 +15,7 @@ import re
from sys import maxint as INFINITY
BLOCKOPENERS = set(["class", "def", "elif", "else", "except", "finally", "for",
- "if", "try", "while"])
+ "if", "try", "while", "with"])
UPDATEINTERVAL = 100 # millisec
FONTUPDATEINTERVAL = 1000 # millisec
diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt
index 235963e..3b3d79a 100644
--- a/Lib/idlelib/NEWS.txt
+++ b/Lib/idlelib/NEWS.txt
@@ -1,7 +1,29 @@
+What's New in IDLE 2.6a1?
+=========================
+
+*Release date: XX-XXX-200X*
+
+- IDLE's version number takes a big jump to match the version number of
+ the Python release of which it's a part.
+
+
What's New in IDLE 1.2c1?
=========================
-*Release date: XX-AUG-2006*
+*Release date: 17-AUG-2006*
+
+- File menu hotkeys: there were three 'p' assignments. Reassign the
+ 'Save Copy As' and 'Print' hotkeys to 'y' and 't'. Change the
+ Shell hotkey from 's' to 'l'.
+
+- IDLE honors new quit() and exit() commands from site.py Quitter() object.
+ Patch 1540892, Jim Jewett
+
+- The 'with' statement is now a Code Context block opener.
+ Patch 1540851, Jim Jewett
+
+- Retrieval of previous shell command was not always preserving indentation
+ (since 1.2a1) Patch 1528468 Tal Einat.
- Changing tokenize (39046) to detect dedent broke tabnanny check (since 1.2a1)
diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py
index 25eb446..d8befff 100644
--- a/Lib/idlelib/PyShell.py
+++ b/Lib/idlelib/PyShell.py
@@ -478,9 +478,6 @@ class ModifiedInterpreter(InteractiveInterpreter):
import sys as _sys
_sys.path = %r
del _sys
- _msg = 'Use File/Exit or your end-of-file key to quit IDLE'
- __builtins__.quit = __builtins__.exit = _msg
- del _msg
\n""" % (sys.path,))
active_seq = None
@@ -514,7 +511,10 @@ class ModifiedInterpreter(InteractiveInterpreter):
print >>sys.__stderr__, errmsg, what
print >>console, errmsg, what
# we received a response to the currently active seq number:
- self.tkconsole.endexecuting()
+ try:
+ self.tkconsole.endexecuting()
+ except AttributeError: # shell may have closed
+ pass
# Reschedule myself
if not self.tkconsole.closing:
self.tkconsole.text.after(self.tkconsole.pollinterval,
@@ -593,7 +593,7 @@ class ModifiedInterpreter(InteractiveInterpreter):
source = source.encode(IOBinding.encoding)
except UnicodeError:
self.tkconsole.resetoutput()
- self.write("Unsupported characters in input")
+ self.write("Unsupported characters in input\n")
return
try:
# InteractiveInterpreter.runsource() calls its runcode() method,
@@ -713,14 +713,17 @@ class ModifiedInterpreter(InteractiveInterpreter):
else:
exec code in self.locals
except SystemExit:
- if tkMessageBox.askyesno(
- "Exit?",
- "Do you want to exit altogether?",
- default="yes",
- master=self.tkconsole.text):
- raise
+ if not self.tkconsole.closing:
+ if tkMessageBox.askyesno(
+ "Exit?",
+ "Do you want to exit altogether?",
+ default="yes",
+ master=self.tkconsole.text):
+ raise
+ else:
+ self.showtraceback()
else:
- self.showtraceback()
+ raise
except:
if use_subprocess:
print >> self.tkconsole.stderr, \
@@ -730,7 +733,10 @@ class ModifiedInterpreter(InteractiveInterpreter):
self.tkconsole.endexecuting()
finally:
if not use_subprocess:
- self.tkconsole.endexecuting()
+ try:
+ self.tkconsole.endexecuting()
+ except AttributeError: # shell may have closed
+ pass
def write(self, s):
"Override base class method"
@@ -794,7 +800,7 @@ class PyShell(OutputWindow):
if use_subprocess:
ms = self.menu_specs
if ms[2][0] != "shell":
- ms.insert(2, ("shell", "_Shell"))
+ ms.insert(2, ("shell", "She_ll"))
self.interp = ModifiedInterpreter(self)
if flist is None:
root = Tk()
@@ -804,9 +810,6 @@ class PyShell(OutputWindow):
#
OutputWindow.__init__(self, flist, None, None)
#
- import __builtin__
- __builtin__.quit = __builtin__.exit = "To exit, type Ctrl-D."
- #
## self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
self.usetabs = True
# indentwidth must be 8 when using tabs. See note in EditorWindow:
@@ -1138,21 +1141,27 @@ class PyShell(OutputWindow):
return "break"
def recall(self, s, event):
+ # remove leading and trailing empty or whitespace lines
+ s = re.sub(r'^\s*\n', '' , s)
+ s = re.sub(r'\n\s*$', '', s)
+ lines = s.split('\n')
self.text.undo_block_start()
try:
self.text.tag_remove("sel", "1.0", "end")
self.text.mark_set("insert", "end-1c")
- s = s.strip()
- lines = s.split('\n')
- prefix = self.text.get("insert linestart","insert").rstrip()
- if prefix and prefix[-1]==':':
+ prefix = self.text.get("insert linestart", "insert")
+ if prefix.rstrip().endswith(':'):
self.newline_and_indent_event(event)
- self.text.insert("insert",lines[0].strip())
+ prefix = self.text.get("insert linestart", "insert")
+ self.text.insert("insert", lines[0].strip())
if len(lines) > 1:
- self.newline_and_indent_event(event)
+ orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
+ new_base_indent = re.search(r'^([ \t]*)', prefix).group(0)
for line in lines[1:]:
- self.text.insert("insert", line.strip())
- self.newline_and_indent_event(event)
+ if line.startswith(orig_base_indent):
+ # replace orig base indentation with new indentation
+ line = new_base_indent + line[len(orig_base_indent):]
+ self.text.insert('insert', '\n'+line.rstrip())
finally:
self.text.see("insert")
self.text.undo_block_stop()
diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py
index 07d3d82..f56b4d4 100644
--- a/Lib/idlelib/idlever.py
+++ b/Lib/idlelib/idlever.py
@@ -1 +1 @@
-IDLE_VERSION = "1.2b3"
+IDLE_VERSION = "2.6a0"
diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py
index 1ef8f44..d5681c8 100644
--- a/Lib/logging/__init__.py
+++ b/Lib/logging/__init__.py
@@ -1337,14 +1337,14 @@ def disable(level):
"""
root.manager.disable = level
-def shutdown():
+def shutdown(handlerList=_handlerList):
"""
Perform any cleanup actions in the logging system (e.g. flushing
buffers).
Should be called at application exit.
"""
- for h in _handlerList[:]: # was _handlers.keys():
+ for h in handlerList[:]:
#errors might occur, for example, if files are locked
#we just ignore them if raiseExceptions is not set
try:
diff --git a/Lib/logging/config.py b/Lib/logging/config.py
index 1d5f8c4..a31e8d0 100644
--- a/Lib/logging/config.py
+++ b/Lib/logging/config.py
@@ -79,7 +79,7 @@ def fileConfig(fname, defaults=None):
logging._acquireLock()
try:
logging._handlers.clear()
- logging._handlerList = []
+ del logging._handlerList[:]
# Handlers add themselves to logging._handlers
handlers = _install_handlers(cp, formatters)
_install_loggers(cp, handlers)
diff --git a/Lib/site.py b/Lib/site.py
index da7bfaa..92798ca 100644
--- a/Lib/site.py
+++ b/Lib/site.py
@@ -27,7 +27,7 @@ sys.path more than once. Blank lines and lines beginning with
'#' are skipped. Lines starting with 'import' are executed.
For example, suppose sys.prefix and sys.exec_prefix are set to
-/usr/local and there is a directory /usr/local/lib/python1.5/site-packages
+/usr/local and there is a directory /usr/local/lib/python2.5/site-packages
with three subdirectories, foo, bar and spam, and two path
configuration files, foo.pth and bar.pth. Assume foo.pth contains the
following:
@@ -44,8 +44,8 @@ and bar.pth contains:
Then the following directories are added to sys.path, in this order:
- /usr/local/lib/python1.5/site-packages/bar
- /usr/local/lib/python1.5/site-packages/foo
+ /usr/local/lib/python2.5/site-packages/bar
+ /usr/local/lib/python2.5/site-packages/foo
Note that bletch is omitted because it doesn't exist; bar precedes foo
because bar.pth comes alphabetically before foo.pth; and spam is
@@ -242,6 +242,12 @@ def setquit():
def __repr__(self):
return 'Use %s() or %s to exit' % (self.name, eof)
def __call__(self, code=None):
+ # Shells like IDLE catch the SystemExit, but listen when their
+ # stdin wrapper is closed.
+ try:
+ sys.stdin.close()
+ except:
+ pass
raise SystemExit(code)
__builtin__.quit = Quitter('quit')
__builtin__.exit = Quitter('exit')
diff --git a/Lib/string.py b/Lib/string.py
index a5837e9..921bd8b 100644
--- a/Lib/string.py
+++ b/Lib/string.py
@@ -35,7 +35,6 @@ printable = digits + letters + punctuation + whitespace
# Case conversion helpers
# Use str to convert Unicode literal in case of -U
-# Note that Cookie.py bogusly uses _idmap :(
l = map(chr, xrange(256))
_idmap = str('').join(l)
del l
diff --git a/Lib/tabnanny.py b/Lib/tabnanny.py
index f38a79f..76665ac 100755
--- a/Lib/tabnanny.py
+++ b/Lib/tabnanny.py
@@ -109,6 +109,10 @@ def check(file):
errprint("%r: Token Error: %s" % (file, msg))
return
+ except IndentationError, msg:
+ errprint("%r: Indentation Error: %s" % (file, msg))
+ return
+
except NannyNag, nag:
badline = nag.get_lineno()
line = nag.get_line()
diff --git a/Lib/tarfile.py b/Lib/tarfile.py
index c185fbd..38cccae 100644
--- a/Lib/tarfile.py
+++ b/Lib/tarfile.py
@@ -411,9 +411,6 @@ class _Stream:
self.buf += self.cmp.flush()
if self.mode == "w" and self.buf:
- blocks, remainder = divmod(len(self.buf), self.bufsize)
- if remainder > 0:
- self.buf += NUL * (self.bufsize - remainder)
self.fileobj.write(self.buf)
self.buf = ""
if self.comptype == "gz":
diff --git a/Lib/test/exception_hierarchy.txt b/Lib/test/exception_hierarchy.txt
index 58131d7..a03f7bb 100644
--- a/Lib/test/exception_hierarchy.txt
+++ b/Lib/test/exception_hierarchy.txt
@@ -45,3 +45,4 @@ BaseException
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+ +-- UnicodeWarning
diff --git a/Lib/test/inspect_fodder2.py b/Lib/test/inspect_fodder2.py
index f150ec6..3d978cf 100644
--- a/Lib/test/inspect_fodder2.py
+++ b/Lib/test/inspect_fodder2.py
@@ -88,3 +88,12 @@ extra85 = 'stop'
def func88():
# comment
return 90
+
+# line 92
+def f():
+ class X:
+ def g():
+ "doc"
+ return 42
+ return X
+method_in_dynamic_class = f().g.im_func
diff --git a/Lib/test/output/test_cgi b/Lib/test/output/test_cgi
index d5d6f75..26eddfa 100644
--- a/Lib/test/output/test_cgi
+++ b/Lib/test/output/test_cgi
@@ -38,3 +38,5 @@ test_cgi
Testing log
Testing initlog 1
Testing log 2
+Test FieldStorage methods that use readline
+Test basic FieldStorage multipart parsing
diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py
index d45ff64..06beb1d 100644
--- a/Lib/test/test_bytes.py
+++ b/Lib/test/test_bytes.py
@@ -60,13 +60,13 @@ class BytesTest(unittest.TestCase):
self.assertRaises(ValueError, bytes, [-1])
self.assertRaises(ValueError, bytes, [-sys.maxint])
self.assertRaises(ValueError, bytes, [-sys.maxint-1])
- self.assertRaises(ValueError, bytes, [-sys.maxint-2])
- self.assertRaises(ValueError, bytes, [-10**100])
+ self.assertRaises(TypeError, bytes, [-sys.maxint-2])
+ self.assertRaises(TypeError, bytes, [-10**100])
self.assertRaises(ValueError, bytes, [256])
self.assertRaises(ValueError, bytes, [257])
self.assertRaises(ValueError, bytes, [sys.maxint])
- self.assertRaises(ValueError, bytes, [sys.maxint+1])
- self.assertRaises(ValueError, bytes, [10**100])
+ self.assertRaises(TypeError, bytes, [sys.maxint+1])
+ self.assertRaises(TypeError, bytes, [10**100])
def test_repr(self):
self.assertEqual(repr(bytes()), "bytes()")
diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py
index f198116..8561723 100644
--- a/Lib/test/test_bz2.py
+++ b/Lib/test/test_bz2.py
@@ -158,10 +158,21 @@ class BZ2FileTest(BaseTest):
sio = StringIO(self.TEXT)
bz2f.writelines(sio.readlines())
bz2f.close()
+ # patch #1535500
+ self.assertRaises(ValueError, bz2f.writelines, ["a"])
f = open(self.filename, 'rb')
self.assertEqual(self.decompress(f.read()), self.TEXT)
f.close()
+ def testWriteMethodsOnReadOnlyFile(self):
+ bz2f = BZ2File(self.filename, "w")
+ bz2f.write("abc")
+ bz2f.close()
+
+ bz2f = BZ2File(self.filename, "r")
+ self.assertRaises(IOError, bz2f.write, "a")
+ self.assertRaises(IOError, bz2f.writelines, ["a"])
+
def testSeekForward(self):
# "Test BZ2File.seek(150, 0)"
self.createTempFile()
diff --git a/Lib/test/test_cgi.py b/Lib/test/test_cgi.py
index 8b0b482..8fe487b 100644
--- a/Lib/test/test_cgi.py
+++ b/Lib/test/test_cgi.py
@@ -2,6 +2,8 @@ from test.test_support import verify, verbose
import cgi
import os
import sys
+import tempfile
+from StringIO import StringIO
class HackedSysModule:
# The regression test will have real values in sys.argv, which
@@ -203,4 +205,71 @@ def main():
cgi.initlog("%s", "Testing log 3")
cgi.log("Testing log 4")
+ print "Test FieldStorage methods that use readline"
+ # FieldStorage uses readline, which has the capacity to read all
+ # contents of the input file into memory; we use readline's size argument
+ # to prevent that for files that do not contain any newlines in
+ # non-GET/HEAD requests
+ class TestReadlineFile:
+ def __init__(self, file):
+ self.file = file
+ self.numcalls = 0
+
+ def readline(self, size=None):
+ self.numcalls += 1
+ if size:
+ return self.file.readline(size)
+ else:
+ return self.file.readline()
+
+ def __getattr__(self, name):
+ file = self.__dict__['file']
+ a = getattr(file, name)
+ if not isinstance(a, int):
+ setattr(self, name, a)
+ return a
+
+ f = TestReadlineFile(tempfile.TemporaryFile())
+ f.write('x' * 256 * 1024)
+ f.seek(0)
+ env = {'REQUEST_METHOD':'PUT'}
+ fs = cgi.FieldStorage(fp=f, environ=env)
+ # if we're not chunking properly, readline is only called twice
+ # (by read_binary); if we are chunking properly, it will be called 5 times
+ # as long as the chunksize is 1 << 16.
+ verify(f.numcalls > 2)
+
+ print "Test basic FieldStorage multipart parsing"
+ env = {'REQUEST_METHOD':'POST', 'CONTENT_TYPE':'multipart/form-data; boundary=---------------------------721837373350705526688164684', 'CONTENT_LENGTH':'558'}
+ postdata = """-----------------------------721837373350705526688164684
+Content-Disposition: form-data; name="id"
+
+1234
+-----------------------------721837373350705526688164684
+Content-Disposition: form-data; name="title"
+
+
+-----------------------------721837373350705526688164684
+Content-Disposition: form-data; name="file"; filename="test.txt"
+Content-Type: text/plain
+
+Testing 123.
+
+-----------------------------721837373350705526688164684
+Content-Disposition: form-data; name="submit"
+
+ Add\x20
+-----------------------------721837373350705526688164684--
+"""
+ fs = cgi.FieldStorage(fp=StringIO(postdata), environ=env)
+ verify(len(fs.list) == 4)
+ expect = [{'name':'id', 'filename':None, 'value':'1234'},
+ {'name':'title', 'filename':None, 'value':''},
+ {'name':'file', 'filename':'test.txt','value':'Testing 123.\n'},
+ {'name':'submit', 'filename':None, 'value':' Add '}]
+ for x in range(len(fs.list)):
+ for k, exp in expect[x].items():
+ got = getattr(fs.list[x], k)
+ verify(got == exp)
+
main()
diff --git a/Lib/test/test_compiler.py b/Lib/test/test_compiler.py
index 1efb6a6..81f2ea8 100644
--- a/Lib/test/test_compiler.py
+++ b/Lib/test/test_compiler.py
@@ -116,6 +116,13 @@ class CompilerTest(unittest.TestCase):
exec c in dct
self.assertEquals(dct.get('result'), 3)
+ def testGenExp(self):
+ c = compiler.compile('list((i,j) for i in range(3) if i < 3'
+ ' for j in range(4) if j > 2)',
+ '<string>',
+ 'eval')
+ self.assertEquals(eval(c), [(0, 3), (1, 3), (2, 3)])
+
NOLINENO = (compiler.ast.Module, compiler.ast.Stmt, compiler.ast.Discard)
diff --git a/Lib/test/test_format.py b/Lib/test/test_format.py
index 2959447..a9b3170 100644
--- a/Lib/test/test_format.py
+++ b/Lib/test/test_format.py
@@ -230,6 +230,14 @@ test_exc(u'no format', '1', TypeError,
test_exc(u'no format', u'1', TypeError,
"not all arguments converted during string formatting")
+class Foobar(long):
+ def __oct__(self):
+ # Returning a non-string should not blow up.
+ return self + 1
+
+test_exc('%o', Foobar(), TypeError,
+ "expected string or Unicode object, long found")
+
if sys.maxint == 2**31-1:
# crashes 2.2.1 and earlier:
try:
diff --git a/Lib/test/test_index.py b/Lib/test/test_index.py
index 45b3b2b..ecb566d 100644
--- a/Lib/test/test_index.py
+++ b/Lib/test/test_index.py
@@ -1,6 +1,7 @@
import unittest
from test import test_support
import operator
+from sys import maxint
class oldstyle:
def __index__(self):
@@ -10,68 +11,116 @@ class newstyle(object):
def __index__(self):
return self.ind
+class TrapInt(int):
+ def __index__(self):
+ return self
+
+class TrapLong(long):
+ def __index__(self):
+ return self
+
class BaseTestCase(unittest.TestCase):
def setUp(self):
self.o = oldstyle()
self.n = newstyle()
- self.o2 = oldstyle()
- self.n2 = newstyle()
def test_basic(self):
self.o.ind = -2
self.n.ind = 2
- assert(self.seq[self.n] == self.seq[2])
- assert(self.seq[self.o] == self.seq[-2])
- assert(operator.index(self.o) == -2)
- assert(operator.index(self.n) == 2)
+ self.assertEqual(operator.index(self.o), -2)
+ self.assertEqual(operator.index(self.n), 2)
+
+ def test_slice(self):
+ self.o.ind = 1
+ self.n.ind = 2
+ slc = slice(self.o, self.o, self.o)
+ check_slc = slice(1, 1, 1)
+ self.assertEqual(slc.indices(self.o), check_slc.indices(1))
+ slc = slice(self.n, self.n, self.n)
+ check_slc = slice(2, 2, 2)
+ self.assertEqual(slc.indices(self.n), check_slc.indices(2))
+
+ def test_wrappers(self):
+ self.o.ind = 4
+ self.n.ind = 5
+ self.assertEqual(6 .__index__(), 6)
+ self.assertEqual(-7L.__index__(), -7)
+ self.assertEqual(self.o.__index__(), 4)
+ self.assertEqual(self.n.__index__(), 5)
+
+ def test_subclasses(self):
+ r = range(10)
+ self.assertEqual(r[TrapInt(5):TrapInt(10)], r[5:10])
+ self.assertEqual(r[TrapLong(5):TrapLong(10)], r[5:10])
+ self.assertEqual(slice(TrapInt()).indices(0), (0,0,1))
+ self.assertEqual(slice(TrapLong(0)).indices(0), (0,0,1))
def test_error(self):
self.o.ind = 'dumb'
self.n.ind = 'bad'
- myfunc = lambda x, obj: obj.seq[x]
self.failUnlessRaises(TypeError, operator.index, self.o)
self.failUnlessRaises(TypeError, operator.index, self.n)
- self.failUnlessRaises(TypeError, myfunc, self.o, self)
- self.failUnlessRaises(TypeError, myfunc, self.n, self)
+ self.failUnlessRaises(TypeError, slice(self.o).indices, 0)
+ self.failUnlessRaises(TypeError, slice(self.n).indices, 0)
+
+
+class SeqTestCase(unittest.TestCase):
+ # This test case isn't run directly. It just defines common tests
+ # to the different sequence types below
+ def setUp(self):
+ self.o = oldstyle()
+ self.n = newstyle()
+ self.o2 = oldstyle()
+ self.n2 = newstyle()
+
+ def test_index(self):
+ self.o.ind = -2
+ self.n.ind = 2
+ self.assertEqual(self.seq[self.n], self.seq[2])
+ self.assertEqual(self.seq[self.o], self.seq[-2])
def test_slice(self):
self.o.ind = 1
self.o2.ind = 3
self.n.ind = 2
self.n2.ind = 4
- assert(self.seq[self.o:self.o2] == self.seq[1:3])
- assert(self.seq[self.n:self.n2] == self.seq[2:4])
+ self.assertEqual(self.seq[self.o:self.o2], self.seq[1:3])
+ self.assertEqual(self.seq[self.n:self.n2], self.seq[2:4])
def test_repeat(self):
self.o.ind = 3
self.n.ind = 2
- assert(self.seq * self.o == self.seq * 3)
- assert(self.seq * self.n == self.seq * 2)
- assert(self.o * self.seq == self.seq * 3)
- assert(self.n * self.seq == self.seq * 2)
+ self.assertEqual(self.seq * self.o, self.seq * 3)
+ self.assertEqual(self.seq * self.n, self.seq * 2)
+ self.assertEqual(self.o * self.seq, self.seq * 3)
+ self.assertEqual(self.n * self.seq, self.seq * 2)
def test_wrappers(self):
- n = self.n
- n.ind = 5
- assert n.__index__() == 5
- assert 6 .__index__() == 6
- assert -7L.__index__() == -7
- assert self.seq.__getitem__(n) == self.seq[5]
- assert self.seq.__mul__(n) == self.seq * 5
- assert self.seq.__rmul__(n) == self.seq * 5
-
- def test_infinite_recusion(self):
- class Trap1(int):
- def __index__(self):
- return self
- class Trap2(long):
- def __index__(self):
- return self
- self.failUnlessRaises(TypeError, operator.getitem, self.seq, Trap1())
- self.failUnlessRaises(TypeError, operator.getitem, self.seq, Trap2())
-
-
-class ListTestCase(BaseTestCase):
+ self.o.ind = 4
+ self.n.ind = 5
+ self.assertEqual(self.seq.__getitem__(self.o), self.seq[4])
+ self.assertEqual(self.seq.__mul__(self.o), self.seq * 4)
+ self.assertEqual(self.seq.__rmul__(self.o), self.seq * 4)
+ self.assertEqual(self.seq.__getitem__(self.n), self.seq[5])
+ self.assertEqual(self.seq.__mul__(self.n), self.seq * 5)
+ self.assertEqual(self.seq.__rmul__(self.n), self.seq * 5)
+
+ def test_subclasses(self):
+ self.assertEqual(self.seq[TrapInt()], self.seq[0])
+ self.assertEqual(self.seq[TrapLong()], self.seq[0])
+
+ def test_error(self):
+ self.o.ind = 'dumb'
+ self.n.ind = 'bad'
+ indexobj = lambda x, obj: obj.seq[x]
+ self.failUnlessRaises(TypeError, indexobj, self.o, self)
+ self.failUnlessRaises(TypeError, indexobj, self.n, self)
+ sliceobj = lambda x, obj: obj.seq[x:]
+ self.failUnlessRaises(TypeError, sliceobj, self.o, self)
+ self.failUnlessRaises(TypeError, sliceobj, self.n, self)
+
+
+class ListTestCase(SeqTestCase):
seq = [0,10,20,30,40,50]
def test_setdelitem(self):
@@ -82,36 +131,36 @@ class ListTestCase(BaseTestCase):
del lst[self.n]
lst[self.o] = 'X'
lst[self.n] = 'Y'
- assert lst == list('abYdefghXj')
+ self.assertEqual(lst, list('abYdefghXj'))
lst = [5, 6, 7, 8, 9, 10, 11]
lst.__setitem__(self.n, "here")
- assert lst == [5, 6, "here", 8, 9, 10, 11]
+ self.assertEqual(lst, [5, 6, "here", 8, 9, 10, 11])
lst.__delitem__(self.n)
- assert lst == [5, 6, 8, 9, 10, 11]
+ self.assertEqual(lst, [5, 6, 8, 9, 10, 11])
def test_inplace_repeat(self):
self.o.ind = 2
self.n.ind = 3
lst = [6, 4]
lst *= self.o
- assert lst == [6, 4, 6, 4]
+ self.assertEqual(lst, [6, 4, 6, 4])
lst *= self.n
- assert lst == [6, 4, 6, 4] * 3
+ self.assertEqual(lst, [6, 4, 6, 4] * 3)
lst = [5, 6, 7, 8, 9, 11]
l2 = lst.__imul__(self.n)
- assert l2 is lst
- assert lst == [5, 6, 7, 8, 9, 11] * 3
+ self.assert_(l2 is lst)
+ self.assertEqual(lst, [5, 6, 7, 8, 9, 11] * 3)
-class TupleTestCase(BaseTestCase):
+class TupleTestCase(SeqTestCase):
seq = (0,10,20,30,40,50)
-class StringTestCase(BaseTestCase):
+class StringTestCase(SeqTestCase):
seq = "this is a test"
-class UnicodeTestCase(BaseTestCase):
+class UnicodeTestCase(SeqTestCase):
seq = u"this is a test"
@@ -120,17 +169,54 @@ class XRangeTestCase(unittest.TestCase):
def test_xrange(self):
n = newstyle()
n.ind = 5
- assert xrange(1, 20)[n] == 6
- assert xrange(1, 20).__getitem__(n) == 6
+ self.assertEqual(xrange(1, 20)[n], 6)
+ self.assertEqual(xrange(1, 20).__getitem__(n), 6)
+
+class OverflowTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.pos = 2**100
+ self.neg = -self.pos
+
+ def test_large_longs(self):
+ self.assertEqual(self.pos.__index__(), self.pos)
+ self.assertEqual(self.neg.__index__(), self.neg)
+
+ def _getitem_helper(self, base):
+ class GetItem(base):
+ def __len__(self):
+ return maxint
+ def __getitem__(self, key):
+ return key
+ def __getslice__(self, i, j):
+ return i, j
+ x = GetItem()
+ self.assertEqual(x[self.pos], self.pos)
+ self.assertEqual(x[self.neg], self.neg)
+ self.assertEqual(x[self.neg:self.pos], (-1, maxint))
+ self.assertEqual(x[self.neg:self.pos:1].indices(maxint), (0, maxint, 1))
+
+ def test_getitem(self):
+ self._getitem_helper(object)
+
+ def test_getitem_classic(self):
+ class Empty: pass
+ self._getitem_helper(Empty)
+
+ def test_sequence_repeat(self):
+ self.failUnlessRaises(OverflowError, lambda: "a" * self.pos)
+ self.failUnlessRaises(OverflowError, lambda: "a" * self.neg)
def test_main():
test_support.run_unittest(
+ BaseTestCase,
ListTestCase,
TupleTestCase,
StringTestCase,
UnicodeTestCase,
XRangeTestCase,
+ OverflowTestCase,
)
if __name__ == "__main__":
diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py
index 99140d2..e9f9ef1 100644
--- a/Lib/test/test_inspect.py
+++ b/Lib/test/test_inspect.py
@@ -276,6 +276,9 @@ class TestBuggyCases(GetSourceBase):
def test_with_comment_instead_of_docstring(self):
self.assertSourceEqual(mod2.func88, 88, 90)
+ def test_method_in_dynamic_class(self):
+ self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
+
# Helper for testing classify_class_attrs.
def attrs_wo_objs(cls):
return [t[:3] for t in inspect.classify_class_attrs(cls)]
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
index fe05123..d6dcc3c 100644
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -493,7 +493,7 @@ def test4():
try:
logging._handlers.clear()
logging._handlers.update(saved_handlers)
- logging._handlerList = saved_handler_list
+ logging._handlerList[:] = saved_handler_list
loggerDict = logging.getLogger().manager.loggerDict
loggerDict.clear()
loggerDict.update(saved_loggers)
@@ -560,7 +560,7 @@ def test5():
try:
logging._handlers.clear()
logging._handlers.update(saved_handlers)
- logging._handlerList = saved_handler_list
+ logging._handlerList[:] = saved_handler_list
loggerDict = logging.getLogger().manager.loggerDict
loggerDict.clear()
loggerDict.update(saved_loggers)
diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py
index 04e856f..1837306 100644
--- a/Lib/test/test_mailbox.py
+++ b/Lib/test/test_mailbox.py
@@ -1,4 +1,5 @@
import os
+import sys
import time
import stat
import socket
@@ -454,7 +455,7 @@ class TestMaildir(TestMailbox):
def setUp(self):
TestMailbox.setUp(self)
- if os.name in ('nt', 'os2'):
+ if os.name in ('nt', 'os2') or sys.platform == 'cygwin':
self._box.colon = '!'
def test_add_MM(self):
@@ -729,11 +730,13 @@ class _TestMboxMMDF(TestMailbox):
# In the parent, sleep a bit to give the child time to acquire
# the lock.
time.sleep(0.5)
- self.assertRaises(mailbox.ExternalClashError,
- self._box.lock)
+ try:
+ self.assertRaises(mailbox.ExternalClashError,
+ self._box.lock)
+ finally:
+ # Wait for child to exit. Locking should now succeed.
+ exited_pid, status = os.waitpid(pid, 0)
- # Wait for child to exit. Locking should now succeed.
- exited_pid, status = os.waitpid(pid, 0)
self._box.lock()
self._box.unlock()
diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py
index a6267d2..13d02bb 100644
--- a/Lib/test/test_signal.py
+++ b/Lib/test/test_signal.py
@@ -6,11 +6,16 @@ import os, sys, time
if sys.platform[:3] in ('win', 'os2') or sys.platform=='riscos':
raise TestSkipped, "Can't test signal on %s" % sys.platform
+MAX_DURATION = 20 # Entire test should last at most 20 sec.
+
if verbose:
x = '-x'
else:
x = '+x'
+
pid = os.getpid()
+if verbose:
+ print "test runner's pid is", pid
# Shell script that will send us asynchronous signals
script = """
@@ -31,7 +36,7 @@ def handlerA(*args):
global a_called
a_called = True
if verbose:
- print "handlerA", args
+ print "handlerA invoked", args
class HandlerBCalled(Exception):
pass
@@ -40,87 +45,110 @@ def handlerB(*args):
global b_called
b_called = True
if verbose:
- print "handlerB", args
+ print "handlerB invoked", args
raise HandlerBCalled, args
-MAX_DURATION = 20
-signal.alarm(MAX_DURATION) # Entire test should last at most 20 sec.
+# Set up a child to send signals to us (the parent) after waiting long
+# enough to receive the alarm. It seems we miss the alarm for some
+# reason. This will hopefully stop the hangs on Tru64/Alpha.
+# Alas, it doesn't. Tru64 appears to miss all the signals at times, or
+# seemingly random subsets of them, and nothing done in force_test_exit
+# so far has actually helped.
+def force_test_exit():
+ # Sigh, both imports seem necessary to avoid errors.
+ import os
+ fork_pid = os.fork()
+ if fork_pid:
+ # In parent.
+ return fork_pid
+
+ # In child.
+ import os, time
+ try:
+ # Wait 5 seconds longer than the expected alarm to give enough
+ # time for the normal sequence of events to occur. This is
+ # just a stop-gap to try to prevent the test from hanging.
+ time.sleep(MAX_DURATION + 5)
+ print >> sys.__stdout__, ' child should not have to kill parent'
+ for signame in "SIGHUP", "SIGUSR1", "SIGUSR2", "SIGALRM":
+ os.kill(pid, getattr(signal, signame))
+ print >> sys.__stdout__, " child sent", signame, "to", pid
+ time.sleep(1)
+ finally:
+ os._exit(0)
+
+# Install handlers.
hup = signal.signal(signal.SIGHUP, handlerA)
usr1 = signal.signal(signal.SIGUSR1, handlerB)
usr2 = signal.signal(signal.SIGUSR2, signal.SIG_IGN)
alrm = signal.signal(signal.SIGALRM, signal.default_int_handler)
-vereq(signal.getsignal(signal.SIGHUP), handlerA)
-vereq(signal.getsignal(signal.SIGUSR1), handlerB)
-vereq(signal.getsignal(signal.SIGUSR2), signal.SIG_IGN)
-
try:
- signal.signal(4242, handlerB)
- raise TestFailed, 'expected ValueError for invalid signal # to signal()'
-except ValueError:
- pass
-try:
- signal.getsignal(4242)
- raise TestFailed, 'expected ValueError for invalid signal # to getsignal()'
-except ValueError:
- pass
+ signal.alarm(MAX_DURATION)
+ vereq(signal.getsignal(signal.SIGHUP), handlerA)
+ vereq(signal.getsignal(signal.SIGUSR1), handlerB)
+ vereq(signal.getsignal(signal.SIGUSR2), signal.SIG_IGN)
+ vereq(signal.getsignal(signal.SIGALRM), signal.default_int_handler)
-try:
- signal.signal(signal.SIGUSR1, None)
- raise TestFailed, 'expected TypeError for non-callable'
-except TypeError:
- pass
+ # Try to ensure this test exits even if there is some problem with alarm.
+ # Tru64/Alpha often hangs and is ultimately killed by the buildbot.
+ fork_pid = force_test_exit()
-# Set up a child to send an alarm signal to us (the parent) after waiting
-# long enough to receive the alarm. It seems we miss the alarm for some
-# reason. This will hopefully stop the hangs on Tru64/Alpha.
-def force_test_exit():
- # Sigh, both imports seem necessary to avoid errors.
- import os
- fork_pid = os.fork()
- if fork_pid == 0:
- # In child
- import os, time
- try:
- # Wait 5 seconds longer than the expected alarm to give enough
- # time for the normal sequence of events to occur. This is
- # just a stop-gap to prevent the test from hanging.
- time.sleep(MAX_DURATION + 5)
- print >> sys.__stdout__, ' child should not have to kill parent'
- for i in range(3):
- os.kill(pid, signal.SIGALARM)
- finally:
- os._exit(0)
- # In parent (or error)
- return fork_pid
+ try:
+ signal.getsignal(4242)
+ raise TestFailed('expected ValueError for invalid signal # to '
+ 'getsignal()')
+ except ValueError:
+ pass
-try:
- os.system(script)
+ try:
+ signal.signal(4242, handlerB)
+ raise TestFailed('expected ValueError for invalid signal # to '
+ 'signal()')
+ except ValueError:
+ pass
- # Try to ensure this test exits even if there is some problem with alarm.
- # Tru64/Alpha sometimes hangs and is ultimately killed by the buildbot.
- fork_pid = force_test_exit()
- print "starting pause() loop..."
+ try:
+ signal.signal(signal.SIGUSR1, None)
+ raise TestFailed('expected TypeError for non-callable')
+ except TypeError:
+ pass
+ # Launch an external script to send us signals.
+ # We expect the external script to:
+ # send HUP, which invokes handlerA to set a_called
+ # send USR1, which invokes handlerB to set b_called and raise
+ # HandlerBCalled
+ # send USR2, which is ignored
+ #
+ # Then we expect the alarm to go off, and its handler raises
+ # KeyboardInterrupt, finally getting us out of the loop.
+ os.system(script)
try:
+ print "starting pause() loop..."
while 1:
- if verbose:
- print "call pause()..."
try:
+ if verbose:
+ print "call pause()..."
signal.pause()
if verbose:
print "pause() returned"
except HandlerBCalled:
if verbose:
print "HandlerBCalled exception caught"
- else:
- pass
except KeyboardInterrupt:
if verbose:
- print "KeyboardInterrupt (assume the alarm() went off)"
+ print "KeyboardInterrupt (the alarm() went off)"
+
+ if not a_called:
+ print 'HandlerA not called'
+
+ if not b_called:
+ print 'HandlerB not called'
+finally:
# Forcibly kill the child we created to ping us if there was a test error.
try:
# Make sure we don't kill ourself if there was a fork error.
@@ -128,16 +156,11 @@ try:
os.kill(fork_pid, signal.SIGKILL)
except:
# If the child killed us, it has probably exited. Killing a
- # non-existant process will raise an error which we don't care about.
+ # non-existent process will raise an error which we don't care about.
pass
- if not a_called:
- print 'HandlerA not called'
-
- if not b_called:
- print 'HandlerB not called'
-
-finally:
+ # Restore handlers.
+ signal.alarm(0) # cancel alarm in case we died early
signal.signal(signal.SIGHUP, hup)
signal.signal(signal.SIGUSR1, usr1)
signal.signal(signal.SIGUSR2, usr2)
diff --git a/Lib/test/test_socketserver.py b/Lib/test/test_socketserver.py
index dd4532f..e4cbb2b 100644
--- a/Lib/test/test_socketserver.py
+++ b/Lib/test/test_socketserver.py
@@ -181,10 +181,19 @@ else:
if hasattr(os, 'fork') and os.name not in ('os2',):
dgramservers.append(ForkingUnixDatagramServer)
+def sloppy_cleanup():
+ # See http://python.org/sf/1540386
+ # We need to reap children here otherwise a child from one server
+ # can be left running for the next server and cause a test failure.
+ time.sleep(DELAY)
+ reap_children()
+
def testall():
testloop(socket.AF_INET, tcpservers, MyStreamHandler, teststream)
+ sloppy_cleanup()
testloop(socket.AF_INET, udpservers, MyDatagramHandler, testdgram)
if hasattr(socket, 'AF_UNIX'):
+ sloppy_cleanup()
testloop(socket.AF_UNIX, streamservers, MyStreamHandler, teststream)
# Alas, on Linux (at least) recvfrom() doesn't return a meaningful
# client address so this cannot work:
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
index 8ee0f41..ebcb8c5 100644
--- a/Lib/test/test_tarfile.py
+++ b/Lib/test/test_tarfile.py
@@ -324,6 +324,27 @@ class WriteSize0Test(BaseTest):
class WriteStreamTest(WriteTest):
sep = '|'
+ def test_padding(self):
+ self.dst.close()
+
+ if self.comp == "gz":
+ f = gzip.GzipFile(self.dstname)
+ s = f.read()
+ f.close()
+ elif self.comp == "bz2":
+ f = bz2.BZ2Decompressor()
+ s = file(self.dstname).read()
+ s = f.decompress(s)
+ self.assertEqual(len(f.unused_data), 0, "trailing data")
+ else:
+ f = file(self.dstname)
+ s = f.read()
+ f.close()
+
+ self.assertEqual(s.count("\0"), tarfile.RECORDSIZE,
+ "incorrect zero padding")
+
+
class WriteGNULongTest(unittest.TestCase):
"""This testcase checks for correct creation of GNU Longname
and Longlink extensions.
diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
index 79335ea..8614ecb 100644
--- a/Lib/test/test_threading.py
+++ b/Lib/test/test_threading.py
@@ -131,6 +131,76 @@ class ThreadTests(unittest.TestCase):
threading._DummyThread))
del threading._active[tid]
+ # PyThreadState_SetAsyncExc() is a CPython-only gimmick, not (currently)
+ # exposed at the Python level. This test relies on ctypes to get at it.
+ def test_PyThreadState_SetAsyncExc(self):
+ try:
+ import ctypes
+ except ImportError:
+ if verbose:
+ print "test_PyThreadState_SetAsyncExc can't import ctypes"
+ return # can't do anything
+
+ set_async_exc = ctypes.pythonapi.PyThreadState_SetAsyncExc
+
+ class AsyncExc(Exception):
+ pass
+
+ exception = ctypes.py_object(AsyncExc)
+
+ # `worker_started` is set by the thread when it's inside a try/except
+ # block waiting to catch the asynchronously set AsyncExc exception.
+ # `worker_saw_exception` is set by the thread upon catching that
+ # exception.
+ worker_started = threading.Event()
+ worker_saw_exception = threading.Event()
+
+ class Worker(threading.Thread):
+ def run(self):
+ self.id = thread.get_ident()
+ self.finished = False
+
+ try:
+ while True:
+ worker_started.set()
+ time.sleep(0.1)
+ except AsyncExc:
+ self.finished = True
+ worker_saw_exception.set()
+
+ t = Worker()
+ t.setDaemon(True) # so if this fails, we don't hang Python at shutdown
+ t.start()
+ if verbose:
+ print " started worker thread"
+
+ # Try a thread id that doesn't make sense.
+ if verbose:
+ print " trying nonsensical thread id"
+ result = set_async_exc(ctypes.c_long(-1), exception)
+ self.assertEqual(result, 0) # no thread states modified
+
+ # Now raise an exception in the worker thread.
+ if verbose:
+ print " waiting for worker thread to get started"
+ worker_started.wait()
+ if verbose:
+ print " verifying worker hasn't exited"
+ self.assert_(not t.finished)
+ if verbose:
+ print " attempting to raise asynch exception in worker"
+ result = set_async_exc(ctypes.c_long(t.id), exception)
+ self.assertEqual(result, 1) # one thread state modified
+ if verbose:
+ print " waiting for worker to say it caught the exception"
+ worker_saw_exception.wait(timeout=10)
+ self.assert_(t.finished)
+ if verbose:
+ print " all OK -- joining worker"
+ if t.finished:
+ t.join()
+ # else the thread is still running, and we have no way to kill it
+
def test_main():
test.test_support.run_unittest(ThreadTests)
diff --git a/Lib/test/test_threadsignals.py b/Lib/test/test_threadsignals.py
index 51e3d97..1f10fe7 100644
--- a/Lib/test/test_threadsignals.py
+++ b/Lib/test/test_threadsignals.py
@@ -49,7 +49,7 @@ class ThreadSignals(unittest.TestCase):
# and might be out of order.) If we haven't seen
# the signals yet, send yet another signal and
# wait for it return.
- if signal_blackboard[signal.SIGUSR2]['tripped'] == 0 \
+ if signal_blackboard[signal.SIGUSR1]['tripped'] == 0 \
or signal_blackboard[signal.SIGUSR2]['tripped'] == 0:
signal.alarm(1)
signal.pause()
diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py
index 4df854e..be7d0c8 100644
--- a/Lib/test/test_urllib2.py
+++ b/Lib/test/test_urllib2.py
@@ -46,6 +46,69 @@ class TrivialTests(unittest.TestCase):
self.assertEquals(urllib2.parse_http_list(string), list)
+def test_request_headers_dict():
+ """
+ The Request.headers dictionary is not a documented interface. It should
+ stay that way, because the complete set of headers are only accessible
+ through the .get_header(), .has_header(), .header_items() interface.
+ However, .headers pre-dates those methods, and so real code will be using
+ the dictionary.
+
+ The introduction in 2.4 of those methods was a mistake for the same reason:
+ code that previously saw all (urllib2 user)-provided headers in .headers
+ now sees only a subset (and the function interface is ugly and incomplete).
+ A better change would have been to replace .headers dict with a dict
+ subclass (or UserDict.DictMixin instance?) that preserved the .headers
+ interface and also provided access to the "unredirected" headers. It's
+ probably too late to fix that, though.
+
+
+ Check .capitalize() case normalization:
+
+ >>> url = "http://example.com"
+ >>> Request(url, headers={"Spam-eggs": "blah"}).headers["Spam-eggs"]
+ 'blah'
+ >>> Request(url, headers={"spam-EggS": "blah"}).headers["Spam-eggs"]
+ 'blah'
+
+ Currently, Request(url, "Spam-eggs").headers["Spam-Eggs"] raises KeyError,
+ but that could be changed in future.
+
+ """
+
+def test_request_headers_methods():
+ """
+ Note the case normalization of header names here, to .capitalize()-case.
+ This should be preserved for backwards-compatibility. (In the HTTP case,
+ normalization to .title()-case is done by urllib2 before sending headers to
+ httplib).
+
+ >>> url = "http://example.com"
+ >>> r = Request(url, headers={"Spam-eggs": "blah"})
+ >>> r.has_header("Spam-eggs")
+ True
+ >>> r.header_items()
+ [('Spam-eggs', 'blah')]
+ >>> r.add_header("Foo-Bar", "baz")
+ >>> items = r.header_items()
+ >>> items.sort()
+ >>> items
+ [('Foo-bar', 'baz'), ('Spam-eggs', 'blah')]
+
+ Note that e.g. r.has_header("spam-EggS") is currently False, and
+ r.get_header("spam-EggS") returns None, but that could be changed in
+ future.
+
+ >>> r.has_header("Not-there")
+ False
+ >>> print r.get_header("Not-there")
+ None
+ >>> r.get_header("Not-there", "default")
+ 'default'
+
+ """
+
+
def test_password_manager(self):
"""
>>> mgr = urllib2.HTTPPasswordMgr()
@@ -676,11 +739,11 @@ class HandlerTests(unittest.TestCase):
r = MockResponse(200, "OK", {}, "")
newreq = h.do_request_(req)
if data is None: # GET
- self.assert_("Content-Length" not in req.unredirected_hdrs)
- self.assert_("Content-Type" not in req.unredirected_hdrs)
+ self.assert_("Content-length" not in req.unredirected_hdrs)
+ self.assert_("Content-type" not in req.unredirected_hdrs)
else: # POST
- self.assertEqual(req.unredirected_hdrs["Content-Length"], "0")
- self.assertEqual(req.unredirected_hdrs["Content-Type"],
+ self.assertEqual(req.unredirected_hdrs["Content-length"], "0")
+ self.assertEqual(req.unredirected_hdrs["Content-type"],
"application/x-www-form-urlencoded")
# XXX the details of Host could be better tested
self.assertEqual(req.unredirected_hdrs["Host"], "example.com")
@@ -692,8 +755,8 @@ class HandlerTests(unittest.TestCase):
req.add_unredirected_header("Host", "baz")
req.add_unredirected_header("Spam", "foo")
newreq = h.do_request_(req)
- self.assertEqual(req.unredirected_hdrs["Content-Length"], "foo")
- self.assertEqual(req.unredirected_hdrs["Content-Type"], "bar")
+ self.assertEqual(req.unredirected_hdrs["Content-length"], "foo")
+ self.assertEqual(req.unredirected_hdrs["Content-type"], "bar")
self.assertEqual(req.unredirected_hdrs["Host"], "baz")
self.assertEqual(req.unredirected_hdrs["Spam"], "foo")
@@ -847,7 +910,7 @@ class HandlerTests(unittest.TestCase):
407, 'Proxy-Authenticate: Basic realm="%s"\r\n\r\n' % realm)
opener.add_handler(auth_handler)
opener.add_handler(http_handler)
- self._test_basic_auth(opener, auth_handler, "Proxy-Authorization",
+ self._test_basic_auth(opener, auth_handler, "Proxy-authorization",
realm, http_handler, password_manager,
"http://acme.example.com:3128/protected",
"proxy.example.com:3128",
diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py
index 0586cfd..90671be 100644
--- a/Lib/test/test_uuid.py
+++ b/Lib/test/test_uuid.py
@@ -16,12 +16,13 @@ class TestUUID(TestCase):
def test_UUID(self):
equal = self.assertEqual
ascending = []
- for (string, curly, hex, bytes, fields, integer, urn,
+ for (string, curly, hex, bytes, bytes_le, fields, integer, urn,
time, clock_seq, variant, version) in [
('00000000-0000-0000-0000-000000000000',
'{00000000-0000-0000-0000-000000000000}',
'00000000000000000000000000000000',
'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
+ '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
(0, 0, 0, 0, 0, 0),
0,
'urn:uuid:00000000-0000-0000-0000-000000000000',
@@ -30,6 +31,7 @@ class TestUUID(TestCase):
'{00010203-0405-0607-0809-0a0b0c0d0e0f}',
'000102030405060708090a0b0c0d0e0f',
'\0\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\x0d\x0e\x0f',
+ '\x03\x02\x01\0\x05\x04\x07\x06\x08\t\n\x0b\x0c\x0d\x0e\x0f',
(0x00010203L, 0x0405, 0x0607, 8, 9, 0x0a0b0c0d0e0fL),
0x000102030405060708090a0b0c0d0e0fL,
'urn:uuid:00010203-0405-0607-0809-0a0b0c0d0e0f',
@@ -38,6 +40,7 @@ class TestUUID(TestCase):
'{02d9e6d5-9467-382e-8f9b-9300a64ac3cd}',
'02d9e6d59467382e8f9b9300a64ac3cd',
'\x02\xd9\xe6\xd5\x94\x67\x38\x2e\x8f\x9b\x93\x00\xa6\x4a\xc3\xcd',
+ '\xd5\xe6\xd9\x02\x67\x94\x2e\x38\x8f\x9b\x93\x00\xa6\x4a\xc3\xcd',
(0x02d9e6d5L, 0x9467, 0x382e, 0x8f, 0x9b, 0x9300a64ac3cdL),
0x02d9e6d59467382e8f9b9300a64ac3cdL,
'urn:uuid:02d9e6d5-9467-382e-8f9b-9300a64ac3cd',
@@ -46,6 +49,7 @@ class TestUUID(TestCase):
'{12345678-1234-5678-1234-567812345678}',
'12345678123456781234567812345678',
'\x12\x34\x56\x78'*4,
+ '\x78\x56\x34\x12\x34\x12\x78\x56\x12\x34\x56\x78\x12\x34\x56\x78',
(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678),
0x12345678123456781234567812345678,
'urn:uuid:12345678-1234-5678-1234-567812345678',
@@ -54,6 +58,7 @@ class TestUUID(TestCase):
'{6ba7b810-9dad-11d1-80b4-00c04fd430c8}',
'6ba7b8109dad11d180b400c04fd430c8',
'\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8',
+ '\x10\xb8\xa7\x6b\xad\x9d\xd1\x11\x80\xb4\x00\xc0\x4f\xd4\x30\xc8',
(0x6ba7b810L, 0x9dad, 0x11d1, 0x80, 0xb4, 0x00c04fd430c8L),
0x6ba7b8109dad11d180b400c04fd430c8L,
'urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8',
@@ -62,6 +67,7 @@ class TestUUID(TestCase):
'{6ba7b811-9dad-11d1-80b4-00c04fd430c8}',
'6ba7b8119dad11d180b400c04fd430c8',
'\x6b\xa7\xb8\x11\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8',
+ '\x11\xb8\xa7\x6b\xad\x9d\xd1\x11\x80\xb4\x00\xc0\x4f\xd4\x30\xc8',
(0x6ba7b811L, 0x9dad, 0x11d1, 0x80, 0xb4, 0x00c04fd430c8L),
0x6ba7b8119dad11d180b400c04fd430c8L,
'urn:uuid:6ba7b811-9dad-11d1-80b4-00c04fd430c8',
@@ -70,6 +76,7 @@ class TestUUID(TestCase):
'{6ba7b812-9dad-11d1-80b4-00c04fd430c8}',
'6ba7b8129dad11d180b400c04fd430c8',
'\x6b\xa7\xb8\x12\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8',
+ '\x12\xb8\xa7\x6b\xad\x9d\xd1\x11\x80\xb4\x00\xc0\x4f\xd4\x30\xc8',
(0x6ba7b812L, 0x9dad, 0x11d1, 0x80, 0xb4, 0x00c04fd430c8L),
0x6ba7b8129dad11d180b400c04fd430c8L,
'urn:uuid:6ba7b812-9dad-11d1-80b4-00c04fd430c8',
@@ -78,6 +85,7 @@ class TestUUID(TestCase):
'{6ba7b814-9dad-11d1-80b4-00c04fd430c8}',
'6ba7b8149dad11d180b400c04fd430c8',
'\x6b\xa7\xb8\x14\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8',
+ '\x14\xb8\xa7\x6b\xad\x9d\xd1\x11\x80\xb4\x00\xc0\x4f\xd4\x30\xc8',
(0x6ba7b814L, 0x9dad, 0x11d1, 0x80, 0xb4, 0x00c04fd430c8L),
0x6ba7b8149dad11d180b400c04fd430c8L,
'urn:uuid:6ba7b814-9dad-11d1-80b4-00c04fd430c8',
@@ -86,6 +94,7 @@ class TestUUID(TestCase):
'{7d444840-9dc0-11d1-b245-5ffdce74fad2}',
'7d4448409dc011d1b2455ffdce74fad2',
'\x7d\x44\x48\x40\x9d\xc0\x11\xd1\xb2\x45\x5f\xfd\xce\x74\xfa\xd2',
+ '\x40\x48\x44\x7d\xc0\x9d\xd1\x11\xb2\x45\x5f\xfd\xce\x74\xfa\xd2',
(0x7d444840L, 0x9dc0, 0x11d1, 0xb2, 0x45, 0x5ffdce74fad2L),
0x7d4448409dc011d1b2455ffdce74fad2L,
'urn:uuid:7d444840-9dc0-11d1-b245-5ffdce74fad2',
@@ -94,6 +103,7 @@ class TestUUID(TestCase):
'{e902893a-9d22-3c7e-a7b8-d6e313b71d9f}',
'e902893a9d223c7ea7b8d6e313b71d9f',
'\xe9\x02\x89\x3a\x9d\x22\x3c\x7e\xa7\xb8\xd6\xe3\x13\xb7\x1d\x9f',
+ '\x3a\x89\x02\xe9\x22\x9d\x7e\x3c\xa7\xb8\xd6\xe3\x13\xb7\x1d\x9f',
(0xe902893aL, 0x9d22, 0x3c7e, 0xa7, 0xb8, 0xd6e313b71d9fL),
0xe902893a9d223c7ea7b8d6e313b71d9fL,
'urn:uuid:e902893a-9d22-3c7e-a7b8-d6e313b71d9f',
@@ -102,6 +112,7 @@ class TestUUID(TestCase):
'{eb424026-6f54-4ef8-a4d0-bb658a1fc6cf}',
'eb4240266f544ef8a4d0bb658a1fc6cf',
'\xeb\x42\x40\x26\x6f\x54\x4e\xf8\xa4\xd0\xbb\x65\x8a\x1f\xc6\xcf',
+ '\x26\x40\x42\xeb\x54\x6f\xf8\x4e\xa4\xd0\xbb\x65\x8a\x1f\xc6\xcf',
(0xeb424026L, 0x6f54, 0x4ef8, 0xa4, 0xd0, 0xbb658a1fc6cfL),
0xeb4240266f544ef8a4d0bb658a1fc6cfL,
'urn:uuid:eb424026-6f54-4ef8-a4d0-bb658a1fc6cf',
@@ -110,6 +121,7 @@ class TestUUID(TestCase):
'{f81d4fae-7dec-11d0-a765-00a0c91e6bf6}',
'f81d4fae7dec11d0a76500a0c91e6bf6',
'\xf8\x1d\x4f\xae\x7d\xec\x11\xd0\xa7\x65\x00\xa0\xc9\x1e\x6b\xf6',
+ '\xae\x4f\x1d\xf8\xec\x7d\xd0\x11\xa7\x65\x00\xa0\xc9\x1e\x6b\xf6',
(0xf81d4faeL, 0x7dec, 0x11d0, 0xa7, 0x65, 0x00a0c91e6bf6L),
0xf81d4fae7dec11d0a76500a0c91e6bf6L,
'urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6',
@@ -118,6 +130,7 @@ class TestUUID(TestCase):
'{fffefdfc-fffe-fffe-fffe-fffefdfcfbfa}',
'fffefdfcfffefffefffefffefdfcfbfa',
'\xff\xfe\xfd\xfc\xff\xfe\xff\xfe\xff\xfe\xff\xfe\xfd\xfc\xfb\xfa',
+ '\xfc\xfd\xfe\xff\xfe\xff\xfe\xff\xff\xfe\xff\xfe\xfd\xfc\xfb\xfa',
(0xfffefdfcL, 0xfffe, 0xfffe, 0xff, 0xfe, 0xfffefdfcfbfaL),
0xfffefdfcfffefffefffefffefdfcfbfaL,
'urn:uuid:fffefdfc-fffe-fffe-fffe-fffefdfcfbfa',
@@ -126,6 +139,7 @@ class TestUUID(TestCase):
'{ffffffff-ffff-ffff-ffff-ffffffffffff}',
'ffffffffffffffffffffffffffffffff',
'\xff'*16,
+ '\xff'*16,
(0xffffffffL, 0xffffL, 0xffffL, 0xff, 0xff, 0xffffffffffffL),
0xffffffffffffffffffffffffffffffffL,
'urn:uuid:ffffffff-ffff-ffff-ffff-ffffffffffff',
@@ -134,12 +148,14 @@ class TestUUID(TestCase):
equivalents = []
# Construct each UUID in several different ways.
for u in [uuid.UUID(string), uuid.UUID(curly), uuid.UUID(hex),
- uuid.UUID(bytes=bytes), uuid.UUID(fields=fields),
- uuid.UUID(int=integer), uuid.UUID(urn)]:
+ uuid.UUID(bytes=bytes), uuid.UUID(bytes_le=bytes_le),
+ uuid.UUID(fields=fields), uuid.UUID(int=integer),
+ uuid.UUID(urn)]:
# Test all conversions and properties of the UUID object.
equal(str(u), string)
equal(int(u), integer)
equal(u.bytes, bytes)
+ equal(u.bytes_le, bytes_le)
equal(u.fields, fields)
equal(u.time_low, fields[0])
equal(u.time_mid, fields[1])
@@ -189,6 +205,11 @@ class TestUUID(TestCase):
badvalue(lambda: uuid.UUID(bytes='\0'*15))
badvalue(lambda: uuid.UUID(bytes='\0'*17))
+ # Badly formed bytes_le.
+ badvalue(lambda: uuid.UUID(bytes_le='abc'))
+ badvalue(lambda: uuid.UUID(bytes_le='\0'*15))
+ badvalue(lambda: uuid.UUID(bytes_le='\0'*17))
+
# Badly formed fields.
badvalue(lambda: uuid.UUID(fields=(1,)))
badvalue(lambda: uuid.UUID(fields=(1, 2, 3, 4, 5)))
@@ -221,51 +242,43 @@ class TestUUID(TestCase):
uuid.UUID(h)
uuid.UUID(hex=h)
uuid.UUID(bytes=b)
+ uuid.UUID(bytes_le=b)
uuid.UUID(fields=f)
uuid.UUID(int=i)
# Wrong number of arguments (positional).
badtype(lambda: uuid.UUID())
badtype(lambda: uuid.UUID(h, b))
- badtype(lambda: uuid.UUID(h, b, f))
- badtype(lambda: uuid.UUID(h, b, f, i))
-
- # Duplicate arguments (named).
- badtype(lambda: uuid.UUID(hex=h, bytes=b))
- badtype(lambda: uuid.UUID(hex=h, fields=f))
- badtype(lambda: uuid.UUID(hex=h, int=i))
- badtype(lambda: uuid.UUID(bytes=b, fields=f))
- badtype(lambda: uuid.UUID(bytes=b, int=i))
- badtype(lambda: uuid.UUID(fields=f, int=i))
- badtype(lambda: uuid.UUID(hex=h, bytes=b, fields=f))
- badtype(lambda: uuid.UUID(hex=h, bytes=b, int=i))
- badtype(lambda: uuid.UUID(hex=h, fields=f, int=i))
- badtype(lambda: uuid.UUID(bytes=b, int=i, fields=f))
- badtype(lambda: uuid.UUID(hex=h, bytes=b, int=i, fields=f))
-
- # Duplicate arguments (positional and named).
- badtype(lambda: uuid.UUID(h, hex=h))
- badtype(lambda: uuid.UUID(h, bytes=b))
- badtype(lambda: uuid.UUID(h, fields=f))
- badtype(lambda: uuid.UUID(h, int=i))
- badtype(lambda: uuid.UUID(h, hex=h, bytes=b))
- badtype(lambda: uuid.UUID(h, hex=h, fields=f))
- badtype(lambda: uuid.UUID(h, hex=h, int=i))
- badtype(lambda: uuid.UUID(h, bytes=b, fields=f))
- badtype(lambda: uuid.UUID(h, bytes=b, int=i))
- badtype(lambda: uuid.UUID(h, fields=f, int=i))
- badtype(lambda: uuid.UUID(h, hex=h, bytes=b, fields=f))
- badtype(lambda: uuid.UUID(h, hex=h, bytes=b, int=i))
- badtype(lambda: uuid.UUID(h, hex=h, fields=f, int=i))
- badtype(lambda: uuid.UUID(h, bytes=b, int=i, fields=f))
- badtype(lambda: uuid.UUID(h, hex=h, bytes=b, int=i, fields=f))
+ badtype(lambda: uuid.UUID(h, b, b))
+ badtype(lambda: uuid.UUID(h, b, b, f))
+ badtype(lambda: uuid.UUID(h, b, b, f, i))
+
+ # Duplicate arguments.
+ for hh in [[], [('hex', h)]]:
+ for bb in [[], [('bytes', b)]]:
+ for bble in [[], [('bytes_le', b)]]:
+ for ii in [[], [('int', i)]]:
+ for ff in [[], [('fields', f)]]:
+ args = dict(hh + bb + bble + ii + ff)
+ if len(args) != 0:
+ badtype(lambda: uuid.UUID(h, **args))
+ if len(args) != 1:
+ badtype(lambda: uuid.UUID(**args))
# Immutability.
u = uuid.UUID(h)
badtype(lambda: setattr(u, 'hex', h))
badtype(lambda: setattr(u, 'bytes', b))
+ badtype(lambda: setattr(u, 'bytes_le', b))
badtype(lambda: setattr(u, 'fields', f))
badtype(lambda: setattr(u, 'int', i))
+ badtype(lambda: setattr(u, 'time_low', 0))
+ badtype(lambda: setattr(u, 'time_mid', 0))
+ badtype(lambda: setattr(u, 'time_hi_version', 0))
+ badtype(lambda: setattr(u, 'time_hi_version', 0))
+ badtype(lambda: setattr(u, 'clock_seq_hi_variant', 0))
+ badtype(lambda: setattr(u, 'clock_seq_low', 0))
+ badtype(lambda: setattr(u, 'node', 0))
def check_node(self, node, source):
individual_group_bit = (node >> 40L) & 1
@@ -356,11 +369,17 @@ class TestUUID(TestCase):
def test_uuid1(self):
equal = self.assertEqual
- # Make sure uuid4() generates UUIDs that are actually version 1.
+ # Make sure uuid1() generates UUIDs that are actually version 1.
for u in [uuid.uuid1() for i in range(10)]:
equal(u.variant, uuid.RFC_4122)
equal(u.version, 1)
+ # Make sure the generated UUIDs are actually unique.
+ uuids = {}
+ for u in [uuid.uuid1() for i in range(1000)]:
+ uuids[u] = 1
+ equal(len(uuids.keys()), 1000)
+
# Make sure the supplied node ID appears in the UUID.
u = uuid.uuid1(0)
equal(u.node, 0)
@@ -408,6 +427,12 @@ class TestUUID(TestCase):
equal(u.variant, uuid.RFC_4122)
equal(u.version, 4)
+ # Make sure the generated UUIDs are actually unique.
+ uuids = {}
+ for u in [uuid.uuid4() for i in range(1000)]:
+ uuids[u] = 1
+ equal(len(uuids.keys()), 1000)
+
def test_uuid5(self):
equal = self.assertEqual
diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py
index 56e7fed..250f791 100644
--- a/Lib/test/test_xml_etree_c.py
+++ b/Lib/test/test_xml_etree_c.py
@@ -204,6 +204,17 @@ def check_encoding(encoding):
"<?xml version='1.0' encoding='%s'?><xml />" % encoding
)
+def bug_1534630():
+ """
+ >>> bob = ET.TreeBuilder()
+ >>> e = bob.data("data")
+ >>> e = bob.start("tag", {})
+ >>> e = bob.end("tag")
+ >>> e = bob.close()
+ >>> serialize(ET, e)
+ '<tag />'
+ """
+
def test_main():
from test import test_xml_etree_c
test_support.run_doctest(test_xml_etree_c, verbosity=True)
diff --git a/Lib/tokenize.py b/Lib/tokenize.py
index a30791c..a9be4cf 100644
--- a/Lib/tokenize.py
+++ b/Lib/tokenize.py
@@ -273,7 +273,8 @@ def generate_tokens(readline):
while column < indents[-1]:
if column not in indents:
raise IndentationError(
- "unindent does not match any outer indentation level")
+ "unindent does not match any outer indentation level",
+ ("<tokenize>", lnum, pos, line))
indents = indents[:-1]
yield (DEDENT, '', (lnum, pos), (lnum, pos), line)
diff --git a/Lib/trace.py b/Lib/trace.py
index e70869c..7ebed71 100644
--- a/Lib/trace.py
+++ b/Lib/trace.py
@@ -179,9 +179,11 @@ def fullmodname(path):
# looking in sys.path for the longest matching prefix. We'll
# assume that the rest is the package name.
+ comparepath = os.path.normcase(path)
longest = ""
for dir in sys.path:
- if path.startswith(dir) and path[len(dir)] == os.path.sep:
+ dir = os.path.normcase(dir)
+ if comparepath.startswith(dir) and comparepath[len(dir)] == os.sep:
if len(dir) > len(longest):
longest = dir
diff --git a/Lib/urllib2.py b/Lib/urllib2.py
index 93cadd7..1e19f33 100644
--- a/Lib/urllib2.py
+++ b/Lib/urllib2.py
@@ -263,11 +263,11 @@ class Request:
def add_header(self, key, val):
# useful for something like authentication
- self.headers[key.title()] = val
+ self.headers[key.capitalize()] = val
def add_unredirected_header(self, key, val):
# will not be added to a redirected request
- self.unredirected_hdrs[key.title()] = val
+ self.unredirected_hdrs[key.capitalize()] = val
def has_header(self, header_name):
return (header_name in self.headers or
@@ -286,7 +286,7 @@ class Request:
class OpenerDirector:
def __init__(self):
client_version = "Python-urllib/%s" % __version__
- self.addheaders = [('User-Agent', client_version)]
+ self.addheaders = [('User-agent', client_version)]
# manage the individual handlers
self.handlers = []
self.handle_open = {}
@@ -675,7 +675,7 @@ class ProxyHandler(BaseHandler):
if user and password:
user_pass = '%s:%s' % (unquote(user), unquote(password))
creds = base64.encodestring(user_pass).strip()
- req.add_header('Proxy-Authorization', 'Basic ' + creds)
+ req.add_header('Proxy-authorization', 'Basic ' + creds)
hostport = unquote(hostport)
req.set_proxy(hostport, proxy_type)
if orig_type == proxy_type:
@@ -819,7 +819,7 @@ class HTTPBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler):
class ProxyBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler):
- auth_header = 'Proxy-Authorization'
+ auth_header = 'Proxy-authorization'
def http_error_407(self, req, fp, code, msg, headers):
# http_error_auth_reqed requires that there is no userinfo component in
@@ -1022,20 +1022,20 @@ class AbstractHTTPHandler(BaseHandler):
if request.has_data(): # POST
data = request.get_data()
- if not request.has_header('Content-Type'):
+ if not request.has_header('Content-type'):
request.add_unredirected_header(
- 'Content-Type',
+ 'Content-type',
'application/x-www-form-urlencoded')
- if not request.has_header('Content-Length'):
+ if not request.has_header('Content-length'):
request.add_unredirected_header(
- 'Content-Length', '%d' % len(data))
+ 'Content-length', '%d' % len(data))
scheme, sel = splittype(request.get_selector())
sel_host, sel_path = splithost(sel)
if not request.has_header('Host'):
request.add_unredirected_header('Host', sel_host or host)
for name, value in self.parent.addheaders:
- name = name.title()
+ name = name.capitalize()
if not request.has_header(name):
request.add_unredirected_header(name, value)
@@ -1067,6 +1067,8 @@ class AbstractHTTPHandler(BaseHandler):
# So make sure the connection gets closed after the (only)
# request.
headers["Connection"] = "close"
+ headers = dict(
+ (name.title(), val) for name, val in headers.items())
try:
h.request(req.get_method(), req.get_selector(), req.data, headers)
r = h.getresponse()
@@ -1217,7 +1219,7 @@ class FileHandler(BaseHandler):
modified = email.Utils.formatdate(stats.st_mtime, usegmt=True)
mtype = mimetypes.guess_type(file)[0]
headers = mimetools.Message(StringIO(
- 'Content-Type: %s\nContent-Length: %d\nLast-Modified: %s\n' %
+ 'Content-type: %s\nContent-length: %d\nLast-modified: %s\n' %
(mtype or 'text/plain', size, modified)))
if host:
host, port = splitport(host)
@@ -1272,9 +1274,9 @@ class FTPHandler(BaseHandler):
headers = ""
mtype = mimetypes.guess_type(req.get_full_url())[0]
if mtype:
- headers += "Content-Type: %s\n" % mtype
+ headers += "Content-type: %s\n" % mtype
if retrlen is not None and retrlen >= 0:
- headers += "Content-Length: %d\n" % retrlen
+ headers += "Content-length: %d\n" % retrlen
sf = StringIO(headers)
headers = mimetools.Message(sf)
return addinfourl(fp, headers, req.get_full_url())
diff --git a/Lib/uuid.py b/Lib/uuid.py
index a6446a1..ae3da25 100644
--- a/Lib/uuid.py
+++ b/Lib/uuid.py
@@ -45,8 +45,6 @@ Typical usage:
"""
__author__ = 'Ka-Ping Yee <ping@zesty.ca>'
-__date__ = '$Date: 2006/06/12 23:15:40 $'.split()[1].replace('/', '-')
-__version__ = '$Revision: 1.30 $'.split()[1]
RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [
'reserved for NCS compatibility', 'specified in RFC 4122',
@@ -57,15 +55,21 @@ class UUID(object):
UUID objects are immutable, hashable, and usable as dictionary keys.
Converting a UUID to a string with str() yields something in the form
'12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts
- four possible forms: a similar string of hexadecimal digits, or a
- string of 16 raw bytes as an argument named 'bytes', or a tuple of
- six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and
- 48-bit values respectively) as an argument named 'fields', or a single
- 128-bit integer as an argument named 'int'.
+ five possible forms: a similar string of hexadecimal digits, or a tuple
+ of six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and
+ 48-bit values respectively) as an argument named 'fields', or a string
+ of 16 bytes (with all the integer fields in big-endian order) as an
+ argument named 'bytes', or a string of 16 bytes (with the first three
+ fields in little-endian order) as an argument named 'bytes_le', or a
+ single 128-bit integer as an argument named 'int'.
UUIDs have these read-only attributes:
- bytes the UUID as a 16-byte string
+ bytes the UUID as a 16-byte string (containing the six
+ integer fields in big-endian byte order)
+
+ bytes_le the UUID as a 16-byte string (with time_low, time_mid,
+ and time_hi_version in little-endian byte order)
fields a tuple of the six integer fields of the UUID,
which are also available as six individual attributes
@@ -94,10 +98,11 @@ class UUID(object):
when the variant is RFC_4122)
"""
- def __init__(self, hex=None, bytes=None, fields=None, int=None,
- version=None):
+ def __init__(self, hex=None, bytes=None, bytes_le=None, fields=None,
+ int=None, version=None):
r"""Create a UUID from either a string of 32 hexadecimal digits,
- a string of 16 bytes as the 'bytes' argument, a tuple of six
+ a string of 16 bytes as the 'bytes' argument, a string of 16 bytes
+ in little-endian order as the 'bytes_le' argument, a tuple of six
integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version,
8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as
the 'fields' argument, or a single 128-bit integer as the 'int'
@@ -109,23 +114,31 @@ class UUID(object):
UUID('12345678123456781234567812345678')
UUID('urn:uuid:12345678-1234-5678-1234-567812345678')
UUID(bytes='\x12\x34\x56\x78'*4)
+ UUID(bytes_le='\x78\x56\x34\x12\x34\x12\x78\x56' +
+ '\x12\x34\x56\x78\x12\x34\x56\x78')
UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
UUID(int=0x12345678123456781234567812345678)
- Exactly one of 'hex', 'bytes', 'fields', or 'int' must be given.
- The 'version' argument is optional; if given, the resulting UUID
- will have its variant and version number set according to RFC 4122,
- overriding bits in the given 'hex', 'bytes', 'fields', or 'int'.
+ Exactly one of 'hex', 'bytes', 'bytes_le', 'fields', or 'int' must
+ be given. The 'version' argument is optional; if given, the resulting
+ UUID will have its variant and version set according to RFC 4122,
+ overriding the given 'hex', 'bytes', 'bytes_le', 'fields', or 'int'.
"""
- if [hex, bytes, fields, int].count(None) != 3:
- raise TypeError('need just one of hex, bytes, fields, or int')
+ if [hex, bytes, bytes_le, fields, int].count(None) != 4:
+ raise TypeError('need one of hex, bytes, bytes_le, fields, or int')
if hex is not None:
hex = hex.replace('urn:', '').replace('uuid:', '')
hex = hex.strip('{}').replace('-', '')
if len(hex) != 32:
raise ValueError('badly formed hexadecimal UUID string')
int = long(hex, 16)
+ if bytes_le is not None:
+ if len(bytes_le) != 16:
+ raise ValueError('bytes_le is not a 16-char string')
+ bytes = (bytes_le[3] + bytes_le[2] + bytes_le[1] + bytes_le[0] +
+ bytes_le[5] + bytes_le[4] + bytes_le[7] + bytes_le[6] +
+ bytes_le[8:])
if bytes is not None:
if len(bytes) != 16:
raise ValueError('bytes is not a 16-char string')
@@ -194,6 +207,13 @@ class UUID(object):
bytes = property(get_bytes)
+ def get_bytes_le(self):
+ bytes = self.bytes
+ return (bytes[3] + bytes[2] + bytes[1] + bytes[0] +
+ bytes[5] + bytes[4] + bytes[7] + bytes[6] + bytes[8:])
+
+ bytes_le = property(get_bytes_le)
+
def get_fields(self):
return (self.time_low, self.time_mid, self.time_hi_version,
self.clock_seq_hi_variant, self.clock_seq_low, self.node)
@@ -448,6 +468,8 @@ def getnode():
if _node is not None:
return _node
+_last_timestamp = None
+
def uuid1(node=None, clock_seq=None):
"""Generate a UUID from a host ID, sequence number, and the current time.
If 'node' is not given, getnode() is used to obtain the hardware
@@ -460,11 +482,15 @@ def uuid1(node=None, clock_seq=None):
_uuid_generate_time(_buffer)
return UUID(bytes=_buffer.raw)
+ global _last_timestamp
import time
nanoseconds = int(time.time() * 1e9)
# 0x01b21dd213814000 is the number of 100-ns intervals between the
# UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
timestamp = int(nanoseconds/100) + 0x01b21dd213814000L
+ if timestamp <= _last_timestamp:
+ timestamp = _last_timestamp + 1
+ _last_timestamp = timestamp
if clock_seq is None:
import random
clock_seq = random.randrange(1<<14L) # instead of stable storage