From 8e2cc91a5938072d9d488dcb4b62fe25500fc424 Mon Sep 17 00:00:00 2001 From: Yilei Yang Date: Mon, 31 Oct 2022 23:53:14 -0700 Subject: [PATCH 01/16] Initial implementation to handle trailing commas in leading parts. --- src/black/brackets.py | 12 +++------ src/black/linegen.py | 17 +++++++++--- src/black/lines.py | 4 +-- src/black/mode.py | 1 + src/black/trans.py | 9 +------ .../trailing_commas_in_leading_parts.py | 26 +++++++++++++++++++ 6 files changed, 47 insertions(+), 22 deletions(-) create mode 100644 tests/data/preview/trailing_commas_in_leading_parts.py diff --git a/src/black/brackets.py b/src/black/brackets.py index 3566f5b6c37..fdc0b8116c5 100644 --- a/src/black/brackets.py +++ b/src/black/brackets.py @@ -57,10 +57,6 @@ DOT_PRIORITY: Final = 1 -class BracketMatchError(Exception): - """Raised when an opening bracket is unable to be matched to a closing bracket.""" - - @dataclass class BracketTracker: """Keeps track of brackets on a line.""" @@ -98,10 +94,10 @@ def mark(self, leaf: Leaf) -> None: try: opening_bracket = self.bracket_match.pop((self.depth, leaf.type)) except KeyError as e: - raise BracketMatchError( - "Unable to match a closing bracket to the following opening" - f" bracket: {leaf}" - ) from e + # OK to have non-matching closing brackets, as the line might be a + # continuation from previous lines and the closing brackets match + # the ones from previously split lines. + return leaf.opening_bracket = opening_bracket if not leaf.value: self.invisible.append(leaf) diff --git a/src/black/linegen.py b/src/black/linegen.py index a2e41bf5912..0250846fe95 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -639,7 +639,7 @@ def right_hand_split( tail_leaves.reverse() body_leaves.reverse() head_leaves.reverse() - head = bracket_split_build_line(head_leaves, line, opening_bracket) + head = bracket_split_build_line(head_leaves, line, opening_bracket, check_should_split_line=True) body = bracket_split_build_line(body_leaves, line, opening_bracket, is_body=True) tail = bracket_split_build_line(tail_leaves, line, opening_bracket) bracket_split_succeeded_or_raise(head, body, tail) @@ -715,7 +715,7 @@ def bracket_split_succeeded_or_raise(head: Line, body: Line, tail: Line) -> None def bracket_split_build_line( - leaves: List[Leaf], original: Line, opening_bracket: Leaf, *, is_body: bool = False + leaves: List[Leaf], original: Line, opening_bracket: Leaf, *, is_body: bool = False, check_should_split_line: bool = False ) -> Line: """Return a new line with given `leaves` and respective comments from `original`. @@ -762,11 +762,12 @@ def bracket_split_build_line( break # Populate the line + check_should_split_line = Preview.handle_trailing_commas_in_leading_parts in original.mode and check_should_split_line for leaf in leaves: - result.append(leaf, preformatted=True) + result.append(leaf, preformatted=True, track_bracket=check_should_split_line) for comment_after in original.comments_after(leaf): result.append(comment_after, preformatted=True) - if is_body and should_split_line(result, opening_bracket): + if (is_body or check_should_split_line) and should_split_line(result, opening_bracket): result.should_split_rhs = True return result @@ -1161,6 +1162,14 @@ def should_split_line(line: Line, opening_bracket: Leaf) -> bool: if last_leaf.type == token.COMMA: trailing_comma = True exclude.add(id(last_leaf)) + else: + # Check commas inside inner parens. + next_leaf = last_leaf + for leaf in reversed(line.leaves[:-1]): + if next_leaf.type in CLOSING_BRACKETS and leaf.type == token.COMMA: + trailing_comma = True + break + next_leaf = leaf max_priority = line.bracket_tracker.max_delimiter_priority(exclude=exclude) except (IndexError, ValueError): return False diff --git a/src/black/lines.py b/src/black/lines.py index 0d074534def..c273a61048d 100644 --- a/src/black/lines.py +++ b/src/black/lines.py @@ -53,7 +53,7 @@ class Line: should_split_rhs: bool = False magic_trailing_comma: Optional[Leaf] = None - def append(self, leaf: Leaf, preformatted: bool = False) -> None: + def append(self, leaf: Leaf, preformatted: bool = False, track_bracket: bool = False) -> None: """Add a new `leaf` to the end of the line. Unless `preformatted` is True, the `leaf` will receive a new consistent @@ -75,7 +75,7 @@ def append(self, leaf: Leaf, preformatted: bool = False) -> None: leaf.prefix += whitespace( leaf, complex_subscript=self.is_complex_subscript(leaf) ) - if self.inside_brackets or not preformatted: + if self.inside_brackets or not preformatted or track_bracket: self.bracket_tracker.mark(leaf) if self.mode.magic_trailing_comma: if self.has_magic_trailing_comma(leaf): diff --git a/src/black/mode.py b/src/black/mode.py index e2eff2391b1..2921e2cf489 100644 --- a/src/black/mode.py +++ b/src/black/mode.py @@ -151,6 +151,7 @@ class Preview(Enum): annotation_parens = auto() empty_lines_before_class_or_def_with_leading_comments = auto() + handle_trailing_commas_in_leading_parts = auto() long_docstring_quotes_on_newline = auto() normalize_docstring_quotes_and_prefixes_properly = auto() one_element_subscript = auto() diff --git a/src/black/trans.py b/src/black/trans.py index 8893ab02aab..a2c739c62ec 100644 --- a/src/black/trans.py +++ b/src/black/trans.py @@ -30,7 +30,6 @@ from mypy_extensions import trait -from black.brackets import BracketMatchError from black.comments import contains_pragma_comment from black.lines import Line, append_leaves from black.mode import Feature @@ -812,13 +811,7 @@ def do_transform(self, line: Line, string_idx: int) -> Iterator[TResult[Line]]: new_line = line.clone() new_line.comments = line.comments.copy() - try: - append_leaves(new_line, line, LL[: string_idx - 1]) - except BracketMatchError: - # HACK: I believe there is currently a bug somewhere in - # right_hand_split() that is causing brackets to not be tracked - # properly by a shared BracketTracker. - append_leaves(new_line, line, LL[: string_idx - 1], preformatted=True) + append_leaves(new_line, line, LL[: string_idx - 1]) string_leaf = Leaf(token.STRING, LL[string_idx].value) LL[string_idx - 1].remove() diff --git a/tests/data/preview/trailing_commas_in_leading_parts.py b/tests/data/preview/trailing_commas_in_leading_parts.py new file mode 100644 index 00000000000..b51af1d258d --- /dev/null +++ b/tests/data/preview/trailing_commas_in_leading_parts.py @@ -0,0 +1,26 @@ +zero( + one, +).two( + three, +).four( + five, +) + +( + a, + b, + c, + d, +) = func1( + arg1 +) and func2(arg2) + + +# Example from https://github.com/psf/black/issues/3229 +def refresh_token(self, device_family, refresh_token, api_key): + return self.orchestration.refresh_token( + data={ + "refreshToken": refresh_token, + }, + api_key=api_key, + )["extensions"]["sdk"]["token"] From 3908d86c7c36aa2b958fb624081f2c59c0e9c3af Mon Sep 17 00:00:00 2001 From: Yilei Yang Date: Tue, 1 Nov 2022 00:24:32 -0700 Subject: [PATCH 02/16] Add changelogs, and format ourselves. --- CHANGES.md | 2 ++ src/black/brackets.py | 2 +- src/black/linegen.py | 20 ++++++++++++++++---- src/black/lines.py | 4 +++- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 1dcd7f09b3c..3842c5cde42 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,6 +17,8 @@ - Enforce empty lines before classes and functions with sticky leading comments (#3302) - Implicitly concatenated strings used as function args are now wrapped inside parentheses (#3307) +- Correctly handle trailing commas that are inside a line's leading non-nested parens + (#3370) ### Configuration diff --git a/src/black/brackets.py b/src/black/brackets.py index fdc0b8116c5..ce78808e1a7 100644 --- a/src/black/brackets.py +++ b/src/black/brackets.py @@ -93,7 +93,7 @@ def mark(self, leaf: Leaf) -> None: self.depth -= 1 try: opening_bracket = self.bracket_match.pop((self.depth, leaf.type)) - except KeyError as e: + except KeyError: # OK to have non-matching closing brackets, as the line might be a # continuation from previous lines and the closing brackets match # the ones from previously split lines. diff --git a/src/black/linegen.py b/src/black/linegen.py index 0250846fe95..3755dea9ef3 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -639,7 +639,9 @@ def right_hand_split( tail_leaves.reverse() body_leaves.reverse() head_leaves.reverse() - head = bracket_split_build_line(head_leaves, line, opening_bracket, check_should_split_line=True) + head = bracket_split_build_line( + head_leaves, line, opening_bracket, check_should_split_line=True + ) body = bracket_split_build_line(body_leaves, line, opening_bracket, is_body=True) tail = bracket_split_build_line(tail_leaves, line, opening_bracket) bracket_split_succeeded_or_raise(head, body, tail) @@ -715,7 +717,12 @@ def bracket_split_succeeded_or_raise(head: Line, body: Line, tail: Line) -> None def bracket_split_build_line( - leaves: List[Leaf], original: Line, opening_bracket: Leaf, *, is_body: bool = False, check_should_split_line: bool = False + leaves: List[Leaf], + original: Line, + opening_bracket: Leaf, + *, + is_body: bool = False, + check_should_split_line: bool = False, ) -> Line: """Return a new line with given `leaves` and respective comments from `original`. @@ -762,12 +769,17 @@ def bracket_split_build_line( break # Populate the line - check_should_split_line = Preview.handle_trailing_commas_in_leading_parts in original.mode and check_should_split_line + check_should_split_line = ( + Preview.handle_trailing_commas_in_leading_parts in original.mode + and check_should_split_line + ) for leaf in leaves: result.append(leaf, preformatted=True, track_bracket=check_should_split_line) for comment_after in original.comments_after(leaf): result.append(comment_after, preformatted=True) - if (is_body or check_should_split_line) and should_split_line(result, opening_bracket): + if (is_body or check_should_split_line) and should_split_line( + result, opening_bracket + ): result.should_split_rhs = True return result diff --git a/src/black/lines.py b/src/black/lines.py index c273a61048d..08281bcf370 100644 --- a/src/black/lines.py +++ b/src/black/lines.py @@ -53,7 +53,9 @@ class Line: should_split_rhs: bool = False magic_trailing_comma: Optional[Leaf] = None - def append(self, leaf: Leaf, preformatted: bool = False, track_bracket: bool = False) -> None: + def append( + self, leaf: Leaf, preformatted: bool = False, track_bracket: bool = False + ) -> None: """Add a new `leaf` to the end of the line. Unless `preformatted` is True, the `leaf` will receive a new consistent From 2213012c27421c5fcfce76719145bb1712cf1f2a Mon Sep 17 00:00:00 2001 From: Yilei Yang Date: Tue, 1 Nov 2022 00:30:22 -0700 Subject: [PATCH 03/16] Make sure skip magic trailing comma still works for things on the left hand side or leading non-nested parens. --- .../data/preview/skip_magic_trailing_comma.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/data/preview/skip_magic_trailing_comma.py b/tests/data/preview/skip_magic_trailing_comma.py index e98174af427..64a2212c025 100644 --- a/tests/data/preview/skip_magic_trailing_comma.py +++ b/tests/data/preview/skip_magic_trailing_comma.py @@ -15,6 +15,24 @@ # Except single element tuples small_tuple = (1,) +# Trailing commas in multiple chained non-nested parens. +zero( + one, +).two( + three, +).four( + five, +) + +( + a, + b, + c, + d, +) = func1( + arg1 +) and func2(arg2) + # output # We should not remove the trailing comma in a single-element subscript. a: tuple[int,] @@ -32,3 +50,8 @@ # Except single element tuples small_tuple = (1,) + +# Trailing commas in multiple chained non-nested parens. +zero(one).two(three).four(five) + +(a, b, c, d) = func1(arg1) and func2(arg2) From 6a14f81f5c6bf82444487b8ecf51c63a529f7b57 Mon Sep 17 00:00:00 2001 From: Yilei Yang Date: Tue, 1 Nov 2022 10:49:11 -0700 Subject: [PATCH 04/16] Fix two bugs and add more tests. 1. The change wasn't guarded by preview mode. 2. Checking trailing commas in inner parens should only be done on the `head` component after bracket split. --- src/black/linegen.py | 94 ++++++++++++++----- .../data/preview/skip_magic_trailing_comma.py | 17 ++++ .../trailing_commas_in_leading_parts.py | 45 +++++++++ .../simple_cases/function_trailing_comma.py | 29 ++++++ 4 files changed, 160 insertions(+), 25 deletions(-) diff --git a/src/black/linegen.py b/src/black/linegen.py index 3755dea9ef3..1b96bba0bc9 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -1,6 +1,7 @@ """ Generating lines of code. """ +import enum import sys from functools import partial, wraps from typing import Collection, Iterator, List, Optional, Set, Union, cast @@ -561,6 +562,12 @@ def _rhs( yield line +class _BracketSplitComponent(enum.Enum): + head = enum.auto() + body = enum.auto() + tail = enum.auto() + + def left_hand_split(line: Line, _features: Collection[Feature] = ()) -> Iterator[Line]: """Split line into many lines, starting with the first matching bracket pair. @@ -591,9 +598,15 @@ def left_hand_split(line: Line, _features: Collection[Feature] = ()) -> Iterator if not matching_bracket: raise CannotSplit("No brackets found") - head = bracket_split_build_line(head_leaves, line, matching_bracket) - body = bracket_split_build_line(body_leaves, line, matching_bracket, is_body=True) - tail = bracket_split_build_line(tail_leaves, line, matching_bracket) + head = bracket_split_build_line( + head_leaves, line, matching_bracket, component=_BracketSplitComponent.head + ) + body = bracket_split_build_line( + body_leaves, line, matching_bracket, component=_BracketSplitComponent.body + ) + tail = bracket_split_build_line( + tail_leaves, line, matching_bracket, component=_BracketSplitComponent.tail + ) bracket_split_succeeded_or_raise(head, body, tail) for result in (head, body, tail): if result: @@ -640,10 +653,14 @@ def right_hand_split( body_leaves.reverse() head_leaves.reverse() head = bracket_split_build_line( - head_leaves, line, opening_bracket, check_should_split_line=True + head_leaves, line, opening_bracket, component=_BracketSplitComponent.head + ) + body = bracket_split_build_line( + body_leaves, line, opening_bracket, component=_BracketSplitComponent.body + ) + tail = bracket_split_build_line( + tail_leaves, line, opening_bracket, component=_BracketSplitComponent.tail ) - body = bracket_split_build_line(body_leaves, line, opening_bracket, is_body=True) - tail = bracket_split_build_line(tail_leaves, line, opening_bracket) bracket_split_succeeded_or_raise(head, body, tail) if ( Feature.FORCE_OPTIONAL_PARENTHESES not in features @@ -721,16 +738,19 @@ def bracket_split_build_line( original: Line, opening_bracket: Leaf, *, - is_body: bool = False, - check_should_split_line: bool = False, + component: _BracketSplitComponent, ) -> Line: """Return a new line with given `leaves` and respective comments from `original`. - If `is_body` is True, the result line is one-indented inside brackets and as such - has its first leaf's prefix normalized and a trailing comma added when expected. + If it's the head component, trailing commas inside inner parens will also be + checked to ensure they are respected. + + If it's the body component, the result line is one-indented inside brackets and as + such has its first leaf's prefix normalized and a trailing comma added when + expected. """ result = Line(mode=original.mode, depth=original.depth) - if is_body: + if component == _BracketSplitComponent.body: result.inside_brackets = True result.depth += 1 if leaves: @@ -769,17 +789,15 @@ def bracket_split_build_line( break # Populate the line - check_should_split_line = ( + track_bracket = ( Preview.handle_trailing_commas_in_leading_parts in original.mode - and check_should_split_line + and component == _BracketSplitComponent.head ) for leaf in leaves: - result.append(leaf, preformatted=True, track_bracket=check_should_split_line) + result.append(leaf, preformatted=True, track_bracket=track_bracket) for comment_after in original.comments_after(leaf): result.append(comment_after, preformatted=True) - if (is_body or check_should_split_line) and should_split_line( - result, opening_bracket - ): + if should_split_line(result, opening_bracket, component): result.should_split_rhs = True return result @@ -1158,30 +1176,56 @@ def maybe_make_parens_invisible_in_atom( return True -def should_split_line(line: Line, opening_bracket: Leaf) -> bool: +def should_split_line( + line: Line, opening_bracket: Leaf, component: _BracketSplitComponent +) -> bool: """Should `line` be immediately split with `delimiter_split()` after RHS?""" + if component == _BracketSplitComponent.tail: + return False + if not (opening_bracket.parent and opening_bracket.value in "[{("): return False - # We're essentially checking if the body is delimited by commas and there's more + # We're essentially checking if the line is delimited by commas and there's more # than one of them (we're excluding the trailing comma and if the delimiter priority # is still commas, that means there's more). exclude = set() trailing_comma = False try: last_leaf = line.leaves[-1] - if last_leaf.type == token.COMMA: + if component == _BracketSplitComponent.body and last_leaf.type == token.COMMA: trailing_comma = True exclude.add(id(last_leaf)) - else: - # Check commas inside inner parens. + elif ( + component == _BracketSplitComponent.head + and Preview.handle_trailing_commas_in_leading_parts in line.mode + ): + # Check commas inside inner parens, we need to only include leaves inside + # the matching brackets. + include: Set[LeafID] = set() + reversed_leaves: List[Leaf] = list(reversed(line.leaves)) + reversed_leaves_ids: List[LeafID] = [id(leaf) for leaf in reversed_leaves] next_leaf = last_leaf - for leaf in reversed(line.leaves[:-1]): + for i, leaf in enumerate(reversed_leaves): + if i == 0: + continue if next_leaf.type in CLOSING_BRACKETS and leaf.type == token.COMMA: - trailing_comma = True - break + # print(f'>>>> {next_leaf=}') + opening = next_leaf.opening_bracket + if opening is None: + continue + try: + opening_bracket_index = reversed_leaves_ids.index(id(opening)) + except ValueError: + pass + else: + trailing_comma = True + include.update( + reversed_leaves_ids[i + 1 : opening_bracket_index - 1] + ) next_leaf = leaf + exclude = set(reversed_leaves_ids) - include max_priority = line.bracket_tracker.max_delimiter_priority(exclude=exclude) except (IndexError, ValueError): return False diff --git a/tests/data/preview/skip_magic_trailing_comma.py b/tests/data/preview/skip_magic_trailing_comma.py index 64a2212c025..c020db79864 100644 --- a/tests/data/preview/skip_magic_trailing_comma.py +++ b/tests/data/preview/skip_magic_trailing_comma.py @@ -24,6 +24,8 @@ five, ) +func1(arg1).func2(arg2,).func3(arg3).func4(arg4,).func5(arg5) + ( a, b, @@ -33,6 +35,17 @@ arg1 ) and func2(arg2) +func( + argument1, + ( + one, + two, + ), + argument4, + argument5, + argument6, +) + # output # We should not remove the trailing comma in a single-element subscript. a: tuple[int,] @@ -54,4 +67,8 @@ # Trailing commas in multiple chained non-nested parens. zero(one).two(three).four(five) +func1(arg1).func2(arg2).func3(arg3).func4(arg4).func5(arg5) + (a, b, c, d) = func1(arg1) and func2(arg2) + +func(argument1, (one, two), argument4, argument5, argument6) diff --git a/tests/data/preview/trailing_commas_in_leading_parts.py b/tests/data/preview/trailing_commas_in_leading_parts.py index b51af1d258d..61c7c24819d 100644 --- a/tests/data/preview/trailing_commas_in_leading_parts.py +++ b/tests/data/preview/trailing_commas_in_leading_parts.py @@ -6,6 +6,51 @@ five, ) +func1(arg1).func2(arg2,).func3(arg3).func4(arg4,).func5(arg5) + +# Inner one-element tuple shouldn't explode +func1(arg1).func2(arg1, (one_tuple,)).func3(arg3) + +( + a, + b, + c, + d, +) = func1( + arg1 +) and func2(arg2) + + +# Example from https://github.com/psf/black/issues/3229 +def refresh_token(self, device_family, refresh_token, api_key): + return self.orchestration.refresh_token( + data={ + "refreshToken": refresh_token, + }, + api_key=api_key, + )["extensions"]["sdk"]["token"] + + +# output + + +zero( + one, +).two( + three, +).four( + five, +) + +func1(arg1).func2( + arg2, +).func3(arg3).func4( + arg4, +).func5(arg5) + +# Inner one-element tuple shouldn't explode +func1(arg1).func2(arg1, (one_tuple,)).func3(arg3) + ( a, b, diff --git a/tests/data/simple_cases/function_trailing_comma.py b/tests/data/simple_cases/function_trailing_comma.py index 429eb0e330f..abe9617c0e9 100644 --- a/tests/data/simple_cases/function_trailing_comma.py +++ b/tests/data/simple_cases/function_trailing_comma.py @@ -49,6 +49,17 @@ def func() -> ((also_super_long_type_annotation_that_may_cause_an_AST_related_cr ): pass + +# Make sure inner one-element tuple won't explode +some_module.some_function( + argument1, (one_element_tuple,), argument4, argument5, argument6 +) + +# Inner trailing comma causes outer to explode +some_module.some_function( + argument1, (one, two,), argument4, argument5, argument6 +) + # output def f( @@ -151,3 +162,21 @@ def func() -> ( ) ): pass + + +# Make sure inner one-element tuple won't explode +some_module.some_function( + argument1, (one_element_tuple,), argument4, argument5, argument6 +) + +# Inner trailing comma causes outer to explode +some_module.some_function( + argument1, + ( + one, + two, + ), + argument4, + argument5, + argument6, +) From c38bf9a57eab7f9fe53c59351ffe85f20bed1a83 Mon Sep 17 00:00:00 2001 From: Yilei Yang Date: Tue, 1 Nov 2022 12:23:59 -0700 Subject: [PATCH 05/16] Switch to importing members. --- src/black/linegen.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/black/linegen.py b/src/black/linegen.py index 1b96bba0bc9..de4e3bc9ef6 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -1,8 +1,8 @@ """ Generating lines of code. """ -import enum import sys +from enum import Enum, auto from functools import partial, wraps from typing import Collection, Iterator, List, Optional, Set, Union, cast @@ -562,10 +562,10 @@ def _rhs( yield line -class _BracketSplitComponent(enum.Enum): - head = enum.auto() - body = enum.auto() - tail = enum.auto() +class _BracketSplitComponent(Enum): + head = auto() + body = auto() + tail = auto() def left_hand_split(line: Line, _features: Collection[Feature] = ()) -> Iterator[Line]: From 0ae0c5c16f49a496e3dfeb08f12561a93b2b2a3a Mon Sep 17 00:00:00 2001 From: Yilei Yang Date: Tue, 1 Nov 2022 17:16:13 -0700 Subject: [PATCH 06/16] WIP: fix the bracket tracker usage. --- src/black/linegen.py | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/black/linegen.py b/src/black/linegen.py index de4e3bc9ef6..e88bc2be904 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -793,11 +793,36 @@ def bracket_split_build_line( Preview.handle_trailing_commas_in_leading_parts in original.mode and component == _BracketSplitComponent.head ) + ids_to_track = set() + if component == _BracketSplitComponent.head: + is_trailing_non_matching_opening_brackets = True + bracket_depth = 0 + for leaf in reversed(leaves): + if leaf is opening_bracket: + continue + if leaf.type in CLOSING_BRACKETS: + is_trailing_non_matching_opening_brackets = False + bracket_depth += 1 + elif leaf.type in OPENING_BRACKETS: + if bracket_depth == 0: + if is_trailing_non_matching_opening_brackets: + continue + else: + break + else: + bracket_depth -= 1 + ids_to_track.add(id(leaf)) for leaf in leaves: - result.append(leaf, preformatted=True, track_bracket=track_bracket) + result.append( + leaf, + preformatted=True, + track_bracket=track_bracket and id(leaf) in ids_to_track, + ) for comment_after in original.comments_after(leaf): result.append(comment_after, preformatted=True) - if should_split_line(result, opening_bracket, component): + if component == _BracketSplitComponent.body and should_split_line( + result, opening_bracket, component + ): result.should_split_rhs = True return result @@ -1210,8 +1235,9 @@ def should_split_line( for i, leaf in enumerate(reversed_leaves): if i == 0: continue - if next_leaf.type in CLOSING_BRACKETS and leaf.type == token.COMMA: - # print(f'>>>> {next_leaf=}') + if leaf.type in CLOSING_BRACKETS and line.has_magic_trailing_comma( + leaf + ): opening = next_leaf.opening_bracket if opening is None: continue From f53c2b938511e543c38a3127b44fb4403f7ebbe0 Mon Sep 17 00:00:00 2001 From: Yilei Yang Date: Tue, 1 Nov 2022 19:22:52 -0700 Subject: [PATCH 07/16] Clean up implementation. --- src/black/brackets.py | 31 ++++++- src/black/linegen.py | 84 +++++-------------- src/black/mode.py | 2 +- .../trailing_commas_in_leading_parts.py | 17 +--- 4 files changed, 52 insertions(+), 82 deletions(-) diff --git a/src/black/brackets.py b/src/black/brackets.py index ce78808e1a7..4452b6c44d8 100644 --- a/src/black/brackets.py +++ b/src/black/brackets.py @@ -2,7 +2,7 @@ import sys from dataclasses import dataclass, field -from typing import Dict, Iterable, List, Optional, Tuple, Union +from typing import Dict, Iterable, List, Optional, Sequence, Set, Tuple, Union if sys.version_info < (3, 8): from typing_extensions import Final @@ -336,3 +336,32 @@ def max_delimiter_priority_in_atom(node: LN) -> Priority: except ValueError: return 0 + + +def get_inner_leaf_ids_with_matching_brackets(leaves: Sequence[Leaf]) -> Set[LeafID]: + """Returns a continuous list of inner leaf ids. + + The list starts with the first opening bracket whose closing bracket is included in + `leaves`, and ends with the last closing bracket whose opening bracket is included + in `leaves`. Leaves in between pairs of matching brackets are included. + """ + ids = set() + is_tail = True + bracket_depth = 0 + for leaf in reversed(leaves): + if leaf.type in CLOSING_BRACKETS: + is_tail = False + bracket_depth += 1 + elif leaf.type in OPENING_BRACKETS: + if bracket_depth == 0: + if is_tail: + # Excluding non matching opening brackets at the tail + continue + else: + # Found a non matching opening bracket at the head, no more leaves + # to return + break + else: + bracket_depth -= 1 + ids.add(id(leaf)) + return ids diff --git a/src/black/linegen.py b/src/black/linegen.py index e88bc2be904..18188f9841b 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -6,7 +6,12 @@ from functools import partial, wraps from typing import Collection, Iterator, List, Optional, Set, Union, cast -from black.brackets import COMMA_PRIORITY, DOT_PRIORITY, max_delimiter_priority_in_atom +from black.brackets import ( + COMMA_PRIORITY, + DOT_PRIORITY, + get_inner_leaf_ids_with_matching_brackets, + max_delimiter_priority_in_atom, +) from black.comments import FMT_OFF, generate_comments, list_comments from black.lines import ( Line, @@ -742,8 +747,8 @@ def bracket_split_build_line( ) -> Line: """Return a new line with given `leaves` and respective comments from `original`. - If it's the head component, trailing commas inside inner parens will also be - checked to ensure they are respected. + If it's the head component, brackets will be tracked so trailing commas are + respected. If it's the body component, the result line is one-indented inside brackets and as such has its first leaf's prefix normalized and a trailing comma added when @@ -789,39 +794,23 @@ def bracket_split_build_line( break # Populate the line - track_bracket = ( - Preview.handle_trailing_commas_in_leading_parts in original.mode + if ( + Preview.handle_trailing_commas_in_head in original.mode and component == _BracketSplitComponent.head - ) - ids_to_track = set() - if component == _BracketSplitComponent.head: - is_trailing_non_matching_opening_brackets = True - bracket_depth = 0 - for leaf in reversed(leaves): - if leaf is opening_bracket: - continue - if leaf.type in CLOSING_BRACKETS: - is_trailing_non_matching_opening_brackets = False - bracket_depth += 1 - elif leaf.type in OPENING_BRACKETS: - if bracket_depth == 0: - if is_trailing_non_matching_opening_brackets: - continue - else: - break - else: - bracket_depth -= 1 - ids_to_track.add(id(leaf)) + ): + leaves_to_track = get_inner_leaf_ids_with_matching_brackets(leaves) + else: + leaves_to_track = set() for leaf in leaves: result.append( leaf, preformatted=True, - track_bracket=track_bracket and id(leaf) in ids_to_track, + track_bracket=id(leaf) in leaves_to_track, ) for comment_after in original.comments_after(leaf): result.append(comment_after, preformatted=True) if component == _BracketSplitComponent.body and should_split_line( - result, opening_bracket, component + result, opening_bracket ): result.should_split_rhs = True return result @@ -1201,57 +1190,22 @@ def maybe_make_parens_invisible_in_atom( return True -def should_split_line( - line: Line, opening_bracket: Leaf, component: _BracketSplitComponent -) -> bool: +def should_split_line(line: Line, opening_bracket: Leaf) -> bool: """Should `line` be immediately split with `delimiter_split()` after RHS?""" - if component == _BracketSplitComponent.tail: - return False - if not (opening_bracket.parent and opening_bracket.value in "[{("): return False - # We're essentially checking if the line is delimited by commas and there's more + # We're essentially checking if the body is delimited by commas and there's more # than one of them (we're excluding the trailing comma and if the delimiter priority # is still commas, that means there's more). exclude = set() trailing_comma = False try: last_leaf = line.leaves[-1] - if component == _BracketSplitComponent.body and last_leaf.type == token.COMMA: + if last_leaf.type == token.COMMA: trailing_comma = True exclude.add(id(last_leaf)) - elif ( - component == _BracketSplitComponent.head - and Preview.handle_trailing_commas_in_leading_parts in line.mode - ): - # Check commas inside inner parens, we need to only include leaves inside - # the matching brackets. - include: Set[LeafID] = set() - reversed_leaves: List[Leaf] = list(reversed(line.leaves)) - reversed_leaves_ids: List[LeafID] = [id(leaf) for leaf in reversed_leaves] - next_leaf = last_leaf - for i, leaf in enumerate(reversed_leaves): - if i == 0: - continue - if leaf.type in CLOSING_BRACKETS and line.has_magic_trailing_comma( - leaf - ): - opening = next_leaf.opening_bracket - if opening is None: - continue - try: - opening_bracket_index = reversed_leaves_ids.index(id(opening)) - except ValueError: - pass - else: - trailing_comma = True - include.update( - reversed_leaves_ids[i + 1 : opening_bracket_index - 1] - ) - next_leaf = leaf - exclude = set(reversed_leaves_ids) - include max_priority = line.bracket_tracker.max_delimiter_priority(exclude=exclude) except (IndexError, ValueError): return False diff --git a/src/black/mode.py b/src/black/mode.py index 2921e2cf489..a3ce20b8619 100644 --- a/src/black/mode.py +++ b/src/black/mode.py @@ -151,7 +151,7 @@ class Preview(Enum): annotation_parens = auto() empty_lines_before_class_or_def_with_leading_comments = auto() - handle_trailing_commas_in_leading_parts = auto() + handle_trailing_commas_in_head = auto() long_docstring_quotes_on_newline = auto() normalize_docstring_quotes_and_prefixes_properly = auto() one_element_subscript = auto() diff --git a/tests/data/preview/trailing_commas_in_leading_parts.py b/tests/data/preview/trailing_commas_in_leading_parts.py index 61c7c24819d..20060f0004f 100644 --- a/tests/data/preview/trailing_commas_in_leading_parts.py +++ b/tests/data/preview/trailing_commas_in_leading_parts.py @@ -1,24 +1,11 @@ -zero( - one, -).two( - three, -).four( - five, -) +zero(one,).two(three,).four(five,) func1(arg1).func2(arg2,).func3(arg3).func4(arg4,).func5(arg5) # Inner one-element tuple shouldn't explode func1(arg1).func2(arg1, (one_tuple,)).func3(arg3) -( - a, - b, - c, - d, -) = func1( - arg1 -) and func2(arg2) +(a, b, c, d,) = func1(arg1) and func2(arg2) # Example from https://github.com/psf/black/issues/3229 From 0892ca1641d6ac024316d955d8c944d01b993933 Mon Sep 17 00:00:00 2001 From: Yilei Yang Date: Tue, 1 Nov 2022 20:40:21 -0700 Subject: [PATCH 08/16] Undo the BracketMatchError change; simply implementation. --- src/black/brackets.py | 43 +++++++++---------------------------------- src/black/linegen.py | 27 +++++++++++++++++---------- src/black/trans.py | 9 ++++++++- 3 files changed, 34 insertions(+), 45 deletions(-) diff --git a/src/black/brackets.py b/src/black/brackets.py index 4452b6c44d8..ffc1ca31cc1 100644 --- a/src/black/brackets.py +++ b/src/black/brackets.py @@ -57,6 +57,10 @@ DOT_PRIORITY: Final = 1 +class BracketMatchError(Exception): + """Raised when an opening bracket is unable to be matched to a closing bracket.""" + + @dataclass class BracketTracker: """Keeps track of brackets on a line.""" @@ -93,11 +97,11 @@ def mark(self, leaf: Leaf) -> None: self.depth -= 1 try: opening_bracket = self.bracket_match.pop((self.depth, leaf.type)) - except KeyError: - # OK to have non-matching closing brackets, as the line might be a - # continuation from previous lines and the closing brackets match - # the ones from previously split lines. - return + except KeyError as e: + raise BracketMatchError( + "Unable to match a closing bracket to the following opening" + f" bracket: {leaf}" + ) from e leaf.opening_bracket = opening_bracket if not leaf.value: self.invisible.append(leaf) @@ -336,32 +340,3 @@ def max_delimiter_priority_in_atom(node: LN) -> Priority: except ValueError: return 0 - - -def get_inner_leaf_ids_with_matching_brackets(leaves: Sequence[Leaf]) -> Set[LeafID]: - """Returns a continuous list of inner leaf ids. - - The list starts with the first opening bracket whose closing bracket is included in - `leaves`, and ends with the last closing bracket whose opening bracket is included - in `leaves`. Leaves in between pairs of matching brackets are included. - """ - ids = set() - is_tail = True - bracket_depth = 0 - for leaf in reversed(leaves): - if leaf.type in CLOSING_BRACKETS: - is_tail = False - bracket_depth += 1 - elif leaf.type in OPENING_BRACKETS: - if bracket_depth == 0: - if is_tail: - # Excluding non matching opening brackets at the tail - continue - else: - # Found a non matching opening bracket at the head, no more leaves - # to return - break - else: - bracket_depth -= 1 - ids.add(id(leaf)) - return ids diff --git a/src/black/linegen.py b/src/black/linegen.py index 18188f9841b..28d92120258 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -6,12 +6,7 @@ from functools import partial, wraps from typing import Collection, Iterator, List, Optional, Set, Union, cast -from black.brackets import ( - COMMA_PRIORITY, - DOT_PRIORITY, - get_inner_leaf_ids_with_matching_brackets, - max_delimiter_priority_in_atom, -) +from black.brackets import COMMA_PRIORITY, DOT_PRIORITY, max_delimiter_priority_in_atom from black.comments import FMT_OFF, generate_comments, list_comments from black.lines import ( Line, @@ -793,14 +788,26 @@ def bracket_split_build_line( leaves.insert(i + 1, new_comma) break - # Populate the line + leaves_to_track = set() if ( Preview.handle_trailing_commas_in_head in original.mode and component == _BracketSplitComponent.head ): - leaves_to_track = get_inner_leaf_ids_with_matching_brackets(leaves) - else: - leaves_to_track = set() + try: + # Only track brackets from the first opening bracket to the last closing + # bracket. + start_index = next( + i for i, l in enumerate(leaves) if l.type in OPENING_BRACKETS + ) + end_index = next( + i for i, l in enumerate(reversed(leaves)) if l.type in CLOSING_BRACKETS + ) + leaves_to_track = set( + id(leaf) for leaf in leaves[start_index : len(leaves) - end_index + 1] + ) + except StopIteration: + pass + # Populate the line for leaf in leaves: result.append( leaf, diff --git a/src/black/trans.py b/src/black/trans.py index a2c739c62ec..8893ab02aab 100644 --- a/src/black/trans.py +++ b/src/black/trans.py @@ -30,6 +30,7 @@ from mypy_extensions import trait +from black.brackets import BracketMatchError from black.comments import contains_pragma_comment from black.lines import Line, append_leaves from black.mode import Feature @@ -811,7 +812,13 @@ def do_transform(self, line: Line, string_idx: int) -> Iterator[TResult[Line]]: new_line = line.clone() new_line.comments = line.comments.copy() - append_leaves(new_line, line, LL[: string_idx - 1]) + try: + append_leaves(new_line, line, LL[: string_idx - 1]) + except BracketMatchError: + # HACK: I believe there is currently a bug somewhere in + # right_hand_split() that is causing brackets to not be tracked + # properly by a shared BracketTracker. + append_leaves(new_line, line, LL[: string_idx - 1], preformatted=True) string_leaf = Leaf(token.STRING, LL[string_idx].value) LL[string_idx - 1].remove() From 227c5f45a9a64b7a2ed1bca97c4416e4931073ca Mon Sep 17 00:00:00 2001 From: Yilei Yang Date: Tue, 1 Nov 2022 20:48:19 -0700 Subject: [PATCH 09/16] Fix lint. --- src/black/brackets.py | 2 +- src/black/linegen.py | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/black/brackets.py b/src/black/brackets.py index ffc1ca31cc1..3566f5b6c37 100644 --- a/src/black/brackets.py +++ b/src/black/brackets.py @@ -2,7 +2,7 @@ import sys from dataclasses import dataclass, field -from typing import Dict, Iterable, List, Optional, Sequence, Set, Tuple, Union +from typing import Dict, Iterable, List, Optional, Tuple, Union if sys.version_info < (3, 8): from typing_extensions import Final diff --git a/src/black/linegen.py b/src/black/linegen.py index 28d92120258..d314c6f7f49 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -788,7 +788,8 @@ def bracket_split_build_line( leaves.insert(i + 1, new_comma) break - leaves_to_track = set() + start_index = len(leaves) + end_index = -1 if ( Preview.handle_trailing_commas_in_head in original.mode and component == _BracketSplitComponent.head @@ -800,19 +801,18 @@ def bracket_split_build_line( i for i, l in enumerate(leaves) if l.type in OPENING_BRACKETS ) end_index = next( - i for i, l in enumerate(reversed(leaves)) if l.type in CLOSING_BRACKETS - ) - leaves_to_track = set( - id(leaf) for leaf in leaves[start_index : len(leaves) - end_index + 1] + len(leaves) - i + for i, l in enumerate(reversed(leaves)) + if l.type in CLOSING_BRACKETS ) except StopIteration: pass # Populate the line - for leaf in leaves: + for i, leaf in enumerate(leaves): result.append( leaf, preformatted=True, - track_bracket=id(leaf) in leaves_to_track, + track_bracket=start_index <= i <= end_index, ) for comment_after in original.comments_after(leaf): result.append(comment_after, preformatted=True) From b334d775a6962f102cce74a77ac185e6a4a834da Mon Sep 17 00:00:00 2001 From: Yilei Yang Date: Wed, 2 Nov 2022 00:11:07 -0700 Subject: [PATCH 10/16] Fix an infinite recursion error. --- src/black/linegen.py | 16 +++++++++++++--- .../preview/trailing_commas_in_leading_parts.py | 16 ++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/black/linegen.py b/src/black/linegen.py index d314c6f7f49..4359aa26fac 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -788,8 +788,7 @@ def bracket_split_build_line( leaves.insert(i + 1, new_comma) break - start_index = len(leaves) - end_index = -1 + leaves_to_track: Set[LeafID] = set() if ( Preview.handle_trailing_commas_in_head in original.mode and component == _BracketSplitComponent.head @@ -807,12 +806,22 @@ def bracket_split_build_line( ) except StopIteration: pass + else: + depth = 0 + for i in range(end_index, start_index-1, -1): + leaf = leaves[i] + if leaf.type in CLOSING_BRACKETS: + depth += 1 + if depth > 0: + leaves_to_track.add(id(leaf)) + if leaf.type in OPENING_BRACKETS: + depth -= 1 # Populate the line for i, leaf in enumerate(leaves): result.append( leaf, preformatted=True, - track_bracket=start_index <= i <= end_index, + track_bracket=id(leaf) in leaves_to_track, ) for comment_after in original.comments_after(leaf): result.append(comment_after, preformatted=True) @@ -1330,6 +1339,7 @@ def run_transformer( # structure), then we can't proceed. Doing so would cause the below # call to `append_leaves()` to fail. or any(leaf.parent is None for leaf in line.leaves) + # or Feature.FORCE_OPTIONAL_PARENTHESES in features ): return result diff --git a/tests/data/preview/trailing_commas_in_leading_parts.py b/tests/data/preview/trailing_commas_in_leading_parts.py index 20060f0004f..676725c12a3 100644 --- a/tests/data/preview/trailing_commas_in_leading_parts.py +++ b/tests/data/preview/trailing_commas_in_leading_parts.py @@ -18,6 +18,14 @@ def refresh_token(self, device_family, refresh_token, api_key): )["extensions"]["sdk"]["token"] +# Edge case where a bug in a working-in-progress version of +# https://github.com/psf/black/pull/3370 causes an infinite recursion. +assert ( + long_module.long_class.long_func().another_func() + == long_module.long_class.long_func()["some_key"].another_func(arg1) +) + + # output @@ -56,3 +64,11 @@ def refresh_token(self, device_family, refresh_token, api_key): }, api_key=api_key, )["extensions"]["sdk"]["token"] + + +# Edge case where a bug in a working-in-progress version of +# https://github.com/psf/black/pull/3370 causes an infinite recursion. +assert ( + long_module.long_class.long_func().another_func() + == long_module.long_class.long_func()["some_key"].another_func(arg1) +) From dec80768dfd67c8f086131c1dc19754d2fedffc5 Mon Sep 17 00:00:00 2001 From: Yilei Yang Date: Wed, 2 Nov 2022 00:13:34 -0700 Subject: [PATCH 11/16] Fix lint errors. --- src/black/linegen.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/black/linegen.py b/src/black/linegen.py index 4359aa26fac..cbe3b9f3091 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -808,7 +808,7 @@ def bracket_split_build_line( pass else: depth = 0 - for i in range(end_index, start_index-1, -1): + for i in range(end_index, start_index - 1, -1): leaf = leaves[i] if leaf.type in CLOSING_BRACKETS: depth += 1 @@ -817,7 +817,7 @@ def bracket_split_build_line( if leaf.type in OPENING_BRACKETS: depth -= 1 # Populate the line - for i, leaf in enumerate(leaves): + for leaf in leaves: result.append( leaf, preformatted=True, From d122d788e846707bbf35a4df555ca5062ad324ef Mon Sep 17 00:00:00 2001 From: Yilei Yang Date: Wed, 2 Nov 2022 00:32:28 -0700 Subject: [PATCH 12/16] Extract a get_leaves_inside_matching_brackets function. --- src/black/brackets.py | 34 +++++++++++++++++++++++++++++++++- src/black/linegen.py | 31 +++++++------------------------ 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/src/black/brackets.py b/src/black/brackets.py index 3566f5b6c37..0a5317f6773 100644 --- a/src/black/brackets.py +++ b/src/black/brackets.py @@ -2,7 +2,7 @@ import sys from dataclasses import dataclass, field -from typing import Dict, Iterable, List, Optional, Tuple, Union +from typing import Dict, Iterable, List, Optional, Sequence, Set, Tuple, Union if sys.version_info < (3, 8): from typing_extensions import Final @@ -340,3 +340,35 @@ def max_delimiter_priority_in_atom(node: LN) -> Priority: except ValueError: return 0 + + +def get_leaves_inside_matching_brackets(leaves: Sequence[Leaf]) -> Set[LeafID]: + """Return leaves that are inside matching brackets. + + The input `leaves` can have non-matching brackets at the head or tail parts. + Matching brackets are included. + """ + try: + # Only track brackets from the first opening bracket to the last closing + # bracket. + start_index = next( + i for i, l in enumerate(leaves) if l.type in OPENING_BRACKETS + ) + end_index = next( + len(leaves) - i + for i, l in enumerate(reversed(leaves)) + if l.type in CLOSING_BRACKETS + ) + except StopIteration: + return set() + ids = set() + depth = 0 + for i in range(end_index, start_index - 1, -1): + leaf = leaves[i] + if leaf.type in CLOSING_BRACKETS: + depth += 1 + if depth > 0: + ids.add(id(leaf)) + if leaf.type in OPENING_BRACKETS: + depth -= 1 + return ids diff --git a/src/black/linegen.py b/src/black/linegen.py index cbe3b9f3091..235b630a748 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -6,7 +6,12 @@ from functools import partial, wraps from typing import Collection, Iterator, List, Optional, Set, Union, cast -from black.brackets import COMMA_PRIORITY, DOT_PRIORITY, max_delimiter_priority_in_atom +from black.brackets import ( + COMMA_PRIORITY, + DOT_PRIORITY, + get_leaves_inside_matching_brackets, + max_delimiter_priority_in_atom, +) from black.comments import FMT_OFF, generate_comments, list_comments from black.lines import ( Line, @@ -793,29 +798,7 @@ def bracket_split_build_line( Preview.handle_trailing_commas_in_head in original.mode and component == _BracketSplitComponent.head ): - try: - # Only track brackets from the first opening bracket to the last closing - # bracket. - start_index = next( - i for i, l in enumerate(leaves) if l.type in OPENING_BRACKETS - ) - end_index = next( - len(leaves) - i - for i, l in enumerate(reversed(leaves)) - if l.type in CLOSING_BRACKETS - ) - except StopIteration: - pass - else: - depth = 0 - for i in range(end_index, start_index - 1, -1): - leaf = leaves[i] - if leaf.type in CLOSING_BRACKETS: - depth += 1 - if depth > 0: - leaves_to_track.add(id(leaf)) - if leaf.type in OPENING_BRACKETS: - depth -= 1 + leaves_to_track = get_leaves_inside_matching_brackets(leaves) # Populate the line for leaf in leaves: result.append( From 0909f3f83c5530dbde6b7d2670a179253c30c1b6 Mon Sep 17 00:00:00 2001 From: "Yilei \"Dolee\" Yang" Date: Tue, 8 Nov 2022 08:32:53 -0800 Subject: [PATCH 13/16] Use is for comparing enums. Co-authored-by: Jelle Zijlstra --- src/black/linegen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/black/linegen.py b/src/black/linegen.py index 235b630a748..545095732b7 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -755,7 +755,7 @@ def bracket_split_build_line( expected. """ result = Line(mode=original.mode, depth=original.depth) - if component == _BracketSplitComponent.body: + if component is _BracketSplitComponent.body: result.inside_brackets = True result.depth += 1 if leaves: From b59190b7f6b6663b38735e9e6f81926dd8e1f063 Mon Sep 17 00:00:00 2001 From: "Yilei \"Dolee\" Yang" Date: Tue, 8 Nov 2022 08:33:01 -0800 Subject: [PATCH 14/16] Use is for comparing enums. Co-authored-by: Jelle Zijlstra --- src/black/linegen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/black/linegen.py b/src/black/linegen.py index 545095732b7..3360027cf3c 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -796,7 +796,7 @@ def bracket_split_build_line( leaves_to_track: Set[LeafID] = set() if ( Preview.handle_trailing_commas_in_head in original.mode - and component == _BracketSplitComponent.head + and component is _BracketSplitComponent.head ): leaves_to_track = get_leaves_inside_matching_brackets(leaves) # Populate the line From 0252a367a3c11600cce529286f4f5f6b77467f54 Mon Sep 17 00:00:00 2001 From: "Yilei \"Dolee\" Yang" Date: Tue, 8 Nov 2022 08:33:08 -0800 Subject: [PATCH 15/16] Use is for comparing enums. Co-authored-by: Jelle Zijlstra --- src/black/linegen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/black/linegen.py b/src/black/linegen.py index 3360027cf3c..15b176bde24 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -808,7 +808,7 @@ def bracket_split_build_line( ) for comment_after in original.comments_after(leaf): result.append(comment_after, preformatted=True) - if component == _BracketSplitComponent.body and should_split_line( + if component is _BracketSplitComponent.body and should_split_line( result, opening_bracket ): result.should_split_rhs = True From 2307a95edd0eee0daf124904b2579525fc702cc5 Mon Sep 17 00:00:00 2001 From: Yilei Yang Date: Tue, 8 Nov 2022 08:33:41 -0800 Subject: [PATCH 16/16] Remove commented out code. --- src/black/linegen.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/black/linegen.py b/src/black/linegen.py index 15b176bde24..219495e9a5e 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -1322,7 +1322,6 @@ def run_transformer( # structure), then we can't proceed. Doing so would cause the below # call to `append_leaves()` to fail. or any(leaf.parent is None for leaf in line.leaves) - # or Feature.FORCE_OPTIONAL_PARENTHESES in features ): return result