1class CtxMgr:
2
3    def __enter__(self):
4        print("__enter__")
5        return self
6
7    def __exit__(self, a, b, c):
8        print("__exit__", repr(a), repr(b))
9
10
11with CtxMgr() as a:
12    print(isinstance(a, CtxMgr))
13
14try:
15    with CtxMgr() as a:
16        raise ValueError
17except ValueError:
18    print("ValueError")
19
20
21class CtxMgr2:
22
23    def __enter__(self):
24        print("__enter__")
25        return self
26
27    def __exit__(self, a, b, c):
28        print("__exit__", repr(a), repr(b))
29        return True
30
31try:
32    with CtxMgr2() as a:
33        raise ValueError
34    print("No ValueError2")
35except ValueError:
36    print("ValueError2")
37
38
39# These recursive try-finally tests are attempt to get some interpretation
40# of last phrase in http://docs.python.org/3.4/library/dis.html#opcode-WITH_CLEANUP
41# "If the stack represents an exception, and the function call returns a 'true'
42# value, this information is "zapped" and replaced with a single WHY_SILENCED
43# to prevent END_FINALLY from re-raising the exception. (But non-local gotos
44# will still be resumed.)"
45print("===")
46with CtxMgr2() as a:
47    try:
48        try:
49            raise ValueError
50            print("No ValueError3")
51        finally:
52            print("finally1")
53    finally:
54        print("finally2")
55
56print("===")
57try:
58    try:
59        with CtxMgr2() as a:
60            try:
61                try:
62                    raise ValueError
63                    print("No ValueError3")
64                finally:
65                    print("finally1")
66            finally:
67                print("finally2")
68    finally:
69        print("finally3")
70finally:
71    print("finally4")
72