Merged pull request #12 from bhy/T423.
[cython.git] / tests / run / withstat.pyx
1 from __future__ import with_statement
2
3 import sys
4
5 def typename(t):
6     name = type(t).__name__
7     if sys.version_info < (2,5):
8         if name == 'classobj' and issubclass(t, MyException):
9             name = 'type'
10         elif name == 'instance' and isinstance(t, MyException):
11             name = 'MyException'
12     return u"<type '%s'>" % name
13
14 class MyException(Exception):
15     pass
16
17 class ContextManager(object):
18     def __init__(self, value, exit_ret = None):
19         self.value = value
20         self.exit_ret = exit_ret
21
22     def __exit__(self, a, b, tb):
23         print u"exit", typename(a), typename(b), typename(tb)
24         return self.exit_ret
25
26     def __enter__(self):
27         print u"enter"
28         return self.value
29
30 def no_as():
31     """
32     >>> no_as()
33     enter
34     hello
35     exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
36     """
37     with ContextManager(u"value"):
38         print u"hello"
39
40 def basic():
41     """
42     >>> basic()
43     enter
44     value
45     exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
46     """
47     with ContextManager(u"value") as x:
48         print x
49
50 def with_pass():
51     """
52     >>> with_pass()
53     enter
54     exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
55     """
56     with ContextManager(u"value") as x:
57         pass
58
59 def with_exception(exit_ret):
60     """
61     >>> with_exception(None)
62     enter
63     value
64     exit <type 'type'> <type 'MyException'> <type 'traceback'>
65     outer except
66     >>> with_exception(True)
67     enter
68     value
69     exit <type 'type'> <type 'MyException'> <type 'traceback'>
70     """
71     try:
72         with ContextManager(u"value", exit_ret=exit_ret) as value:
73             print value
74             raise MyException()
75     except:
76         print u"outer except"
77
78 def multitarget():
79     """
80     >>> multitarget()
81     enter
82     1 2 3 4 5
83     exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
84     """
85     with ContextManager((1, 2, (3, (4, 5)))) as (a, b, (c, (d, e))):
86         print a, b, c, d, e
87
88 def tupletarget():
89     """
90     >>> tupletarget()
91     enter
92     (1, 2, (3, (4, 5)))
93     exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
94     """
95     with ContextManager((1, 2, (3, (4, 5)))) as t:
96         print t
97
98 def typed():
99     """
100     >>> typed()
101     enter
102     10
103     exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
104     """
105     cdef unsigned char i
106     c = ContextManager(255)
107     with c as i:
108         i += 11
109         print i
110
111 def multimanager():
112     """
113     >>> multimanager()
114     enter
115     enter
116     enter
117     enter
118     enter
119     enter
120     2
121     value
122     1 2 3 4 5
123     nested
124     exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
125     exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
126     exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
127     exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
128     exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
129     exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
130     """
131     with ContextManager(1), ContextManager(2) as x, ContextManager(u'value') as y,\
132             ContextManager(3), ContextManager((1, 2, (3, (4, 5)))) as (a, b, (c, (d, e))):
133         with ContextManager(u'nested') as nested:
134             print x
135             print y
136             print a, b, c, d, e
137             print nested
138
139 # Tests borrowed from pyregr test_with.py,
140 # modified to follow the constraints of Cython.
141 import unittest
142
143 class Dummy(object):
144     def __init__(self, value=None, gobble=False):
145         if value is None:
146             value = self
147         self.value = value
148         self.gobble = gobble
149         self.enter_called = False
150         self.exit_called = False
151
152     def __enter__(self):
153         self.enter_called = True
154         return self.value
155
156     def __exit__(self, *exc_info):
157         self.exit_called = True
158         self.exc_info = exc_info
159         if self.gobble:
160             return True
161
162 class InitRaises(object):
163     def __init__(self): raise RuntimeError()
164
165 class EnterRaises(object):
166     def __enter__(self): raise RuntimeError()
167     def __exit__(self, *exc_info): pass
168
169 class ExitRaises(object):
170     def __enter__(self): pass
171     def __exit__(self, *exc_info): raise RuntimeError()
172
173 class NestedWith(unittest.TestCase):
174     """
175     >>> NestedWith().runTest()
176     """
177
178     def runTest(self):
179         self.testNoExceptions()
180         self.testExceptionInExprList()
181         self.testExceptionInEnter()
182         self.testExceptionInExit()
183         self.testEnterReturnsTuple()
184
185     def testNoExceptions(self):
186         with Dummy() as a, Dummy() as b:
187             self.assertTrue(a.enter_called)
188             self.assertTrue(b.enter_called)
189         self.assertTrue(a.exit_called)
190         self.assertTrue(b.exit_called)
191
192     def testExceptionInExprList(self):
193         try:
194             with Dummy() as a, InitRaises():
195                 pass
196         except:
197             pass
198         self.assertTrue(a.enter_called)
199         self.assertTrue(a.exit_called)
200
201     def testExceptionInEnter(self):
202         try:
203             with Dummy() as a, EnterRaises():
204                 self.fail('body of bad with executed')
205         except RuntimeError:
206             pass
207         else:
208             self.fail('RuntimeError not reraised')
209         self.assertTrue(a.enter_called)
210         self.assertTrue(a.exit_called)
211
212     def testExceptionInExit(self):
213         body_executed = False
214         with Dummy(gobble=True) as a, ExitRaises():
215             body_executed = True
216         self.assertTrue(a.enter_called)
217         self.assertTrue(a.exit_called)
218         self.assertTrue(body_executed)
219         self.assertNotEqual(a.exc_info[0], None)
220
221     def testEnterReturnsTuple(self):
222         with Dummy(value=(1,2)) as (a1, a2), \
223              Dummy(value=(10, 20)) as (b1, b2):
224             self.assertEquals(1, a1)
225             self.assertEquals(2, a2)
226             self.assertEquals(10, b1)
227             self.assertEquals(20, b2)