Remove unnecessary parentheses from tuple unpacking in for
loops (#2945)
This commit is contained in:
parent
3800ebd81d
commit
14e5ce5412
@ -15,6 +15,7 @@
|
|||||||
<!-- Changes that affect Black's preview style -->
|
<!-- Changes that affect Black's preview style -->
|
||||||
|
|
||||||
- Code cell separators `#%%` are now standardised to `# %%` (#2919)
|
- Code cell separators `#%%` are now standardised to `# %%` (#2919)
|
||||||
|
- Remove unnecessary parentheses from tuple unpacking in `for` loops (#2945)
|
||||||
- Avoid magic-trailing-comma in single-element subscripts (#2942)
|
- Avoid magic-trailing-comma in single-element subscripts (#2942)
|
||||||
|
|
||||||
### _Blackd_
|
### _Blackd_
|
||||||
|
@ -841,7 +841,11 @@ def normalize_invisible_parens(
|
|||||||
|
|
||||||
if check_lpar:
|
if check_lpar:
|
||||||
if child.type == syms.atom:
|
if child.type == syms.atom:
|
||||||
if maybe_make_parens_invisible_in_atom(child, parent=node):
|
if maybe_make_parens_invisible_in_atom(
|
||||||
|
child,
|
||||||
|
parent=node,
|
||||||
|
preview=preview,
|
||||||
|
):
|
||||||
wrap_in_parentheses(node, child, visible=False)
|
wrap_in_parentheses(node, child, visible=False)
|
||||||
elif is_one_tuple(child):
|
elif is_one_tuple(child):
|
||||||
wrap_in_parentheses(node, child, visible=True)
|
wrap_in_parentheses(node, child, visible=True)
|
||||||
@ -865,7 +869,11 @@ def normalize_invisible_parens(
|
|||||||
check_lpar = isinstance(child, Leaf) and child.value in parens_after
|
check_lpar = isinstance(child, Leaf) and child.value in parens_after
|
||||||
|
|
||||||
|
|
||||||
def maybe_make_parens_invisible_in_atom(node: LN, parent: LN) -> bool:
|
def maybe_make_parens_invisible_in_atom(
|
||||||
|
node: LN,
|
||||||
|
parent: LN,
|
||||||
|
preview: bool = False,
|
||||||
|
) -> bool:
|
||||||
"""If it's safe, make the parens in the atom `node` invisible, recursively.
|
"""If it's safe, make the parens in the atom `node` invisible, recursively.
|
||||||
Additionally, remove repeated, adjacent invisible parens from the atom `node`
|
Additionally, remove repeated, adjacent invisible parens from the atom `node`
|
||||||
as they are redundant.
|
as they are redundant.
|
||||||
@ -873,13 +881,23 @@ def maybe_make_parens_invisible_in_atom(node: LN, parent: LN) -> bool:
|
|||||||
Returns whether the node should itself be wrapped in invisible parentheses.
|
Returns whether the node should itself be wrapped in invisible parentheses.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
if (
|
||||||
|
preview
|
||||||
|
and parent.type == syms.for_stmt
|
||||||
|
and isinstance(node.prev_sibling, Leaf)
|
||||||
|
and node.prev_sibling.type == token.NAME
|
||||||
|
and node.prev_sibling.value == "for"
|
||||||
|
):
|
||||||
|
for_stmt_check = False
|
||||||
|
else:
|
||||||
|
for_stmt_check = True
|
||||||
|
|
||||||
if (
|
if (
|
||||||
node.type != syms.atom
|
node.type != syms.atom
|
||||||
or is_empty_tuple(node)
|
or is_empty_tuple(node)
|
||||||
or is_one_tuple(node)
|
or is_one_tuple(node)
|
||||||
or (is_yield(node) and parent.type != syms.expr_stmt)
|
or (is_yield(node) and parent.type != syms.expr_stmt)
|
||||||
or max_delimiter_priority_in_atom(node) >= COMMA_PRIORITY
|
or (max_delimiter_priority_in_atom(node) >= COMMA_PRIORITY and for_stmt_check)
|
||||||
):
|
):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -902,7 +920,7 @@ def maybe_make_parens_invisible_in_atom(node: LN, parent: LN) -> bool:
|
|||||||
# make parentheses invisible
|
# make parentheses invisible
|
||||||
first.value = ""
|
first.value = ""
|
||||||
last.value = ""
|
last.value = ""
|
||||||
maybe_make_parens_invisible_in_atom(middle, parent=parent)
|
maybe_make_parens_invisible_in_atom(middle, parent=parent, preview=preview)
|
||||||
|
|
||||||
if is_atom_with_invisible_parens(middle):
|
if is_atom_with_invisible_parens(middle):
|
||||||
# Strip the invisible parens from `middle` by replacing
|
# Strip the invisible parens from `middle` by replacing
|
||||||
|
@ -127,6 +127,7 @@ class Preview(Enum):
|
|||||||
"""Individual preview style features."""
|
"""Individual preview style features."""
|
||||||
|
|
||||||
string_processing = auto()
|
string_processing = auto()
|
||||||
|
remove_redundant_parens = auto()
|
||||||
one_element_subscript = auto()
|
one_element_subscript = auto()
|
||||||
|
|
||||||
|
|
||||||
|
@ -365,7 +365,7 @@ def do_match(self, line: Line) -> TMatchResult:
|
|||||||
|
|
||||||
is_valid_index = is_valid_index_factory(LL)
|
is_valid_index = is_valid_index_factory(LL)
|
||||||
|
|
||||||
for (i, leaf) in enumerate(LL):
|
for i, leaf in enumerate(LL):
|
||||||
if (
|
if (
|
||||||
leaf.type == token.STRING
|
leaf.type == token.STRING
|
||||||
and is_valid_index(i + 1)
|
and is_valid_index(i + 1)
|
||||||
@ -570,7 +570,7 @@ def make_naked(string: str, string_prefix: str) -> str:
|
|||||||
|
|
||||||
# Build the final line ('new_line') that this method will later return.
|
# Build the final line ('new_line') that this method will later return.
|
||||||
new_line = line.clone()
|
new_line = line.clone()
|
||||||
for (i, leaf) in enumerate(LL):
|
for i, leaf in enumerate(LL):
|
||||||
if i == string_idx:
|
if i == string_idx:
|
||||||
new_line.append(string_leaf)
|
new_line.append(string_leaf)
|
||||||
|
|
||||||
@ -691,7 +691,7 @@ def do_match(self, line: Line) -> TMatchResult:
|
|||||||
|
|
||||||
is_valid_index = is_valid_index_factory(LL)
|
is_valid_index = is_valid_index_factory(LL)
|
||||||
|
|
||||||
for (idx, leaf) in enumerate(LL):
|
for idx, leaf in enumerate(LL):
|
||||||
# Should be a string...
|
# Should be a string...
|
||||||
if leaf.type != token.STRING:
|
if leaf.type != token.STRING:
|
||||||
continue
|
continue
|
||||||
@ -1713,7 +1713,7 @@ def _assert_match(LL: List[Leaf]) -> Optional[int]:
|
|||||||
if parent_type(LL[0]) == syms.assert_stmt and LL[0].value == "assert":
|
if parent_type(LL[0]) == syms.assert_stmt and LL[0].value == "assert":
|
||||||
is_valid_index = is_valid_index_factory(LL)
|
is_valid_index = is_valid_index_factory(LL)
|
||||||
|
|
||||||
for (i, leaf) in enumerate(LL):
|
for i, leaf in enumerate(LL):
|
||||||
# We MUST find a comma...
|
# We MUST find a comma...
|
||||||
if leaf.type == token.COMMA:
|
if leaf.type == token.COMMA:
|
||||||
idx = i + 2 if is_empty_par(LL[i + 1]) else i + 1
|
idx = i + 2 if is_empty_par(LL[i + 1]) else i + 1
|
||||||
@ -1751,7 +1751,7 @@ def _assign_match(LL: List[Leaf]) -> Optional[int]:
|
|||||||
):
|
):
|
||||||
is_valid_index = is_valid_index_factory(LL)
|
is_valid_index = is_valid_index_factory(LL)
|
||||||
|
|
||||||
for (i, leaf) in enumerate(LL):
|
for i, leaf in enumerate(LL):
|
||||||
# We MUST find either an '=' or '+=' symbol...
|
# We MUST find either an '=' or '+=' symbol...
|
||||||
if leaf.type in [token.EQUAL, token.PLUSEQUAL]:
|
if leaf.type in [token.EQUAL, token.PLUSEQUAL]:
|
||||||
idx = i + 2 if is_empty_par(LL[i + 1]) else i + 1
|
idx = i + 2 if is_empty_par(LL[i + 1]) else i + 1
|
||||||
@ -1794,7 +1794,7 @@ def _dict_match(LL: List[Leaf]) -> Optional[int]:
|
|||||||
if syms.dictsetmaker in [parent_type(LL[0]), parent_type(LL[0].parent)]:
|
if syms.dictsetmaker in [parent_type(LL[0]), parent_type(LL[0].parent)]:
|
||||||
is_valid_index = is_valid_index_factory(LL)
|
is_valid_index = is_valid_index_factory(LL)
|
||||||
|
|
||||||
for (i, leaf) in enumerate(LL):
|
for i, leaf in enumerate(LL):
|
||||||
# We MUST find a colon...
|
# We MUST find a colon...
|
||||||
if leaf.type == token.COLON:
|
if leaf.type == token.COLON:
|
||||||
idx = i + 2 if is_empty_par(LL[i + 1]) else i + 1
|
idx = i + 2 if is_empty_par(LL[i + 1]) else i + 1
|
||||||
|
@ -599,7 +599,7 @@ def foo():
|
|||||||
|
|
||||||
|
|
||||||
def foo(xxxx):
|
def foo(xxxx):
|
||||||
for (xxx_xxxx, _xxx_xxx, _xxx_xxxxx, xxx_xxxx) in xxxx:
|
for xxx_xxxx, _xxx_xxx, _xxx_xxxxx, xxx_xxxx in xxxx:
|
||||||
for xxx in xxx_xxxx:
|
for xxx in xxx_xxxx:
|
||||||
assert ("x" in xxx) or (xxx in xxx_xxx_xxxxx), (
|
assert ("x" in xxx) or (xxx in xxx_xxx_xxxxx), (
|
||||||
"{0} xxxxxxx xx {1}, xxx {1} xx xxx xx xxxx xx xxx xxxx: xxx xxxx {2}"
|
"{0} xxxxxxx xx {1}, xxx {1} xx xxx xx xxxx xx xxx xxxx: xxx xxxx {2}"
|
||||||
|
40
tests/data/remove_for_brackets.py
Normal file
40
tests/data/remove_for_brackets.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# Only remove tuple brackets after `for`
|
||||||
|
for (k, v) in d.items():
|
||||||
|
print(k, v)
|
||||||
|
|
||||||
|
# Don't touch tuple brackets after `in`
|
||||||
|
for module in (core, _unicodefun):
|
||||||
|
if hasattr(module, "_verify_python3_env"):
|
||||||
|
module._verify_python3_env = lambda: None
|
||||||
|
|
||||||
|
# Brackets remain for long for loop lines
|
||||||
|
for (why_would_anyone_choose_to_name_a_loop_variable_with_a_name_this_long, i_dont_know_but_we_should_still_check_the_behaviour_if_they_do) in d.items():
|
||||||
|
print(k, v)
|
||||||
|
|
||||||
|
for (k, v) in dfkasdjfldsjflkdsjflkdsjfdslkfjldsjfgkjdshgkljjdsfldgkhsdofudsfudsofajdslkfjdslkfjldisfjdffjsdlkfjdlkjjkdflskadjldkfjsalkfjdasj.items():
|
||||||
|
print(k, v)
|
||||||
|
|
||||||
|
# output
|
||||||
|
# Only remove tuple brackets after `for`
|
||||||
|
for k, v in d.items():
|
||||||
|
print(k, v)
|
||||||
|
|
||||||
|
# Don't touch tuple brackets after `in`
|
||||||
|
for module in (core, _unicodefun):
|
||||||
|
if hasattr(module, "_verify_python3_env"):
|
||||||
|
module._verify_python3_env = lambda: None
|
||||||
|
|
||||||
|
# Brackets remain for long for loop lines
|
||||||
|
for (
|
||||||
|
why_would_anyone_choose_to_name_a_loop_variable_with_a_name_this_long,
|
||||||
|
i_dont_know_but_we_should_still_check_the_behaviour_if_they_do,
|
||||||
|
) in d.items():
|
||||||
|
print(k, v)
|
||||||
|
|
||||||
|
for (
|
||||||
|
k,
|
||||||
|
v,
|
||||||
|
) in (
|
||||||
|
dfkasdjfldsjflkdsjflkdsjfdslkfjldsjfgkjdshgkljjdsfldgkhsdofudsfudsofajdslkfjdslkfjldisfjdffjsdlkfjdlkjjkdflskadjldkfjsalkfjdasj.items()
|
||||||
|
):
|
||||||
|
print(k, v)
|
@ -80,6 +80,7 @@
|
|||||||
"long_strings__edge_case",
|
"long_strings__edge_case",
|
||||||
"long_strings__regression",
|
"long_strings__regression",
|
||||||
"percent_precedence",
|
"percent_precedence",
|
||||||
|
"remove_for_brackets",
|
||||||
"one_element_subscript",
|
"one_element_subscript",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user