Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parenthesize conditional expressions #2278

Merged
merged 19 commits into from
Dec 29, 2022
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
76a2301
Parenthesize conditional expressions
JEphron May 30, 2021
6ba1a2f
Update CHANGES PR number
JEphron May 30, 2021
0842927
Clarify changes
JEphron May 30, 2021
cf7b62a
Merge branch 'main' into jephron/conditional-expression-fix
ichard26 Jul 6, 2021
fae1744
Merge branch 'main' into jephron/conditional-expression-fix
JEphron Jul 10, 2021
dd2faef
Add more tests for conditional expression formatting
JEphron Jul 10, 2021
20c2d81
Use invisible parens which can be automatically stripped
JEphron Aug 7, 2021
2a0abd2
Update test
JEphron Aug 7, 2021
266cbf4
Merge remote-tracking branch 'upstream/main' into jephron/conditional…
JEphron Aug 7, 2021
fff3266
Merge branch 'main' of github.com:psf/black into jephron/conditional-…
JEphron Oct 6, 2021
06a02f3
Merge branch 'main' into jephron/conditional-expression-fix
ichard26 Dec 1, 2021
214edbd
Merge branch 'main' into jephron/conditional-expression-fix
JelleZijlstra Jan 10, 2022
b0e09b2
Merge branch 'main' into jephron/conditional-expression-fix
JelleZijlstra Jan 14, 2022
c9457a7
Merge branch 'main' into jephron/conditional-expression-fix
JelleZijlstra Feb 21, 2022
0f424ff
Make conditional parenthesization part of preview
JEphron Feb 21, 2022
295dc24
Add a couple more test cases for conditional parenthesization
JEphron Feb 21, 2022
89b065c
Merge branch 'main' into jephron/conditional-expression-fix
JelleZijlstra Dec 18, 2022
d876179
reformat
JelleZijlstra Dec 18, 2022
2fecc15
Merge branch 'main' into jephron/conditional-expression-fix
JelleZijlstra Dec 29, 2022
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
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- Fix determination of f-string expression spans (#2654)
- Fix parser error location on invalid syntax in a `match` statement (#2649)
- Functions and classes in blocks now have more consistent surrounding spacing (#2472)
- Multiline conditional expressions are now always parenthesized (#2278)

## 21.11b1

Expand Down
15 changes: 15 additions & 0 deletions src/black/linegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,21 @@ def visit_default(self, node: LN) -> Iterator[Line]:
self.current_line.append(node)
yield from super().visit_default(node)

def visit_test(self, node: Node) -> Iterator[Line]:
"""Visit an `x if y else z` test"""

already_parenthesized = (
node.prev_sibling and node.prev_sibling.type == token.LPAR
)

if not already_parenthesized:
lpar = Leaf(token.LPAR, "")
rpar = Leaf(token.RPAR, "")
node.insert_child(0, lpar)
node.append_child(rpar)

yield from self.visit_default(node)

def visit_INDENT(self, node: Leaf) -> Iterator[Line]:
"""Increase indentation level, maybe yield a line."""
# In blib2to3 INDENT never holds comments.
Expand Down
116 changes: 116 additions & 0 deletions tests/data/conditional_expression.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
long_kwargs_single_line = my_function(
foo="test, this is a sample value",
bar=some_long_value_name_foo_bar_baz if some_boolean_variable else some_fallback_value_foo_bar_baz,
baz="hello, this is a another value",
)

multiline_kwargs_indented = my_function(
foo="test, this is a sample value",
bar=some_long_value_name_foo_bar_baz
if some_boolean_variable
else some_fallback_value_foo_bar_baz,
baz="hello, this is a another value",
)

imploding_kwargs = my_function(
foo="test, this is a sample value",
bar=a
if foo
else b,
baz="hello, this is a another value",
)

imploding_line = (
1
if 1 + 1 == 2
else 0
)

exploding_line = "hello this is a slightly long string" if some_long_value_name_foo_bar_baz else "this one is a little shorter"

positional_argument_test(some_long_value_name_foo_bar_baz if some_boolean_variable else some_fallback_value_foo_bar_baz)

def weird_default_argument(x=some_long_value_name_foo_bar_baz
if SOME_CONSTANT
else some_fallback_value_foo_bar_baz):
pass

nested = "hello this is a slightly long string" if (some_long_value_name_foo_bar_baz if
nesting_test_expressions else some_fallback_value_foo_bar_baz) \
else "this one is a little shorter"

generator_expression = (
some_long_value_name_foo_bar_baz if some_boolean_variable else some_fallback_value_foo_bar_baz for some_boolean_variable in some_iterable
)

# output

long_kwargs_single_line = my_function(
foo="test, this is a sample value",
bar=(
some_long_value_name_foo_bar_baz
if some_boolean_variable
else some_fallback_value_foo_bar_baz
),
baz="hello, this is a another value",
)

multiline_kwargs_indented = my_function(
foo="test, this is a sample value",
bar=(
some_long_value_name_foo_bar_baz
if some_boolean_variable
else some_fallback_value_foo_bar_baz
),
baz="hello, this is a another value",
)

imploding_kwargs = my_function(
foo="test, this is a sample value",
bar=a if foo else b,
baz="hello, this is a another value",
)

imploding_line = 1 if 1 + 1 == 2 else 0

exploding_line = (
"hello this is a slightly long string"
if some_long_value_name_foo_bar_baz
else "this one is a little shorter"
)

positional_argument_test(
some_long_value_name_foo_bar_baz
if some_boolean_variable
else some_fallback_value_foo_bar_baz
)


def weird_default_argument(
x=(
some_long_value_name_foo_bar_baz
if SOME_CONSTANT
else some_fallback_value_foo_bar_baz
),
):
pass


nested = (
"hello this is a slightly long string"
if (
some_long_value_name_foo_bar_baz
if nesting_test_expressions
else some_fallback_value_foo_bar_baz
)
else "this one is a little shorter"
)

generator_expression = (
(
some_long_value_name_foo_bar_baz
if some_boolean_variable
else some_fallback_value_foo_bar_baz
)
for some_boolean_variable in some_iterable
)
1 change: 1 addition & 0 deletions tests/test_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"comment_after_escaped_newline",
"composition",
"composition_no_trailing_comma",
"conditional_expression",
"docstring",
"empty_lines",
"expression",
Expand Down