diff --git a/pep-0343.txt b/pep-0343.txt index ea4346009..175f02495 100644 --- a/pep-0343.txt +++ b/pep-0343.txt @@ -111,7 +111,7 @@ Motivation and Summary example, it was impossible to do this for the opening example. The idea was to define the template like this: - @with_template + @contextmanager def opening(filename): f = open(filename) try: @@ -258,7 +258,7 @@ Generator Decorator that makes it possible to use a generator that yields exactly once to control a with-statement. Here's a sketch of such a decorator: - class Wrapper(object): + class ContextManager(object): def __init__(self, gen): self.gen = gen @@ -285,16 +285,16 @@ Generator Decorator else: raise RuntimeError("generator caught exception") - def with_template(func): + def contextmanager(func): def helper(*args, **kwds): - return Wrapper(func(*args, **kwds)) + return ContextManager(func(*args, **kwds)) return helper This decorator could be used as follows: - @with_template + @contextmanager def opening(filename): - f = open(filename) # IOError here is untouched by Wrapper + f = open(filename) # IOError is untouched by ContextManager try: yield f finally: @@ -332,18 +332,20 @@ Optional Extensions is entered). OTOH such mistakes are easily diagnosed; for example, the - with_template decorator above raises RuntimeError when the second + contextmanager decorator above raises RuntimeError when the second with-statement calls f.__enter__() again. -Open Issues +Resolved Open Issues - Discussion on python-dev has revealed some open issues. I list - them here, with my preferred resolution and its motivation. The - PEP as currently written reflects this preferred resolution. + Discussion on python-dev revealed some open issues. I list them + here, with my preferred resolution and its motivation. The PEP + has been accepted without these being challenged, so the issues + are now resolved. - 1. The __exit__() method of the with_template decorator class catches - StopIteration and considers it equivalent to re-raising the exception - passed to throw(). Is allowing StopIteration right here? + 1. The __exit__() method of the contextmanager decorator class + catches StopIteration and considers it equivalent to re-raising + the exception passed to throw(). Is allowing StopIteration + right here? This is so that a generator doing cleanup depending on the exception thrown (like the transactional() example below) can @@ -368,7 +370,7 @@ Examples 1. A template for ensuring that a lock, acquired at the start of a block, is released when the block is left: - @with_template + @contextmanager def locking(lock): lock.acquire() try: @@ -390,7 +392,7 @@ Examples 2. A template for opening a file that ensures the file is closed when the block is left: - @with_template + @contextmanager def opening(filename, mode="r"): f = open(filename, mode) try: @@ -407,7 +409,7 @@ Examples 3. A template for committing or rolling back a database transaction: - @with_template + @contextmanager def transactional(db): db.begin() try: @@ -433,7 +435,7 @@ Examples 5. Redirect stdout temporarily: - @with_template + @contextmanager def redirecting_stdout(new_stdout): save_stdout = sys.stdout sys.stdout = new_stdout @@ -454,7 +456,7 @@ Examples 6. A variant on opening() that also returns an error condition: - @with_template + @contextmanager def opening_w_error(filename, mode="r"): try: f = open(filename, mode) @@ -491,7 +493,7 @@ Examples import decimal - @with_template + @contextmanager def extra_precision(places=2): c = decimal.getcontext() saved_prec = c.prec @@ -520,7 +522,7 @@ Examples 9. Here's a more general Decimal-context-switching template: - @with_template + @contextmanager def decimal_context(newctx=None): oldctx = decimal.getcontext() if newctx is None: @@ -545,7 +547,7 @@ Examples 10. A generic "object-closing" template: - @with_template + @contextmanager def closing(obj): try: yield obj