Skip to content

Commit 50ed622

Browse files
rdrllJelleZijlstra
andauthored
Fix long case blocks not split into multiple lines (#4024)
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
1 parent 46be1f8 commit 50ed622

6 files changed

Lines changed: 101 additions & 21 deletions

File tree

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
indented less (#3964)
2626
- Multiline list and dict unpacking as the sole argument to a function is now also
2727
indented less (#3992)
28+
- Fix a bug where long `case` blocks were not split into multiple lines. Also enable
29+
general trailing comma rules on `case` blocks (#4024)
2830
- Keep requiring two empty lines between module-level docstring and first function or
2931
class definition. (#4028)
3032

src/black/linegen.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1229,7 +1229,7 @@ def normalize_prefix(leaf: Leaf, *, inside_brackets: bool) -> None:
12291229
leaf.prefix = ""
12301230

12311231

1232-
def normalize_invisible_parens(
1232+
def normalize_invisible_parens( # noqa: C901
12331233
node: Node, parens_after: Set[str], *, mode: Mode, features: Collection[Feature]
12341234
) -> None:
12351235
"""Make existing optional parentheses invisible or create new ones.
@@ -1260,6 +1260,17 @@ def normalize_invisible_parens(
12601260
child, parens_after=parens_after, mode=mode, features=features
12611261
)
12621262

1263+
# Fixes a bug where invisible parens are not properly wrapped around
1264+
# case blocks.
1265+
if (
1266+
isinstance(child, Node)
1267+
and child.type == syms.case_block
1268+
and Preview.long_case_block_line_splitting in mode
1269+
):
1270+
normalize_invisible_parens(
1271+
child, parens_after={"case"}, mode=mode, features=features
1272+
)
1273+
12631274
# Add parentheses around long tuple unpacking in assignments.
12641275
if (
12651276
index == 0
@@ -1305,6 +1316,17 @@ def normalize_invisible_parens(
13051316
# invisible parentheses to work more precisely.
13061317
continue
13071318

1319+
elif (
1320+
isinstance(child, Leaf)
1321+
and child.next_sibling is not None
1322+
and child.next_sibling.type == token.COLON
1323+
and child.value == "case"
1324+
and Preview.long_case_block_line_splitting in mode
1325+
):
1326+
# A special patch for "case case:" scenario, the second occurrence
1327+
# of case will be not parsed as a Python keyword.
1328+
break
1329+
13081330
elif not (isinstance(child, Leaf) and is_multiline_string(child)):
13091331
wrap_in_parentheses(node, child, visible=False)
13101332

src/black/mode.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ class Preview(Enum):
193193
hug_parens_with_braces_and_square_brackets = auto()
194194
allow_empty_first_line_before_new_block_or_comment = auto()
195195
single_line_format_skip_with_multiple_comments = auto()
196+
long_case_block_line_splitting = auto()
196197

197198

198199
class Deprecated(UserWarning):

tests/data/cases/pattern_matching_extras.py

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,6 @@ def func(match: case, case: match) -> case:
3030
...
3131

3232

33-
match maybe, multiple:
34-
case perhaps, 5:
35-
pass
36-
case perhaps, 6,:
37-
pass
38-
39-
40-
match more := (than, one), indeed,:
41-
case _, (5, 6):
42-
pass
43-
case [[5], (6)], [7],:
44-
pass
45-
case _:
46-
pass
47-
48-
4933
match a, *b, c:
5034
case [*_]:
5135
assert "seq" == _
@@ -67,12 +51,12 @@ def func(match: case, case: match) -> case:
6751
),
6852
):
6953
pass
70-
7154
case [a as match]:
7255
pass
73-
7456
case case:
7557
pass
58+
case something:
59+
pass
7660

7761

7862
match match:
@@ -98,10 +82,8 @@ def func(match: case, case: match) -> case:
9882
match something:
9983
case 1 as a:
10084
pass
101-
10285
case 2 as b, 3 as c:
10386
pass
104-
10587
case 4 as d, (5 as e), (6 | 7 as g), *h:
10688
pass
10789

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# flags: --preview --minimum-version=3.10
2+
match x:
3+
case "abcd" | "abcd" | "abcd" :
4+
pass
5+
case "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd":
6+
pass
7+
case xxxxxxxxxxxxxxxxxxxxxxx:
8+
pass
9+
10+
# output
11+
12+
match x:
13+
case "abcd" | "abcd" | "abcd":
14+
pass
15+
case (
16+
"abcd"
17+
| "abcd"
18+
| "abcd"
19+
| "abcd"
20+
| "abcd"
21+
| "abcd"
22+
| "abcd"
23+
| "abcd"
24+
| "abcd"
25+
| "abcd"
26+
| "abcd"
27+
| "abcd"
28+
| "abcd"
29+
| "abcd"
30+
| "abcd"
31+
):
32+
pass
33+
case xxxxxxxxxxxxxxxxxxxxxxx:
34+
pass
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# flags: --preview --minimum-version=3.10
2+
match maybe, multiple:
3+
case perhaps, 5:
4+
pass
5+
case perhaps, 6,:
6+
pass
7+
8+
9+
match more := (than, one), indeed,:
10+
case _, (5, 6):
11+
pass
12+
case [[5], (6)], [7],:
13+
pass
14+
case _:
15+
pass
16+
17+
18+
# output
19+
20+
match maybe, multiple:
21+
case perhaps, 5:
22+
pass
23+
case (
24+
perhaps,
25+
6,
26+
):
27+
pass
28+
29+
30+
match more := (than, one), indeed,:
31+
case _, (5, 6):
32+
pass
33+
case (
34+
[[5], (6)],
35+
[7],
36+
):
37+
pass
38+
case _:
39+
pass

0 commit comments

Comments
 (0)