| import sys |
| from collections import deque |
| |
| |
| class nested(object): |
| def __init__(self, *contexts): |
| self.contexts = contexts |
| self.entered = None |
| |
| def __context__(self): |
| return self |
| |
| def __enter__(self): |
| if self.entered is not None: |
| raise RuntimeError("Context is not reentrant") |
| self.entered = deque() |
| vars = [] |
| try: |
| for context in self.contexts: |
| mgr = context.__context__() |
| vars.append(mgr.__enter__()) |
| self.entered.appendleft(mgr) |
| except: |
| self.__exit__(*sys.exc_info()) |
| raise |
| return vars |
| |
| def __exit__(self, *exc_info): |
| # Behave like nested with statements |
| # first in, last out |
| # New exceptions override old ones |
| ex = exc_info |
| for mgr in self.entered: |
| try: |
| mgr.__exit__(*ex) |
| except: |
| ex = sys.exc_info() |
| self.entered = None |
| if ex is not exc_info: |
| raise ex[0], ex[1], ex[2] |