Issue #26182: Raise DeprecationWarning for improper use of async/await keywords
This commit is contained in:
parent
6775231597
commit
8987c9d219
|
@ -519,7 +519,7 @@ def sleep(delay, result=None, *, loop=None):
|
|||
h.cancel()
|
||||
|
||||
|
||||
def async(coro_or_future, *, loop=None):
|
||||
def async_(coro_or_future, *, loop=None):
|
||||
"""Wrap a coroutine in a future.
|
||||
|
||||
If the argument is a Future, it is returned directly.
|
||||
|
@ -532,6 +532,11 @@ def async(coro_or_future, *, loop=None):
|
|||
|
||||
return ensure_future(coro_or_future, loop=loop)
|
||||
|
||||
# Silence DeprecationWarning:
|
||||
globals()['async'] = async_
|
||||
async_.__name__ = 'async'
|
||||
del async_
|
||||
|
||||
|
||||
def ensure_future(coro_or_future, *, loop=None):
|
||||
"""Wrap a coroutine or an awaitable in a future.
|
||||
|
|
|
@ -358,57 +358,110 @@ class AsyncBadSyntaxTest(unittest.TestCase):
|
|||
with self.subTest(code=code), self.assertRaises(SyntaxError):
|
||||
compile(code, "<test>", "exec")
|
||||
|
||||
def test_badsyntax_2(self):
|
||||
samples = [
|
||||
"""def foo():
|
||||
await = 1
|
||||
""",
|
||||
|
||||
"""class Bar:
|
||||
def async(): pass
|
||||
""",
|
||||
|
||||
"""class Bar:
|
||||
async = 1
|
||||
""",
|
||||
|
||||
"""class async:
|
||||
pass
|
||||
""",
|
||||
|
||||
"""class await:
|
||||
pass
|
||||
""",
|
||||
|
||||
"""import math as await""",
|
||||
|
||||
"""def async():
|
||||
pass""",
|
||||
|
||||
"""def foo(*, await=1):
|
||||
pass"""
|
||||
|
||||
"""async = 1""",
|
||||
|
||||
"""print(await=1)"""
|
||||
]
|
||||
|
||||
for code in samples:
|
||||
with self.subTest(code=code), self.assertWarnsRegex(
|
||||
DeprecationWarning,
|
||||
"'await' will become reserved keywords"):
|
||||
compile(code, "<test>", "exec")
|
||||
|
||||
def test_badsyntax_3(self):
|
||||
with self.assertRaises(DeprecationWarning):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("error")
|
||||
compile("async = 1", "<test>", "exec")
|
||||
|
||||
def test_goodsyntax_1(self):
|
||||
# Tests for issue 24619
|
||||
|
||||
def foo(await):
|
||||
async def foo(): pass
|
||||
async def foo():
|
||||
pass
|
||||
return await + 1
|
||||
self.assertEqual(foo(10), 11)
|
||||
samples = [
|
||||
'''def foo(await):
|
||||
async def foo(): pass
|
||||
async def foo():
|
||||
pass
|
||||
return await + 1
|
||||
''',
|
||||
|
||||
def foo(await):
|
||||
async def foo(): pass
|
||||
async def foo(): pass
|
||||
return await + 2
|
||||
self.assertEqual(foo(20), 22)
|
||||
'''def foo(await):
|
||||
async def foo(): pass
|
||||
async def foo(): pass
|
||||
return await + 1
|
||||
''',
|
||||
|
||||
def foo(await):
|
||||
'''def foo(await):
|
||||
|
||||
async def foo(): pass
|
||||
async def foo(): pass
|
||||
|
||||
async def foo(): pass
|
||||
async def foo(): pass
|
||||
|
||||
return await + 2
|
||||
self.assertEqual(foo(20), 22)
|
||||
return await + 1
|
||||
''',
|
||||
|
||||
def foo(await):
|
||||
"""spam"""
|
||||
async def foo(): \
|
||||
pass
|
||||
# 123
|
||||
async def foo(): pass
|
||||
# 456
|
||||
return await + 2
|
||||
self.assertEqual(foo(20), 22)
|
||||
'''def foo(await):
|
||||
"""spam"""
|
||||
async def foo(): \
|
||||
pass
|
||||
# 123
|
||||
async def foo(): pass
|
||||
# 456
|
||||
return await + 1
|
||||
''',
|
||||
|
||||
def foo(await):
|
||||
def foo(): pass
|
||||
def foo(): pass
|
||||
async def bar(): return await_
|
||||
await_ = await
|
||||
try:
|
||||
bar().send(None)
|
||||
except StopIteration as ex:
|
||||
return ex.args[0]
|
||||
self.assertEqual(foo(42), 42)
|
||||
'''def foo(await):
|
||||
def foo(): pass
|
||||
def foo(): pass
|
||||
async def bar(): return await_
|
||||
await_ = await
|
||||
try:
|
||||
bar().send(None)
|
||||
except StopIteration as ex:
|
||||
return ex.args[0] + 1
|
||||
'''
|
||||
]
|
||||
|
||||
async def f():
|
||||
async def g(): pass
|
||||
await z
|
||||
await = 1
|
||||
self.assertTrue(inspect.iscoroutinefunction(f))
|
||||
for code in samples:
|
||||
with self.subTest(code=code):
|
||||
loc = {}
|
||||
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
exec(code, loc, loc)
|
||||
|
||||
self.assertEqual(loc['foo'](10), 11)
|
||||
|
||||
|
||||
class TokenizerRegrTest(unittest.TestCase):
|
||||
|
|
|
@ -1345,18 +1345,6 @@ class GrammarTests(unittest.TestCase):
|
|||
self.assertEqual(m.other, 42)
|
||||
|
||||
def test_async_await(self):
|
||||
async = 1
|
||||
await = 2
|
||||
self.assertEqual(async, 1)
|
||||
|
||||
def async():
|
||||
nonlocal await
|
||||
await = 10
|
||||
async()
|
||||
self.assertEqual(await, 10)
|
||||
|
||||
self.assertFalse(bool(async.__code__.co_flags & inspect.CO_COROUTINE))
|
||||
|
||||
async def test():
|
||||
def sum():
|
||||
pass
|
||||
|
|
|
@ -353,14 +353,14 @@ class _AsyncDeprecatedProperty:
|
|||
class DocumentLS:
|
||||
"""Mixin to create documents that conform to the load/save spec."""
|
||||
|
||||
async = _AsyncDeprecatedProperty()
|
||||
async_ = False
|
||||
locals()['async'] = _AsyncDeprecatedProperty() # Avoid DeprecationWarning
|
||||
|
||||
def _get_async(self):
|
||||
return False
|
||||
|
||||
def _set_async(self, async):
|
||||
if async:
|
||||
def _set_async(self, flag):
|
||||
if flag:
|
||||
raise xml.dom.NotSupportedErr(
|
||||
"asynchronous document loading is not supported")
|
||||
|
||||
|
|
|
@ -21,6 +21,9 @@ Core and Builtins
|
|||
- Issue #28120: Fix dict.pop() for splitted dictionary when trying to remove a
|
||||
"pending key" (Not yet inserted in split-table). Patch by Xiang Zhang.
|
||||
|
||||
- Issue #26182: Raise DeprecationWarning when async and await keywords are
|
||||
used as variable/attribute/class/function name.
|
||||
|
||||
Library
|
||||
-------
|
||||
|
||||
|
|
20
Python/ast.c
20
Python/ast.c
|
@ -938,6 +938,26 @@ forbidden_name(struct compiling *c, identifier name, const node *n,
|
|||
ast_error(c, n, "assignment to keyword");
|
||||
return 1;
|
||||
}
|
||||
if (PyUnicode_CompareWithASCIIString(name, "async") == 0 ||
|
||||
PyUnicode_CompareWithASCIIString(name, "await") == 0)
|
||||
{
|
||||
PyObject *message = PyUnicode_FromString(
|
||||
"'async' and 'await' will become reserved keywords"
|
||||
" in Python 3.7");
|
||||
if (message == NULL) {
|
||||
return 1;
|
||||
}
|
||||
if (PyErr_WarnExplicitObject(
|
||||
PyExc_DeprecationWarning,
|
||||
message,
|
||||
c->c_filename,
|
||||
LINENO(n),
|
||||
NULL,
|
||||
NULL) < 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (full_checks) {
|
||||
const char * const *p;
|
||||
for (p = FORBIDDEN; *p; p++) {
|
||||
|
|
Loading…
Reference in New Issue