1import sys
2
3
4def typename(t):
5    name = type(t).__name__
6    if sys.version_info < (2,5):
7        if name == 'classobj' and issubclass(t, MyException):
8            name = 'type'
9        elif name == 'instance' and isinstance(t, MyException):
10            name = 'MyException'
11    return "<type '%s'>" % name
12
13
14class MyException(Exception):
15    pass
16
17
18class ContextManager(object):
19    def __init__(self, value, exit_ret = None):
20        self.value = value
21        self.exit_ret = exit_ret
22
23    def __exit__(self, a, b, tb):
24        print("exit %s %s %s" % (typename(a), typename(b), typename(tb)))
25        return self.exit_ret
26
27    def __enter__(self):
28        print("enter")
29        return self.value
30
31
32def no_as():
33    """
34    >>> no_as()
35    enter
36    hello
37    exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
38    """
39    with ContextManager("value"):
40        print("hello")
41
42
43def basic():
44    """
45    >>> basic()
46    enter
47    value
48    exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
49    """
50    with ContextManager("value") as x:
51        print(x)
52
53
54def with_pass():
55    """
56    >>> with_pass()
57    enter
58    exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
59    """
60    with ContextManager("value") as x:
61        pass
62
63
64def with_return():
65    """
66    >>> print(with_return())
67    enter
68    exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
69    value
70    """
71    with ContextManager("value") as x:
72        return x
73
74
75def with_break():
76    """
77    >>> print(with_break())
78    enter
79    exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
80    a
81    """
82    for c in list("abc"):
83        with ContextManager("value") as x:
84            break
85        print("FAILED")
86    return c
87
88
89def with_continue():
90    """
91    >>> print(with_continue())
92    enter
93    exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
94    enter
95    exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
96    enter
97    exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
98    c
99    """
100    for c in list("abc"):
101        with ContextManager("value") as x:
102            continue
103        print("FAILED")
104    return c
105
106
107def with_exception(exit_ret):
108    """
109    >>> with_exception(None)
110    enter
111    value
112    exit <type 'type'> <type 'MyException'> <type 'traceback'>
113    outer except
114    >>> with_exception(True)
115    enter
116    value
117    exit <type 'type'> <type 'MyException'> <type 'traceback'>
118    """
119    try:
120        with ContextManager("value", exit_ret=exit_ret) as value:
121            print(value)
122            raise MyException()
123    except:
124        print("outer except")
125
126
127def with_real_lock():
128    """
129    >>> with_real_lock()
130    about to acquire lock
131    holding lock
132    lock no longer held
133    """
134    from threading import Lock
135    lock = Lock()
136
137    print("about to acquire lock")
138
139    with lock:
140        print("holding lock")
141
142    print("lock no longer held")
143
144
145def functions_in_with():
146    """
147    >>> f = functions_in_with()
148    enter
149    exit <type 'type'> <type 'MyException'> <type 'traceback'>
150    outer except
151    >>> f(1)[0]
152    1
153    >>> print(f(1)[1])
154    value
155    """
156    try:
157        with ContextManager("value") as value:
158            def f(x): return x, value
159            make = lambda x:x()
160            raise make(MyException)
161    except:
162        print("outer except")
163    return f
164
165
166def multitarget():
167    """
168    >>> multitarget()
169    enter
170    1 2 3 4 5
171    exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
172    """
173    with ContextManager((1, 2, (3, (4, 5)))) as (a, b, (c, (d, e))):
174        print('%s %s %s %s %s' % (a, b, c, d, e))
175
176
177def tupletarget():
178    """
179    >>> tupletarget()
180    enter
181    (1, 2, (3, (4, 5)))
182    exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
183    """
184    with ContextManager((1, 2, (3, (4, 5)))) as t:
185        print(t)
186
187
188class GetManager(object):
189    def get(self, *args):
190        return ContextManager(*args)
191
192
193def manager_from_expression():
194    """
195    >>> manager_from_expression()
196    enter
197    1
198    exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
199    enter
200    2
201    exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
202    """
203    with GetManager().get(1) as x:
204        print(x)
205    g = GetManager()
206    with g.get(2) as x:
207        print(x)
208