Skip to content
Snippets Groups Projects
Unverified Commit eb91b79a authored by Ian Stapleton Cordasco's avatar Ian Stapleton Cordasco Committed by GitHub
Browse files

Merge pull request #684 from jdufresne/async-await

Add W606 warning for async and await keywords in Python 3.7
parents 01ecae5a 1711fb42
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -9,6 +9,8 @@ New checks:
* Add W504 warning for checking that a break doesn't happen after a binary
operator. This check is ignored by default
* Add W605 warning for invalid escape sequences in string literals
* Add W606 warning for 'async' and 'await' reserved keywords being introduced
in Python 3.7
 
2.3.1 (2017-01-31)
------------------
Loading
Loading
Loading
Loading
@@ -419,6 +419,8 @@ This is the current list of error and warning codes:
+------------+----------------------------------------------------------------------+
| W605 | invalid escape sequence '\x' |
+------------+----------------------------------------------------------------------+
| W606 | 'async' and 'await' are reserved keywords starting with Python 3.7 |
+------------+----------------------------------------------------------------------+
 
 
**(*)** In the default configuration, the checks **E121**, **E123**, **E126**,
Loading
Loading
Loading
Loading
@@ -1507,6 +1507,60 @@ def python_3000_invalid_escape_sequence(logical_line, tokens):
pos = string.find('\\', pos + 1)
 
 
@register_check
def python_3000_async_await_keywords(logical_line, tokens):
"""'async' and 'await' are reserved keywords starting with Python 3.7
W606: async = 42
W606: await = 42
Okay: async def read_data(db):\n data = await db.fetch('SELECT ...')
"""
# The Python tokenize library before Python 3.5 recognizes async/await as a
# NAME token. Therefore, use a state machine to look for the possible
# async/await constructs as defined by the Python grammar:
# https://docs.python.org/3/reference/grammar.html
state = None
for token_type, text, start, end, line in tokens:
error = False
if state is None:
if token_type == tokenize.NAME:
if text == 'async':
state = ('async_stmt', start)
elif text == 'await':
state = ('await', start)
elif state[0] == 'async_stmt':
if token_type == tokenize.NAME and text in ('def', 'with', 'for'):
# One of funcdef, with_stmt, or for_stmt. Return to looking
# for async/await names.
state = None
else:
error = True
elif state[0] == 'await':
if token_type in (tokenize.NAME, tokenize.NUMBER, tokenize.STRING):
# An await expression. Return to looking for async/await names.
state = None
else:
error = True
if error:
yield (
state[1],
"W606 'async' and 'await' are reserved keywords starting with "
"Python 3.7",
)
state = None
# Last token
if state is not None:
yield (
state[1],
"W606 'async' and 'await' are reserved keywords starting with "
"Python 3.7",
)
##############################################################################
# Helper functions
##############################################################################
Loading
Loading
Loading
Loading
@@ -29,3 +29,48 @@ regex = r'''
\\.png$
'''
s = '\\'
#: W606
async = 42
#: W606
await = 42
#: W606
def async():
pass
#: W606
def await():
pass
#: W606
class async:
pass
#: W606
class await:
pass
#: Okay
async def read_data(db):
data = await db.fetch('SELECT ...')
#: Okay
if await fut:
pass
if (await fut):
pass
if await fut + 1:
pass
if (await fut) + 1:
pass
pair = await fut, 'spam'
pair = (await fut), 'spam'
with await fut, open():
pass
with (await fut), open():
pass
await foo()['spam'].baz()()
return await coro()
return (await coro())
res = await coro() ** 2
res = (await coro()) ** 2
func(a1=await coro(), a2=0)
func(a1=(await coro()), a2=0)
await foo() + await bar()
(await foo()) + (await bar())
-await foo()
-(await foo())
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment