]> git.madduck.net Git - etc/vim.git/commitdiff

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Blank line between nested and function def in stub files. (#3862)
authorkonsti <konstin@mailbox.org>
Sat, 9 Sep 2023 01:51:27 +0000 (03:51 +0200)
committerGitHub <noreply@github.com>
Sat, 9 Sep 2023 01:51:27 +0000 (18:51 -0700)
The idea behind this change is that we stop looking into previous body to determine if there should be a blank before a function or class definition.

Input:

```python
import sys

if sys.version_info > (3, 7):
    class Nested1:
        assignment = 1
        def function_definition(self): ...
    def f1(self) -> str: ...
    class Nested2:
        def function_definition(self): ...
        assignment = 1
    def f2(self) -> str: ...

if sys.version_info > (3, 7):
    def nested1():
        assignment = 1
        def function_definition(self): ...
    def f1(self) -> str: ...
    def nested2():
        def function_definition(self): ...
        assignment = 1
    def f2(self) -> str: ...
```

Stable style
```python
import sys

if sys.version_info > (3, 7):
    class Nested1:
        assignment = 1
        def function_definition(self): ...

    def f1(self) -> str: ...

    class Nested2:
        def function_definition(self): ...
        assignment = 1
    def f2(self) -> str: ...

if sys.version_info > (3, 7):
    def nested1():
        assignment = 1
        def function_definition(self): ...

    def f1(self) -> str: ...
    def nested2():
        def function_definition(self): ...
        assignment = 1
    def f2(self) -> str: ...
```

In the stable formatting, we have a blank line sometimes, not depending on the previous statement on the same level, but on the last (potentially nested) statement in the previous body.

#2783/#3564 fixes this for classes in preview style:

```python
import sys

if sys.version_info > (3, 7):
    class Nested1:
        assignment = 1
        def function_definition(self): ...

    def f1(self) -> str: ...

    class Nested2:
        def function_definition(self): ...
        assignment = 1

    def f2(self) -> str: ...

if sys.version_info > (3, 7):
    def nested1():
        assignment = 1
        def function_definition(self): ...

    def f1(self) -> str: ...
    def nested2():
        def function_definition(self): ...
        assignment = 1
    def f2(self) -> str: ...
```

This PR additionally fixes this for function definitions:

```python
if sys.version_info > (3, 7):
    if sys.platform == "win32":
        assignment = 1
        def function_definition(self): ...

    def f1(self) -> str: ...
    if sys.platform != "win32":
        def function_definition(self): ...
        assignment = 1

    def f2(self) -> str: ...

if sys.version_info > (3, 8):
    if sys.platform == "win32":
        assignment = 1
        def function_definition(self): ...

    class F1: ...
    if sys.platform != "win32":
        def function_definition(self): ...
        assignment = 1

    class F2: ...
```

You can see the effect of this change on typeshed in https://github.com/konstin/typeshed/pull/1/files. As baseline, the preview mode changes without this PR are at https://github.com/konstin/typeshed/pull/2.

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
CHANGES.md
src/black/lines.py
src/black/mode.py
tests/data/miscellaneous/nested_class_stub.pyi [deleted file]
tests/data/miscellaneous/nested_stub.pyi [new file with mode: 0644]
tests/test_format.py

index 4aa3123fab63ba58b7abc0cc49881134fcc674a7..b0fa5f8745ec84abd65e39a7b265f1011d249ba9 100644 (file)
@@ -171,6 +171,8 @@ expected to become part of Black's stable style in January 2024.
 - For stubs, enforce one blank line after a nested class with a body other than just
   `...` (#3564)
 - Improve handling of multiline strings by changing line split behavior (#1879)
 - For stubs, enforce one blank line after a nested class with a body other than just
   `...` (#3564)
 - Improve handling of multiline strings by changing line split behavior (#1879)
+- In stub files, add a blank line between a statement with a body (e.g an
+  `if sys.version_info > (3, x):`) and a function definition on the same level. (#3862)
 
 ### Parser
 
 
 ### Parser
 
index f3044ce47b89970c8c505b88ad9ba0d9d6f81909..71b657a0654802ef0cc80772981c37907ac9c5d0 100644 (file)
@@ -711,6 +711,17 @@ class EmptyLineTracker:
                     newlines = 0
                 else:
                     newlines = 1
                     newlines = 0
                 else:
                     newlines = 1
+            # Remove case `self.previous_line.depth > current_line.depth` below when
+            # this becomes stable.
+            #
+            # Don't inspect the previous line if it's part of the body of the previous
+            # statement in the same level, we always want a blank line if there's
+            # something with a body preceding.
+            elif (
+                Preview.blank_line_between_nested_and_def_stub_file in current_line.mode
+                and self.previous_line.depth > current_line.depth
+            ):
+                newlines = 1
             elif (
                 current_line.is_def or current_line.is_decorator
             ) and not self.previous_line.is_def:
             elif (
                 current_line.is_def or current_line.is_decorator
             ) and not self.previous_line.is_def:
index 06d20b7a7d668a16e5d846746c8c5da2f18a9c87..8a855ac495aa1b8fbaccc0c427090e08b0a6a108 100644 (file)
@@ -170,6 +170,7 @@ class Preview(Enum):
 
     add_trailing_comma_consistently = auto()
     blank_line_after_nested_stub_class = auto()
 
     add_trailing_comma_consistently = auto()
     blank_line_after_nested_stub_class = auto()
+    blank_line_between_nested_and_def_stub_file = auto()
     hex_codes_in_unicode_sequences = auto()
     improved_async_statements_handling = auto()
     multiline_string_handling = auto()
     hex_codes_in_unicode_sequences = auto()
     improved_async_statements_handling = auto()
     multiline_string_handling = auto()
diff --git a/tests/data/miscellaneous/nested_class_stub.pyi b/tests/data/miscellaneous/nested_class_stub.pyi
deleted file mode 100644 (file)
index daf281b..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-class Outer:
-    class InnerStub: ...
-    outer_attr_after_inner_stub: int
-    class Inner:
-        inner_attr: int
-    outer_attr: int
-
-# output
-class Outer:
-    class InnerStub: ...
-    outer_attr_after_inner_stub: int
-
-    class Inner:
-        inner_attr: int
-
-    outer_attr: int
diff --git a/tests/data/miscellaneous/nested_stub.pyi b/tests/data/miscellaneous/nested_stub.pyi
new file mode 100644 (file)
index 0000000..15e69d8
--- /dev/null
@@ -0,0 +1,43 @@
+import sys
+
+class Outer:
+    class InnerStub: ...
+    outer_attr_after_inner_stub: int
+    class Inner:
+        inner_attr: int
+    outer_attr: int
+
+if sys.version_info > (3, 7):
+    if sys.platform == "win32":
+        assignment = 1
+        def function_definition(self): ...
+    def f1(self) -> str: ...
+    if sys.platform != "win32":
+        def function_definition(self): ...
+        assignment = 1
+    def f2(self) -> str: ...
+
+# output
+
+import sys
+
+class Outer:
+    class InnerStub: ...
+    outer_attr_after_inner_stub: int
+
+    class Inner:
+        inner_attr: int
+
+    outer_attr: int
+
+if sys.version_info > (3, 7):
+    if sys.platform == "win32":
+        assignment = 1
+        def function_definition(self): ...
+
+    def f1(self) -> str: ...
+    if sys.platform != "win32":
+        def function_definition(self): ...
+        assignment = 1
+
+    def f2(self) -> str: ...
\ No newline at end of file
index 0650a2d6e53aa710c91f6395810acea43c9e0bac..f3db423b6371df0ca5c6e3692046c92bf5250777 100644 (file)
@@ -201,9 +201,9 @@ def test_stub() -> None:
     assert_format(source, expected, mode)
 
 
     assert_format(source, expected, mode)
 
 
-def test_nested_class_stub() -> None:
+def test_nested_stub() -> None:
     mode = replace(DEFAULT_MODE, is_pyi=True, preview=True)
     mode = replace(DEFAULT_MODE, is_pyi=True, preview=True)
-    source, expected = read_data("miscellaneous", "nested_class_stub.pyi")
+    source, expected = read_data("miscellaneous", "nested_stub.pyi")
     assert_format(source, expected, mode)
 
 
     assert_format(source, expected, mode)