summaryrefslogtreecommitdiff
path: root/pycodestyle.py
diff options
context:
space:
mode:
Diffstat (limited to 'pycodestyle.py')
-rwxr-xr-xpycodestyle.py54
1 files changed, 54 insertions, 0 deletions
diff --git a/pycodestyle.py b/pycodestyle.py
index 7131f2a..5f02187 100755
--- a/pycodestyle.py
+++ b/pycodestyle.py
@@ -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
##############################################################################