summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorƁukasz Langa <lukasz@langa.pl>2017-01-06 17:36:27 -0800
committerIan Cordasco <sigmavirus24@users.noreply.github.com>2017-01-06 19:36:27 -0600
commitdae4fa70d8d5fd98e81ceb72c007c0c60725dfec (patch)
tree570c96da9ef3dae3e8a1da8fe8f4a480e555bab8
parent34a06960aa2621cbacd8e41db4e0ebe6e324dc5a (diff)
downloadpyflakes-dae4fa70d8d5fd98e81ceb72c007c0c60725dfec.tar.gz
Enable support for PEP 526 annotated assignments (#84)
Without this change, code with annotated assignments is crashing pyflakes with an attribute error (`object has no attribute 'ANNASSIGN'`). Test plan: new tests introduced conforming to behavior described in the PEP.
-rw-r--r--pyflakes/checker.py18
-rw-r--r--pyflakes/test/test_other.py61
2 files changed, 79 insertions, 0 deletions
diff --git a/pyflakes/checker.py b/pyflakes/checker.py
index caa9db5..3e8dc8d 100644
--- a/pyflakes/checker.py
+++ b/pyflakes/checker.py
@@ -1335,3 +1335,21 @@ class Checker(object):
del self.scope[node.name]
except KeyError:
pass
+
+ def ANNASSIGN(self, node):
+ """
+ Annotated assignments don't have annotations evaluated on function
+ scope, hence the custom implementation.
+
+ See: PEP 526.
+ """
+ if node.value:
+ # Only bind the *targets* if the assignment has a value.
+ # Otherwise it's not really ast.Store and shouldn't silence
+ # UndefinedLocal warnings.
+ self.handleNode(node.target, node)
+ if not isinstance(self.scope, FunctionScope):
+ self.handleNode(node.annotation, node)
+ if node.value:
+ # If the assignment has value, handle the *value* now.
+ self.handleNode(node.value, node)
diff --git a/pyflakes/test/test_other.py b/pyflakes/test/test_other.py
index 109bc66..6f02001 100644
--- a/pyflakes/test/test_other.py
+++ b/pyflakes/test/test_other.py
@@ -1808,3 +1808,64 @@ class TestAsyncStatements(TestCase):
mom = 'mom'
f'{hi} {mom}'
''')
+
+ @skipIf(version_info < (3, 6), 'new in Python 3.6')
+ def test_variable_annotations(self):
+ self.flakes('''
+ name: str
+ age: int
+ ''')
+ self.flakes('''
+ name: str = 'Bob'
+ age: int = 18
+ ''')
+ self.flakes('''
+ class C:
+ name: str
+ age: int
+ ''')
+ self.flakes('''
+ class C:
+ name: str = 'Bob'
+ age: int = 18
+ ''')
+ self.flakes('''
+ def f():
+ name: str
+ age: int
+ ''')
+ self.flakes('''
+ def f():
+ name: str = 'Bob'
+ age: int = 18
+ foo: not_a_real_type = None
+ ''', m.UnusedVariable, m.UnusedVariable, m.UnusedVariable)
+ self.flakes('''
+ def f():
+ name: str
+ print(name)
+ ''', m.UndefinedName)
+ self.flakes('''
+ foo: not_a_real_type
+ ''', m.UndefinedName)
+ self.flakes('''
+ foo: not_a_real_type = None
+ ''', m.UndefinedName)
+ self.flakes('''
+ class C:
+ foo: not_a_real_type
+ ''', m.UndefinedName)
+ self.flakes('''
+ class C:
+ foo: not_a_real_type = None
+ ''', m.UndefinedName)
+ self.flakes('''
+ def f():
+ class C:
+ foo: not_a_real_type
+ ''', m.UndefinedName)
+ self.flakes('''
+ def f():
+ class C:
+ foo: not_a_real_type = None
+ ''', m.UndefinedName)