Skip to content

Commit 2db5ab0

Browse files
Allow empty line after block open before a comment or compound statement (#3967)
1 parent 0a37888 commit 2db5ab0

5 files changed

Lines changed: 138 additions & 1 deletion

File tree

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
### Preview style
1414

1515
- Fix merging implicit multiline strings that have inline comments (#3956)
16+
- Allow empty first line after block open before a comment or compound statement (#3967)
1617

1718
### Configuration
1819

src/black/lines.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
STANDALONE_COMMENT,
2525
TEST_DESCENDANTS,
2626
child_towards,
27+
is_docstring,
28+
is_funcdef,
2729
is_import,
2830
is_multiline_string,
2931
is_one_sequence_between,
@@ -686,7 +688,30 @@ def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
686688
return 0, 1
687689
return before, 1
688690

689-
if self.previous_line and self.previous_line.opens_block:
691+
is_empty_first_line_ok = (
692+
Preview.allow_empty_first_line_before_new_block_or_comment
693+
in current_line.mode
694+
and (
695+
# If it's a standalone comment
696+
current_line.leaves[0].type == STANDALONE_COMMENT
697+
# If it opens a new block
698+
or current_line.opens_block
699+
# If it's a triple quote comment (but not at the start of a funcdef)
700+
or (
701+
is_docstring(current_line.leaves[0])
702+
and self.previous_line
703+
and self.previous_line.leaves[0]
704+
and self.previous_line.leaves[0].parent
705+
and not is_funcdef(self.previous_line.leaves[0].parent)
706+
)
707+
)
708+
)
709+
710+
if (
711+
self.previous_line
712+
and self.previous_line.opens_block
713+
and not is_empty_first_line_ok
714+
):
690715
return 0, 0
691716
return before, 0
692717

src/black/mode.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ class Preview(Enum):
190190
module_docstring_newlines = auto()
191191
accept_raw_docstrings = auto()
192192
fix_power_op_line_length = auto()
193+
allow_empty_first_line_before_new_block_or_comment = auto()
193194

194195

195196
class Deprecated(UserWarning):

src/black/nodes.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,10 @@ def is_multiline_string(leaf: Leaf) -> bool:
718718
return has_triple_quotes(leaf.value) and "\n" in leaf.value
719719

720720

721+
def is_funcdef(node: Node) -> bool:
722+
return node.type == syms.funcdef
723+
724+
721725
def is_stub_suite(node: Node) -> bool:
722726
"""Return True if `node` is a suite with a stub body."""
723727

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# flags: --preview
2+
def foo():
3+
"""
4+
Docstring
5+
"""
6+
7+
# Here we go
8+
if x:
9+
10+
# This is also now fine
11+
a = 123
12+
13+
else:
14+
# But not necessary
15+
a = 123
16+
17+
if y:
18+
19+
while True:
20+
21+
"""
22+
Long comment here
23+
"""
24+
a = 123
25+
26+
if z:
27+
28+
for _ in range(100):
29+
a = 123
30+
else:
31+
32+
try:
33+
34+
# this should be ok
35+
a = 123
36+
except:
37+
38+
"""also this"""
39+
a = 123
40+
41+
42+
def bar():
43+
44+
if x:
45+
a = 123
46+
47+
48+
def baz():
49+
50+
# OK
51+
if x:
52+
a = 123
53+
54+
# output
55+
56+
def foo():
57+
"""
58+
Docstring
59+
"""
60+
61+
# Here we go
62+
if x:
63+
64+
# This is also now fine
65+
a = 123
66+
67+
else:
68+
# But not necessary
69+
a = 123
70+
71+
if y:
72+
73+
while True:
74+
75+
"""
76+
Long comment here
77+
"""
78+
a = 123
79+
80+
if z:
81+
82+
for _ in range(100):
83+
a = 123
84+
else:
85+
86+
try:
87+
88+
# this should be ok
89+
a = 123
90+
except:
91+
92+
"""also this"""
93+
a = 123
94+
95+
96+
def bar():
97+
98+
if x:
99+
a = 123
100+
101+
102+
def baz():
103+
104+
# OK
105+
if x:
106+
a = 123

0 commit comments

Comments
 (0)