summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/asyncio/tasks.py7
-rw-r--r--Lib/test/test_coroutines.py137
-rw-r--r--Lib/test/test_grammar.py12
-rw-r--r--Lib/xml/dom/xmlbuilder.py6
-rw-r--r--Misc/NEWS3
-rw-r--r--Python/ast.c20
6 files changed, 127 insertions, 58 deletions
diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py
index 35c945c..4c66546 100644
--- a/Lib/asyncio/tasks.py
+++ b/Lib/asyncio/tasks.py
@@ -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.
diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py
index 154ce7f..f2839a7 100644
--- a/Lib/test/test_coroutines.py
+++ b/Lib/test/test_coroutines.py
@@ -358,57 +358,110 @@ class AsyncBadSyntaxTest(unittest.TestCase):
with self.subTest(code=code), self.assertRaises(SyntaxError):
compile(code, "<test>", "exec")
- def test_goodsyntax_1(self):
- # Tests for issue 24619
+ def test_badsyntax_2(self):
+ samples = [
+ """def foo():
+ await = 1
+ """,
+
+ """class Bar:
+ def async(): pass
+ """,
- def foo(await):
- async def foo(): pass
- async def foo():
+ """class Bar:
+ async = 1
+ """,
+
+ """class async:
pass
- return await + 1
- self.assertEqual(foo(10), 11)
+ """,
- def foo(await):
- async def foo(): pass
- async def foo(): pass
- return await + 2
- self.assertEqual(foo(20), 22)
+ """class await:
+ pass
+ """,
- def foo(await):
+ """import math as await""",
- async def foo(): pass
+ """def async():
+ pass""",
- async def foo(): pass
+ """def foo(*, await=1):
+ pass"""
- return await + 2
- self.assertEqual(foo(20), 22)
+ """async = 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):
- 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)
+ """print(await=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), 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
+
+ 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 + 1
+ ''',
+
+ '''def foo(await):
+
+ async def foo(): pass
+
+ async def foo(): pass
+
+ return await + 1
+ ''',
+
+ '''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] + 1
+ '''
+ ]
+
+ 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):
diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py
index 67a61d4..03f2c84 100644
--- a/Lib/test/test_grammar.py
+++ b/Lib/test/test_grammar.py
@@ -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
diff --git a/Lib/xml/dom/xmlbuilder.py b/Lib/xml/dom/xmlbuilder.py
index 444f0b2..e9a1536 100644
--- a/Lib/xml/dom/xmlbuilder.py
+++ b/Lib/xml/dom/xmlbuilder.py
@@ -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")
diff --git a/Misc/NEWS b/Misc/NEWS
index 4c23930..4655b5e 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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
-------
diff --git a/Python/ast.c b/Python/ast.c
index 765d24e..deea579 100644
--- a/Python/ast.c
+++ b/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++) {