Skip to content

Commit

Permalink
Allow empty line after block open before a comment or compound statem…
Browse files Browse the repository at this point in the history
…ent (#3967)
  • Loading branch information
henriholopainen authored Oct 23, 2023
1 parent 0a37888 commit 2db5ab0
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
### Preview style

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

### Configuration

Expand Down
27 changes: 26 additions & 1 deletion src/black/lines.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
STANDALONE_COMMENT,
TEST_DESCENDANTS,
child_towards,
is_docstring,
is_funcdef,
is_import,
is_multiline_string,
is_one_sequence_between,
Expand Down Expand Up @@ -686,7 +688,30 @@ def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
return 0, 1
return before, 1

if self.previous_line and self.previous_line.opens_block:
is_empty_first_line_ok = (
Preview.allow_empty_first_line_before_new_block_or_comment
in current_line.mode
and (
# If it's a standalone comment
current_line.leaves[0].type == STANDALONE_COMMENT
# If it opens a new block
or current_line.opens_block
# If it's a triple quote comment (but not at the start of a funcdef)
or (
is_docstring(current_line.leaves[0])
and self.previous_line
and self.previous_line.leaves[0]
and self.previous_line.leaves[0].parent
and not is_funcdef(self.previous_line.leaves[0].parent)
)
)
)

if (
self.previous_line
and self.previous_line.opens_block
and not is_empty_first_line_ok
):
return 0, 0
return before, 0

Expand Down
1 change: 1 addition & 0 deletions src/black/mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ class Preview(Enum):
module_docstring_newlines = auto()
accept_raw_docstrings = auto()
fix_power_op_line_length = auto()
allow_empty_first_line_before_new_block_or_comment = auto()


class Deprecated(UserWarning):
Expand Down
4 changes: 4 additions & 0 deletions src/black/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,10 @@ def is_multiline_string(leaf: Leaf) -> bool:
return has_triple_quotes(leaf.value) and "\n" in leaf.value


def is_funcdef(node: Node) -> bool:
return node.type == syms.funcdef


def is_stub_suite(node: Node) -> bool:
"""Return True if `node` is a suite with a stub body."""

Expand Down
106 changes: 106 additions & 0 deletions tests/data/cases/preview_allow_empty_first_line_in_special_cases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# flags: --preview
def foo():
"""
Docstring
"""

# Here we go
if x:

# This is also now fine
a = 123

else:
# But not necessary
a = 123

if y:

while True:

"""
Long comment here
"""
a = 123

if z:

for _ in range(100):
a = 123
else:

try:

# this should be ok
a = 123
except:

"""also this"""
a = 123


def bar():

if x:
a = 123


def baz():

# OK
if x:
a = 123

# output

def foo():
"""
Docstring
"""

# Here we go
if x:

# This is also now fine
a = 123

else:
# But not necessary
a = 123

if y:

while True:

"""
Long comment here
"""
a = 123

if z:

for _ in range(100):
a = 123
else:

try:

# this should be ok
a = 123
except:

"""also this"""
a = 123


def bar():

if x:
a = 123


def baz():

# OK
if x:
a = 123

0 comments on commit 2db5ab0

Please sign in to comment.