Skip to content

Commit 9e1cc30

Browse files
committed
Blank line between nested and function def in stub files.
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. psf#2783/psf#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 konstin/typeshed#2.
1 parent 8daa64a commit 9e1cc30

File tree

6 files changed

+59
-18
lines changed

6 files changed

+59
-18
lines changed

CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ expected to become part of Black's stable style in January 2024.
170170
- For stubs, enforce one blank line after a nested class with a body other than just
171171
`...` (#3564)
172172
- Improve handling of multiline strings by changing line split behavior (#1879)
173+
- In stub files, add a blank line between a statement with a body (e.g an
174+
`if sys.version_info > (3, x):`) and a function definition on the same level. (#3862)
173175

174176
### Parser
175177

src/black/lines.py

+11
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,17 @@ def _maybe_empty_lines_for_class_or_def( # noqa: C901
709709
newlines = 0
710710
else:
711711
newlines = 1
712+
# Remove case `self.previous_line.depth > current_line.depth` below when
713+
# this becomes stable.
714+
#
715+
# Don't inspect the previous line if it's part of the body of the previous
716+
# statement in the same level, we always want a blank line if there's
717+
# something with a body preceding.
718+
elif (
719+
Preview.blank_line_between_nested_and_def_stub_file
720+
and self.previous_line.depth > current_line.depth
721+
):
722+
newlines = 1
712723
elif (
713724
current_line.is_def or current_line.is_decorator
714725
) and not self.previous_line.is_def:

src/black/mode.py

+1
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ class Preview(Enum):
170170

171171
add_trailing_comma_consistently = auto()
172172
blank_line_after_nested_stub_class = auto()
173+
blank_line_between_nested_and_def_stub_file = auto()
173174
hex_codes_in_unicode_sequences = auto()
174175
improved_async_statements_handling = auto()
175176
multiline_string_handling = auto()

tests/data/miscellaneous/nested_class_stub.pyi

-16
This file was deleted.
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import sys
2+
3+
class Outer:
4+
class InnerStub: ...
5+
outer_attr_after_inner_stub: int
6+
class Inner:
7+
inner_attr: int
8+
outer_attr: int
9+
10+
if sys.version_info > (3, 7):
11+
if sys.platform == "win32":
12+
assignment = 1
13+
def function_definition(self): ...
14+
def f1(self) -> str: ...
15+
if sys.platform != "win32":
16+
def function_definition(self): ...
17+
assignment = 1
18+
def f2(self) -> str: ...
19+
20+
# output
21+
22+
import sys
23+
24+
class Outer:
25+
class InnerStub: ...
26+
outer_attr_after_inner_stub: int
27+
28+
class Inner:
29+
inner_attr: int
30+
31+
outer_attr: int
32+
33+
if sys.version_info > (3, 7):
34+
if sys.platform == "win32":
35+
assignment = 1
36+
def function_definition(self): ...
37+
38+
def f1(self) -> str: ...
39+
if sys.platform != "win32":
40+
def function_definition(self): ...
41+
assignment = 1
42+
43+
def f2(self) -> str: ...

tests/test_format.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -194,9 +194,9 @@ def test_stub() -> None:
194194
assert_format(source, expected, mode)
195195

196196

197-
def test_nested_class_stub() -> None:
197+
def test_nested_stub() -> None:
198198
mode = replace(DEFAULT_MODE, is_pyi=True, preview=True)
199-
source, expected = read_data("miscellaneous", "nested_class_stub.pyi")
199+
source, expected = read_data("miscellaneous", "nested_stub.pyi")
200200
assert_format(source, expected, mode)
201201

202202

0 commit comments

Comments
 (0)