From 9a779ea98ec7c0edff9fa9ff4a60b1fcc589a2b9 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 4 Oct 2009 20:07:34 +0000 Subject: [PATCH] Merged revisions 74524,74556 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r74524 | gregory.p.smith | 2009-08-20 04:39:38 -0500 (Thu, 20 Aug 2009) | 2 lines Add weakref support to the thread.lock type. ........ r74556 | kristjan.jonsson | 2009-08-27 17:20:21 -0500 (Thu, 27 Aug 2009) | 2 lines issue 6275 Add an "exc_value" attribute to the _AssertRaisesContext context manager in the unittest package. This allows further tests on the exception that was raised after the context manager exits. ........ --- Doc/library/unittest.rst | 4 ++++ Doc/library/weakref.rst | 3 +++ Lib/test/test_unittest.py | 15 +++++++++++++++ Lib/unittest/case.py | 1 + Modules/_threadmodule.c | 9 +++++++-- 5 files changed, 30 insertions(+), 2 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index fefae04be9e..494c2d7fbc0 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -891,6 +891,10 @@ Test cases with self.failUnlessRaises(some_error_class): do_something() + The context manager will store the caught exception object in its + :attr:`exc_value` attribute. This can be useful if the intention + is to perform additional checks on the exception raised. + .. versionchanged:: 3.1 Added the ability to use :meth:`assertRaises` as a context manager. diff --git a/Doc/library/weakref.rst b/Doc/library/weakref.rst index 9aaa58a4bfb..d4751b11c1f 100644 --- a/Doc/library/weakref.rst +++ b/Doc/library/weakref.rst @@ -61,6 +61,9 @@ instances, functions written in Python (but not in C), instance methods, sets, frozensets, file objects, :term:`generator`\s, type objects, sockets, arrays, deques, and regular expression pattern objects. +.. versionchanged:: 2.7 + Added support for thread.lock and threading.Lock. + Several built-in types such as :class:`list` and :class:`dict` do not directly support weak references but can add support through subclassing:: diff --git a/Lib/test/test_unittest.py b/Lib/test/test_unittest.py index 40de797d560..108802db3d7 100644 --- a/Lib/test/test_unittest.py +++ b/Lib/test/test_unittest.py @@ -2834,6 +2834,21 @@ test case self.assertRaisesRegexp, Exception, re.compile('^Expected$'), Stub) + def testAssertRaisesExcValue(self): + class ExceptionMock(Exception): + pass + + def Stub(foo): + raise ExceptionMock(foo) + v = "particular value" + + ctx = self.assertRaises(ExceptionMock) + with ctx: + Stub(v) + e = ctx.exc_value + self.assertTrue(isinstance(e, ExceptionMock)) + self.assertEqual(e.args[0], v) + def testSynonymAssertMethodNames(self): """Test undocumented method name synonyms. diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py index 77ca278b5df..660ddebccae 100644 --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -116,6 +116,7 @@ class _AssertRaisesContext(object): if not issubclass(exc_type, self.expected): # let unexpected exceptions pass through return False + self.exc_value = exc_value #store for later retrieval if self.expected_regex is None: return True diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 744e94da253..41696989a1a 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -3,6 +3,7 @@ /* Interface to Sjoerd's portable C thread library */ #include "Python.h" +#include "structmember.h" /* offsetof */ #ifndef WITH_THREAD #error "Error! The rest of Python is not compiled with thread support." @@ -20,12 +21,15 @@ static PyObject *ThreadError; typedef struct { PyObject_HEAD PyThread_type_lock lock_lock; + PyObject *in_weakreflist; } lockobject; static void lock_dealloc(lockobject *self) { assert(self->lock_lock); + if (self->in_weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *) self); /* Unlock the lock so it's safe to free it */ PyThread_acquire_lock(self->lock_lock, 0); PyThread_release_lock(self->lock_lock); @@ -140,12 +144,12 @@ static PyTypeObject Locktype = { 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ 0, /*tp_doc*/ 0, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ + offsetof(lockobject, in_weakreflist), /*tp_weaklistoffset*/ 0, /*tp_iter*/ 0, /*tp_iternext*/ lock_methods, /*tp_methods*/ @@ -159,6 +163,7 @@ newlockobject(void) if (self == NULL) return NULL; self->lock_lock = PyThread_allocate_lock(); + self->in_weakreflist = NULL; if (self->lock_lock == NULL) { PyObject_Del(self); self = NULL;