1 """Utilities for with-statement contexts. See PEP 343."""
5 __all__
= ["contextmanager", "nested", "closing"]
7 class GeneratorContextManager(object):
8 """Helper for @contextmanager decorator."""
10 def __init__(self
, gen
):
15 return self
.gen
.next()
17 raise RuntimeError("generator didn't yield")
19 def __exit__(self
, type, value
, traceback
):
26 raise RuntimeError("generator didn't stop")
29 self
.gen
.throw(type, value
, traceback
)
30 raise RuntimeError("generator didn't stop after throw()")
31 except StopIteration, exc
:
32 # Suppress the exception *unless* it's the same exception that
33 # was passed to throw(). This prevents a StopIteration
34 # raised inside the "with" statement from being suppressed
35 return exc
is not value
37 # only re-raise if it's *not* the exception that was
38 # passed to throw(), because __exit__() must not raise
39 # an exception unless __exit__() itself failed. But throw()
40 # has to raise the exception to signal propagation, so this
41 # fixes the impedance mismatch between the throw() protocol
42 # and the __exit__() protocol.
44 if sys
.exc_info()[1] is not value
:
48 def contextmanager(func
):
49 """@contextmanager decorator.
54 def some_generator(<arguments>):
63 with some_generator(<arguments>) as <variable>:
76 def helper(*args
, **kwds
):
77 return GeneratorContextManager(func(*args
, **kwds
))
79 helper
.__name
__ = func
.__name
__
80 helper
.__doc
__ = func
.__doc
__
81 helper
.__dict
__ = func
.__dict
__
88 def nested(*managers
):
89 """Support multiple context managers in a single with-statement.
93 with nested(A, B, C) as (X, Y, Z):
96 is equivalent to this:
106 exc
= (None, None, None)
111 enter
= mgr
.__enter
__
122 exc
= (None, None, None)
125 if exc
!= (None, None, None):
126 # Don't rely on sys.exc_info() still containing
127 # the right information. Another exception may
128 # have been raised and caught by an exit method
129 raise exc
[0], exc
[1], exc
[2]
132 class closing(object):
133 """Context to automatically close something at the end of a block.
137 with closing(<module>.open(<arguments>)) as f:
140 is equivalent to this:
142 f = <module>.open(<arguments>)
149 def __init__(self
, thing
):
153 def __exit__(self
, *exc_info
):