diff --git a/pep-0343.txt b/pep-0343.txt index e616132ef..fb8d998a8 100644 --- a/pep-0343.txt +++ b/pep-0343.txt @@ -227,21 +227,22 @@ Specification: The 'with' Statement ctx = (EXPR).__context__() exit = exc.__exit__ # Not calling it yet - res = ctx.__enter__() + value = ctx.__enter__() exc = (None, None, None) try: try: - VAR = res # Only if "as VAR" is present + VAR = value # Only if "as VAR" is present BLOCK except: - exc = sys.exc_info() - raise + exc = None + exit(*sys.exc_info()) finally: - exit(*exc) + if exc: + exit(*exc) - Here, the lowercase variables are internal variables and not - accessible to the user; they will most likely be implemented as - special registers or stack positions. + Here, the lowercase variables (ctx, exit, value, exc) are internal + variables and not accessible to the user; they will most likely be + implemented as special registers or stack positions. The details of the above translation are intended to prescribe the exact semantics. If any of the relevant methods are not found as @@ -264,20 +265,32 @@ Specification: The 'with' Statement object each time its __context__ method is invoked. If the "as VAR" part of the syntax is omitted, the "VAR =" part of - the translation is omitted (but abc.__enter__() is still called). + the translation is omitted (but ctx.__enter__() is still called). - The calling convention for abc.__exit__() is as follows. If the + The calling convention for ctx.__exit__() is as follows. If the finally-suite was reached through normal completion of BLOCK or through a non-local goto (a break, continue or return statement in - BLOCK), abc.__exit__() is called with three None arguments. If + BLOCK), ctx.__exit__() is called with three None arguments. If the finally-suite was reached through an exception raised in - BLOCK, abc.__exit__() is called with three arguments representing + BLOCK, ctx.__exit__() is called with three arguments representing the exception type, value, and traceback. - The motivation for this API to __exit__(), as opposed to the - argument-less __exit__() from PEP 310, was given by the - transactional() use case, example 3 below. The template in that - example must commit or roll back the transaction depending on + IMPORTANT: if ctx.__exit__() is passed exception information, it + *must* re-raise the exception, unless it wants the exception to be + ignored. That is, if ctx.__exit__() returns normally, execution + continues at the next statement after the with-statement, even if + an exception happened inside the with-statement. However, if the + with-statement was left via a non-local goto (break, continue or + return), this non-local return is resumed when ctx.__exit__() + returns normally. The motivation for this detail is to make a + try/except block in a context manager created from a decorated + generator behave exactly as if the body of the generator were + expanded in-line at the place of the with-statement. + + The motivation for passing the exception details to __exit__(), as + opposed to the argument-less __exit__() from PEP 310, was given by + the transactional() use case, example 3 below. The template in + that example must commit or roll back the transaction depending on whether an exception occurred or not. Rather than just having a boolean flag indicating whether an exception occurred, we pass the complete exception information, for the benefit of an @@ -291,6 +304,20 @@ Specification: The 'with' Statement non-local goto should be considered unexceptional for the purposes of a database transaction roll-back decision. +Transition Plan + + In Python 2.5, the new syntax will only be recognized if a future + statement is present: + + from __future__ import with_statement + + This will make both 'with' and 'as' keywords. Without the future + statement, using 'with' or 'as' as an identifier will cause a + DeprecationWarning to be issued. + + In Python 2.6, the new syntax will always be recognized; 'with' + and 'as' are always keywords. + Generator Decorator With PEP 342 accepted, it is possible to write a decorator @@ -394,6 +421,7 @@ Optional Extensions - threading.Lock - threading.RLock - threading.Condition + - threading.Semaphore and threading.BoundedSemaphore Standard Terminology @@ -598,6 +626,7 @@ Examples yield None except: db.rollback() + raise else: db.commit()