From 0d09dd2a6a682bd3d1cfbd405c8a9cb0792718dc Mon Sep 17 00:00:00 2001 From: "Phillip J. Eby" Date: Sat, 25 Mar 2006 00:26:26 +0000 Subject: [PATCH] Document the difference between a normal return from __exit__() and an exception return. 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. --- pep-0343.txt | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/pep-0343.txt b/pep-0343.txt index 7ca5c0fb4..3fe1bb8f5 100644 --- a/pep-0343.txt +++ b/pep-0343.txt @@ -312,6 +312,24 @@ Specification: The 'with' Statement non-local goto should be considered unexceptional for the purposes of a database transaction roll-back decision. + To facilitate chaining of contexts, __exit__() methods should + *not* reraise the error that is passed in, because it is always the + responsibility of the *caller* to do any reraising. + + That way, if the caller needs to tell whether the __exit__() + invocation *failed* (as opposed to successfully cleaning up before + propagating the original error), it can do so. + + If __exit__() returns without an error, this can then be + interpreted as success of the __exit__() method itself (whether the + original error is to be propagated or suppressed). + + However, if __exit__() propagates an exception to its caller, this + means that __exit__() *itself* has failed. Thus, __exit__() + methods should avoid raising errors unless they have actually + failed. (And allowing the original error to proceed isn't a + failure.) + Transition Plan In Python 2.5, the new syntax will only be recognized if a future @@ -357,9 +375,12 @@ Generator Decorator 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 # only reraise if it's a new exception def contextmanager(func): def helper(*args, **kwds):