From 6edd2586082f62a5ac61af5acab77b63919faa47 Mon Sep 17 00:00:00 2001 From: "Phillip J. Eby" Date: Sat, 25 Mar 2006 00:28:24 +0000 Subject: [PATCH] Fix a problem with @contextmanager not detecting a broken generator that yields after a throw(). Make @contextmanager not reraise exceptions, but return a false value in that case instead. Add test cases for both behaviors. --- Lib/contextlib.py | 5 ++++- Lib/test/test_contextlib.py | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/Lib/contextlib.py b/Lib/contextlib.py index 0a5d608503..282fc51004 100644 --- a/Lib/contextlib.py +++ b/Lib/contextlib.py @@ -30,9 +30,12 @@ class GeneratorContextManager(object): else: try: self.gen.throw(type, value, traceback) - return True + raise RuntimeError("generator didn't stop after throw()") except StopIteration: return True + except: + if sys.exc_info()[1] is not value: + raise def contextmanager(func): diff --git a/Lib/test/test_contextlib.py b/Lib/test/test_contextlib.py index f8db88cc58..7d7f8d281c 100644 --- a/Lib/test/test_contextlib.py +++ b/Lib/test/test_contextlib.py @@ -45,6 +45,28 @@ class ContextManagerTestCase(unittest.TestCase): self.fail("Expected ZeroDivisionError") self.assertEqual(state, [1, 42, 999]) + def test_contextmanager_no_reraise(self): + @contextmanager + def whee(): + yield + ctx = whee().__context__() + ctx.__enter__() + # Calling __exit__ should not result in an exception + self.failIf(ctx.__exit__(TypeError, TypeError("foo"), None)) + + def test_contextmanager_trap_yield_after_throw(self): + @contextmanager + def whoo(): + try: + yield + except: + yield + ctx = whoo().__context__() + ctx.__enter__() + self.assertRaises( + RuntimeError, ctx.__exit__, TypeError, TypeError("foo"), None + ) + def test_contextmanager_except(self): state = [] @contextmanager -- 2.40.0