diff --git a/CHANGES.md b/CHANGES.md index 992b3800405..2c2fb7c5732 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -21,6 +21,8 @@ parentheses (#3307) - Correctly handle trailing commas that are inside a line's leading non-nested parens (#3370) +- Correctly handle trailing commas inside dictionaries where a comment is after the + final entry (#3393) ### Configuration diff --git a/src/black/linegen.py b/src/black/linegen.py index 219495e9a5e..2d968ab3c80 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -830,6 +830,25 @@ def split_wrapper(line: Line, features: Collection[Feature] = ()) -> Iterator[Li return split_wrapper +def _get_last_non_comment_leaf(line: Line) -> Optional[int]: + for leaf_idx in range(len(line.leaves) - 1, 0, -1): + if line.leaves[leaf_idx].type != STANDALONE_COMMENT: + return leaf_idx + return None + + +def _safe_add_trailing_comma(safe: bool, delimiter_priority: int, line: Line) -> Line: + if ( + safe + and delimiter_priority == COMMA_PRIORITY + and line.leaves[-1].type != token.COMMA + and line.leaves[-1].type != STANDALONE_COMMENT + ): + new_comma = Leaf(token.COMMA, ",") + line.append(new_comma) + return line + + @dont_increase_indentation def delimiter_split(line: Line, features: Collection[Feature] = ()) -> Iterator[Line]: """Split according to delimiters of the highest priority. @@ -871,7 +890,8 @@ def append_to_line(leaf: Leaf) -> Iterator[Line]: ) current_line.append(leaf) - for leaf in line.leaves: + last_non_comment_leaf = _get_last_non_comment_leaf(line) + for leaf_idx, leaf in enumerate(line.leaves): yield from append_to_line(leaf) for comment_after in line.comments_after(leaf): @@ -888,6 +908,11 @@ def append_to_line(leaf: Leaf) -> Iterator[Line]: trailing_comma_safe and Feature.TRAILING_COMMA_IN_CALL in features ) + if last_leaf.type == STANDALONE_COMMENT and leaf_idx == last_non_comment_leaf: + current_line = _safe_add_trailing_comma( + trailing_comma_safe, delimiter_priority, current_line + ) + leaf_priority = bt.delimiters.get(id(leaf)) if leaf_priority == delimiter_priority: yield current_line @@ -896,14 +921,9 @@ def append_to_line(leaf: Leaf) -> Iterator[Line]: mode=line.mode, depth=line.depth, inside_brackets=line.inside_brackets ) if current_line: - if ( - trailing_comma_safe - and delimiter_priority == COMMA_PRIORITY - and current_line.leaves[-1].type != token.COMMA - and current_line.leaves[-1].type != STANDALONE_COMMENT - ): - new_comma = Leaf(token.COMMA, ",") - current_line.append(new_comma) + current_line = _safe_add_trailing_comma( + trailing_comma_safe, delimiter_priority, current_line + ) yield current_line diff --git a/tests/data/simple_cases/function_trailing_comma.py b/tests/data/simple_cases/function_trailing_comma.py index abe9617c0e9..2040d501fc2 100644 --- a/tests/data/simple_cases/function_trailing_comma.py +++ b/tests/data/simple_cases/function_trailing_comma.py @@ -1,5 +1,29 @@ def f(a,): d = {'key': 'value',} + e = { + "a": fun(msg, "ts"), + "longggggggggggggggid": ..., + "longgggggggggggggggggggkey": ..., "created": ... + # "longkey": ... + } + f = [ + arg1, + arg2, + arg3, arg4 + # comment + ] + g = ( + arg1, + arg2, + arg3, arg4 + # comment + ) + h = { + arg1, + arg2, + arg3, arg4 + # comment + } tup = (1,) def f2(a,b,): @@ -68,6 +92,34 @@ def f( d = { "key": "value", } + e = { + "a": fun(msg, "ts"), + "longggggggggggggggid": ..., + "longgggggggggggggggggggkey": ..., + "created": ..., + # "longkey": ... + } + f = [ + arg1, + arg2, + arg3, + arg4, + # comment + ] + g = ( + arg1, + arg2, + arg3, + arg4, + # comment + ) + h = { + arg1, + arg2, + arg3, + arg4, + # comment + } tup = (1,)