[Arnold deVos, responding to himself] > > This template eats eats the exception, which will cause a RuntimeError > > in the proposed Wrapper, I think. A raise after rollback is needed.
No, the generator returns after rolling back, which causes throw() to raise StopIteration, which is good enough for the wrapper as written. > Actually, the Wrapper as written in the PEP does not raise RuntimeError > if the generator catches a block's exception. > > Shouldn't the relevant clause in the Wrapper go like this: > > try: > self.gen.throw(type, value, traceback) > except type: > return > except StopIteration: > raise RuntimeError("generator caught exception") > else: > raise RuntimeError("generator didn't stop") I considered that, but decided that it should be okay for the generator to respond to a throw() by returning (thus replacing the exception thrown by StopIteration) since the call to __exit__() is contained inside a finally-clause, so that when __exit__() returns normally, the finally-clause will re-raise the original exception anyway. Note that there are currently no other use cases for throw() except the with_template decorator and the close() method. Both allow the generator to respond either by letting the exception pass through it unchanged (after executing finally-clauses if present) or by simply returning (which will raise StopIteration in the caller of throw()). Erroneous behaviors are, in both cases, raising some other exception or *yielding* another value. There may be *other* use cases for yielding a value, for example, a future (looping) block-statement a la PEP 343. Raising another exception is always an indication of a bug in the generator. > And the transaction template would go like this (re-raising the exception): > > @with_template > def transactional(db): > db.begin() > try: > yield None > except: > db.rollback() > raise > else: > db.commit() > > At least this is what I gleaned from the earlier threads. It means that > the template does not appear to supress an exception that it cannot > actually supress. I disagree (at the -0 to -0.5 level); given that the with_template decorator allows StopIteration, I think that "appearing to suppress an exception it doesn't actually suppress" is a minor sin -- the key point is that the cleanup gets executed and doesn't raise a new exception or reaches a yield-statement. I'll summarize this discussion in the PEP. -- --Guido van Rossum (home page: http://www.python.org/~guido/) _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com