python-2.5.2/win32/Lib/contextlib.py
changeset 0 ae805ac0140d
equal deleted inserted replaced
-1:000000000000 0:ae805ac0140d
       
     1 """Utilities for with-statement contexts.  See PEP 343."""
       
     2 
       
     3 import sys
       
     4 
       
     5 __all__ = ["contextmanager", "nested", "closing"]
       
     6 
       
     7 class GeneratorContextManager(object):
       
     8     """Helper for @contextmanager decorator."""
       
     9 
       
    10     def __init__(self, gen):
       
    11         self.gen = gen
       
    12 
       
    13     def __enter__(self):
       
    14         try:
       
    15             return self.gen.next()
       
    16         except StopIteration:
       
    17             raise RuntimeError("generator didn't yield")
       
    18 
       
    19     def __exit__(self, type, value, traceback):
       
    20         if type is None:
       
    21             try:
       
    22                 self.gen.next()
       
    23             except StopIteration:
       
    24                 return
       
    25             else:
       
    26                 raise RuntimeError("generator didn't stop")
       
    27         else:
       
    28             if value is None:
       
    29                 # Need to force instantiation so we can reliably
       
    30                 # tell if we get the same exception back
       
    31                 value = type()
       
    32             try:
       
    33                 self.gen.throw(type, value, traceback)
       
    34                 raise RuntimeError("generator didn't stop after throw()")
       
    35             except StopIteration, exc:
       
    36                 # Suppress the exception *unless* it's the same exception that
       
    37                 # was passed to throw().  This prevents a StopIteration
       
    38                 # raised inside the "with" statement from being suppressed
       
    39                 return exc is not value
       
    40             except:
       
    41                 # only re-raise if it's *not* the exception that was
       
    42                 # passed to throw(), because __exit__() must not raise
       
    43                 # an exception unless __exit__() itself failed.  But throw()
       
    44                 # has to raise the exception to signal propagation, so this
       
    45                 # fixes the impedance mismatch between the throw() protocol
       
    46                 # and the __exit__() protocol.
       
    47                 #
       
    48                 if sys.exc_info()[1] is not value:
       
    49                     raise
       
    50 
       
    51 
       
    52 def contextmanager(func):
       
    53     """@contextmanager decorator.
       
    54 
       
    55     Typical usage:
       
    56 
       
    57         @contextmanager
       
    58         def some_generator(<arguments>):
       
    59             <setup>
       
    60             try:
       
    61                 yield <value>
       
    62             finally:
       
    63                 <cleanup>
       
    64 
       
    65     This makes this:
       
    66 
       
    67         with some_generator(<arguments>) as <variable>:
       
    68             <body>
       
    69 
       
    70     equivalent to this:
       
    71 
       
    72         <setup>
       
    73         try:
       
    74             <variable> = <value>
       
    75             <body>
       
    76         finally:
       
    77             <cleanup>
       
    78 
       
    79     """
       
    80     def helper(*args, **kwds):
       
    81         return GeneratorContextManager(func(*args, **kwds))
       
    82     try:
       
    83         helper.__name__ = func.__name__
       
    84         helper.__doc__ = func.__doc__
       
    85         helper.__dict__ = func.__dict__
       
    86     except:
       
    87         pass
       
    88     return helper
       
    89 
       
    90 
       
    91 @contextmanager
       
    92 def nested(*managers):
       
    93     """Support multiple context managers in a single with-statement.
       
    94 
       
    95     Code like this:
       
    96 
       
    97         with nested(A, B, C) as (X, Y, Z):
       
    98             <body>
       
    99 
       
   100     is equivalent to this:
       
   101 
       
   102         with A as X:
       
   103             with B as Y:
       
   104                 with C as Z:
       
   105                     <body>
       
   106 
       
   107     """
       
   108     exits = []
       
   109     vars = []
       
   110     exc = (None, None, None)
       
   111     try:
       
   112         try:
       
   113             for mgr in managers:
       
   114                 exit = mgr.__exit__
       
   115                 enter = mgr.__enter__
       
   116                 vars.append(enter())
       
   117                 exits.append(exit)
       
   118             yield vars
       
   119         except:
       
   120             exc = sys.exc_info()
       
   121     finally:
       
   122         while exits:
       
   123             exit = exits.pop()
       
   124             try:
       
   125                 if exit(*exc):
       
   126                     exc = (None, None, None)
       
   127             except:
       
   128                 exc = sys.exc_info()
       
   129         if exc != (None, None, None):
       
   130             # Don't rely on sys.exc_info() still containing
       
   131             # the right information. Another exception may
       
   132             # have been raised and caught by an exit method
       
   133             raise exc[0], exc[1], exc[2]
       
   134 
       
   135 
       
   136 class closing(object):
       
   137     """Context to automatically close something at the end of a block.
       
   138 
       
   139     Code like this:
       
   140 
       
   141         with closing(<module>.open(<arguments>)) as f:
       
   142             <block>
       
   143 
       
   144     is equivalent to this:
       
   145 
       
   146         f = <module>.open(<arguments>)
       
   147         try:
       
   148             <block>
       
   149         finally:
       
   150             f.close()
       
   151 
       
   152     """
       
   153     def __init__(self, thing):
       
   154         self.thing = thing
       
   155     def __enter__(self):
       
   156         return self.thing
       
   157     def __exit__(self, *exc_info):
       
   158         self.thing.close()