fix: Remove parenthesis around sole list items (#4312)

This commit is contained in:
cobalt 2024-11-27 21:59:29 -06:00 committed by GitHub
parent 17efac45f9
commit 96ca1b6be3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 436 additions and 3 deletions

View File

@ -17,6 +17,8 @@
<!-- Changes that affect Black's preview style --> <!-- Changes that affect Black's preview style -->
- Remove parentheses around sole list items (#4312)
### Configuration ### Configuration
<!-- Changes to how Black can be configured --> <!-- Changes to how Black can be configured -->

View File

@ -38,6 +38,9 @@ Currently, the following features are included in the preview style:
blocks when the line is too long blocks when the line is too long
- `pep646_typed_star_arg_type_var_tuple`: fix type annotation spacing between * and more - `pep646_typed_star_arg_type_var_tuple`: fix type annotation spacing between * and more
complex type variable tuple (i.e. `def fn(*args: *tuple[*Ts, T]) -> None: pass`) complex type variable tuple (i.e. `def fn(*args: *tuple[*Ts, T]) -> None: pass`)
- `remove_lone_list_item_parens`: remove redundant parentheses around lone list items
(depends on unstable `hug_parens_with_braces_and_square_brackets` feature in some
cases)
(labels/unstable-features)= (labels/unstable-features)=

View File

@ -507,6 +507,22 @@ def visit_NUMBER(self, leaf: Leaf) -> Iterator[Line]:
normalize_numeric_literal(leaf) normalize_numeric_literal(leaf)
yield from self.visit_default(leaf) yield from self.visit_default(leaf)
def visit_atom(self, node: Node) -> Iterator[Line]:
"""Visit any atom"""
if (
Preview.remove_lone_list_item_parens in self.mode
and len(node.children) == 3
):
first = node.children[0]
last = node.children[-1]
if (first.type == token.LSQB and last.type == token.RSQB) or (
first.type == token.LBRACE and last.type == token.RBRACE
):
# Lists or sets of one item
maybe_make_parens_invisible_in_atom(node.children[1], parent=node)
yield from self.visit_default(node)
def visit_fstring(self, node: Node) -> Iterator[Line]: def visit_fstring(self, node: Node) -> Iterator[Line]:
# currently we don't want to format and split f-strings at all. # currently we don't want to format and split f-strings at all.
string_leaf = fstring_to_string(node) string_leaf = fstring_to_string(node)
@ -1643,9 +1659,6 @@ def maybe_make_parens_invisible_in_atom(
not is_type_ignore_comment_string(middle.prefix.strip()) not is_type_ignore_comment_string(middle.prefix.strip())
): ):
first.value = "" first.value = ""
if first.prefix.strip():
# Preserve comments before first paren
middle.prefix = first.prefix + middle.prefix
last.value = "" last.value = ""
maybe_make_parens_invisible_in_atom( maybe_make_parens_invisible_in_atom(
middle, middle,
@ -1657,6 +1670,13 @@ def maybe_make_parens_invisible_in_atom(
# Strip the invisible parens from `middle` by replacing # Strip the invisible parens from `middle` by replacing
# it with the child in-between the invisible parens # it with the child in-between the invisible parens
middle.replace(middle.children[1]) middle.replace(middle.children[1])
if middle.children[0].prefix.strip():
# Preserve comments before first paren
middle.children[1].prefix = (
middle.children[0].prefix + middle.children[1].prefix
)
if middle.children[-1].prefix.strip(): if middle.children[-1].prefix.strip():
# Preserve comments before last paren # Preserve comments before last paren
last.prefix = middle.children[-1].prefix + last.prefix last.prefix = middle.children[-1].prefix + last.prefix

View File

@ -210,6 +210,9 @@ class Preview(Enum):
docstring_check_for_newline = auto() docstring_check_for_newline = auto()
remove_redundant_guard_parens = auto() remove_redundant_guard_parens = auto()
parens_for_long_if_clauses_in_case_block = auto() parens_for_long_if_clauses_in_case_block = auto()
# NOTE: remove_lone_list_item_parens requires
# hug_parens_with_braces_and_square_brackets to remove parens in some cases
remove_lone_list_item_parens = auto()
pep646_typed_star_arg_type_var_tuple = auto() pep646_typed_star_arg_type_var_tuple = auto()

View File

@ -91,6 +91,7 @@
"docstring_check_for_newline", "docstring_check_for_newline",
"remove_redundant_guard_parens", "remove_redundant_guard_parens",
"parens_for_long_if_clauses_in_case_block", "parens_for_long_if_clauses_in_case_block",
"remove_lone_list_item_parens",
"pep646_typed_star_arg_type_var_tuple" "pep646_typed_star_arg_type_var_tuple"
] ]
}, },

View File

@ -0,0 +1,158 @@
# flags: --preview
items = [(123)]
items = [(True)]
items = [(((((True)))))]
items = [(((((True,)))))]
items = [((((()))))]
items = [(x for x in [1])]
items = {(123)}
items = {(True)}
items = {(((((True)))))}
# Requires `hug_parens_with_braces_and_square_brackets` unstable style to remove parentheses
# around multiline values
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2"}
if some_var == ""
else {"key": "val"}
)
]
# Comments should not cause crashes
items = [
( # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
) # comment
]
items = [ # comment
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
] # comment
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"} # comment
if some_var == "long strings"
else {"key": "val"}
)
]
items = [ # comment
( # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
) # comment
] # comment
# output
items = [123]
items = [True]
items = [True]
items = [(True,)]
items = [()]
items = [(x for x in [1])]
items = {123}
items = {True}
items = {True}
# Requires `hug_parens_with_braces_and_square_brackets` unstable style to remove parentheses
# around multiline values
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [{"key1": "val1", "key2": "val2"} if some_var == "" else {"key": "val"}]
# Comments should not cause crashes
items = [
( # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
) # comment
]
items = [ # comment
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
] # comment
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"} # comment
if some_var == "long strings"
else {"key": "val"}
)
]
items = [ # comment
( # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
) # comment
] # comment

View File

@ -0,0 +1,246 @@
# flags: --unstable
items = [(x for x in [1])]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2"}
if some_var == ""
else {"key": "val"}
)
]
items = [
(
"123456890123457890123468901234567890"
if some_var == "long strings"
else "123467890123467890"
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
and some_var == "long strings"
and {"key": "val"}
)
]
items = [
(
"123456890123457890123468901234567890"
and some_var == "long strings"
and "123467890123467890"
)
]
items = [
(
long_variable_name
and even_longer_variable_name
and yet_another_very_long_variable_name
)
]
# Shouldn't remove trailing commas
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
),
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
and some_var == "long strings"
and {"key": "val"}
),
]
items = [
(
"123456890123457890123468901234567890"
and some_var == "long strings"
and "123467890123467890"
),
]
items = [
(
long_variable_name
and even_longer_variable_name
and yet_another_very_long_variable_name
),
]
# Shouldn't add parentheses
items = [
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
]
items = [{"key1": "val1", "key2": "val2"} if some_var == "" else {"key": "val"}]
# Shouldn't crash with comments
items = [
( # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
) # comment
]
items = [ # comment
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
] # comment
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"} # comment
if some_var == "long strings"
else {"key": "val"}
)
]
items = [ # comment
( # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
) # comment
] # comment
# output
items = [(x for x in [1])]
items = [
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
]
items = [{"key1": "val1", "key2": "val2"} if some_var == "" else {"key": "val"}]
items = [
"123456890123457890123468901234567890"
if some_var == "long strings"
else "123467890123467890"
]
items = [
{"key1": "val1", "key2": "val2", "key3": "val3"}
and some_var == "long strings"
and {"key": "val"}
]
items = [
"123456890123457890123468901234567890"
and some_var == "long strings"
and "123467890123467890"
]
items = [
long_variable_name
and even_longer_variable_name
and yet_another_very_long_variable_name
]
# Shouldn't remove trailing commas
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
),
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
and some_var == "long strings"
and {"key": "val"}
),
]
items = [
(
"123456890123457890123468901234567890"
and some_var == "long strings"
and "123467890123467890"
),
]
items = [
(
long_variable_name
and even_longer_variable_name
and yet_another_very_long_variable_name
),
]
# Shouldn't add parentheses
items = [
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
]
items = [{"key1": "val1", "key2": "val2"} if some_var == "" else {"key": "val"}]
# Shouldn't crash with comments
items = [ # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
]
items = [
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
] # comment
items = [ # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
]
items = [
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
] # comment
items = [
{"key1": "val1", "key2": "val2", "key3": "val3"} # comment
if some_var == "long strings"
else {"key": "val"}
]
items = [ # comment # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
]
items = [
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
] # comment # comment