Merge 3.6 (issue #26182)

This commit is contained in:
Yury Selivanov 2016-09-15 12:50:51 -04:00
commit 96a042253f
6 changed files with 125 additions and 56 deletions

View file

@ -519,7 +519,7 @@ def sleep(delay, result=None, *, loop=None):
h.cancel() h.cancel()
def async(coro_or_future, *, loop=None): def async_(coro_or_future, *, loop=None):
"""Wrap a coroutine in a future. """Wrap a coroutine in a future.
If the argument is a Future, it is returned directly. 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) 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): def ensure_future(coro_or_future, *, loop=None):
"""Wrap a coroutine or an awaitable in a future. """Wrap a coroutine or an awaitable in a future.

View file

@ -358,57 +358,110 @@ class AsyncBadSyntaxTest(unittest.TestCase):
with self.subTest(code=code), self.assertRaises(SyntaxError): with self.subTest(code=code), self.assertRaises(SyntaxError):
compile(code, "<test>", "exec") 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): def test_goodsyntax_1(self):
# Tests for issue 24619 # Tests for issue 24619
def foo(await): samples = [
async def foo(): pass '''def foo(await):
async def foo(): async def foo(): pass
pass async def foo():
return await + 1 pass
self.assertEqual(foo(10), 11) 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 return await + 1
self.assertEqual(foo(20), 22) ''',
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 return await + 1
self.assertEqual(foo(20), 22) ''',
def foo(await): '''def foo(await):
"""spam""" """spam"""
async def foo(): \ async def foo(): \
pass pass
# 123 # 123
async def foo(): pass async def foo(): pass
# 456 # 456
return await + 2 return await + 1
self.assertEqual(foo(20), 22) ''',
def foo(await): '''def foo(await):
def foo(): pass def foo(): pass
def foo(): pass def foo(): pass
async def bar(): return await_ async def bar(): return await_
await_ = await await_ = await
try: try:
bar().send(None) bar().send(None)
except StopIteration as ex: except StopIteration as ex:
return ex.args[0] return ex.args[0] + 1
self.assertEqual(foo(42), 42) '''
]
async def f(): for code in samples:
async def g(): pass with self.subTest(code=code):
await z loc = {}
await = 1
self.assertTrue(inspect.iscoroutinefunction(f)) with warnings.catch_warnings():
warnings.simplefilter("ignore")
exec(code, loc, loc)
self.assertEqual(loc['foo'](10), 11)
class TokenizerRegrTest(unittest.TestCase): class TokenizerRegrTest(unittest.TestCase):

View file

@ -1345,18 +1345,6 @@ class GrammarTests(unittest.TestCase):
self.assertEqual(m.other, 42) self.assertEqual(m.other, 42)
def test_async_await(self): 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(): async def test():
def sum(): def sum():
pass pass

View file

@ -353,14 +353,14 @@ class _AsyncDeprecatedProperty:
class DocumentLS: class DocumentLS:
"""Mixin to create documents that conform to the load/save spec.""" """Mixin to create documents that conform to the load/save spec."""
async = _AsyncDeprecatedProperty()
async_ = False async_ = False
locals()['async'] = _AsyncDeprecatedProperty() # Avoid DeprecationWarning
def _get_async(self): def _get_async(self):
return False return False
def _set_async(self, async): def _set_async(self, flag):
if async: if flag:
raise xml.dom.NotSupportedErr( raise xml.dom.NotSupportedErr(
"asynchronous document loading is not supported") "asynchronous document loading is not supported")

View file

@ -21,6 +21,9 @@ Core and Builtins
- Issue #28120: Fix dict.pop() for splitted dictionary when trying to remove a - 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. "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 Library
------- -------

View file

@ -938,6 +938,26 @@ forbidden_name(struct compiling *c, identifier name, const node *n,
ast_error(c, n, "assignment to keyword"); ast_error(c, n, "assignment to keyword");
return 1; 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) { if (full_checks) {
const char * const *p; const char * const *p;
for (p = FORBIDDEN; *p; p++) { for (p = FORBIDDEN; *p; p++) {