From 342427e15bf118e6c208b8f774b3ab882e49b7c9 2018-08-27 14:55:30 From: Paul Ganssle Date: 2018-08-27 14:55:30 Subject: [PATCH] Refactor and tweak async-in-function tests This improves Python3.5 compatibility, since "yield" in an async function was a SyntaxError in 3.5, but not in later versions Also adds a test for async methods. --- diff --git a/IPython/core/tests/test_async_helpers.py b/IPython/core/tests/test_async_helpers.py index c294c82..748f3f1 100644 --- a/IPython/core/tests/test_async_helpers.py +++ b/IPython/core/tests/test_async_helpers.py @@ -5,6 +5,7 @@ Should only trigger on python 3.5+ or will have syntax errors. """ import sys +from itertools import chain, repeat import nose.tools as nt from textwrap import dedent, indent from unittest import TestCase @@ -155,18 +156,22 @@ if sys.version_info > (3, 5): # detection isn't *too* aggressive, and works inside a function func_contexts = [] - func_contexts.append(('func', dedent(""" + func_contexts.append(('func', False, dedent(""" def f():"""))) - func_contexts.append(('method', dedent(""" + func_contexts.append(('method', False, dedent(""" class MyClass: def __init__(self): """))) - func_contexts.append(('async-func', dedent(""" + func_contexts.append(('async-func', True, dedent(""" async def f():"""))) - func_contexts.append(('closure', dedent(""" + func_contexts.append(('async-method', True, dedent(""" + class MyClass: + async def f(self):"""))) + + func_contexts.append(('closure', False, dedent(""" def f(): def g(): """))) @@ -184,28 +189,41 @@ if sys.version_info > (3, 5): return context + '\n' + indented_case # Gather and run the tests - vals = ('return', 'yield') - success_tests = self._get_top_level_cases() - failure_tests = self._get_ry_syntax_errors() + # yield is allowed in async functions, starting in Python 3.6, + # and yield from is not allowed in any version + vals = ('return', 'yield', 'yield from (_ for _ in range(3))') + async_safe = (True, + sys.version_info >= (3, 6), + False) + vals = tuple(zip(vals, async_safe)) - for context_name, context in func_contexts: - # These tests should now successfully run - for test_name, test_case in success_tests: - nested_case = nest_case(context, test_case) + success_tests = zip(self._get_top_level_cases(), repeat(False)) + failure_tests = zip(self._get_ry_syntax_errors(), repeat(True)) - for val in vals: - with self.subTest((test_name, context_name, val)): - iprc(nested_case.format(val=val)) + tests = chain(success_tests, failure_tests) - # These tests should still raise a SyntaxError - for test_name, test_case in failure_tests: + for context_name, async_func, context in func_contexts: + for (test_name, test_case), should_fail in tests: nested_case = nest_case(context, test_case) - for val in vals: - with self.subTest((test_name, context_name, val)): - with self.assertRaises(SyntaxError): - iprc(nested_case.format(val=val)) + for val, async_safe in vals: + val_should_fail = (should_fail or + (async_func and not async_safe)) + + test_id = (context_name, test_name, val) + cell = nested_case.format(val=val) + + with self.subTest(test_id): + if val_should_fail: + msg = ("SyntaxError not raised for %s" % + str(test_id)) + with self.assertRaises(SyntaxError, msg=msg): + iprc(cell) + + print(cell) + else: + iprc(cell) def test_execute(self):