On 2/28/06, Mike Bland
On 2/28/06, Guido van Rossum
wrote: I just realized that there's a bug in the with-statement as currently checked in. __exit__ is supposed to re-raise the exception if there was one; if it returns normally, the finally clause is NOT to re-raise it. The fix is relatively simple (I believe) but requires updating lots of unit tests. It'll be a while.
Hmm. My understanding was that __exit__ was *not* to reraise it, but was simply given the opportunity to record the exception-in-progress.
Yes, that's what the PEP said. :-( Unfortunately the way the PEP is specified, the intended equivalence between writing a try/except in a @contextmanager-decorated generator and writing things out explicitly is lost. The plan was that this: @contextmanager def foo(): try: yield except Exception: pass with foo(): 1/0 would be equivalent to this: try: 1/0 except Exception: pass IOW with GENERATOR(): BLOCK becomes a macro call, and GENERATOR() becomes a macro definition; its body is the macro expansion with "yield" replaced by BLOCK. But in order to get those semantics, it must be possible for __exit__() to signal that the exception passed into it should *not* be re-raised. The current expansion uses roughly this: finally: ctx.__exit__(*exc) and here the finally clause will re-raise the exception (if there was one). I ran into this when writing unit tests for @contextmanager. -- --Guido van Rossum (home page: http://www.python.org/~guido/)