diff options
Diffstat (limited to 'Lib/contextlib.py')
-rw-r--r-- | Lib/contextlib.py | 62 |
1 files changed, 14 insertions, 48 deletions
diff --git a/Lib/contextlib.py b/Lib/contextlib.py index bffa0c4902..4633cff7a4 100644 --- a/Lib/contextlib.py +++ b/Lib/contextlib.py @@ -4,9 +4,20 @@ import sys from functools import wraps from warnings import warn -__all__ = ["contextmanager", "nested", "closing"] +__all__ = ["contextmanager", "closing", "ContextDecorator"] -class GeneratorContextManager(object): + +class ContextDecorator(object): + "A base class or mixin that enables context managers to work as decorators." + def __call__(self, func): + @wraps(func) + def inner(*args, **kwds): + with self: + return func(*args, **kwds) + return inner + + +class _GeneratorContextManager(ContextDecorator): """Helper for @contextmanager decorator.""" def __init__(self, gen): @@ -81,55 +92,10 @@ def contextmanager(func): """ @wraps(func) def helper(*args, **kwds): - return GeneratorContextManager(func(*args, **kwds)) + return _GeneratorContextManager(func(*args, **kwds)) return helper -@contextmanager -def nested(*managers): - """Combine multiple context managers into a single nested context manager. - - This function has been deprecated in favour of the multiple manager form - of the with statement. - - The one advantage of this function over the multiple manager form of the - with statement is that argument unpacking allows it to be - used with a variable number of context managers as follows: - - with nested(*managers): - do_something() - - """ - warn("With-statements now directly support multiple context managers", - DeprecationWarning, 3) - exits = [] - vars = [] - exc = (None, None, None) - try: - for mgr in managers: - exit = mgr.__exit__ - enter = mgr.__enter__ - vars.append(enter()) - exits.append(exit) - yield vars - except: - exc = sys.exc_info() - finally: - while exits: - exit = exits.pop() - try: - if exit(*exc): - exc = (None, None, None) - except: - exc = sys.exc_info() - if exc != (None, None, None): - # Don't rely on sys.exc_info() still containing - # the right information. Another exception may - # have been raised and caught by an exit method - # exc[1] already has the __traceback__ attribute populated - raise exc[1] - - class closing(object): """Context to automatically close something at the end of a block. |