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