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