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