Repository: PyCQA/pyflakes (python)

Issue:
crash: AttributeError: 'Module' object has no attribute 'parent'
9dd73ec54411a563410872b47e76f0f89f34ecfe seems to introduce a bug that causes pyflakes to crash on this code:

```python3
class foo:
    pass


async def func(foo: foo):
    pass
```

**backtrace:**
```
$ venv/bin/pyflakes foo.py                  
Traceback (most recent call last):
  File "venv/bin/pyflakes", line 11, in <module>
    sys.exit(main())
  File "venv/lib/python3.7/site-packages/pyflakes/api.py", line 207, in main
    warnings = checkRecursive(args, reporter)
  File "venv/lib/python3.7/site-packages/pyflakes/api.py", line 156, in checkRecursive
    warnings += checkPath(sourcePath, reporter)
  File "venv/lib/python3.7/site-packages/pyflakes/api.py", line 99, in checkPath
    return check(codestr, filename, reporter)
  File "venv/lib/python3.7/site-packages/pyflakes/api.py", line 74, in check
    w = checker.Checker(tree, filename)
  File "venv/lib/python3.7/site-packages/pyflakes/checker.py", line 579, in __init__
    self.runDeferred(self._deferredFunctions)
  File "venv/lib/python3.7/site-packages/pyflakes/checker.py", line 616, in runDeferred
    handler()
  File "venv/lib/python3.7/site-packages/pyflakes/checker.py", line 1354, in runFunction 
    self.handleChildren(node, omit='decorator_list')
  File "venv/lib/python3.7/site-packages/pyflakes/checker.py", line 957, in handleChildren
    self.handleNode(node, tree)
  File "venv/lib/python3.7/site-packages/pyflakes/checker.py", line 1004, in handleNode
    handler(node)
  File "venv/lib/python3.7/site-packages/pyflakes/checker.py", line 1379, in ARGUMENTS
    self.handleChildren(node, omit=('defaults', 'kw_defaults'))
  File "venv/lib/python3.7/site-packages/pyflakes/checker.py", line 957, in handleChildren
    self.handleNode(node, tree)
  File "venv/lib/python3.7/site-packages/pyflakes/checker.py", line 1004, in handleNode
    handler(node)
  File "venv/lib/python3.7/site-packages/pyflakes/checker.py", line 1388, in ARG
    self.addBinding(node, Argument(node.arg, self.getScopeNode(node)))
  File "venv/lib/python3.7/site-packages/pyflakes/checker.py", line 784, in addBinding
    parent_stmt = self.getParent(value.source)
  File "venv/lib/python3.7/site-packages/pyflakes/checker.py", line 722, in getParent
    node = node.parent
AttributeError: 'Module' object has no attribute 'parent'
```

**version:**

  * debian/unstable
  * python3.7 (from debian)
  * pyflakes 066ba4a93c1077f9154d6ff3806fe1e3a66843a1

Pull request description:
Set the proper scope for `async def`
Resolves #401

Patch:
diff --git a/pyflakes/checker.py b/pyflakes/checker.py
index 3c4fa0f..e94bc71 100644
--- a/pyflakes/checker.py
+++ b/pyflakes/checker.py
@@ -20,6 +20,7 @@ from pyflakes import messages
 PY2 = sys.version_info < (3, 0)
 PY35_PLUS = sys.version_info >= (3, 5)    # Python 3.5 and above
 PY36_PLUS = sys.version_info >= (3, 6)    # Python 3.6 and above
+PY38_PLUS = sys.version_info >= (3, 8)
 try:
     sys.pypy_version_info
     PYPY = True
@@ -618,6 +619,8 @@ class Checker(object):
         ast.GeneratorExp: GeneratorScope,
         ast.DictComp: GeneratorScope,
     }
+    if PY35_PLUS:
+        _ast_node_scope[ast.AsyncFunctionDef] = FunctionScope,
 
     nodeDepth = 0
     offset = None
@@ -1073,7 +1076,7 @@ class Checker(object):
         if not isinstance(node, ast.Str):
             return (None, None)
 
-        if PYPY:
+        if PYPY or PY38_PLUS:
             doctest_lineno = node.lineno - 1
         else:
             # Computed incorrectly if the docstring has backslash


Test patch:
diff --git a/pyflakes/test/test_type_annotations.py b/pyflakes/test/test_type_annotations.py
index e828412..1ed676b 100644
--- a/pyflakes/test/test_type_annotations.py
+++ b/pyflakes/test/test_type_annotations.py
@@ -179,6 +179,13 @@ class TestTypeAnnotations(TestCase):
         a: 'a: "A"'
         ''', m.ForwardAnnotationSyntaxError)
 
+    @skipIf(version_info < (3, 5), 'new in Python 3.5')
+    def test_annotated_async_def(self):
+        self.flakes('''
+        class c: pass
+        async def func(c: c) -> None: pass
+        ''')
+
     @skipIf(version_info < (3, 7), 'new in Python 3.7')
     def test_postponed_annotations(self):
         self.flakes('''