Parenthesize conditional expressions (#2278)
Co-authored-by: Jordan Ephron <JEphron@users.noreply.github.com> Co-authored-by: Richard Si <63936253+ichard26@users.noreply.github.com> Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
This commit is contained in:
parent
0abe85eebb
commit
4e3303fa08
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
<!-- Changes that affect Black's preview style -->
|
<!-- Changes that affect Black's preview style -->
|
||||||
|
|
||||||
|
- Add parentheses around `if`-`else` expressions (#2278)
|
||||||
- Improve the performance on large expressions that contain many strings (#3467)
|
- Improve the performance on large expressions that contain many strings (#3467)
|
||||||
- Fix a crash in preview style with assert + parenthesized string (#3415)
|
- Fix a crash in preview style with assert + parenthesized string (#3415)
|
||||||
- Fix crashes in preview style with walrus operators used in function return annotations
|
- Fix crashes in preview style with walrus operators used in function return annotations
|
||||||
|
@ -478,16 +478,20 @@ def main( # noqa: C901
|
|||||||
)
|
)
|
||||||
|
|
||||||
normalized = [
|
normalized = [
|
||||||
|
(
|
||||||
(source, source)
|
(source, source)
|
||||||
if source == "-"
|
if source == "-"
|
||||||
else (normalize_path_maybe_ignore(Path(source), root), source)
|
else (normalize_path_maybe_ignore(Path(source), root), source)
|
||||||
|
)
|
||||||
for source in src
|
for source in src
|
||||||
]
|
]
|
||||||
srcs_string = ", ".join(
|
srcs_string = ", ".join(
|
||||||
[
|
[
|
||||||
|
(
|
||||||
f'"{_norm}"'
|
f'"{_norm}"'
|
||||||
if _norm
|
if _norm
|
||||||
else f'\033[31m"{source} (skipping - invalid)"\033[34m'
|
else f'\033[31m"{source} (skipping - invalid)"\033[34m'
|
||||||
|
)
|
||||||
for _norm, source in normalized
|
for _norm, source in normalized
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
@ -140,6 +140,22 @@ def visit_default(self, node: LN) -> Iterator[Line]:
|
|||||||
self.current_line.append(node)
|
self.current_line.append(node)
|
||||||
yield from super().visit_default(node)
|
yield from super().visit_default(node)
|
||||||
|
|
||||||
|
def visit_test(self, node: Node) -> Iterator[Line]:
|
||||||
|
"""Visit an `x if y else z` test"""
|
||||||
|
|
||||||
|
if Preview.parenthesize_conditional_expressions in self.mode:
|
||||||
|
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]:
|
def visit_INDENT(self, node: Leaf) -> Iterator[Line]:
|
||||||
"""Increase indentation level, maybe yield a line."""
|
"""Increase indentation level, maybe yield a line."""
|
||||||
# In blib2to3 INDENT never holds comments.
|
# In blib2to3 INDENT never holds comments.
|
||||||
|
@ -161,6 +161,7 @@ class Preview(Enum):
|
|||||||
# NOTE: string_processing requires wrap_long_dict_values_in_parens
|
# NOTE: string_processing requires wrap_long_dict_values_in_parens
|
||||||
# for https://github.com/psf/black/issues/3117 to be fixed.
|
# for https://github.com/psf/black/issues/3117 to be fixed.
|
||||||
string_processing = auto()
|
string_processing = auto()
|
||||||
|
parenthesize_conditional_expressions = auto()
|
||||||
skip_magic_trailing_comma_in_subscript = auto()
|
skip_magic_trailing_comma_in_subscript = auto()
|
||||||
wrap_long_dict_values_in_parens = auto()
|
wrap_long_dict_values_in_parens = auto()
|
||||||
|
|
||||||
|
160
tests/data/conditional_expression.py
Normal file
160
tests/data/conditional_expression.py
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def limit_offset_sql(self, low_mark, high_mark):
|
||||||
|
"""Return LIMIT/OFFSET SQL clause."""
|
||||||
|
limit, offset = self._get_limit_offset_params(low_mark, high_mark)
|
||||||
|
return " ".join(
|
||||||
|
sql
|
||||||
|
for sql in (
|
||||||
|
"LIMIT %d" % limit if limit else None,
|
||||||
|
("OFFSET %d" % offset) if offset else None,
|
||||||
|
)
|
||||||
|
if sql
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def something():
|
||||||
|
clone._iterable_class = (
|
||||||
|
NamedValuesListIterable
|
||||||
|
if named
|
||||||
|
else FlatValuesListIterable
|
||||||
|
if flat
|
||||||
|
else ValuesListIterable
|
||||||
|
)
|
||||||
|
|
||||||
|
# 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
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def limit_offset_sql(self, low_mark, high_mark):
|
||||||
|
"""Return LIMIT/OFFSET SQL clause."""
|
||||||
|
limit, offset = self._get_limit_offset_params(low_mark, high_mark)
|
||||||
|
return " ".join(
|
||||||
|
sql
|
||||||
|
for sql in (
|
||||||
|
"LIMIT %d" % limit if limit else None,
|
||||||
|
("OFFSET %d" % offset) if offset else None,
|
||||||
|
)
|
||||||
|
if sql
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def something():
|
||||||
|
clone._iterable_class = (
|
||||||
|
NamedValuesListIterable
|
||||||
|
if named
|
||||||
|
else FlatValuesListIterable if flat else ValuesListIterable
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user