diff options
author | Ćukasz Langa <lukasz@langa.pl> | 2017-01-06 17:36:27 -0800 |
---|---|---|
committer | Ian Cordasco <sigmavirus24@users.noreply.github.com> | 2017-01-06 19:36:27 -0600 |
commit | dae4fa70d8d5fd98e81ceb72c007c0c60725dfec (patch) | |
tree | 570c96da9ef3dae3e8a1da8fe8f4a480e555bab8 | |
parent | 34a06960aa2621cbacd8e41db4e0ebe6e324dc5a (diff) | |
download | pyflakes-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.py | 18 | ||||
-rw-r--r-- | pyflakes/test/test_other.py | 61 |
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) |