diff --git a/CHANGES.md b/CHANGES.md index 4bf98d87cfe..4e97c1f2e46 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -21,6 +21,7 @@ - Fix crash on `await ...` (where `...` is a literal `Ellipsis`) (#4676) - Remove support for pre-python 3.7 `await/async` as soft keywords/variable names (#4676) +- Fix crash on parenthesized expression inside a type parameter bound (#4684) ### Preview style diff --git a/src/black/linegen.py b/src/black/linegen.py index fa574ca215e..032ab687835 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -787,12 +787,26 @@ def left_hand_split( head_leaves: list[Leaf] = [] current_leaves = head_leaves matching_bracket: Optional[Leaf] = None - for leaf in line.leaves: + depth = 0 + for index, leaf in enumerate(line.leaves): + if index == 2 and leaf.type == token.LSQB: + # A [ at index 2 means this is a type param, so start + # tracking the depth + depth += 1 + elif depth > 0: + if leaf.type == token.LSQB: + depth += 1 + elif leaf.type == token.RSQB: + depth -= 1 if ( current_leaves is body_leaves and leaf.type in CLOSING_BRACKETS and leaf.opening_bracket is matching_bracket and isinstance(matching_bracket, Leaf) + # If the code is still on LPAR and we are inside a type + # param, ignore the match since this is searching + # for the function arguments + and not (leaf_type == token.LPAR and depth > 0) ): ensure_visible(leaf) ensure_visible(matching_bracket) diff --git a/tests/data/cases/type_params.py b/tests/data/cases/type_params.py index f8fc3855741..124292d6d54 100644 --- a/tests/data/cases/type_params.py +++ b/tests/data/cases/type_params.py @@ -15,6 +15,8 @@ def magic[Trailing, Comma,](): pass def weird_syntax[T: lambda: 42, U: a or b](): pass +def name_3[name_0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if aaaaaaaaaaa else name_3](): pass + # output @@ -62,3 +64,9 @@ def magic[ def weird_syntax[T: lambda: 42, U: a or b](): pass + + +def name_3[ + name_0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if aaaaaaaaaaa else name_3 +](): + pass