mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-23 13:05:58 +00:00
Format ExprIfExp (ternary operator) (#5597)
## Summary Format `ExprIfExp`, also known as the ternary operator or inline `if`. It can look like ```python a1 = 1 if True else 2 ``` but also ```python b1 = ( # We return "a" ... "a" # that's our True value # ... if this condition matches ... if True # that's our test # ... otherwise we return "b§ else "b" # that's our False value ) ``` This also fixes a visitor order bug. The jaccard index on django goes from 0.911 to 0.915. ## Test Plan I added fixtures without and with comments in strange places.
This commit is contained in:
parent
0f9d7283e7
commit
0b9af031fb
9 changed files with 328 additions and 212 deletions
33
crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/if.py
vendored
Normal file
33
crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/if.py
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
a1 = 1 if True else 2
|
||||
|
||||
a2 = "this is a very long text that will make the group break to check that parentheses are added" if True else 2
|
||||
|
||||
# These comment should be kept in place
|
||||
b1 = (
|
||||
# We return "a" ...
|
||||
"a" # that's our True value
|
||||
# ... if this condition matches ...
|
||||
if True # that's our test
|
||||
# ... otherwise we return "b"
|
||||
else "b" # that's our False value
|
||||
)
|
||||
|
||||
# These only need to be stable, bonus is we also keep the order
|
||||
c1 = (
|
||||
"a" # 1
|
||||
if # 2
|
||||
True # 3
|
||||
else # 4
|
||||
"b" # 5
|
||||
)
|
||||
c2 = (
|
||||
"a" # 1
|
||||
# 2
|
||||
if # 3
|
||||
# 4
|
||||
True # 5
|
||||
# 6
|
||||
else # 7
|
||||
# 8
|
||||
"b" # 9
|
||||
)
|
|
@ -1,8 +1,8 @@
|
|||
use std::cmp::Ordering;
|
||||
|
||||
use ruff_text_size::TextRange;
|
||||
use ruff_text_size::{TextLen, TextRange};
|
||||
use rustpython_parser::ast;
|
||||
use rustpython_parser::ast::{Expr, ExprSlice, Ranged};
|
||||
use rustpython_parser::ast::{Expr, ExprIfExp, ExprSlice, Ranged};
|
||||
|
||||
use ruff_python_ast::node::{AnyNodeRef, AstNode};
|
||||
use ruff_python_ast::source_code::Locator;
|
||||
|
@ -14,7 +14,9 @@ use crate::expression::expr_slice::{assign_comment_in_slice, ExprSliceCommentSec
|
|||
use crate::other::arguments::{
|
||||
assign_argument_separator_comment_placement, find_argument_separators,
|
||||
};
|
||||
use crate::trivia::{first_non_trivia_token_rev, SimpleTokenizer, Token, TokenKind};
|
||||
use crate::trivia::{
|
||||
first_non_trivia_token, first_non_trivia_token_rev, SimpleTokenizer, Token, TokenKind,
|
||||
};
|
||||
|
||||
/// Implements the custom comment placement logic.
|
||||
pub(super) fn place_comment<'a>(
|
||||
|
@ -37,6 +39,7 @@ pub(super) fn place_comment<'a>(
|
|||
handle_dict_unpacking_comment,
|
||||
handle_slice_comments,
|
||||
handle_attribute_comment,
|
||||
handle_expr_if_comment,
|
||||
];
|
||||
for handler in HANDLERS {
|
||||
comment = match handler(comment, locator) {
|
||||
|
@ -1154,6 +1157,82 @@ fn handle_attribute_comment<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
/// Assign comments between `if` and `test` and `else` and `orelse` as leading to the respective
|
||||
/// node.
|
||||
///
|
||||
/// ```python
|
||||
/// x = (
|
||||
/// "a"
|
||||
/// if # leading comment of `True`
|
||||
/// True
|
||||
/// else # leading comment of `"b"`
|
||||
/// "b"
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// This placement ensures comments remain in their previous order. This an edge case that only
|
||||
/// happens if the comments are in a weird position but it also doesn't hurt handling it.
|
||||
fn handle_expr_if_comment<'a>(
|
||||
comment: DecoratedComment<'a>,
|
||||
locator: &Locator,
|
||||
) -> CommentPlacement<'a> {
|
||||
let Some(expr_if) = comment.enclosing_node().expr_if_exp() else {
|
||||
return CommentPlacement::Default(comment);
|
||||
};
|
||||
let ExprIfExp {
|
||||
range: _,
|
||||
test,
|
||||
body,
|
||||
orelse,
|
||||
} = expr_if;
|
||||
|
||||
if comment.line_position().is_own_line() {
|
||||
return CommentPlacement::Default(comment);
|
||||
}
|
||||
|
||||
// Find the if and the else
|
||||
let if_token =
|
||||
find_only_token_str_in_range(TextRange::new(body.end(), test.start()), locator, "if");
|
||||
let else_token =
|
||||
find_only_token_str_in_range(TextRange::new(test.end(), orelse.start()), locator, "else");
|
||||
|
||||
// Between `if` and `test`
|
||||
if if_token.range.start() < comment.slice().start() && comment.slice().start() < test.start() {
|
||||
return CommentPlacement::leading(test.as_ref().into(), comment);
|
||||
}
|
||||
|
||||
// Between `else` and `orelse`
|
||||
if else_token.range.start() < comment.slice().start()
|
||||
&& comment.slice().start() < orelse.start()
|
||||
{
|
||||
return CommentPlacement::leading(orelse.as_ref().into(), comment);
|
||||
}
|
||||
|
||||
CommentPlacement::Default(comment)
|
||||
}
|
||||
|
||||
/// Looks for a multi char token in the range that contains no other tokens. `SimpleTokenizer` only
|
||||
/// works with single char tokens so we check that we have the right token by string comparison.
|
||||
fn find_only_token_str_in_range(range: TextRange, locator: &Locator, token_str: &str) -> Token {
|
||||
let token =
|
||||
first_non_trivia_token(range.start(), locator.contents()).expect("Expected a token");
|
||||
debug_assert!(
|
||||
locator.after(token.start()).starts_with(token_str),
|
||||
"expected a `{token_str}` token",
|
||||
);
|
||||
debug_assert!(
|
||||
SimpleTokenizer::new(
|
||||
locator.contents(),
|
||||
TextRange::new(token.start() + token_str.text_len(), range.end())
|
||||
)
|
||||
.skip_trivia()
|
||||
.next()
|
||||
.is_none(),
|
||||
"Didn't expect any other token"
|
||||
);
|
||||
token
|
||||
}
|
||||
|
||||
/// Returns `true` if `right` is `Some` and `left` and `right` are referentially equal.
|
||||
fn are_same_optional<'a, T>(left: AnyNodeRef, right: Option<T>) -> bool
|
||||
where
|
||||
|
|
|
@ -1,21 +1,42 @@
|
|||
use crate::comments::Comments;
|
||||
use crate::comments::{leading_comments, Comments};
|
||||
use crate::expression::parentheses::{
|
||||
default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize,
|
||||
};
|
||||
use crate::{not_yet_implemented_custom_text, FormatNodeRule, PyFormatter};
|
||||
use ruff_formatter::{write, Buffer, FormatResult};
|
||||
use crate::{AsFormat, FormatNodeRule, PyFormatter};
|
||||
use ruff_formatter::prelude::{group, soft_line_break_or_space, space, text};
|
||||
use ruff_formatter::{format_args, write, Buffer, FormatResult};
|
||||
use rustpython_parser::ast::ExprIfExp;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct FormatExprIfExp;
|
||||
|
||||
impl FormatNodeRule<ExprIfExp> for FormatExprIfExp {
|
||||
fn fmt_fields(&self, _item: &ExprIfExp, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
fn fmt_fields(&self, item: &ExprIfExp, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
let ExprIfExp {
|
||||
range: _,
|
||||
test,
|
||||
body,
|
||||
orelse,
|
||||
} = item;
|
||||
let comments = f.context().comments().clone();
|
||||
// We place `if test` and `else orelse` on a single line, so the `test` and `orelse` leading
|
||||
// comments go on the line before the `if` or `else` instead of directly ahead `test` or
|
||||
// `orelse`
|
||||
write!(
|
||||
f,
|
||||
[not_yet_implemented_custom_text(
|
||||
"NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false"
|
||||
)]
|
||||
[group(&format_args![
|
||||
body.format(),
|
||||
soft_line_break_or_space(),
|
||||
leading_comments(comments.leading_comments(test.as_ref())),
|
||||
text("if"),
|
||||
space(),
|
||||
test.format(),
|
||||
soft_line_break_or_space(),
|
||||
leading_comments(comments.leading_comments(orelse.as_ref())),
|
||||
text("else"),
|
||||
space(),
|
||||
orelse.format()
|
||||
])]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ def something():
|
|||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -1,90 +1,50 @@
|
||||
@@ -1,20 +1,16 @@
|
||||
long_kwargs_single_line = my_function(
|
||||
foo="test, this is a sample value",
|
||||
- bar=(
|
||||
|
@ -87,7 +87,9 @@ def something():
|
|||
- if some_boolean_variable
|
||||
- else some_fallback_value_foo_bar_baz
|
||||
- ),
|
||||
+ bar=NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false,
|
||||
+ 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",
|
||||
)
|
||||
|
||||
|
@ -98,33 +100,13 @@ def something():
|
|||
- if some_boolean_variable
|
||||
- else some_fallback_value_foo_bar_baz
|
||||
- ),
|
||||
+ bar=NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false,
|
||||
+ 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,
|
||||
+ bar=NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false,
|
||||
baz="hello, this is a another value",
|
||||
)
|
||||
|
||||
-imploding_line = 1 if 1 + 1 == 2 else 0
|
||||
+imploding_line = NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
|
||||
-exploding_line = (
|
||||
- "hello this is a slightly long string"
|
||||
- if some_long_value_name_foo_bar_baz
|
||||
- else "this one is a little shorter"
|
||||
-)
|
||||
+exploding_line = NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
|
||||
positional_argument_test(
|
||||
- some_long_value_name_foo_bar_baz
|
||||
- if some_boolean_variable
|
||||
- else some_fallback_value_foo_bar_baz
|
||||
+ NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
)
|
||||
@@ -40,11 +36,9 @@
|
||||
|
||||
|
||||
def weird_default_argument(
|
||||
|
@ -133,21 +115,15 @@ def something():
|
|||
- if SOME_CONSTANT
|
||||
- else some_fallback_value_foo_bar_baz
|
||||
- ),
|
||||
+ x=NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
+ 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"
|
||||
-)
|
||||
+nested = NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
@@ -59,26 +53,14 @@
|
||||
else "this one is a little shorter"
|
||||
)
|
||||
|
||||
-generator_expression = (
|
||||
- (
|
||||
|
@ -174,13 +150,6 @@ def something():
|
|||
)
|
||||
|
||||
|
||||
def something():
|
||||
clone._iterable_class = (
|
||||
- NamedValuesListIterable
|
||||
- if named
|
||||
- else FlatValuesListIterable if flat else ValuesListIterable
|
||||
+ NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
)
|
||||
```
|
||||
|
||||
## Ruff Output
|
||||
|
@ -188,38 +157,58 @@ def something():
|
|||
```py
|
||||
long_kwargs_single_line = my_function(
|
||||
foo="test, this is a sample value",
|
||||
bar=NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false,
|
||||
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=NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false,
|
||||
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=NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false,
|
||||
bar=a if foo else b,
|
||||
baz="hello, this is a another value",
|
||||
)
|
||||
|
||||
imploding_line = NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
imploding_line = 1 if 1 + 1 == 2 else 0
|
||||
|
||||
exploding_line = NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
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(
|
||||
NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
some_long_value_name_foo_bar_baz
|
||||
if some_boolean_variable
|
||||
else some_fallback_value_foo_bar_baz
|
||||
)
|
||||
|
||||
|
||||
def weird_default_argument(
|
||||
x=NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
x=some_long_value_name_foo_bar_baz
|
||||
if SOME_CONSTANT
|
||||
else some_fallback_value_foo_bar_baz,
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
nested = NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
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 = (NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in [])
|
||||
|
||||
|
@ -234,7 +223,9 @@ def limit_offset_sql(self, low_mark, high_mark):
|
|||
|
||||
def something():
|
||||
clone._iterable_class = (
|
||||
NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
NamedValuesListIterable
|
||||
if named
|
||||
else FlatValuesListIterable if flat else ValuesListIterable
|
||||
)
|
||||
```
|
||||
|
||||
|
|
|
@ -274,7 +274,7 @@ last_call()
|
|||
Name
|
||||
None
|
||||
True
|
||||
@@ -31,33 +31,39 @@
|
||||
@@ -31,18 +31,15 @@
|
||||
-1
|
||||
~int and not v1 ^ 123 + v2 | True
|
||||
(~int) and (not ((v1 ^ (123 + v2)) | True))
|
||||
|
@ -291,16 +291,6 @@ last_call()
|
|||
- "port1": port1_resource,
|
||||
- "port2": port2_resource,
|
||||
-}[port_id]
|
||||
-1 if True else 2
|
||||
-str or None if True else str or bytes or None
|
||||
-(str or None) if True else (str or bytes or None)
|
||||
-str or None if (1 if True else 2) else str or bytes or None
|
||||
-(str or None) if (1 if True else 2) else (str or bytes or None)
|
||||
-(
|
||||
- (super_long_variable_name or None)
|
||||
- if (1 if super_long_test_name else 2)
|
||||
- else (str or bytes or None)
|
||||
-)
|
||||
+lambda x: True
|
||||
+lambda x: True
|
||||
+lambda x: True
|
||||
|
@ -308,25 +298,14 @@ last_call()
|
|||
+lambda x: True
|
||||
+manylambdas = lambda x: True
|
||||
+foo = lambda x: True
|
||||
+NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
+NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
+NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
+NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
+NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
+(NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false)
|
||||
{"2.7": dead, "3.7": (long_live or die_hard)}
|
||||
1 if True else 2
|
||||
str or None if True else str or bytes or None
|
||||
(str or None) if True else (str or bytes or None)
|
||||
@@ -57,7 +54,13 @@
|
||||
{"2.7": dead, "3.7": (long_live or die_hard), **{"3.6": verygood}}
|
||||
{**a, **b, **c}
|
||||
-{"2.7", "3.6", "3.7", "3.8", "3.9", ("4.0" if gilectomy else "3.10")}
|
||||
{"2.7", "3.6", "3.7", "3.8", "3.9", ("4.0" if gilectomy else "3.10")}
|
||||
-({"a": "b"}, (True or False), (+value), "string", b"bytes") or None
|
||||
+{
|
||||
+ "2.7",
|
||||
+ "3.6",
|
||||
+ "3.7",
|
||||
+ "3.8",
|
||||
+ "3.9",
|
||||
+ (NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false),
|
||||
+}
|
||||
+(
|
||||
+ {"a": "b"},
|
||||
+ (True or False),
|
||||
|
@ -337,7 +316,7 @@ last_call()
|
|||
()
|
||||
(1,)
|
||||
(1, 2)
|
||||
@@ -69,40 +75,37 @@
|
||||
@@ -69,40 +72,37 @@
|
||||
2,
|
||||
3,
|
||||
]
|
||||
|
@ -396,7 +375,7 @@ last_call()
|
|||
Python3 > Python2 > COBOL
|
||||
Life is Life
|
||||
call()
|
||||
@@ -115,10 +118,10 @@
|
||||
@@ -115,10 +115,10 @@
|
||||
arg,
|
||||
another,
|
||||
kwarg="hey",
|
||||
|
@ -410,7 +389,7 @@ last_call()
|
|||
call(**self.screen_kwargs)
|
||||
call(b, **self.screen_kwargs)
|
||||
lukasz.langa.pl
|
||||
@@ -131,34 +134,28 @@
|
||||
@@ -131,34 +131,28 @@
|
||||
tuple[str, ...]
|
||||
tuple[str, int, float, dict[str, int]]
|
||||
tuple[
|
||||
|
@ -458,26 +437,16 @@ last_call()
|
|||
numpy[0, :]
|
||||
numpy[:, i]
|
||||
numpy[0, :2]
|
||||
@@ -172,20 +169,27 @@
|
||||
@@ -172,7 +166,7 @@
|
||||
numpy[1 : c + 1, c]
|
||||
numpy[-(c + 1) :, d]
|
||||
numpy[:, l[-2]]
|
||||
-numpy[:, ::-1]
|
||||
+numpy[:, :: -1]
|
||||
numpy[np.newaxis, :]
|
||||
-(str or None) if (sys.version_info[0] > (3,)) else (str or bytes or None)
|
||||
+NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
(str or None) if (sys.version_info[0] > (3,)) else (str or bytes or None)
|
||||
{"2.7": dead, "3.7": long_live or die_hard}
|
||||
-{"2.7", "3.6", "3.7", "3.8", "3.9", "4.0" if gilectomy else "3.10"}
|
||||
+{
|
||||
+ "2.7",
|
||||
+ "3.6",
|
||||
+ "3.7",
|
||||
+ "3.8",
|
||||
+ "3.9",
|
||||
+ NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false,
|
||||
+}
|
||||
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]
|
||||
@@ -181,11 +175,11 @@
|
||||
(SomeName)
|
||||
SomeName
|
||||
(Good, Bad, Ugly)
|
||||
|
@ -494,7 +463,7 @@ last_call()
|
|||
{
|
||||
"id": "1",
|
||||
"type": "type",
|
||||
@@ -200,32 +204,22 @@
|
||||
@@ -200,32 +194,22 @@
|
||||
c = 1
|
||||
d = (1,) + a + (2,)
|
||||
e = (1,).count(1)
|
||||
|
@ -537,7 +506,7 @@ last_call()
|
|||
Ø = set()
|
||||
authors.łukasz.say_thanks()
|
||||
mapping = {
|
||||
@@ -237,29 +231,29 @@
|
||||
@@ -237,29 +221,33 @@
|
||||
|
||||
|
||||
def gen():
|
||||
|
@ -564,7 +533,11 @@ last_call()
|
|||
-), "Short message"
|
||||
-assert parens is TooMany
|
||||
+print(*NOT_YET_IMPLEMENTED_ExprStarred)
|
||||
+print(**NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false)
|
||||
+print(
|
||||
+ **{1: 3}
|
||||
+ if False
|
||||
+ else {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict}
|
||||
+)
|
||||
+print(*NOT_YET_IMPLEMENTED_ExprStarred)
|
||||
+NOT_YET_IMPLEMENTED_StmtAssert
|
||||
+NOT_YET_IMPLEMENTED_StmtAssert
|
||||
|
@ -580,7 +553,7 @@ last_call()
|
|||
...
|
||||
for i in call():
|
||||
...
|
||||
@@ -328,13 +322,18 @@
|
||||
@@ -328,13 +316,18 @@
|
||||
):
|
||||
return True
|
||||
if (
|
||||
|
@ -602,7 +575,7 @@ last_call()
|
|||
^ aaaaaaaa.i << aaaaaaaa.k >> aaaaaaaa.l**aaaaaaaa.m // aaaaaaaa.n
|
||||
):
|
||||
return True
|
||||
@@ -342,7 +341,8 @@
|
||||
@@ -342,7 +335,8 @@
|
||||
~aaaaaaaaaaaaaaaa.a
|
||||
+ aaaaaaaaaaaaaaaa.b
|
||||
- aaaaaaaaaaaaaaaa.c * aaaaaaaaaaaaaaaa.d @ aaaaaaaaaaaaaaaa.e
|
||||
|
@ -659,23 +632,20 @@ lambda x: True
|
|||
lambda x: True
|
||||
manylambdas = lambda x: True
|
||||
foo = lambda x: True
|
||||
NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
(NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false)
|
||||
1 if True else 2
|
||||
str or None if True else str or bytes or None
|
||||
(str or None) if True else (str or bytes or None)
|
||||
str or None if (1 if True else 2) else str or bytes or None
|
||||
(str or None) if (1 if True else 2) else (str or bytes or None)
|
||||
(
|
||||
(super_long_variable_name or None)
|
||||
if (1 if super_long_test_name else 2)
|
||||
else (str or bytes or None)
|
||||
)
|
||||
{"2.7": dead, "3.7": (long_live or die_hard)}
|
||||
{"2.7": dead, "3.7": (long_live or die_hard), **{"3.6": verygood}}
|
||||
{**a, **b, **c}
|
||||
{
|
||||
"2.7",
|
||||
"3.6",
|
||||
"3.7",
|
||||
"3.8",
|
||||
"3.9",
|
||||
(NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false),
|
||||
}
|
||||
{"2.7", "3.6", "3.7", "3.8", "3.9", ("4.0" if gilectomy else "3.10")}
|
||||
(
|
||||
{"a": "b"},
|
||||
(True or False),
|
||||
|
@ -790,16 +760,9 @@ numpy[-(c + 1) :, d]
|
|||
numpy[:, l[-2]]
|
||||
numpy[:, :: -1]
|
||||
numpy[np.newaxis, :]
|
||||
NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
|
||||
(str or None) if (sys.version_info[0] > (3,)) else (str or bytes or None)
|
||||
{"2.7": dead, "3.7": long_live or die_hard}
|
||||
{
|
||||
"2.7",
|
||||
"3.6",
|
||||
"3.7",
|
||||
"3.8",
|
||||
"3.9",
|
||||
NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false,
|
||||
}
|
||||
{"2.7", "3.6", "3.7", "3.8", "3.9", "4.0" if gilectomy else "3.10"}
|
||||
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]
|
||||
(SomeName)
|
||||
SomeName
|
||||
|
@ -861,7 +824,11 @@ async def f():
|
|||
|
||||
|
||||
print(*NOT_YET_IMPLEMENTED_ExprStarred)
|
||||
print(**NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false)
|
||||
print(
|
||||
**{1: 3}
|
||||
if False
|
||||
else {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict}
|
||||
)
|
||||
print(*NOT_YET_IMPLEMENTED_ExprStarred)
|
||||
NOT_YET_IMPLEMENTED_StmtAssert
|
||||
NOT_YET_IMPLEMENTED_StmtAssert
|
||||
|
|
|
@ -211,7 +211,7 @@ d={'a':1,
|
|||
# Comment 1
|
||||
|
||||
# Comment 2
|
||||
@@ -17,30 +16,54 @@
|
||||
@@ -17,30 +16,44 @@
|
||||
|
||||
# fmt: off
|
||||
def func_no_args():
|
||||
|
@ -268,35 +268,15 @@ d={'a':1,
|
|||
+
|
||||
+
|
||||
# fmt: on
|
||||
-def spaces(a=1, b=(), c=[], d={}, e=True, f=-1, g=1 if False else 2, h="", i=r""):
|
||||
def spaces(a=1, b=(), c=[], d={}, e=True, f=-1, g=1 if False else 2, h="", i=r""):
|
||||
- offset = attr.ib(default=attr.Factory(lambda: _r.uniform(1, 2)))
|
||||
- assert task._cancel_stack[: len(old_stack)] == old_stack
|
||||
+def spaces(
|
||||
+ a=1,
|
||||
+ b=(),
|
||||
+ c=[],
|
||||
+ d={},
|
||||
+ e=True,
|
||||
+ f=-1,
|
||||
+ g=NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false,
|
||||
+ h="",
|
||||
+ i=r"",
|
||||
+):
|
||||
+ offset = attr.ib(default=attr.Factory(lambda x: True))
|
||||
+ NOT_YET_IMPLEMENTED_StmtAssert
|
||||
|
||||
|
||||
def spaces_types(
|
||||
@@ -50,7 +73,7 @@
|
||||
d: dict = {},
|
||||
e: bool = True,
|
||||
f: int = -1,
|
||||
- g: int = 1 if False else 2,
|
||||
+ g: int = NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false,
|
||||
h: str = "",
|
||||
i: str = r"",
|
||||
):
|
||||
@@ -63,55 +86,54 @@
|
||||
@@ -63,55 +76,54 @@
|
||||
|
||||
something = {
|
||||
# fmt: off
|
||||
|
@ -371,7 +351,7 @@ d={'a':1,
|
|||
# fmt: on
|
||||
|
||||
|
||||
@@ -132,10 +154,10 @@
|
||||
@@ -132,10 +144,10 @@
|
||||
"""Another known limitation."""
|
||||
# fmt: on
|
||||
# fmt: off
|
||||
|
@ -386,7 +366,7 @@ d={'a':1,
|
|||
# fmt: on
|
||||
# fmt: off
|
||||
# ...but comments still get reformatted even though they should not be
|
||||
@@ -153,9 +175,7 @@
|
||||
@@ -153,9 +165,7 @@
|
||||
)
|
||||
)
|
||||
# fmt: off
|
||||
|
@ -397,7 +377,7 @@ d={'a':1,
|
|||
# fmt: on
|
||||
_type_comment_re = re.compile(
|
||||
r"""
|
||||
@@ -178,7 +198,7 @@
|
||||
@@ -178,7 +188,7 @@
|
||||
$
|
||||
""",
|
||||
# fmt: off
|
||||
|
@ -406,7 +386,7 @@ d={'a':1,
|
|||
# fmt: on
|
||||
)
|
||||
|
||||
@@ -216,8 +236,7 @@
|
||||
@@ -216,8 +226,7 @@
|
||||
xxxxxxxxxx_xxxxxxxxxxx_xxxxxxx_xxxxxxxxx=5,
|
||||
)
|
||||
# fmt: off
|
||||
|
@ -476,17 +456,7 @@ def function_signature_stress_test(
|
|||
|
||||
|
||||
# fmt: on
|
||||
def spaces(
|
||||
a=1,
|
||||
b=(),
|
||||
c=[],
|
||||
d={},
|
||||
e=True,
|
||||
f=-1,
|
||||
g=NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false,
|
||||
h="",
|
||||
i=r"",
|
||||
):
|
||||
def spaces(a=1, b=(), c=[], d={}, e=True, f=-1, g=1 if False else 2, h="", i=r""):
|
||||
offset = attr.ib(default=attr.Factory(lambda x: True))
|
||||
NOT_YET_IMPLEMENTED_StmtAssert
|
||||
|
||||
|
@ -498,7 +468,7 @@ def spaces_types(
|
|||
d: dict = {},
|
||||
e: bool = True,
|
||||
f: int = -1,
|
||||
g: int = NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false,
|
||||
g: int = 1 if False else 2,
|
||||
h: str = "",
|
||||
i: str = r"",
|
||||
):
|
||||
|
|
|
@ -126,7 +126,7 @@ def __await__(): return (yield)
|
|||
if False:
|
||||
...
|
||||
for i in range(10):
|
||||
@@ -41,12 +40,22 @@
|
||||
@@ -41,12 +40,12 @@
|
||||
debug: bool = False,
|
||||
**kwargs,
|
||||
) -> str:
|
||||
|
@ -134,35 +134,15 @@ def __await__(): return (yield)
|
|||
+ return text[number : -1]
|
||||
|
||||
|
||||
-def spaces(a=1, b=(), c=[], d={}, e=True, f=-1, g=1 if False else 2, h="", i=r""):
|
||||
def spaces(a=1, b=(), c=[], d={}, e=True, f=-1, g=1 if False else 2, h="", i=r""):
|
||||
- offset = attr.ib(default=attr.Factory(lambda: _r.uniform(10000, 200000)))
|
||||
- assert task._cancel_stack[: len(old_stack)] == old_stack
|
||||
+def spaces(
|
||||
+ a=1,
|
||||
+ b=(),
|
||||
+ c=[],
|
||||
+ d={},
|
||||
+ e=True,
|
||||
+ f=-1,
|
||||
+ g=NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false,
|
||||
+ h="",
|
||||
+ i=r"",
|
||||
+):
|
||||
+ offset = attr.ib(default=attr.Factory(lambda x: True))
|
||||
+ NOT_YET_IMPLEMENTED_StmtAssert
|
||||
|
||||
|
||||
def spaces_types(
|
||||
@@ -56,7 +65,7 @@
|
||||
d: dict = {},
|
||||
e: bool = True,
|
||||
f: int = -1,
|
||||
- g: int = 1 if False else 2,
|
||||
+ g: int = NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false,
|
||||
h: str = "",
|
||||
i: str = r"",
|
||||
):
|
||||
@@ -64,19 +73,17 @@
|
||||
@@ -64,19 +63,17 @@
|
||||
|
||||
|
||||
def spaces2(result=_core.Value(None)):
|
||||
|
@ -190,7 +170,7 @@ def __await__(): return (yield)
|
|||
|
||||
|
||||
def long_lines():
|
||||
@@ -135,14 +142,8 @@
|
||||
@@ -135,14 +132,8 @@
|
||||
a,
|
||||
**kwargs,
|
||||
) -> A:
|
||||
|
@ -257,17 +237,7 @@ def function_signature_stress_test(
|
|||
return text[number : -1]
|
||||
|
||||
|
||||
def spaces(
|
||||
a=1,
|
||||
b=(),
|
||||
c=[],
|
||||
d={},
|
||||
e=True,
|
||||
f=-1,
|
||||
g=NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false,
|
||||
h="",
|
||||
i=r"",
|
||||
):
|
||||
def spaces(a=1, b=(), c=[], d={}, e=True, f=-1, g=1 if False else 2, h="", i=r""):
|
||||
offset = attr.ib(default=attr.Factory(lambda x: True))
|
||||
NOT_YET_IMPLEMENTED_StmtAssert
|
||||
|
||||
|
@ -279,7 +249,7 @@ def spaces_types(
|
|||
d: dict = {},
|
||||
e: bool = True,
|
||||
f: int = -1,
|
||||
g: int = NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false,
|
||||
g: int = 1 if False else 2,
|
||||
h: str = "",
|
||||
i: str = r"",
|
||||
):
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/if.py
|
||||
---
|
||||
## Input
|
||||
```py
|
||||
a1 = 1 if True else 2
|
||||
|
||||
a2 = "this is a very long text that will make the group break to check that parentheses are added" if True else 2
|
||||
|
||||
# These comment should be kept in place
|
||||
b1 = (
|
||||
# We return "a" ...
|
||||
"a" # that's our True value
|
||||
# ... if this condition matches ...
|
||||
if True # that's our test
|
||||
# ... otherwise we return "b"
|
||||
else "b" # that's our False value
|
||||
)
|
||||
|
||||
# These only need to be stable, bonus is we also keep the order
|
||||
c1 = (
|
||||
"a" # 1
|
||||
if # 2
|
||||
True # 3
|
||||
else # 4
|
||||
"b" # 5
|
||||
)
|
||||
c2 = (
|
||||
"a" # 1
|
||||
# 2
|
||||
if # 3
|
||||
# 4
|
||||
True # 5
|
||||
# 6
|
||||
else # 7
|
||||
# 8
|
||||
"b" # 9
|
||||
)
|
||||
```
|
||||
|
||||
## Output
|
||||
```py
|
||||
a1 = 1 if True else 2
|
||||
|
||||
a2 = (
|
||||
"this is a very long text that will make the group break to check that parentheses are added"
|
||||
if True
|
||||
else 2
|
||||
)
|
||||
|
||||
# These comment should be kept in place
|
||||
b1 = (
|
||||
# We return "a" ...
|
||||
"a" # that's our True value
|
||||
# ... if this condition matches ...
|
||||
if True # that's our test
|
||||
# ... otherwise we return "b"
|
||||
else "b" # that's our False value
|
||||
)
|
||||
|
||||
# These only need to be stable, bonus is we also keep the order
|
||||
c1 = (
|
||||
"a" # 1
|
||||
# 2
|
||||
if True # 3
|
||||
# 4
|
||||
else "b" # 5
|
||||
)
|
||||
c2 = (
|
||||
"a" # 1
|
||||
# 2
|
||||
# 3
|
||||
# 4
|
||||
if True # 5
|
||||
# 6
|
||||
# 7
|
||||
# 8
|
||||
else "b" # 9
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue