Repository: psf/black

Issue:
`blank_line_after_nested_stub_class`: Doesn't work if previous line is function def
**Describe the bug**

This is regarding the `blank_line_after_nested_stub_class` preview style. If the class body ends with a function definition with ellipsis, it fails to recognize to add the blank line.

**To Reproduce**

For example, take this code and add it to a `file.pyi` stub file:

```python
class TopLevel:
    class Nested1:
        foo: int
        def bar(self): ...
    field = 1

    class Nested2:
        def bar(self): ...
        foo: int
    field = 1
```

And run it with these arguments:

```sh
$ black file.pyi
```

The resulting code is:

```python
class TopLevel:
    class Nested1:
        foo: int
        def bar(self): ...
    field = 1

    class Nested2:
        def bar(self): ...
        foo: int

    field = 1
```

Notice that the blank line is added only after `Nested2` and not after `Nested`.

**Expected behavior**

Expected the blank line to be added after both `Nested1` and `Nested2`.

**Environment**

- Black's version: `24.1a1`
- OS and Python version: MacOS/Python 3.11.3

**Additional context**

The problem seems to be the first `if` condition here:

https://github.com/psf/black/blob/8fec1c30855890cc9cfce5ae6d633a1c1a21d724/src/black/lines.py#L632-L641

I think the solution would be to switch the condition such that the `elif` is checked first.



Discussion:

Resolving patch:
diff --git a/src/black/lines.py b/src/black/lines.py
--- a/src/black/lines.py
+++ b/src/black/lines.py
@@ -640,15 +640,15 @@ def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
         if previous_def is not None:
             assert self.previous_line is not None
             if self.mode.is_pyi:
-                if depth and not current_line.is_def and self.previous_line.is_def:
-                    # Empty lines between attributes and methods should be preserved.
-                    before = 1 if user_had_newline else 0
-                elif (
+                if (
                     Preview.blank_line_after_nested_stub_class in self.mode
                     and previous_def.is_class
                     and not previous_def.is_stub_class
                 ):
                     before = 1
+                elif depth and not current_line.is_def and self.previous_line.is_def:
+                    # Empty lines between attributes and methods should be preserved.
+                    before = 1 if user_had_newline else 0
                 elif depth:
                     before = 0
                 else:


Test patch:
diff --git a/tests/data/cases/nested_stub.py b/tests/data/cases/nested_stub.py
--- a/tests/data/cases/nested_stub.py
+++ b/tests/data/cases/nested_stub.py
@@ -18,6 +18,18 @@ def function_definition(self): ...
         assignment = 1
     def f2(self) -> str: ...
 
+
+class TopLevel:
+    class Nested1:
+        foo: int
+        def bar(self): ...
+    field = 1
+
+    class Nested2:
+        def bar(self): ...
+        foo: int
+    field = 1
+
 # output
 
 import sys
@@ -41,4 +53,17 @@ def f1(self) -> str: ...
         def function_definition(self): ...
         assignment = 1
 
-    def f2(self) -> str: ...
\ No newline at end of file
+    def f2(self) -> str: ...
+
+class TopLevel:
+    class Nested1:
+        foo: int
+        def bar(self): ...
+
+    field = 1
+
+    class Nested2:
+        def bar(self): ...
+        foo: int
+
+    field = 1