#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()