Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

<!-- Changes that affect Black's preview style -->

- Fix unnecessary parentheses around short RHS expressions in indexed assignments like
`x[key] = expr` (#5095)
- Improve heuristics around whether blank lines should appear before, within and after
groups of same-name decorated functions (such as `@overload` groups) in `.pyi` stub
files (#5021)
Expand Down
2 changes: 1 addition & 1 deletion src/black/linegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -1066,7 +1066,7 @@ def _maybe_split_omitting_optional_parens(
# in this case; attempting a split without them is a waste of time)
and not line.is_import
# and we can actually remove the parens
and can_omit_invisible_parens(rhs, mode.line_length)
and can_omit_invisible_parens(rhs, mode.line_length, mode)
):
omit = {id(rhs.closing_bracket), *omit}
try:
Expand Down
18 changes: 18 additions & 0 deletions src/black/lines.py
Original file line number Diff line number Diff line change
Expand Up @@ -1350,6 +1350,7 @@ def can_be_split(line: Line) -> bool:
def can_omit_invisible_parens(
rhs: RHSResult,
line_length: int,
mode: Mode = Mode(),
Comment thread
ParamChordiya marked this conversation as resolved.
Outdated
) -> bool:
"""Does `rhs.body` have a shape safe to reformat without optional parens around it?

Expand Down Expand Up @@ -1479,6 +1480,23 @@ def can_omit_invisible_parens(
if _can_omit_closing_paren(line, last=last, line_length=line_length):
return True

# For assignment RHS where the LHS contains brackets (e.g. indexed
# assignments like `x[key] = expr`), allow omitting optional parens
# if the body is short enough. The split will happen at the LHS
# brackets instead, and _prefer_split_rhs_oop_over_rhs will decide
# whether it actually produces better output.
if (
Preview.fix_unnecessary_parens_in_indexed_assignment in mode
and len(rhs.head.leaves) >= 2
and rhs.head.leaves[-2].type == token.EQUAL
and any(leaf.type in BRACKETS for leaf in rhs.head.leaves[:-2])
):
# Only when the body is short enough to fit on the tail line
# after the LHS bracket split (e.g. `] = 10 - 5`).
body_length = str_width(str(line).strip("\n"))
Comment thread
ParamChordiya marked this conversation as resolved.
Outdated
if body_length <= line_length // 2:
return True
Comment thread
cobaltt7 marked this conversation as resolved.
Outdated

return False


Expand Down
1 change: 1 addition & 0 deletions src/black/mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ class Preview(Enum):
wrap_long_dict_values_in_parens = auto()
fix_if_guard_explosion_in_case_statement = auto()
pyi_overload_group_blank_lines = auto()
fix_unnecessary_parens_in_indexed_assignment = auto()


UNSTABLE_FEATURES: set[Preview] = {
Expand Down
21 changes: 21 additions & 0 deletions tests/data/cases/preview_prefer_rhs_split_indexed_assignment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# flags: --preview

# Indexed assignment with a short RHS expression should not get unnecessary parens.
dictionary_of_arrays["long_key_name_for_the_example"][
very_long_index_name, index_zero
] = 10 - 5

# Unformatted input: the unnecessary parens should be removed.
dictionary_of_arrays["long_key_name_for_the_example"][very_long_index_name, index_zero] = (10 - 5)

# output

# Indexed assignment with a short RHS expression should not get unnecessary parens.
dictionary_of_arrays["long_key_name_for_the_example"][
very_long_index_name, index_zero
] = 10 - 5

# Unformatted input: the unnecessary parens should be removed.
dictionary_of_arrays["long_key_name_for_the_example"][
very_long_index_name, index_zero
] = 10 - 5
Loading