, - , , contextçlib.nested, , .
Contexts can be passed to it either as an object of a context protocol, or as a tuple, where the first member is the called object, which will be called with the remainder of the tuple as parameters in a managed environment:
import sys
import traceback
class NestContext(object):
def __init__(self, *objects):
self.objects = objects
def __enter__(self):
self.contexts = []
for obj in self.objects:
if isinstance(obj, tuple):
try:
obj = obj[0](*obj[1:])
except Exception, error:
self.__exit__(type(error), error, sys.exc_info()[2])
raise
try:
context = obj.__enter__()
except Exception, error:
self.__exit__(type(error), error, sys.exc_info()[2])
raise
self.contexts.append(context)
return self
def __iter__(self):
for context in self.contexts:
yield context
def __exit__(self, *args):
for context in reversed(self.contexts):
try:
context.__exit__(*args)
except Exception, error:
sys.stderr.write(str(error))
if __name__ == "__main__":
class PlainContext(object):
counter = 0
def __enter__(self):
self.counter = self.__class__.counter
print self.counter
self.__class__.counter += 1
return self
def __exit__(self, *args):
print "exiting %d" % self.counter
with NestContext(*((PlainContext,) for i in range(10))) as all_contexts:
print tuple(all_contexts)
source
share