From 351b0eefb0aa95d09a898cc8183c02586991fa0d Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sat, 13 Aug 2022 06:41:34 -0700 Subject: [PATCH] Strip trailing commas in subscripts with -C (#3209) Fixes #2296, #3204 --- CHANGES.md | 2 ++ src/black/lines.py | 18 +++++++++- src/black/mode.py | 1 + .../data/preview/skip_magic_trailing_comma.py | 34 +++++++++++++++++++ tests/test_format.py | 7 +++- 5 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 tests/data/preview/skip_magic_trailing_comma.py diff --git a/CHANGES.md b/CHANGES.md index 79f4ce59187..fb7a2723b67 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -24,6 +24,8 @@ this is invalid. This was a bug introduced in version 22.6.0. (#3166) - `--skip-string-normalization` / `-S` now prevents docstring prefixes from being normalized as expected (#3168) +- When using `--skip-magic-trailing-comma` or `-C`, trailing commas are stripped from + subscript expressions with more than 1 element (#3209) ### _Blackd_ diff --git a/src/black/lines.py b/src/black/lines.py index 1ebc7808901..30622650d53 100644 --- a/src/black/lines.py +++ b/src/black/lines.py @@ -273,6 +273,8 @@ def has_magic_trailing_comma( - it's not a single-element subscript Additionally, if ensure_removable: - it's not from square bracket indexing + (specifically, single-element square bracket indexing with + Preview.skip_magic_trailing_comma_in_subscript) """ if not ( closing.type in CLOSING_BRACKETS @@ -301,8 +303,22 @@ def has_magic_trailing_comma( if not ensure_removable: return True + comma = self.leaves[-1] - return bool(comma.parent and comma.parent.type == syms.listmaker) + if comma.parent is None: + return False + if Preview.skip_magic_trailing_comma_in_subscript in self.mode: + return ( + comma.parent.type != syms.subscriptlist + or closing.opening_bracket is None + or not is_one_sequence_between( + closing.opening_bracket, + closing, + self.leaves, + brackets=(token.LSQB, token.RSQB), + ) + ) + return comma.parent.type == syms.listmaker if self.is_import: return True diff --git a/src/black/mode.py b/src/black/mode.py index f6d0cbf62bd..6c0847e8bcc 100644 --- a/src/black/mode.py +++ b/src/black/mode.py @@ -156,6 +156,7 @@ class Preview(Enum): remove_block_trailing_newline = auto() remove_redundant_parens = auto() string_processing = auto() + skip_magic_trailing_comma_in_subscript = auto() class Deprecated(UserWarning): diff --git a/tests/data/preview/skip_magic_trailing_comma.py b/tests/data/preview/skip_magic_trailing_comma.py new file mode 100644 index 00000000000..e98174af427 --- /dev/null +++ b/tests/data/preview/skip_magic_trailing_comma.py @@ -0,0 +1,34 @@ +# We should not remove the trailing comma in a single-element subscript. +a: tuple[int,] +b = tuple[int,] + +# But commas in multiple element subscripts should be removed. +c: tuple[int, int,] +d = tuple[int, int,] + +# Remove commas for non-subscripts. +small_list = [1,] +list_of_types = [tuple[int,],] +small_set = {1,} +set_of_types = {tuple[int,],} + +# Except single element tuples +small_tuple = (1,) + +# output +# We should not remove the trailing comma in a single-element subscript. +a: tuple[int,] +b = tuple[int,] + +# But commas in multiple element subscripts should be removed. +c: tuple[int, int] +d = tuple[int, int] + +# Remove commas for non-subscripts. +small_list = [1] +list_of_types = [tuple[int,]] +small_set = {1} +set_of_types = {tuple[int,]} + +# Except single element tuples +small_tuple = (1,) diff --git a/tests/test_format.py b/tests/test_format.py index 3645934721f..01cd61eef63 100644 --- a/tests/test_format.py +++ b/tests/test_format.py @@ -36,7 +36,12 @@ def test_simple_format(filename: str) -> None: @pytest.mark.parametrize("filename", all_data_cases("preview")) def test_preview_format(filename: str) -> None: - check_file("preview", filename, black.Mode(preview=True)) + magic_trailing_comma = filename != "skip_magic_trailing_comma" + check_file( + "preview", + filename, + black.Mode(preview=True, magic_trailing_comma=magic_trailing_comma), + ) @pytest.mark.parametrize("filename", all_data_cases("preview_39"))