Repository: PyCQA/pyflakes (python)

Issue:
Class-level `TypeVar` resulting in "undefined name" error
Minimal sample:
```
from typing import TypeVar


class IdClass:
    Y = TypeVar('Y')

    def id(self, x: Y) -> Y:
        return x
```
Result:
```
# pyflakes t.py 
t.py:7: undefined name 'Y'
```

MyPy supports such typing annotations and does not complain about this file.
Probably this issue is related to similar ones #427 and #126 

Pull request:
fix return annotation is class level variable caused undefined
resolves #441 

Check following code will pyflakes

```Python
class Test:

    def t(self, x) -> Y:
        return x
```

will get

```
t.py:3:23 undefined name 'Y'
t.py:3:23 undefined name 'Y'
```

It will get same error twice. First is in `handleAnnotation`

https://github.com/PyCQA/pyflakes/blob/0b163640274b15b74ac9a650cf24439b0205fc76/pyflakes/checker.py#L1207-L1221

Second is in

https://github.com/PyCQA/pyflakes/blob/0b163640274b15b74ac9a650cf24439b0205fc76/pyflakes/checker.py#L1479-L1483

But in the second situation, it has wrong scope. It will check `FunctionScope` -> `ClassScope` -> `ModuleScope`

So it will cause another problem.

```Python
from typing import TypeVar


class Test:
    Y = TypeVar('Y')

    def t(self, x) -> Y:
        Y = 2
        return x
```

It will report no error here. Because in method `t`'s body, `Y` is defined. But if I remove `Y = 2`, like

```Python
from typing import TypeVar


class Test:
    Y = TypeVar('Y')

    def t(self, x) -> Y:
        return x
```

It will report `t.py:7:23 undefined name 'Y'`. It does not see `Y` which is defined in Class Scope, because

https://github.com/PyCQA/pyflakes/blob/0b163640274b15b74ac9a650cf24439b0205fc76/pyflakes/checker.py#L921-L967

Firstly, it checks `t`' body, but `Y` is not found. Then it will test if this is a `GeneratorScope`. Obviously, it's not. In next scope which is a `ClassScope`, the check will skip, because `in_generator` is `False`.

Patch:
diff --git a/pyflakes/checker.py b/pyflakes/checker.py
index 0e636c1..83f92aa 100644
--- a/pyflakes/checker.py
+++ b/pyflakes/checker.py
@@ -1480,7 +1480,7 @@ class Checker(object):
 
             self.pushScope()
 
-            self.handleChildren(node, omit='decorator_list')
+            self.handleChildren(node, omit=['decorator_list', 'returns'])
 
             def checkUnusedAssignments():
                 """


Test patch:
diff --git a/pyflakes/test/test_type_annotations.py b/pyflakes/test/test_type_annotations.py
index 03f70bb..9c34dcf 100644
--- a/pyflakes/test/test_type_annotations.py
+++ b/pyflakes/test/test_type_annotations.py
@@ -342,3 +342,23 @@ class TestTypeAnnotations(TestCase):
         x = 1
         # type: F
         """)
+
+    @skipIf(version_info < (3,), 'new in Python 3')
+    def test_return_annotation_is_class_scope_variable(self):
+        self.flakes("""
+        from typing import TypeVar
+        class Test:
+            Y = TypeVar('Y')
+
+            def t(self, x: Y) -> Y:
+                return x
+        """)
+
+    @skipIf(version_info < (3,), 'new in Python 3')
+    def test_return_annotation_is_function_body_variable(self):
+        self.flakes("""
+        class Test:
+            def t(self) -> Y:
+                Y = 2
+                return Y
+        """, m.UndefinedName)