Skip to content

Commit 92c1d74

Browse files
Add trailing newlines to STANDALONE_COMMENT nodes to prevent parsing errors
1 parent 6ea3ef8 commit 92c1d74

File tree

3 files changed

+56
-0
lines changed

3 files changed

+56
-0
lines changed

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
- Fix bug where comments preceding `# fmt: off`/`# fmt: on` blocks were incorrectly
1919
removed, particularly affecting Jupytext's `# %% [markdown]` comments (#4845)
20+
- Fix crash when multiple `# fmt: skip` comments are used in a multi-part if-clause
21+
(#4872)
2022

2123
### Preview style
2224

src/black/comments.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,17 @@ def _handle_regular_fmt_block(
409409
else:
410410
standalone_comment_prefix = prefix[:previous_consumed] + "\n" * comment.newlines
411411

412+
# Ensure STANDALONE_COMMENT nodes have trailing newlines when stringified
413+
# This prevents multiple fmt: skip comments from being concatenated on one line
414+
for node in ignored_nodes:
415+
if isinstance(node, Leaf) and node.type == STANDALONE_COMMENT:
416+
if not node.value.endswith("\n"):
417+
node.value += "\n"
418+
elif isinstance(node, Node):
419+
for leaf in node.leaves():
420+
if leaf.type == STANDALONE_COMMENT and not leaf.value.endswith("\n"):
421+
leaf.value += "\n"
422+
412423
hidden_value = "".join(str(n) for n in ignored_nodes)
413424
comment_lineno = leaf.lineno - comment.newlines
414425

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Issue 4731: Multiple fmt: skip in multi-part if-clause
2+
class ClassWithALongName:
3+
Constant1 = 1
4+
Constant2 = 2
5+
Constant3 = 3
6+
7+
8+
def test():
9+
if (
10+
"cond1" == "cond1"
11+
and "cond2" == "cond2"
12+
and 1 in (
13+
ClassWithALongName.Constant1,
14+
ClassWithALongName.Constant2,
15+
ClassWithALongName.Constant3, # fmt: skip
16+
) # fmt: skip
17+
):
18+
return True
19+
return False
20+
21+
22+
# output
23+
24+
25+
# Issue 4731: Multiple fmt: skip in multi-part if-clause
26+
class ClassWithALongName:
27+
Constant1 = 1
28+
Constant2 = 2
29+
Constant3 = 3
30+
31+
32+
def test():
33+
if (
34+
"cond1" == "cond1"
35+
and "cond2" == "cond2"
36+
and 1 in (
37+
ClassWithALongName.Constant1,
38+
ClassWithALongName.Constant2,
39+
ClassWithALongName.Constant3, # fmt: skip
40+
) # fmt: skip
41+
):
42+
return True
43+
return False

0 commit comments

Comments
 (0)