diff options
author | Jörn Heissler <joernheissler@users.noreply.github.com> | 2018-12-22 16:57:51 +0100 |
---|---|---|
committer | Ian Stapleton Cordasco <graffatcolmingov@gmail.com> | 2018-12-22 09:57:51 -0600 |
commit | 6ee966df7e1973771f578bb6d5d041785a0685ec (patch) | |
tree | 000b3a68b449fff9eb479659637dcbcf367f92a3 | |
parent | c6cc4b625b41683db8ff5287947c64744e8bae2b (diff) | |
download | pyflakes-6ee966df7e1973771f578bb6d5d041785a0685ec.tar.gz |
Add support for PEP 563 (#356) (#374)
* Test with py3.7; Travis should use Xenial for 3.7 and nightly.
* Add support for PEP 563 (#356)
If a module imports annotations from __future__, postpone the evaluation
of annotations like it is done for annotation strings.
-rw-r--r-- | pyflakes/checker.py | 18 | ||||
-rw-r--r-- | pyflakes/test/test_other.py | 18 |
2 files changed, 36 insertions, 0 deletions
diff --git a/pyflakes/checker.py b/pyflakes/checker.py index 5c12820..e05bdf4 100644 --- a/pyflakes/checker.py +++ b/pyflakes/checker.py @@ -476,6 +476,7 @@ class GeneratorScope(Scope): class ModuleScope(Scope): """Scope for a module.""" _futures_allowed = True + _annotations_future_enabled = False class DoctestScope(ModuleScope): @@ -629,6 +630,19 @@ class Checker(object): self.scope._futures_allowed = False @property + def annotationsFutureEnabled(self): + scope = self.scopeStack[0] + if not isinstance(scope, ModuleScope): + return False + return scope._annotations_future_enabled + + @annotationsFutureEnabled.setter + def annotationsFutureEnabled(self, value): + assert value is True + assert isinstance(self.scope, ModuleScope) + self.scope._annotations_future_enabled = True + + @property def scope(self): return self.scopeStack[-1] @@ -1068,6 +1082,8 @@ class Checker(object): self.handleNode(parsed_annotation, node) self.deferFunction(handleForwardAnnotation) + elif self.annotationsFutureEnabled: + self.deferFunction(lambda: self.handleNode(annotation, node)) else: self.handleNode(annotation, node) @@ -1448,6 +1464,8 @@ class Checker(object): if alias.name not in __future__.all_feature_names: self.report(messages.FutureFeatureNotDefined, node, alias.name) + if alias.name == 'annotations': + self.annotationsFutureEnabled = True elif alias.name == '*': # Only Python 2, local import * is a SyntaxWarning if not PY2 and not isinstance(self.scope, ModuleScope): diff --git a/pyflakes/test/test_other.py b/pyflakes/test/test_other.py index b8301ea..d0fff0a 100644 --- a/pyflakes/test/test_other.py +++ b/pyflakes/test/test_other.py @@ -2055,6 +2055,24 @@ class TestAsyncStatements(TestCase): a: 'a: "A"' ''', m.ForwardAnnotationSyntaxError) + @skipIf(version_info < (3, 7), 'new in Python 3.7') + def test_postponed_annotations(self): + self.flakes(''' + from __future__ import annotations + def f(a: A) -> A: pass + class A: + b: B + class B: pass + ''') + + self.flakes(''' + from __future__ import annotations + def f(a: A) -> A: pass + class A: + b: Undefined + class B: pass + ''', m.UndefinedName) + def test_raise_notimplemented(self): self.flakes(''' raise NotImplementedError("This is fine") |