mirror of
https://github.com/python/cpython.git
synced 2025-10-19 05:08:28 +00:00

This was started by Mike Bland and completed by Guido (with help from Neal). This still needs a __future__ statement added; Thomas is working on Michael's patch for that aspect. There's a small amount of code cleanup and refactoring in ast.c, compile.c and ceval.c (I fixed the lltrace behavior when EXT_POP is used -- however I had to make lltrace a static global).
41 lines
1.1 KiB
Python
41 lines
1.1 KiB
Python
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]
|
|
|