##// END OF EJS Templates
Test that using wrong runner/coroutine pair does not crash....
Matthias Bussonnier -
Show More

The requested changes are too big and content was truncated. Show full diff

1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,255 +1,277 b''
1 1 """
2 2 Test for async helpers.
3 3
4 4 Should only trigger on python 3.5+ or will have syntax errors.
5 5 """
6 6
7 7 import sys
8 8 from itertools import chain, repeat
9 9 import nose.tools as nt
10 10 from textwrap import dedent, indent
11 11 from unittest import TestCase
12 12 from IPython.testing.decorators import skip_without
13 13
14 14 ip = get_ipython()
15 15 iprc = lambda x: ip.run_cell(dedent(x)).raise_error()
16 iprc_nr = lambda x: ip.run_cell(dedent(x))
16 17
17 18 if sys.version_info > (3, 5):
18 19 from IPython.core.async_helpers import _should_be_async
19 20
20 21 class AsyncTest(TestCase):
21 22 def test_should_be_async(self):
22 23 nt.assert_false(_should_be_async("False"))
23 24 nt.assert_true(_should_be_async("await bar()"))
24 25 nt.assert_true(_should_be_async("x = await bar()"))
25 26 nt.assert_false(
26 27 _should_be_async(
27 28 dedent(
28 29 """
29 30 async def awaitable():
30 31 pass
31 32 """
32 33 )
33 34 )
34 35 )
35 36
36 37 def _get_top_level_cases(self):
37 38 # These are test cases that should be valid in a function
38 39 # but invalid outside of a function.
39 40 test_cases = []
40 41 test_cases.append(('basic', "{val}"))
41 42
42 43 # Note, in all conditional cases, I use True instead of
43 44 # False so that the peephole optimizer won't optimize away
44 45 # the return, so CPython will see this as a syntax error:
45 46 #
46 47 # while True:
47 48 # break
48 49 # return
49 50 #
50 51 # But not this:
51 52 #
52 53 # while False:
53 54 # return
54 55 #
55 56 # See https://bugs.python.org/issue1875
56 57
57 58 test_cases.append(('if', dedent("""
58 59 if True:
59 60 {val}
60 61 """)))
61 62
62 63 test_cases.append(('while', dedent("""
63 64 while True:
64 65 {val}
65 66 break
66 67 """)))
67 68
68 69 test_cases.append(('try', dedent("""
69 70 try:
70 71 {val}
71 72 except:
72 73 pass
73 74 """)))
74 75
75 76 test_cases.append(('except', dedent("""
76 77 try:
77 78 pass
78 79 except:
79 80 {val}
80 81 """)))
81 82
82 83 test_cases.append(('finally', dedent("""
83 84 try:
84 85 pass
85 86 except:
86 87 pass
87 88 finally:
88 89 {val}
89 90 """)))
90 91
91 92 test_cases.append(('for', dedent("""
92 93 for _ in range(4):
93 94 {val}
94 95 """)))
95 96
96 97
97 98 test_cases.append(('nested', dedent("""
98 99 if True:
99 100 while True:
100 101 {val}
101 102 break
102 103 """)))
103 104
104 105 test_cases.append(('deep-nested', dedent("""
105 106 if True:
106 107 while True:
107 108 break
108 109 for x in range(3):
109 110 if True:
110 111 while True:
111 112 for x in range(3):
112 113 {val}
113 114 """)))
114 115
115 116 return test_cases
116 117
117 118 def _get_ry_syntax_errors(self):
118 119 # This is a mix of tests that should be a syntax error if
119 120 # return or yield whether or not they are in a function
120 121
121 122 test_cases = []
122 123
123 124 test_cases.append(('class', dedent("""
124 125 class V:
125 126 {val}
126 127 """)))
127 128
128 129 test_cases.append(('nested-class', dedent("""
129 130 class V:
130 131 class C:
131 132 {val}
132 133 """)))
133 134
134 135 return test_cases
135 136
136 137
137 138 def test_top_level_return_error(self):
138 139 tl_err_test_cases = self._get_top_level_cases()
139 140 tl_err_test_cases.extend(self._get_ry_syntax_errors())
140 141
141 142 vals = ('return', 'yield', 'yield from (_ for _ in range(3))')
142 143
143 144 for test_name, test_case in tl_err_test_cases:
144 145 # This example should work if 'pass' is used as the value
145 146 with self.subTest((test_name, 'pass')):
146 147 iprc(test_case.format(val='pass'))
147 148
148 149 # It should fail with all the values
149 150 for val in vals:
150 151 with self.subTest((test_name, val)):
151 152 msg = "Syntax error not raised for %s, %s" % (test_name, val)
152 153 with self.assertRaises(SyntaxError, msg=msg):
153 154 iprc(test_case.format(val=val))
154 155
155 156 def test_in_func_no_error(self):
156 157 # Test that the implementation of top-level return/yield
157 158 # detection isn't *too* aggressive, and works inside a function
158 159 func_contexts = []
159 160
160 161 func_contexts.append(('func', False, dedent("""
161 162 def f():""")))
162 163
163 164 func_contexts.append(('method', False, dedent("""
164 165 class MyClass:
165 166 def __init__(self):
166 167 """)))
167 168
168 169 func_contexts.append(('async-func', True, dedent("""
169 170 async def f():""")))
170 171
171 172 func_contexts.append(('async-method', True, dedent("""
172 173 class MyClass:
173 174 async def f(self):""")))
174 175
175 176 func_contexts.append(('closure', False, dedent("""
176 177 def f():
177 178 def g():
178 179 """)))
179 180
180 181 def nest_case(context, case):
181 182 # Detect indentation
182 183 lines = context.strip().splitlines()
183 184 prefix_len = 0
184 185 for c in lines[-1]:
185 186 if c != ' ':
186 187 break
187 188 prefix_len += 1
188 189
189 190 indented_case = indent(case, ' ' * (prefix_len + 4))
190 191 return context + '\n' + indented_case
191 192
192 193 # Gather and run the tests
193 194
194 195 # yield is allowed in async functions, starting in Python 3.6,
195 196 # and yield from is not allowed in any version
196 197 vals = ('return', 'yield', 'yield from (_ for _ in range(3))')
197 198 async_safe = (True,
198 199 sys.version_info >= (3, 6),
199 200 False)
200 201 vals = tuple(zip(vals, async_safe))
201 202
202 203 success_tests = zip(self._get_top_level_cases(), repeat(False))
203 204 failure_tests = zip(self._get_ry_syntax_errors(), repeat(True))
204 205
205 206 tests = chain(success_tests, failure_tests)
206 207
207 208 for context_name, async_func, context in func_contexts:
208 209 for (test_name, test_case), should_fail in tests:
209 210 nested_case = nest_case(context, test_case)
210 211
211 212 for val, async_safe in vals:
212 213 val_should_fail = (should_fail or
213 214 (async_func and not async_safe))
214 215
215 216 test_id = (context_name, test_name, val)
216 217 cell = nested_case.format(val=val)
217 218
218 219 with self.subTest(test_id):
219 220 if val_should_fail:
220 221 msg = ("SyntaxError not raised for %s" %
221 222 str(test_id))
222 223 with self.assertRaises(SyntaxError, msg=msg):
223 224 iprc(cell)
224 225
225 226 print(cell)
226 227 else:
227 228 iprc(cell)
228 229
229 230
230 231 def test_execute(self):
231 232 iprc("""
232 233 import asyncio
233 234 await asyncio.sleep(0.001)
234 235 """
235 236 )
236 237
237 238 def test_autoawait(self):
238 239 iprc("%autoawait False")
239 240 iprc("%autoawait True")
240 241 iprc("""
241 242 from asyncio import sleep
242 243 await sleep(0.1)
243 244 """
244 245 )
245 246
246 247 @skip_without('curio')
247 248 def test_autoawait_curio(self):
248 249 iprc("%autoawait curio")
249 250
250 251 @skip_without('trio')
251 252 def test_autoawait_trio(self):
252 253 iprc("%autoawait trio")
253 254
255 @skip_without('trio')
256 def test_autoawait_trio_wrong_sleep(self):
257 iprc("%autoawait trio")
258 res = iprc_nr("""
259 import asyncio
260 await asyncio.sleep(0)
261 """)
262 with nt.assert_raises(TypeError):
263 res.raise_error()
264
265 @skip_without('trio')
266 def test_autoawait_asyncio_wrong_sleep(self):
267 iprc("%autoawait asyncio")
268 res = iprc_nr("""
269 import trio
270 await trio.sleep(0)
271 """)
272 with nt.assert_raises(RuntimeError):
273 res.raise_error()
274
275
254 276 def tearDown(self):
255 277 ip.loop_runner = "asyncio"
General Comments 0
You need to be logged in to leave comments. Login now