"""Utilities for with-statement contexts. See PEP 343."""
from functools import wraps
__all__ = ["contextmanager", "closing", "ContextDecorator"]
"A base class or mixin that enables context managers to work as decorators."
"""Return a recreated instance of self.
Allows otherwise one-shot context managers like
_GeneratorContextManager to support use as
decorators via implicit recreation.
Note: this is a private interface just for _GCM in 3.2 but will be
renamed and documented for third party use in 3.3
def __call__(self, func):
def inner(*args, **kwds):
return func(*args, **kwds)
"""Helper for @contextmanager decorator."""
def __init__(self, func, *args, **kwds):
self.gen = func(*args, **kwds)
self.func, self.args, self.kwds = func, args, kwds
# _GCM instances are one-shot context managers, so the
# CM must be recreated each time a decorated function is
return self.__class__(self.func, *self.args, **self.kwds)
raise RuntimeError("generator didn't yield")
def __exit__(self, type, value, traceback):
if type is None:
raise RuntimeError("generator didn't stop")
if value is None:
# Need to force instantiation so we can reliably
# tell if we get the same exception back
value = type()
self.gen.throw(type, value, traceback)
raise RuntimeError("generator didn't stop after throw()")
except StopIteration as exc:
# Suppress the exception *unless* it's the same exception that
# was passed to throw(). This prevents a StopIteration
# raised inside the "with" statement from being suppressed
return exc is not value
# only re-raise if it's *not* the exception that was
# passed to throw(), because __exit__() must not raise
# an exception unless __exit__() itself failed. But throw()
# has to raise the exception to signal propagation, so this
# fixes the impedance mismatch between the throw() protocol
# and the __exit__() protocol.
if sys.exc_info() is not value:
This makes this:
with some_generator(<arguments>) as <variable>:
equivalent to this:
<variable> = <value>
def helper(*args, **kwds):
return _GeneratorContextManager(func, *args, **kwds)
"""Context to automatically close something at the end of a block.
Code like this:
with closing(<module>.open(<arguments>)) as f:
is equivalent to this:
f = <module>.open(<arguments>)
def __init__(self, thing):
self.thing = thing
def __exit__(self, *exc_info):