summaryrefslogtreecommitdiffstats
path: root/Lib/test/nested.py
blob: a20cf43e7a63ffc65bf632dc01ddf619229d2ac5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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]