Repository: asottile/pyupgrade

Issue:
Should not rewrite to `yield from` inside `async def`
oops, totally forgot about this.

Currently this is happening but this is forbidden by [PEP 525](https://www.python.org/dev/peps/pep-0525/#asynchronous-yield-from)

```diff
 async def f():
-    for x in y:
-        yield x
+    yield from y
```

Discussion:

Patch:
diff --git a/pyupgrade.py b/pyupgrade.py
index 7313835..cc8dc38 100644
--- a/pyupgrade.py
+++ b/pyupgrade.py
@@ -1023,6 +1023,7 @@ class FindPy3Plus(ast.NodeVisitor):
         self._class_info_stack = []
         self._in_comp = 0
         self.super_calls = {}
+        self._in_async_def = False
         self.yield_from_fors = set()
 
     def _is_six(self, node, names):
@@ -1101,7 +1102,17 @@ class FindPy3Plus(ast.NodeVisitor):
         else:
             self.generic_visit(node)
 
-    visit_FunctionDef = visit_Lambda = _visit_func
+    def _visit_sync_func(self, node):
+        self._in_async_def, orig = False, self._in_async_def
+        self._visit_func(node)
+        self._in_async_def = orig
+
+    visit_FunctionDef = visit_Lambda = _visit_sync_func
+
+    def visit_AsyncFunctionDef(self, node):  # pragma: no cover (py35+)
+        self._in_async_def, orig = True, self._in_async_def
+        self._visit_func(node)
+        self._in_async_def = orig
 
     def _visit_comp(self, node):
         self._in_comp += 1
@@ -1235,6 +1246,7 @@ class FindPy3Plus(ast.NodeVisitor):
 
     def visit_For(self, node):  # type: (ast.For) -> None
         if (
+            not self._in_async_def and
             len(node.body) == 1 and
             isinstance(node.body[0], ast.Expr) and
             isinstance(node.body[0].value, ast.Yield) and
@@ -1541,9 +1553,6 @@ def _fix_py3_plus(contents_text):
         else:
             j = i
             while tokens[j].src != node.attr:
-                # timid: if we see a parenthesis here, skip it
-                if tokens[j].src == ')':
-                    return
                 j += 1
             tokens[i:j + 1] = [new_token]
 


Test patch:
diff --git a/tests/pyupgrade_test.py b/tests/pyupgrade_test.py
index ef78b95..cf45171 100644
--- a/tests/pyupgrade_test.py
+++ b/tests/pyupgrade_test.py
@@ -1102,10 +1102,6 @@ def test_fix_classes(s, expected):
         'class C(six.with_metaclass(*a)): pass',
         '@six.add_metaclass(*a)\n'
         'class C: pass\n',
-        # parenthesized part of attribute
-        '(\n'
-        '    six\n'
-        ').text_type(u)\n',
     ),
 )
 def test_fix_six_noop(s):
@@ -1540,6 +1536,44 @@ def test_fix_yield_from(s, expected):
     assert _fix_py3_plus(s) == expected
 
 
+@pytest.mark.xfail(
+    sys.version_info < (3, 5),
+    reason='async introduced in python 3.5',
+)
+@pytest.mark.parametrize(
+    ('s', 'expected'),
+    (
+        (
+            'async def f():\n'
+            '    for x in [1, 2]:\n'
+            '        yield x\n'
+            '\n'
+            '    def g():\n'
+            '        for x in [1, 2, 3]:\n'
+            '            yield x\n'
+            '\n'
+            '    for x in [1, 2]:\n'
+            '        yield x\n'
+            '\n'
+            '    return g',
+            'async def f():\n'
+            '    for x in [1, 2]:\n'
+            '        yield x\n'
+            '\n'
+            '    def g():\n'
+            '        yield from [1, 2, 3]\n'
+            '\n'
+            '    for x in [1, 2]:\n'
+            '        yield x\n'
+            '\n'
+            '    return g',
+        ),
+    ),
+)
+def test_fix_async_yield_from(s, expected):
+    assert _fix_py3_plus(s) == expected
+
+
 @pytest.mark.parametrize(
     's',
     (