Repository: google/yapf

Issue:
yapf 0.28.0 now removes blank line between class docstring and first function
Given this code:

```python
class Foo:
    """Cool class"""

    def bar(self):
        """Cool function"""
        pass
```

yapf 0.28.0 now removes the line after `"""Cool class"""`, which makes `pydocstyle` complain with:
> D204: 1 blank line required after class docstring

Yapf 0.27.0 keeps this blank line.

Comments:

Patch:
diff --git a/CHANGELOG b/CHANGELOG
index a35ce68..4cecbd3 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -6,6 +6,10 @@
 ### Added
 - Look at the 'pyproject.toml' file to see if it contains ignore file information
   for YAPF.
+### Fixed
+- Enable `BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF` knob for "pep8" style, so
+  method definitions inside a class are surrounded by a single blank line as
+  prescribed by PEP8.
 
 ## [0.31.0] 2021-03-14
 ### Added
diff --git a/yapf/yapflib/style.py b/yapf/yapflib/style.py
index 3d27109..a1e6940 100644
--- a/yapf/yapflib/style.py
+++ b/yapf/yapflib/style.py
@@ -418,7 +418,7 @@ def CreatePEP8Style():
       ALLOW_SPLIT_BEFORE_DEFAULT_OR_NAMED_ASSIGNS=True,
       ALLOW_SPLIT_BEFORE_DICT_VALUE=True,
       ARITHMETIC_PRECEDENCE_INDICATION=False,
-      BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF=False,
+      BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF=True,
       BLANK_LINE_BEFORE_CLASS_DOCSTRING=False,
       BLANK_LINE_BEFORE_MODULE_DOCSTRING=False,
       BLANK_LINES_AROUND_TOP_LEVEL_DEFINITION=2,
@@ -479,7 +479,6 @@ def CreateGoogleStyle():
   """Create the Google formatting style."""
   style = CreatePEP8Style()
   style['ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT'] = False
-  style['BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF'] = True
   style['COLUMN_LIMIT'] = 80
   style['INDENT_DICTIONARY_VALUE'] = True
   style['INDENT_WIDTH'] = 4
@@ -511,6 +510,7 @@ def CreateFacebookStyle():
   """Create the Facebook formatting style."""
   style = CreatePEP8Style()
   style['ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT'] = False
+  style['BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF'] = False
   style['COLUMN_LIMIT'] = 80
   style['DEDENT_CLOSING_BRACKETS'] = True
   style['INDENT_CLOSING_BRACKETS'] = False


Test patch:
diff --git a/yapftests/reformatter_basic_test.py b/yapftests/reformatter_basic_test.py
index a67e4c4..8dce567 100644
--- a/yapftests/reformatter_basic_test.py
+++ b/yapftests/reformatter_basic_test.py
@@ -1982,6 +1982,7 @@ class A(object):
   def testStableDictionaryFormatting(self):
     code = textwrap.dedent("""\
         class A(object):
+
           def method(self):
             filters = {
                 'expressions': [{
diff --git a/yapftests/reformatter_pep8_test.py b/yapftests/reformatter_pep8_test.py
index a5301f1..e1202c2 100644
--- a/yapftests/reformatter_pep8_test.py
+++ b/yapftests/reformatter_pep8_test.py
@@ -50,22 +50,22 @@ class TestsForPEP8Style(yapf_test_helper.YAPFTest):
     uwlines = yapf_test_helper.ParseAndUnwrap(code)
     self.assertCodeEqual(code, reformatter.Reformat(uwlines))
 
-  def testNoBlankBetweenClassAndDef(self):
+  def testBlankBetweenClassAndDef(self):
     unformatted_code = textwrap.dedent("""\
         class Foo:
-
           def joe():
             pass
         """)
     expected_formatted_code = textwrap.dedent("""\
         class Foo:
+
             def joe():
                 pass
         """)
     uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code)
     self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(uwlines))
 
-  def testNoBlankBetweenDefsInClass(self):
+  def testBlankBetweenDefsInClass(self):
     unformatted_code = textwrap.dedent('''\
         class TestClass:
             def __init__(self):
@@ -77,6 +77,7 @@ class TestsForPEP8Style(yapf_test_helper.YAPFTest):
         ''')
     expected_formatted_code = textwrap.dedent('''\
         class TestClass:
+
             def __init__(self):
                 self.running = False
 
@@ -174,6 +175,7 @@ class TestsForPEP8Style(yapf_test_helper.YAPFTest):
         """)
     expected_formatted_code = textwrap.dedent("""\
         def f():
+
             def g():
                 while (xxxxxxxxxxxxxxxxxxxx(yyyyyyyyyyyyy[zzzzz]) == 'aaaaaaaaaaa'
                        and xxxxxxxxxxxxxxxxxxxx(
@@ -341,11 +343,13 @@ class TestsForPEP8Style(yapf_test_helper.YAPFTest):
   def testSplitAroundNamedAssigns(self):
     unformatted_code = textwrap.dedent("""\
         class a():
+
             def a(): return a(
              aaaaaaaaaa=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)
         """)
     expected_formatted_code = textwrap.dedent("""\
         class a():
+
             def a():
                 return a(
                     aaaaaaaaaa=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
@@ -501,6 +505,7 @@ class Demo:
     """
     Demo docs
     """
+
     def foo(self):
         """
         foo docs
@@ -602,6 +607,7 @@ class _():
         """)
     expected_formatted_code = textwrap.dedent("""\
 class _():
+
     def __init__(
             self,
             title: Optional[str],
diff --git a/yapftests/reformatter_python3_test.py b/yapftests/reformatter_python3_test.py
index d06e406..ae55755 100644
--- a/yapftests/reformatter_python3_test.py
+++ b/yapftests/reformatter_python3_test.py
@@ -238,6 +238,7 @@ None.__ne__()
       return
     code = textwrap.dedent("""\
         async def outer():
+
             async def inner():
                 pass
         """)
@@ -365,6 +366,7 @@ class Foo:
 """
     expected_formatted_code = """\
 class Foo:
+
     def foo(self):
         foofoofoofoofoofoofoofoo('foofoofoofoofoo', {
             'foo': 'foo',
diff --git a/yapftests/yapf_test.py b/yapftests/yapf_test.py
index dc0d0a5..4e062cf 100644
--- a/yapftests/yapf_test.py
+++ b/yapftests/yapf_test.py
@@ -735,12 +735,14 @@ class CommandLineTest(unittest.TestCase):
   def testDisableButAdjustIndentations(self):
     unformatted_code = textwrap.dedent("""\
         class SplitPenaltyTest(unittest.TestCase):
+
           def testUnbreakable(self):
             self._CheckPenalties(tree, [
             ])  # yapf: disable
         """)
     expected_formatted_code = textwrap.dedent("""\
         class SplitPenaltyTest(unittest.TestCase):
+
             def testUnbreakable(self):
                 self._CheckPenalties(tree, [
                 ])  # yapf: disable