Repository: google/yapf
Pull request #779 (2019-11-13 07:54:11)

Fix async for else indentation
Previously:

    async def fn():
        async for message in websocket:
            pass
        else:
            pass

was indented as:

    async def fn():
        async for message in websocket:
            pass
            else:
            pass

which breaks the code and crashes any further runs of yapf on that
codebase because of parse errors.

Fixes issue #622 

googlebot: 
Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

:memo: **Please visit <https://cla.developers.google.com/> to sign.**

Once you've signed (or fixed any issues), please reply here with `@googlebot I signed it!` and we'll verify it.

----

#### What to do if you already signed the CLA

##### Individual signers

*   It's possible we don't have your GitHub username or you're using a different email address on your commit. Check [your existing CLA data](https://cla.developers.google.com/clas) and verify that your [email is set on your git commits](https://help.github.com/articles/setting-your-email-in-git/).

##### Corporate signers

*   Your company has a Point of Contact who decides which employees are authorized to participate. Ask your POC to be added to the group of authorized contributors. If you don't know who your Point of Contact is, direct the Google project maintainer to [go/cla#troubleshoot](http://go/cla#troubleshoot) ([Public version](https://opensource.google/docs/cla/#troubleshoot)).
*   The email used to register you as an authorized contributor must be the email used for the Git commit. Check [your existing CLA data](https://cla.developers.google.com/clas) and verify that your [email is set on your git commits](https://help.github.com/articles/setting-your-email-in-git/).
*   The email used to register you as an authorized contributor must also be [attached to your GitHub account](https://github.com/settings/emails).
		

ℹ️ **Googlers: [Go here](https://goto.google.com/prinfo/https%3A%2F%2Fgithub.com%2Fgoogle%2Fyapf%2Fpull%2F779) for more info**.

<!-- need_sender_cla -->
Kaali: @googlebot I signed it!
googlebot: CLAs look good, thanks!

ℹ️ **Googlers: [Go here](https://goto.google.com/prinfo/https%3A%2F%2Fgithub.com%2Fgoogle%2Fyapf%2Fpull%2F779) for more info**.

<!-- ok -->

Patch:
diff --git a/CHANGELOG b/CHANGELOG
index 2195884..1f3002d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -19,6 +19,7 @@
 - Make sure we have parameters before we start calculating penalties for
   splitting them.
 - Indicate if a class/function is nested to ensure blank lines when needed.
+- Fix extra indentation in async-for else statement.
 
 ## [0.28.0] 2019-07-11
 ### Added
diff --git a/yapf/yapflib/pytree_unwrapper.py b/yapf/yapflib/pytree_unwrapper.py
index f4d9cba..c7e32a3 100644
--- a/yapf/yapflib/pytree_unwrapper.py
+++ b/yapf/yapflib/pytree_unwrapper.py
@@ -224,6 +224,8 @@ class PyTreeUnwrapper(pytree_visitor.PyTreeVisitor):
       if pytree_utils.NodeName(child) == 'ASYNC':
         break
     for child in node.children[index].children:
+      if pytree_utils.NodeName(child) == 'NAME' and child.value == 'else':
+        self._StartNewLine()
       self.Visit(child)
 
   def Visit_decorator(self, node):  # pylint: disable=invalid-name


Test patch:
diff --git a/yapftests/reformatter_python3_test.py b/yapftests/reformatter_python3_test.py
index ff7bf74..83f6a70 100644
--- a/yapftests/reformatter_python3_test.py
+++ b/yapftests/reformatter_python3_test.py
@@ -398,6 +398,35 @@ def rrrrrrrrrrrrrrrrrrrrrr(
     uwlines = yapf_test_helper.ParseAndUnwrap(code)
     self.assertCodeEqual(code, reformatter.Reformat(uwlines))
 
+  def testAsyncForElseNotIndentedInsideBody(self):
+    if sys.version_info[1] < 5:
+      return
+    code = textwrap.dedent("""\
+    async def fn():
+        async for message in websocket:
+            for i in range(10):
+                pass
+            else:
+                pass
+        else:
+            pass
+    """)
+    uwlines = yapf_test_helper.ParseAndUnwrap(code)
+    self.assertCodeEqual(code, reformatter.Reformat(uwlines))
+
+  def testForElseInAsyncNotMixedWithAsyncFor(self):
+    if sys.version_info[1] < 5:
+      return
+    code = textwrap.dedent("""\
+    async def fn():
+        for i in range(10):
+            pass
+        else:
+            pass
+    """)
+    uwlines = yapf_test_helper.ParseAndUnwrap(code)
+    self.assertCodeEqual(code, reformatter.Reformat(uwlines))
+
 
 if __name__ == '__main__':
   unittest.main()