#3021: Antoine Pitrou's Lexical exception handlers

This commit is contained in:
Benjamin Peterson 2008-06-11 15:59:43 +00:00
parent e8465f2b41
commit eec3d71379
17 changed files with 410 additions and 303 deletions

View file

@ -427,6 +427,7 @@ class ExceptionTests(unittest.TestCase):
local_ref = obj
raise MyException(obj)
# Qualified "except" with "as"
obj = MyObj()
wr = weakref.ref(obj)
try:
@ -437,6 +438,113 @@ class ExceptionTests(unittest.TestCase):
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)

View file

@ -16,6 +16,13 @@ def get_tb():
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 @@ class TestRaise(unittest.TestCase):
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 @@ class TestRemovedFunctionality(unittest.TestCase):
def test_main():
support.run_unittest(__name__)
if __name__ == "__main__":
unittest.main()