#3021: Antoine Pitrou's Lexical exception handlers
diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py
index 41b9413..9068554 100644
--- a/Lib/test/test_exceptions.py
+++ b/Lib/test/test_exceptions.py
@@ -427,6 +427,7 @@
local_ref = obj
raise MyException(obj)
+ # Qualified "except" with "as"
obj = MyObj()
wr = weakref.ref(obj)
try:
@@ -437,6 +438,113 @@
obj = wr()
self.failUnless(obj is None, "%s" % obj)
+ # Qualified "except" without "as"
+ obj = MyObj()
+ wr = weakref.ref(obj)
+ try:
+ inner_raising_func()
+ except MyException:
+ pass
+ obj = None
+ obj = wr()
+ self.failUnless(obj is None, "%s" % obj)
+
+ # Bare "except"
+ obj = MyObj()
+ wr = weakref.ref(obj)
+ try:
+ inner_raising_func()
+ except:
+ pass
+ obj = None
+ obj = wr()
+ self.failUnless(obj is None, "%s" % obj)
+
+ # "except" with premature block leave
+ obj = MyObj()
+ wr = weakref.ref(obj)
+ for i in [0]:
+ try:
+ inner_raising_func()
+ except:
+ break
+ obj = None
+ obj = wr()
+ self.failUnless(obj is None, "%s" % obj)
+
+ # "except" block raising another exception
+ obj = MyObj()
+ wr = weakref.ref(obj)
+ try:
+ try:
+ inner_raising_func()
+ except:
+ raise KeyError
+ except KeyError:
+ obj = None
+ obj = wr()
+ self.failUnless(obj is None, "%s" % obj)
+
+ # Some complicated construct
+ obj = MyObj()
+ wr = weakref.ref(obj)
+ try:
+ inner_raising_func()
+ except MyException:
+ try:
+ try:
+ raise
+ finally:
+ raise
+ except MyException:
+ pass
+ obj = None
+ obj = wr()
+ self.failUnless(obj is None, "%s" % obj)
+
+ # Inside an exception-silencing "with" block
+ class Context:
+ def __enter__(self):
+ return self
+ def __exit__ (self, exc_type, exc_value, exc_tb):
+ return True
+ obj = MyObj()
+ wr = weakref.ref(obj)
+ with Context():
+ inner_raising_func()
+ obj = None
+ obj = wr()
+ self.failUnless(obj is None, "%s" % obj)
+
+ def test_generator_leaking(self):
+ # Test that generator exception state doesn't leak into the calling
+ # frame
+ def yield_raise():
+ try:
+ raise KeyError("caught")
+ except KeyError:
+ yield sys.exc_info()[0]
+ yield sys.exc_info()[0]
+ yield sys.exc_info()[0]
+ g = yield_raise()
+ self.assertEquals(next(g), KeyError)
+ self.assertEquals(sys.exc_info()[0], None)
+ self.assertEquals(next(g), KeyError)
+ self.assertEquals(sys.exc_info()[0], None)
+ self.assertEquals(next(g), None)
+
+ # Same test, but inside an exception handler
+ try:
+ raise TypeError("foo")
+ except TypeError:
+ g = yield_raise()
+ self.assertEquals(next(g), KeyError)
+ self.assertEquals(sys.exc_info()[0], TypeError)
+ self.assertEquals(next(g), KeyError)
+ self.assertEquals(sys.exc_info()[0], TypeError)
+ self.assertEquals(next(g), TypeError)
+ del g
+ self.assertEquals(sys.exc_info()[0], TypeError)
def test_main():
run_unittest(ExceptionTests)
diff --git a/Lib/test/test_raise.py b/Lib/test/test_raise.py
index 89e2190..5f0070e 100644
--- a/Lib/test/test_raise.py
+++ b/Lib/test/test_raise.py
@@ -16,6 +16,13 @@
return sys.exc_info()[2]
+class Context:
+ def __enter__(self):
+ return self
+ def __exit__(self, exc_type, exc_value, exc_tb):
+ return True
+
+
class TestRaise(unittest.TestCase):
def test_invalid_reraise(self):
try:
@@ -37,6 +44,71 @@
else:
self.fail("No exception raised")
+ def test_except_reraise(self):
+ def reraise():
+ try:
+ raise TypeError("foo")
+ except:
+ try:
+ raise KeyError("caught")
+ except KeyError:
+ pass
+ raise
+ self.assertRaises(TypeError, reraise)
+
+ def test_finally_reraise(self):
+ def reraise():
+ try:
+ raise TypeError("foo")
+ except:
+ try:
+ raise KeyError("caught")
+ finally:
+ raise
+ self.assertRaises(KeyError, reraise)
+
+ def test_nested_reraise(self):
+ def nested_reraise():
+ raise
+ def reraise():
+ try:
+ raise TypeError("foo")
+ except:
+ nested_reraise()
+ self.assertRaises(TypeError, reraise)
+
+ def test_with_reraise1(self):
+ def reraise():
+ try:
+ raise TypeError("foo")
+ except:
+ with Context():
+ pass
+ raise
+ self.assertRaises(TypeError, reraise)
+
+ def test_with_reraise2(self):
+ def reraise():
+ try:
+ raise TypeError("foo")
+ except:
+ with Context():
+ raise KeyError("caught")
+ raise
+ self.assertRaises(TypeError, reraise)
+
+ def test_yield_reraise(self):
+ def reraise():
+ try:
+ raise TypeError("foo")
+ except:
+ yield 1
+ raise
+ g = reraise()
+ next(g)
+ self.assertRaises(TypeError, lambda: next(g))
+ self.assertRaises(StopIteration, lambda: next(g))
+
def test_erroneous_exception(self):
class MyException(Exception):
def __init__(self):
@@ -158,6 +230,5 @@
def test_main():
support.run_unittest(__name__)
-
if __name__ == "__main__":
unittest.main()