Fix long case blocks not split into multiple lines (#4024)

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
This commit is contained in:
rdrll 2023-11-07 06:31:58 -08:00 committed by GitHub
parent 46be1f8e54
commit 50ed6221d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 101 additions and 21 deletions

View File

@ -25,6 +25,8 @@
indented less (#3964)
- Multiline list and dict unpacking as the sole argument to a function is now also
indented less (#3992)
- Fix a bug where long `case` blocks were not split into multiple lines. Also enable
general trailing comma rules on `case` blocks (#4024)
- Keep requiring two empty lines between module-level docstring and first function or
class definition. (#4028)

View File

@ -1229,7 +1229,7 @@ def normalize_prefix(leaf: Leaf, *, inside_brackets: bool) -> None:
leaf.prefix = ""
def normalize_invisible_parens(
def normalize_invisible_parens( # noqa: C901
node: Node, parens_after: Set[str], *, mode: Mode, features: Collection[Feature]
) -> None:
"""Make existing optional parentheses invisible or create new ones.
@ -1260,6 +1260,17 @@ def normalize_invisible_parens(
child, parens_after=parens_after, mode=mode, features=features
)
# Fixes a bug where invisible parens are not properly wrapped around
# case blocks.
if (
isinstance(child, Node)
and child.type == syms.case_block
and Preview.long_case_block_line_splitting in mode
):
normalize_invisible_parens(
child, parens_after={"case"}, mode=mode, features=features
)
# Add parentheses around long tuple unpacking in assignments.
if (
index == 0
@ -1305,6 +1316,17 @@ def normalize_invisible_parens(
# invisible parentheses to work more precisely.
continue
elif (
isinstance(child, Leaf)
and child.next_sibling is not None
and child.next_sibling.type == token.COLON
and child.value == "case"
and Preview.long_case_block_line_splitting in mode
):
# A special patch for "case case:" scenario, the second occurrence
# of case will be not parsed as a Python keyword.
break
elif not (isinstance(child, Leaf) and is_multiline_string(child)):
wrap_in_parentheses(node, child, visible=False)

View File

@ -193,6 +193,7 @@ class Preview(Enum):
hug_parens_with_braces_and_square_brackets = auto()
allow_empty_first_line_before_new_block_or_comment = auto()
single_line_format_skip_with_multiple_comments = auto()
long_case_block_line_splitting = auto()
class Deprecated(UserWarning):

View File

@ -30,22 +30,6 @@ def func(match: case, case: match) -> case:
...
match maybe, multiple:
case perhaps, 5:
pass
case perhaps, 6,:
pass
match more := (than, one), indeed,:
case _, (5, 6):
pass
case [[5], (6)], [7],:
pass
case _:
pass
match a, *b, c:
case [*_]:
assert "seq" == _
@ -67,12 +51,12 @@ def func(match: case, case: match) -> case:
),
):
pass
case [a as match]:
pass
case case:
pass
case something:
pass
match match:
@ -98,10 +82,8 @@ def func(match: case, case: match) -> case:
match something:
case 1 as a:
pass
case 2 as b, 3 as c:
pass
case 4 as d, (5 as e), (6 | 7 as g), *h:
pass

View File

@ -0,0 +1,34 @@
# flags: --preview --minimum-version=3.10
match x:
case "abcd" | "abcd" | "abcd" :
pass
case "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd":
pass
case xxxxxxxxxxxxxxxxxxxxxxx:
pass
# output
match x:
case "abcd" | "abcd" | "abcd":
pass
case (
"abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
):
pass
case xxxxxxxxxxxxxxxxxxxxxxx:
pass

View File

@ -0,0 +1,39 @@
# flags: --preview --minimum-version=3.10
match maybe, multiple:
case perhaps, 5:
pass
case perhaps, 6,:
pass
match more := (than, one), indeed,:
case _, (5, 6):
pass
case [[5], (6)], [7],:
pass
case _:
pass
# output
match maybe, multiple:
case perhaps, 5:
pass
case (
perhaps,
6,
):
pass
match more := (than, one), indeed,:
case _, (5, 6):
pass
case (
[[5], (6)],
[7],
):
pass
case _:
pass