Update Black tests (#20794)

Summary
--

```shell
git clone git@github.com:psf/black.git ../other/black
crates/ruff_python_formatter/resources/test/fixtures/import_black_tests.py ../other/black
```

Then ran our tests and accepted the snapshots

I had to make a small fix to our tuple normalization logic for `del`
statements
in the second commit, otherwise the tests were panicking at a changed
AST. I
think the new implementation is closer to the intention described in the
nearby
comment anyway, though.

The first commit adds the new Python, settings, and `.expect` files, the
next three commits make some small
fixes to help get the tests running, and then the fifth commit accepts
all but one of the new snapshots. The last commit includes the new
unsupported syntax error for one f-string example, tracked in #20774.

Test Plan
--

Newly imported tests. I went through all of the new snapshots and added
review comments below. I think they're all expected, except a few cases
I wasn't 100% sure about.
This commit is contained in:
Brent Westbrook 2025-10-14 10:14:59 -04:00 committed by GitHub
parent 9090aead0f
commit 1ed9b215b9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
123 changed files with 6607 additions and 343 deletions

View file

@ -108,7 +108,8 @@ fn black_compatibility() {
let expected_output = fs::read_to_string(&expected_path)
.unwrap_or_else(|_| panic!("Expected Black output file '{expected_path:?}' to exist"));
ensure_unchanged_ast(&content, &formatted_code, &options, input_path);
let unsupported_syntax_errors =
ensure_unchanged_ast(&content, &formatted_code, &options, input_path);
if formatted_code == expected_output {
// Black and Ruff formatting matches. Delete any existing snapshot files because the Black output
@ -163,6 +164,20 @@ fn black_compatibility() {
write!(snapshot, "{}", Header::new("Black Output")).unwrap();
write!(snapshot, "{}", CodeFrame::new("python", &expected_output)).unwrap();
if !unsupported_syntax_errors.is_empty() {
write!(snapshot, "{}", Header::new("New Unsupported Syntax Errors")).unwrap();
writeln!(
snapshot,
"{}",
DisplayDiagnostics::new(
&DummyFileResolver,
&DisplayDiagnosticConfig::default().format(DiagnosticFormat::Full),
&unsupported_syntax_errors
)
)
.unwrap();
}
insta::with_settings!({
omit_expression => true,
input_file => input_path,

View file

@ -1,8 +1,5 @@
use regex::Regex;
use std::sync::LazyLock;
use {
itertools::Either::{Left, Right},
regex::Regex,
};
use ruff_python_ast::{
self as ast, BytesLiteralFlags, Expr, FStringFlags, FStringPart, InterpolatedStringElement,
@ -46,18 +43,9 @@ impl Transformer for Normalizer {
fn visit_stmt(&self, stmt: &mut Stmt) {
if let Stmt::Delete(delete) = stmt {
// Treat `del a, b` and `del (a, b)` equivalently.
delete.targets = delete
.targets
.clone()
.into_iter()
.flat_map(|target| {
if let Expr::Tuple(tuple) = target {
Left(tuple.elts.into_iter())
} else {
Right(std::iter::once(target))
}
})
.collect();
if let [Expr::Tuple(tuple)] = delete.targets.as_slice() {
delete.targets = tuple.elts.clone();
}
}
transformer::walk_stmt(self, stmt);

View file

@ -0,0 +1,204 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/cantfit.py
---
## Input
```python
# long variable name
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = 0
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = 1 # with a comment
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = [
1, 2, 3
]
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = function()
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = function(
arg1, arg2, arg3
)
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = function(
[1, 2, 3], arg1, [1, 2, 3], arg2, [1, 2, 3], arg3
)
# long function name
normal_name = but_the_function_name_is_now_ridiculously_long_and_it_is_still_super_annoying()
normal_name = but_the_function_name_is_now_ridiculously_long_and_it_is_still_super_annoying(
arg1, arg2, arg3
)
normal_name = but_the_function_name_is_now_ridiculously_long_and_it_is_still_super_annoying(
[1, 2, 3], arg1, [1, 2, 3], arg2, [1, 2, 3], arg3
)
string_variable_name = (
"a string that is waaaaaaaayyyyyyyy too long, even in parens, there's nothing you can do" # noqa
)
for key in """
hostname
port
username
""".split():
if key in self.connect_kwargs:
raise ValueError(err.format(key))
concatenated_strings = "some strings that are " "concatenated implicitly, so if you put them on separate " "lines it will fit"
del concatenated_strings, string_variable_name, normal_function_name, normal_name, need_more_to_make_the_line_long_enough
del ([], name_1, name_2), [(), [], name_4, name_3], name_1[[name_2 for name_1 in name_0]]
del (),
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,18 +1,12 @@
# long variable name
-this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = (
- 0
-)
-this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = (
- 1 # with a comment
-)
+this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = 0
+this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = 1 # with a comment
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = [
1,
2,
3,
]
-this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = (
- function()
-)
+this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = function()
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = function(
arg1, arg2, arg3
)
@@ -58,4 +52,4 @@
[(), [], name_4, name_3],
name_1[[name_2 for name_1 in name_0]],
)
-del ((),)
+del ()
```
## Ruff Output
```python
# long variable name
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = 0
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = 1 # with a comment
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = [
1,
2,
3,
]
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = function()
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = function(
arg1, arg2, arg3
)
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = function(
[1, 2, 3], arg1, [1, 2, 3], arg2, [1, 2, 3], arg3
)
# long function name
normal_name = (
but_the_function_name_is_now_ridiculously_long_and_it_is_still_super_annoying()
)
normal_name = (
but_the_function_name_is_now_ridiculously_long_and_it_is_still_super_annoying(
arg1, arg2, arg3
)
)
normal_name = (
but_the_function_name_is_now_ridiculously_long_and_it_is_still_super_annoying(
[1, 2, 3], arg1, [1, 2, 3], arg2, [1, 2, 3], arg3
)
)
string_variable_name = "a string that is waaaaaaaayyyyyyyy too long, even in parens, there's nothing you can do" # noqa
for key in """
hostname
port
username
""".split():
if key in self.connect_kwargs:
raise ValueError(err.format(key))
concatenated_strings = (
"some strings that are "
"concatenated implicitly, so if you put them on separate "
"lines it will fit"
)
del (
concatenated_strings,
string_variable_name,
normal_function_name,
normal_name,
need_more_to_make_the_line_long_enough,
)
del (
([], name_1, name_2),
[(), [], name_4, name_3],
name_1[[name_2 for name_1 in name_0]],
)
del ()
```
## Black Output
```python
# long variable name
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = (
0
)
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = (
1 # with a comment
)
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = [
1,
2,
3,
]
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = (
function()
)
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = function(
arg1, arg2, arg3
)
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = function(
[1, 2, 3], arg1, [1, 2, 3], arg2, [1, 2, 3], arg3
)
# long function name
normal_name = (
but_the_function_name_is_now_ridiculously_long_and_it_is_still_super_annoying()
)
normal_name = (
but_the_function_name_is_now_ridiculously_long_and_it_is_still_super_annoying(
arg1, arg2, arg3
)
)
normal_name = (
but_the_function_name_is_now_ridiculously_long_and_it_is_still_super_annoying(
[1, 2, 3], arg1, [1, 2, 3], arg2, [1, 2, 3], arg3
)
)
string_variable_name = "a string that is waaaaaaaayyyyyyyy too long, even in parens, there's nothing you can do" # noqa
for key in """
hostname
port
username
""".split():
if key in self.connect_kwargs:
raise ValueError(err.format(key))
concatenated_strings = (
"some strings that are "
"concatenated implicitly, so if you put them on separate "
"lines it will fit"
)
del (
concatenated_strings,
string_variable_name,
normal_function_name,
normal_name,
need_more_to_make_the_line_long_enough,
)
del (
([], name_1, name_2),
[(), [], name_4, name_3],
name_1[[name_2 for name_1 in name_0]],
)
del ((),)
```

View file

@ -0,0 +1,76 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/fmtskip10.py
---
## Input
```python
def foo(): return "mock" # fmt: skip
if True: print("yay") # fmt: skip
for i in range(10): print(i) # fmt: skip
j = 1 # fmt: skip
while j < 10: j += 1 # fmt: skip
b = [c for c in "A very long string that would normally generate some kind of collapse, since it is this long"] # fmt: skip
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,8 +1,14 @@
-def foo(): return "mock" # fmt: skip
-if True: print("yay") # fmt: skip
-for i in range(10): print(i) # fmt: skip
+def foo():
+ return "mock" # fmt: skip
+
+
+if True:
+ print("yay") # fmt: skip
+for i in range(10):
+ print(i) # fmt: skip
-j = 1 # fmt: skip
-while j < 10: j += 1 # fmt: skip
+j = 1 # fmt: skip
+while j < 10:
+ j += 1 # fmt: skip
-b = [c for c in "A very long string that would normally generate some kind of collapse, since it is this long"] # fmt: skip
+b = [c for c in "A very long string that would normally generate some kind of collapse, since it is this long"] # fmt: skip
```
## Ruff Output
```python
def foo():
return "mock" # fmt: skip
if True:
print("yay") # fmt: skip
for i in range(10):
print(i) # fmt: skip
j = 1 # fmt: skip
while j < 10:
j += 1 # fmt: skip
b = [c for c in "A very long string that would normally generate some kind of collapse, since it is this long"] # fmt: skip
```
## Black Output
```python
def foo(): return "mock" # fmt: skip
if True: print("yay") # fmt: skip
for i in range(10): print(i) # fmt: skip
j = 1 # fmt: skip
while j < 10: j += 1 # fmt: skip
b = [c for c in "A very long string that would normally generate some kind of collapse, since it is this long"] # fmt: skip
```

View file

@ -72,3 +72,17 @@ f'Hello \'{tricky + "example"}\''
f"Tried directories {str(rootdirs)} \
but none started with prefix {parentdir_prefix}"
```
## New Unsupported Syntax Errors
error[invalid-syntax]: Cannot reuse outer quote character in f-strings on Python 3.10 (syntax was added in Python 3.12)
--> fstring.py:6:9
|
4 | f"some f-string with {a} {few():.2f} {formatted.values!r}"
5 | f"some f-string with {a} {few(''):.2f} {formatted.values!r}"
6 | f"{f'''{"nested"} inner'''} outer"
| ^
7 | f'"{f"{nested} inner"}" outer'
8 | f"space between opening braces: { {a for a in (1, 2, 3)} }"
|
warning: Only accept new syntax errors if they are also present in the input. The formatter should not introduce syntax errors.

View file

@ -0,0 +1,126 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/fstring_quotations.py
---
## Input
```python
# Regression tests for long f-strings, including examples from issue #3623
a = (
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
f'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"{"b"}"'
)
a = (
f'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"{"b"}"'
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
)
a = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + \
f'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"{"b"}"'
a = f'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"{"b"}"' + \
f'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"{"b"}"'
a = (
f'bbbbbbb"{"b"}"'
'aaaaaaaa'
)
a = (
f'"{"b"}"'
)
a = (
f'\"{"b"}\"'
)
a = (
r'\"{"b"}\"'
)
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -20,7 +20,7 @@
+ f'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"{"b"}"'
)
-a = f'bbbbbbb"{"b"}"' "aaaaaaaa"
+a = f'bbbbbbb"{"b"}"aaaaaaaa'
a = f'"{"b"}"'
```
## Ruff Output
```python
# Regression tests for long f-strings, including examples from issue #3623
a = (
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
f'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"{"b"}"'
)
a = (
f'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"{"b"}"'
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
)
a = (
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ f'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"{"b"}"'
)
a = (
f'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"{"b"}"'
+ f'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"{"b"}"'
)
a = f'bbbbbbb"{"b"}"aaaaaaaa'
a = f'"{"b"}"'
a = f'"{"b"}"'
a = r'\"{"b"}\"'
```
## Black Output
```python
# Regression tests for long f-strings, including examples from issue #3623
a = (
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
f'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"{"b"}"'
)
a = (
f'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"{"b"}"'
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
)
a = (
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ f'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"{"b"}"'
)
a = (
f'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"{"b"}"'
+ f'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"{"b"}"'
)
a = f'bbbbbbb"{"b"}"' "aaaaaaaa"
a = f'"{"b"}"'
a = f'"{"b"}"'
a = r'\"{"b"}\"'
```

View file

@ -0,0 +1,561 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/generics_wrapping.py
---
## Input
```python
def plain[T, B](a: T, b: T) -> T:
return a
def arg_magic[T, B](a: T, b: T,) -> T:
return a
def type_param_magic[T, B,](a: T, b: T) -> T:
return a
def both_magic[T, B,](a: T, b: T,) -> T:
return a
def plain_multiline[
T,
B
](
a: T,
b: T
) -> T:
return a
def arg_magic_multiline[
T,
B
](
a: T,
b: T,
) -> T:
return a
def type_param_magic_multiline[
T,
B,
](
a: T,
b: T
) -> T:
return a
def both_magic_multiline[
T,
B,
](
a: T,
b: T,
) -> T:
return a
def plain_mixed1[
T,
B
](a: T, b: T) -> T:
return a
def plain_mixed2[T, B](
a: T,
b: T
) -> T:
return a
def arg_magic_mixed1[
T,
B
](a: T, b: T,) -> T:
return a
def arg_magic_mixed2[T, B](
a: T,
b: T,
) -> T:
return a
def type_param_magic_mixed1[
T,
B,
](a: T, b: T) -> T:
return a
def type_param_magic_mixed2[T, B,](
a: T,
b: T
) -> T:
return a
def both_magic_mixed1[
T,
B,
](a: T, b: T,) -> T:
return a
def both_magic_mixed2[T, B,](
a: T,
b: T,
) -> T:
return a
def something_something_function[
T: Model
](param: list[int], other_param: type[T], *, some_other_param: bool = True) -> QuerySet[
T
]:
pass
def func[A_LOT_OF_GENERIC_TYPES: AreBeingDefinedHere, LIKE_THIS, AND_THIS, ANOTHER_ONE, AND_YET_ANOTHER_ONE: ThisOneHasTyping](a: T, b: T, c: T, d: T, e: T, f: T, g: T, h: T, i: T, j: T, k: T, l: T, m: T, n: T, o: T, p: T) -> T:
return a
def with_random_comments[
Z
# bye
]():
return a
def func[
T, # comment
U # comment
,
Z: # comment
int
](): pass
def func[
T, # comment but it's long so it doesn't just move to the end of the line
U # comment comment comm comm ent ent
,
Z: # comment ent ent comm comm comment
int
](): pass
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -12,9 +12,7 @@
def type_param_magic[
T,
B,
-](
- a: T, b: T
-) -> T:
+](a: T, b: T) -> T:
return a
@@ -42,9 +40,7 @@
def type_param_magic_multiline[
T,
B,
-](
- a: T, b: T
-) -> T:
+](a: T, b: T) -> T:
return a
@@ -83,18 +79,14 @@
def type_param_magic_mixed1[
T,
B,
-](
- a: T, b: T
-) -> T:
+](a: T, b: T) -> T:
return a
def type_param_magic_mixed2[
T,
B,
-](
- a: T, b: T
-) -> T:
+](a: T, b: T) -> T:
return a
@@ -158,13 +150,19 @@
return a
-def func[T, U, Z: int](): # comment # comment # comment
+def func[
+ T, # comment
+ U, # comment
+ Z: # comment
+ int,
+]():
pass
def func[
T, # comment but it's long so it doesn't just move to the end of the line
U, # comment comment comm comm ent ent
- Z: int, # comment ent ent comm comm comment
+ Z: # comment ent ent comm comm comment
+ int,
]():
pass
```
## Ruff Output
```python
def plain[T, B](a: T, b: T) -> T:
return a
def arg_magic[T, B](
a: T,
b: T,
) -> T:
return a
def type_param_magic[
T,
B,
](a: T, b: T) -> T:
return a
def both_magic[
T,
B,
](
a: T,
b: T,
) -> T:
return a
def plain_multiline[T, B](a: T, b: T) -> T:
return a
def arg_magic_multiline[T, B](
a: T,
b: T,
) -> T:
return a
def type_param_magic_multiline[
T,
B,
](a: T, b: T) -> T:
return a
def both_magic_multiline[
T,
B,
](
a: T,
b: T,
) -> T:
return a
def plain_mixed1[T, B](a: T, b: T) -> T:
return a
def plain_mixed2[T, B](a: T, b: T) -> T:
return a
def arg_magic_mixed1[T, B](
a: T,
b: T,
) -> T:
return a
def arg_magic_mixed2[T, B](
a: T,
b: T,
) -> T:
return a
def type_param_magic_mixed1[
T,
B,
](a: T, b: T) -> T:
return a
def type_param_magic_mixed2[
T,
B,
](a: T, b: T) -> T:
return a
def both_magic_mixed1[
T,
B,
](
a: T,
b: T,
) -> T:
return a
def both_magic_mixed2[
T,
B,
](
a: T,
b: T,
) -> T:
return a
def something_something_function[T: Model](
param: list[int], other_param: type[T], *, some_other_param: bool = True
) -> QuerySet[T]:
pass
def func[
A_LOT_OF_GENERIC_TYPES: AreBeingDefinedHere,
LIKE_THIS,
AND_THIS,
ANOTHER_ONE,
AND_YET_ANOTHER_ONE: ThisOneHasTyping,
](
a: T,
b: T,
c: T,
d: T,
e: T,
f: T,
g: T,
h: T,
i: T,
j: T,
k: T,
l: T,
m: T,
n: T,
o: T,
p: T,
) -> T:
return a
def with_random_comments[
Z
# bye
]():
return a
def func[
T, # comment
U, # comment
Z: # comment
int,
]():
pass
def func[
T, # comment but it's long so it doesn't just move to the end of the line
U, # comment comment comm comm ent ent
Z: # comment ent ent comm comm comment
int,
]():
pass
```
## Black Output
```python
def plain[T, B](a: T, b: T) -> T:
return a
def arg_magic[T, B](
a: T,
b: T,
) -> T:
return a
def type_param_magic[
T,
B,
](
a: T, b: T
) -> T:
return a
def both_magic[
T,
B,
](
a: T,
b: T,
) -> T:
return a
def plain_multiline[T, B](a: T, b: T) -> T:
return a
def arg_magic_multiline[T, B](
a: T,
b: T,
) -> T:
return a
def type_param_magic_multiline[
T,
B,
](
a: T, b: T
) -> T:
return a
def both_magic_multiline[
T,
B,
](
a: T,
b: T,
) -> T:
return a
def plain_mixed1[T, B](a: T, b: T) -> T:
return a
def plain_mixed2[T, B](a: T, b: T) -> T:
return a
def arg_magic_mixed1[T, B](
a: T,
b: T,
) -> T:
return a
def arg_magic_mixed2[T, B](
a: T,
b: T,
) -> T:
return a
def type_param_magic_mixed1[
T,
B,
](
a: T, b: T
) -> T:
return a
def type_param_magic_mixed2[
T,
B,
](
a: T, b: T
) -> T:
return a
def both_magic_mixed1[
T,
B,
](
a: T,
b: T,
) -> T:
return a
def both_magic_mixed2[
T,
B,
](
a: T,
b: T,
) -> T:
return a
def something_something_function[T: Model](
param: list[int], other_param: type[T], *, some_other_param: bool = True
) -> QuerySet[T]:
pass
def func[
A_LOT_OF_GENERIC_TYPES: AreBeingDefinedHere,
LIKE_THIS,
AND_THIS,
ANOTHER_ONE,
AND_YET_ANOTHER_ONE: ThisOneHasTyping,
](
a: T,
b: T,
c: T,
d: T,
e: T,
f: T,
g: T,
h: T,
i: T,
j: T,
k: T,
l: T,
m: T,
n: T,
o: T,
p: T,
) -> T:
return a
def with_random_comments[
Z
# bye
]():
return a
def func[T, U, Z: int](): # comment # comment # comment
pass
def func[
T, # comment but it's long so it doesn't just move to the end of the line
U, # comment comment comm comm ent ent
Z: int, # comment ent ent comm comm comment
]():
pass
```

View file

@ -0,0 +1,114 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/long_strings__type_annotations.py
---
## Input
```python
def func(
arg1,
arg2,
) -> Set["this_is_a_very_long_module_name.AndAVeryLongClasName"
".WithAVeryVeryVeryVeryVeryLongSubClassName"]:
pass
def func(
argument: (
"VeryLongClassNameWithAwkwardGenericSubtype[int] |"
"VeryLongClassNameWithAwkwardGenericSubtype[str]"
),
) -> (
"VeryLongClassNameWithAwkwardGenericSubtype[int] |"
"VeryLongClassNameWithAwkwardGenericSubtype[str]"
):
pass
def func(
argument: (
"int |"
"str"
),
) -> Set["int |"
" str"]:
pass
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -21,6 +21,6 @@
def func(
- argument: "int |" "str",
-) -> Set["int |" " str"]:
+ argument: ("int |str"),
+) -> Set["int | str"]:
pass
```
## Ruff Output
```python
def func(
arg1,
arg2,
) -> Set[
"this_is_a_very_long_module_name.AndAVeryLongClasName"
".WithAVeryVeryVeryVeryVeryLongSubClassName"
]:
pass
def func(
argument: (
"VeryLongClassNameWithAwkwardGenericSubtype[int] |"
"VeryLongClassNameWithAwkwardGenericSubtype[str]"
),
) -> (
"VeryLongClassNameWithAwkwardGenericSubtype[int] |"
"VeryLongClassNameWithAwkwardGenericSubtype[str]"
):
pass
def func(
argument: ("int |str"),
) -> Set["int | str"]:
pass
```
## Black Output
```python
def func(
arg1,
arg2,
) -> Set[
"this_is_a_very_long_module_name.AndAVeryLongClasName"
".WithAVeryVeryVeryVeryVeryLongSubClassName"
]:
pass
def func(
argument: (
"VeryLongClassNameWithAwkwardGenericSubtype[int] |"
"VeryLongClassNameWithAwkwardGenericSubtype[str]"
),
) -> (
"VeryLongClassNameWithAwkwardGenericSubtype[int] |"
"VeryLongClassNameWithAwkwardGenericSubtype[str]"
):
pass
def func(
argument: "int |" "str",
) -> Set["int |" " str"]:
pass
```

View file

@ -1,122 +0,0 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/no_blank_line_before_docstring.py
snapshot_kind: text
---
## Input
```python
def line_before_docstring():
"""Please move me up"""
class LineBeforeDocstring:
"""Please move me up"""
class EvenIfThereIsAMethodAfter:
"""I'm the docstring"""
def method(self):
pass
class TwoLinesBeforeDocstring:
"""I want to be treated the same as if I were closer"""
class MultilineDocstringsAsWell:
"""I'm so far
and on so many lines...
"""
class SingleQuotedDocstring:
"I'm a docstring but I don't even get triple quotes."
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -25,5 +25,4 @@
class SingleQuotedDocstring:
-
"I'm a docstring but I don't even get triple quotes."
```
## Ruff Output
```python
def line_before_docstring():
"""Please move me up"""
class LineBeforeDocstring:
"""Please move me up"""
class EvenIfThereIsAMethodAfter:
"""I'm the docstring"""
def method(self):
pass
class TwoLinesBeforeDocstring:
"""I want to be treated the same as if I were closer"""
class MultilineDocstringsAsWell:
"""I'm so far
and on so many lines...
"""
class SingleQuotedDocstring:
"I'm a docstring but I don't even get triple quotes."
```
## Black Output
```python
def line_before_docstring():
"""Please move me up"""
class LineBeforeDocstring:
"""Please move me up"""
class EvenIfThereIsAMethodAfter:
"""I'm the docstring"""
def method(self):
pass
class TwoLinesBeforeDocstring:
"""I want to be treated the same as if I were closer"""
class MultilineDocstringsAsWell:
"""I'm so far
and on so many lines...
"""
class SingleQuotedDocstring:
"I'm a docstring but I don't even get triple quotes."
```

View file

@ -1,7 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/pep604_union_types_line_breaks.py
snapshot_kind: text
---
## Input
@ -27,7 +26,7 @@ z: (Short
z: (int) = 2.3
z: ((int)) = foo()
# In case I go for not enforcing parentheses, this might get improved at the same time
# In case I go for not enforcing parantheses, this might get improved at the same time
x = (
z
== 9999999999999999999999999999999999999999
@ -166,7 +165,7 @@ z: Short | Short2 | Short3 | Short4 = 8
z: int = 2.3
z: int = foo()
# In case I go for not enforcing parentheses, this might get improved at the same time
# In case I go for not enforcing parantheses, this might get improved at the same time
x = (
z
== 9999999999999999999999999999999999999999
@ -270,7 +269,7 @@ z: Short | Short2 | Short3 | Short4 = 8
z: int = 2.3
z: int = foo()
# In case I go for not enforcing parentheses, this might get improved at the same time
# In case I go for not enforcing parantheses, this might get improved at the same time
x = (
z
== 9999999999999999999999999999999999999999

View file

@ -80,8 +80,9 @@ x = f"a{2+2:=^{foo(x+y**2):something else}}b"
x = f"a{2+2:=^{foo(x+y**2):something else}one more}b"
f'{(abc:=10)}'
f"This is a really long string, but just make sure that you reflow fstrings {
2+2:d}"
f"""This is a really long string, but just make sure that you reflow fstrings {
2+2:d
}"""
f"This is a really long string, but just make sure that you reflow fstrings correctly {2+2:d}"
f"{2+2=}"
@ -168,7 +169,7 @@ rf"\{"a"}"
x = """foo {{ {2 + 2}bar
baz"""
@@ -28,55 +26,48 @@
@@ -28,55 +26,50 @@
x = f"""foo {{ {2 + 2}bar {{ baz"""
@ -231,16 +232,16 @@ rf"\{"a"}"
+x = f"a{2 + 2:=^{foo(x + y**2):something else}one more}b"
+f"{(abc := 10)}"
-f"This is a really long string, but just make sure that you reflow fstrings {
f"""This is a really long string, but just make sure that you reflow fstrings {
- 2+2:d
-}"
+ 2 + 2:d
}"""
-f"This is a really long string, but just make sure that you reflow fstrings correctly {2+2:d}"
+f"This is a really long string, but just make sure that you reflow fstrings {2 + 2:d}"
+f"This is a really long string, but just make sure that you reflow fstrings correctly {2 + 2:d}"
f"{2+2=}"
f"{2+2 = }"
@@ -88,14 +79,10 @@
@@ -88,14 +81,10 @@
%d
}"""
@ -257,7 +258,7 @@ rf"\{"a"}"
)
f"`escape` only permitted in {{'html', 'latex', 'latex-math'}}, \
@@ -105,8 +92,10 @@
@@ -105,8 +94,10 @@
rf"\{{\}}"
f"""
@ -270,7 +271,7 @@ rf"\{"a"}"
"""
value: str = f"""foo
@@ -124,13 +113,15 @@
@@ -124,13 +115,15 @@
f'{{\\"kind\\":\\"ConfigMap\\",\\"metadata\\":{{\\"annotations\\":{{}},\\"name\\":\\"cluster-info\\",\\"namespace\\":\\"amazon-cloudwatch\\"}}}}'
@ -364,7 +365,9 @@ x = f"a{2 + 2:=^{foo(x + y**2):something else}}b"
x = f"a{2 + 2:=^{foo(x + y**2):something else}one more}b"
f"{(abc := 10)}"
f"This is a really long string, but just make sure that you reflow fstrings {2 + 2:d}"
f"""This is a really long string, but just make sure that you reflow fstrings {
2 + 2:d
}"""
f"This is a really long string, but just make sure that you reflow fstrings correctly {2 + 2:d}"
f"{2+2=}"
@ -503,9 +506,9 @@ x = f"a{2+2:=^{foo(x+y**2):something else}}b"
x = f"a{2+2:=^{foo(x+y**2):something else}one more}b"
f"{(abc:=10)}"
f"This is a really long string, but just make sure that you reflow fstrings {
f"""This is a really long string, but just make sure that you reflow fstrings {
2+2:d
}"
}"""
f"This is a really long string, but just make sure that you reflow fstrings correctly {2+2:d}"
f"{2+2=}"

View file

@ -0,0 +1,123 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/prefer_rhs_split_reformatted.py
---
## Input
```python
# Test cases separate from `prefer_rhs_split.py` that contains unformatted source.
# Left hand side fits in a single line but will still be exploded by the
# magic trailing comma.
first_value, (m1, m2,), third_value = xxxxxx_yyyyyy_zzzzzz_wwwwww_uuuuuuu_vvvvvvvvvvv(
arg1,
arg2,
)
# Make when when the left side of assignment plus the opening paren "... = (" is
# exactly line length limit + 1, it won't be split like that.
xxxxxxxxx_yyy_zzzzzzzz[xx.xxxxxx(x_yyy_zzzzzz.xxxxx[0]), x_yyy_zzzzzz.xxxxxx(xxxx=1)] = 1
# Regression test for #1187
print(
dict(
a=1,
b=2 if some_kind_of_data is not None else some_other_kind_of_data, # some explanation of why this is actually necessary
c=3,
)
)
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -24,9 +24,9 @@
print(
dict(
a=1,
- b=(
- 2 if some_kind_of_data is not None else some_other_kind_of_data
- ), # some explanation of why this is actually necessary
+ b=2
+ if some_kind_of_data is not None
+ else some_other_kind_of_data, # some explanation of why this is actually necessary
c=3,
)
)
```
## Ruff Output
```python
# Test cases separate from `prefer_rhs_split.py` that contains unformatted source.
# Left hand side fits in a single line but will still be exploded by the
# magic trailing comma.
(
first_value,
(
m1,
m2,
),
third_value,
) = xxxxxx_yyyyyy_zzzzzz_wwwwww_uuuuuuu_vvvvvvvvvvv(
arg1,
arg2,
)
# Make when when the left side of assignment plus the opening paren "... = (" is
# exactly line length limit + 1, it won't be split like that.
xxxxxxxxx_yyy_zzzzzzzz[
xx.xxxxxx(x_yyy_zzzzzz.xxxxx[0]), x_yyy_zzzzzz.xxxxxx(xxxx=1)
] = 1
# Regression test for #1187
print(
dict(
a=1,
b=2
if some_kind_of_data is not None
else some_other_kind_of_data, # some explanation of why this is actually necessary
c=3,
)
)
```
## Black Output
```python
# Test cases separate from `prefer_rhs_split.py` that contains unformatted source.
# Left hand side fits in a single line but will still be exploded by the
# magic trailing comma.
(
first_value,
(
m1,
m2,
),
third_value,
) = xxxxxx_yyyyyy_zzzzzz_wwwwww_uuuuuuu_vvvvvvvvvvv(
arg1,
arg2,
)
# Make when when the left side of assignment plus the opening paren "... = (" is
# exactly line length limit + 1, it won't be split like that.
xxxxxxxxx_yyy_zzzzzzzz[
xx.xxxxxx(x_yyy_zzzzzz.xxxxx[0]), x_yyy_zzzzzz.xxxxxx(xxxx=1)
] = 1
# Regression test for #1187
print(
dict(
a=1,
b=(
2 if some_kind_of_data is not None else some_other_kind_of_data
), # some explanation of why this is actually necessary
c=3,
)
)
```

View file

@ -1,7 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_comments7.py
snapshot_kind: text
---
## Input
@ -157,7 +156,12 @@ square = Square(4) # type: Optional[Square]
```diff
--- Black
+++ Ruff
@@ -34,13 +34,9 @@
@@ -29,17 +29,14 @@
MyLovelyCompanyTeamProjectComponent as component, # DRY
)
+
result = 1 # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
result = 1 # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
@ -173,7 +177,7 @@ square = Square(4) # type: Optional[Square]
def func():
@@ -52,12 +48,19 @@
@@ -51,12 +48,19 @@
0.0789,
a[-1], # type: ignore
)
@ -194,7 +198,7 @@ square = Square(4) # type: Optional[Square]
0.0456,
0.0789,
0.0123,
@@ -91,53 +94,39 @@
@@ -90,53 +94,39 @@
# metadata_version errors.
(
{},
@ -264,7 +268,7 @@ square = Square(4) # type: Optional[Square]
),
],
)
@@ -150,8 +139,8 @@
@@ -149,8 +139,8 @@
# Regression test for https://github.com/psf/black/issues/3756.
[
@ -466,7 +470,6 @@ from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component
MyLovelyCompanyTeamProjectComponent as component, # DRY
)
result = 1 # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
result = 1 # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

View file

@ -0,0 +1,325 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_import_line_collapse.py
---
## Input
```python
from middleman.authentication import validate_oauth_token
logger = logging.getLogger(__name__)
# case 2 comment after import
from middleman.authentication import validate_oauth_token
#comment
logger = logging.getLogger(__name__)
# case 3 comment after import
from middleman.authentication import validate_oauth_token
# comment
logger = logging.getLogger(__name__)
from middleman.authentication import validate_oauth_token
logger = logging.getLogger(__name__)
# case 4 try catch with import after import
import os
import os
try:
import os
except Exception:
pass
try:
import os
def func():
a = 1
except Exception:
pass
# case 5 multiple imports
import os
import os
import os
import os
for i in range(10):
print(i)
# case 6 import in function
def func():
print()
import os
def func():
pass
print()
def func():
import os
a = 1
print()
def func():
import os
a = 1
print()
def func():
import os
a = 1
print()
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,11 +1,11 @@
from middleman.authentication import validate_oauth_token
+
logger = logging.getLogger(__name__)
# case 2 comment after import
from middleman.authentication import validate_oauth_token
-
# comment
logger = logging.getLogger(__name__)
@@ -20,6 +20,7 @@
from middleman.authentication import validate_oauth_token
+
logger = logging.getLogger(__name__)
@@ -27,6 +28,7 @@
import os
import os
+
try:
import os
except Exception:
@@ -49,6 +51,7 @@
import os
import os
+
for i in range(10):
print(i)
```
## Ruff Output
```python
from middleman.authentication import validate_oauth_token
logger = logging.getLogger(__name__)
# case 2 comment after import
from middleman.authentication import validate_oauth_token
# comment
logger = logging.getLogger(__name__)
# case 3 comment after import
from middleman.authentication import validate_oauth_token
# comment
logger = logging.getLogger(__name__)
from middleman.authentication import validate_oauth_token
logger = logging.getLogger(__name__)
# case 4 try catch with import after import
import os
import os
try:
import os
except Exception:
pass
try:
import os
def func():
a = 1
except Exception:
pass
# case 5 multiple imports
import os
import os
import os
import os
for i in range(10):
print(i)
# case 6 import in function
def func():
print()
import os
def func():
pass
print()
def func():
import os
a = 1
print()
def func():
import os
a = 1
print()
def func():
import os
a = 1
print()
```
## Black Output
```python
from middleman.authentication import validate_oauth_token
logger = logging.getLogger(__name__)
# case 2 comment after import
from middleman.authentication import validate_oauth_token
# comment
logger = logging.getLogger(__name__)
# case 3 comment after import
from middleman.authentication import validate_oauth_token
# comment
logger = logging.getLogger(__name__)
from middleman.authentication import validate_oauth_token
logger = logging.getLogger(__name__)
# case 4 try catch with import after import
import os
import os
try:
import os
except Exception:
pass
try:
import os
def func():
a = 1
except Exception:
pass
# case 5 multiple imports
import os
import os
import os
import os
for i in range(10):
print(i)
# case 6 import in function
def func():
print()
import os
def func():
pass
print()
def func():
import os
a = 1
print()
def func():
import os
a = 1
print()
def func():
import os
a = 1
print()
```

View file

@ -1,11 +1,31 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_long_dict_values.py
snapshot_kind: text
---
## Input
```python
x = {
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": (
"xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxx{xx}xxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx"
)
}
x = {
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": (
"xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxx{xx}xxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx"
),
}
x = {
"foo": bar,
"foo": bar,
"foo": (
xx_xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxxxxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx
),
}
x = {
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": "xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxx"
}
my_dict = {
"something_something":
r"Lorem ipsum dolor sit amet, an sed convenire eloquentiam \t"
@ -13,23 +33,90 @@ my_dict = {
r"signiferumque, duo ea vocibus consetetur scriptorem. Facer \t",
}
# Function calls as keys
tasks = {
get_key_name(
foo,
bar,
baz,
): src,
loop.run_in_executor(): src,
loop.run_in_executor(xx_xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxxxxx): src,
loop.run_in_executor(
xx_xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxxxxx_xxxxx_xxxxx
): src,
loop.run_in_executor(): (
xx_xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxxxxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx
),
}
# Dictionary comprehensions
tasks = {
key_name: (
xx_xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxxxxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx
)
for src in sources
}
tasks = {key_name: foobar for src in sources}
tasks = {
get_key_name(
src,
): "foo"
for src in sources
}
tasks = {
get_key_name(
foo,
bar,
baz,
): src
for src in sources
}
tasks = {
get_key_name(): (
xx_xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxxxxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx
)
for src in sources
}
tasks = {get_key_name(): foobar for src in sources}
# Delimiters inside the value
def foo():
def bar():
x = {
common.models.DateTimeField: datetime(2020, 1, 31, tzinfo=utc) + timedelta(
days=i
),
}
x = {
common.models.DateTimeField: (
datetime(2020, 1, 31, tzinfo=utc) + timedelta(days=i)
),
}
x = {
"foobar": (123 + 456),
}
x = {
"foobar": (123) + 456,
}
my_dict = {
"a key in my dict": a_very_long_variable * and_a_very_long_function_call() / 100000.0
}
my_dict = {
"a key in my dict": a_very_long_variable * and_a_very_long_function_call() * and_another_long_func() / 100000.0
}
my_dict = {
"a key in my dict": MyClass.some_attribute.first_call().second_call().third_call(some_args="some value")
}
{
'xxxxxx':
"xxxxxx":
xxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxx(
xxxxxxxxxxxxxx={
'x':
"x":
xxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxx(
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=(
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
@ -37,8 +124,8 @@ my_dict = {
xxxxxxxxxxxxx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx={
'x': x.xx,
'x': x.x,
"x": x.xx,
"x": x.x,
}))))
}),
}
@ -69,7 +156,9 @@ class Random:
```diff
--- Black
+++ Ruff
@@ -1,32 +1,26 @@
@@ -20,11 +20,9 @@
}
my_dict = {
- "something_something": (
- r"Lorem ipsum dolor sit amet, an sed convenire eloquentiam \t"
@ -81,6 +170,31 @@ class Random:
+ r"signiferumque, duo ea vocibus consetetur scriptorem. Facer \t",
}
# Function calls as keys
@@ -79,9 +77,8 @@
def foo():
def bar():
x = {
- common.models.DateTimeField: (
- datetime(2020, 1, 31, tzinfo=utc) + timedelta(days=i)
- ),
+ common.models.DateTimeField: datetime(2020, 1, 31, tzinfo=utc)
+ + timedelta(days=i),
}
x = {
common.models.DateTimeField: (
@@ -89,7 +86,7 @@
),
}
x = {
- "foobar": 123 + 456,
+ "foobar": (123 + 456),
}
x = {
"foobar": (123) + 456,
@@ -97,24 +94,20 @@
my_dict = {
- "a key in my dict": (
- a_very_long_variable * and_a_very_long_function_call() / 100000.0
@ -89,7 +203,6 @@ class Random:
+ * and_a_very_long_function_call()
+ / 100000.0
}
my_dict = {
- "a key in my dict": (
- a_very_long_variable
@ -102,7 +215,6 @@ class Random:
+ * and_another_long_func()
+ / 100000.0
}
my_dict = {
- "a key in my dict": (
- MyClass.some_attribute.first_call()
@ -115,7 +227,16 @@ class Random:
}
{
@@ -58,9 +52,9 @@
@@ -139,17 +132,17 @@
class Random:
def func():
- random_service.status.active_states.inactive = make_new_top_level_state_from_dict(
- {
+ random_service.status.active_states.inactive = (
+ make_new_top_level_state_from_dict({
"topLevelBase": {
"secondaryBase": {
"timestamp": 1234,
"latitude": 1,
"longitude": 2,
@ -127,31 +248,120 @@ class Random:
+ ).ToJsonString(),
}
},
})
- }
+ })
)
```
## Ruff Output
```python
x = {
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": (
"xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxx{xx}xxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx"
)
}
x = {
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": (
"xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxx{xx}xxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx"
),
}
x = {
"foo": bar,
"foo": bar,
"foo": (
xx_xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxxxxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx
),
}
x = {
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": "xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxx"
}
my_dict = {
"something_something": r"Lorem ipsum dolor sit amet, an sed convenire eloquentiam \t"
r"signiferumque, duo ea vocibus consetetur scriptorem. Facer \t"
r"signiferumque, duo ea vocibus consetetur scriptorem. Facer \t",
}
# Function calls as keys
tasks = {
get_key_name(
foo,
bar,
baz,
): src,
loop.run_in_executor(): src,
loop.run_in_executor(xx_xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxxxxx): src,
loop.run_in_executor(
xx_xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxxxxx_xxxxx_xxxxx
): src,
loop.run_in_executor(): (
xx_xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxxxxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx
),
}
# Dictionary comprehensions
tasks = {
key_name: (
xx_xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxxxxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx
)
for src in sources
}
tasks = {key_name: foobar for src in sources}
tasks = {
get_key_name(
src,
): "foo"
for src in sources
}
tasks = {
get_key_name(
foo,
bar,
baz,
): src
for src in sources
}
tasks = {
get_key_name(): (
xx_xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxxxxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx
)
for src in sources
}
tasks = {get_key_name(): foobar for src in sources}
# Delimiters inside the value
def foo():
def bar():
x = {
common.models.DateTimeField: datetime(2020, 1, 31, tzinfo=utc)
+ timedelta(days=i),
}
x = {
common.models.DateTimeField: (
datetime(2020, 1, 31, tzinfo=utc) + timedelta(days=i)
),
}
x = {
"foobar": (123 + 456),
}
x = {
"foobar": (123) + 456,
}
my_dict = {
"a key in my dict": a_very_long_variable
* and_a_very_long_function_call()
/ 100000.0
}
my_dict = {
"a key in my dict": a_very_long_variable
* and_a_very_long_function_call()
* and_another_long_func()
/ 100000.0
}
my_dict = {
"a key in my dict": MyClass.some_attribute.first_call()
.second_call()
@ -199,6 +409,27 @@ class Random:
## Black Output
```python
x = {
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": (
"xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxx{xx}xxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx"
)
}
x = {
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": (
"xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxx{xx}xxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx"
),
}
x = {
"foo": bar,
"foo": bar,
"foo": (
xx_xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxxxxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx
),
}
x = {
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": "xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxx"
}
my_dict = {
"something_something": (
r"Lorem ipsum dolor sit amet, an sed convenire eloquentiam \t"
@ -207,12 +438,80 @@ my_dict = {
),
}
# Function calls as keys
tasks = {
get_key_name(
foo,
bar,
baz,
): src,
loop.run_in_executor(): src,
loop.run_in_executor(xx_xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxxxxx): src,
loop.run_in_executor(
xx_xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxxxxx_xxxxx_xxxxx
): src,
loop.run_in_executor(): (
xx_xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxxxxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx
),
}
# Dictionary comprehensions
tasks = {
key_name: (
xx_xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxxxxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx
)
for src in sources
}
tasks = {key_name: foobar for src in sources}
tasks = {
get_key_name(
src,
): "foo"
for src in sources
}
tasks = {
get_key_name(
foo,
bar,
baz,
): src
for src in sources
}
tasks = {
get_key_name(): (
xx_xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxxxxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx
)
for src in sources
}
tasks = {get_key_name(): foobar for src in sources}
# Delimiters inside the value
def foo():
def bar():
x = {
common.models.DateTimeField: (
datetime(2020, 1, 31, tzinfo=utc) + timedelta(days=i)
),
}
x = {
common.models.DateTimeField: (
datetime(2020, 1, 31, tzinfo=utc) + timedelta(days=i)
),
}
x = {
"foobar": 123 + 456,
}
x = {
"foobar": (123) + 456,
}
my_dict = {
"a key in my dict": (
a_very_long_variable * and_a_very_long_function_call() / 100000.0
)
}
my_dict = {
"a key in my dict": (
a_very_long_variable
@ -221,7 +520,6 @@ my_dict = {
/ 100000.0
)
}
my_dict = {
"a key in my dict": (
MyClass.some_attribute.first_call()
@ -252,8 +550,8 @@ my_dict = {
class Random:
def func():
random_service.status.active_states.inactive = (
make_new_top_level_state_from_dict({
random_service.status.active_states.inactive = make_new_top_level_state_from_dict(
{
"topLevelBase": {
"secondaryBase": {
"timestamp": 1234,
@ -264,6 +562,6 @@ class Random:
),
}
},
})
}
)
```

View file

@ -1,7 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_long_strings.py
snapshot_kind: text
---
## Input
@ -286,7 +285,7 @@ string_with_escaped_nameescape = (
"........................................................................... \\N{LAO KO LA}"
)
msg = lambda x: f"this is a very very very long lambda value {x} that doesn't fit on a single line"
msg = lambda x: f"this is a very very very very long lambda value {x} that doesn't fit on a single line"
dict_with_lambda_values = {
"join": lambda j: (
@ -335,6 +334,20 @@ log.info(f'''Skipping: {"a" == 'b'} {desc["ms_name"]} {money=} {dte=} {pos_share
log.info(f'''Skipping: {'a' == "b"=} {desc["ms_name"]} {money=} {dte=} {pos_share=} {desc["status"]} {desc["exposure_max"]}''')
log.info(f"""Skipping: {'a' == 'b'} {desc['ms_name']} {money=} {dte=} {pos_share=} {desc['status']} {desc['exposure_max']}""")
x = {
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": (
"xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxx{xx}xxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx"
)
}
x = {
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": "xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxx{xx}xxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx",
}
x = {
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": (
"xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxx"
)
}
```
## Black Differences
@ -841,7 +854,7 @@ log.info(f"""Skipping: {'a' == 'b'} {desc['ms_name']} {money=} {dte=} {pos_share
long_unmergable_string_with_pragma = (
"This is a really long string that can't be merged because it has a likely pragma at the end" # type: ignore
@@ -468,51 +358,24 @@
@@ -468,49 +358,24 @@
" of it."
)
@ -893,16 +906,15 @@ log.info(f"""Skipping: {'a' == 'b'} {desc['ms_name']} {money=} {dte=} {pos_share
-)
+string_with_escaped_nameescape = "........................................................................... \\N{LAO KO LA}"
msg = (
- lambda x: (
- f"this is a very very very long lambda value {x} that doesn't fit on a single"
- " line"
- )
+ lambda x: f"this is a very very very long lambda value {x} that doesn't fit on a single line"
-msg = lambda x: (
- f"this is a very very very very long lambda value {x} that doesn't fit on a"
- " single line"
+msg = (
+ lambda x: f"this is a very very very very long lambda value {x} that doesn't fit on a single line"
)
dict_with_lambda_values = {
@@ -524,65 +387,58 @@
@@ -522,65 +387,58 @@
# Complex string concatenations with a method call in the middle.
code = (
@ -927,50 +939,50 @@ log.info(f"""Skipping: {'a' == 'b'} {desc['ms_name']} {money=} {dte=} {pos_share
+call(body=("%s %s" % ((",".join(items)), suffix)))
log.info(
- "Skipping:"
- f' {desc["db_id"]=} {desc["ms_name"]} {money=} {dte=} {pos_share=} {desc["status"]=} {desc["exposure_max"]=}'
- f'Skipping: {desc["db_id"]=} {desc["ms_name"]} {money=} {dte=} {pos_share=}'
- f' {desc["status"]=} {desc["exposure_max"]=}'
+ f'Skipping: {desc["db_id"]=} {desc["ms_name"]} {money=} {dte=} {pos_share=} {desc["status"]=} {desc["exposure_max"]=}'
)
log.info(
- "Skipping:"
- f" {desc['db_id']=} {desc['ms_name']} {money=} {dte=} {pos_share=} {desc['status']=} {desc['exposure_max']=}"
- f"Skipping: {desc['db_id']=} {desc['ms_name']} {money=} {dte=} {pos_share=}"
- f" {desc['status']=} {desc['exposure_max']=}"
+ f"Skipping: {desc['db_id']=} {desc['ms_name']} {money=} {dte=} {pos_share=} {desc['status']=} {desc['exposure_max']=}"
)
log.info(
- "Skipping:"
- f" {desc['db_id']} {foo('bar',x=123)} {'foo' != 'bar'} {(x := 'abc=')} {pos_share=} {desc['status']} {desc['exposure_max']}"
- f'Skipping: {desc["db_id"]} {foo("bar",x=123)} {"foo" != "bar"} {(x := "abc=")}'
- f' {pos_share=} {desc["status"]} {desc["exposure_max"]}'
+ f"Skipping: {desc['db_id']} {foo('bar', x=123)} {'foo' != 'bar'} {(x := 'abc=')} {pos_share=} {desc['status']} {desc['exposure_max']}"
)
log.info(
- "Skipping:"
- f' {desc["db_id"]} {desc["ms_name"]} {money=} {(x := "abc=")=} {pos_share=} {desc["status"]} {desc["exposure_max"]}'
- f'Skipping: {desc["db_id"]} {desc["ms_name"]} {money=} {(x := "abc=")=}'
- f' {pos_share=} {desc["status"]} {desc["exposure_max"]}'
+ f'Skipping: {desc["db_id"]} {desc["ms_name"]} {money=} {(x := "abc=")=} {pos_share=} {desc["status"]} {desc["exposure_max"]}'
)
log.info(
- "Skipping:"
- f' {desc["db_id"]} {foo("bar",x=123)=} {money=} {dte=} {pos_share=} {desc["status"]} {desc["exposure_max"]}'
- f'Skipping: {desc["db_id"]} {foo("bar",x=123)=} {money=} {dte=} {pos_share=}'
- f' {desc["status"]} {desc["exposure_max"]}'
+ f'Skipping: {desc["db_id"]} {foo("bar",x=123)=} {money=} {dte=} {pos_share=} {desc["status"]} {desc["exposure_max"]}'
)
log.info(
- "Skipping:"
- f' {foo("asdf")=} {desc["ms_name"]} {money=} {dte=} {pos_share=} {desc["status"]} {desc["exposure_max"]}'
- f'Skipping: {foo("asdf")=} {desc["ms_name"]} {money=} {dte=} {pos_share=}'
- f' {desc["status"]} {desc["exposure_max"]}'
+ f'Skipping: {foo("asdf")=} {desc["ms_name"]} {money=} {dte=} {pos_share=} {desc["status"]} {desc["exposure_max"]}'
)
log.info(
- "Skipping:"
- f" {'a' == 'b' == 'c' == 'd'} {desc['ms_name']} {money=} {dte=} {pos_share=} {desc['status']} {desc['exposure_max']}"
- f'Skipping: {"a" == "b" == "c" == "d"} {desc["ms_name"]} {money=} {dte=}'
- f' {pos_share=} {desc["status"]} {desc["exposure_max"]}'
+ f"Skipping: {'a' == 'b' == 'c' == 'd'} {desc['ms_name']} {money=} {dte=} {pos_share=} {desc['status']} {desc['exposure_max']}"
)
log.info(
- "Skipping:"
- f' {"a" == "b" == "c" == "d"=} {desc["ms_name"]} {money=} {dte=} {pos_share=} {desc["status"]} {desc["exposure_max"]}'
- f'Skipping: {"a" == "b" == "c" == "d"=} {desc["ms_name"]} {money=} {dte=}'
- f' {pos_share=} {desc["status"]} {desc["exposure_max"]}'
+ f'Skipping: {"a" == "b" == "c" == "d"=} {desc["ms_name"]} {money=} {dte=} {pos_share=} {desc["status"]} {desc["exposure_max"]}'
)
@ -986,13 +998,30 @@ log.info(f"""Skipping: {'a' == 'b'} {desc['ms_name']} {money=} {dte=} {pos_share
)
log.info(
@@ -590,5 +446,5 @@
@@ -588,7 +446,7 @@
)
log.info(
- f"""Skipping: {'a' == 'b'} {desc['ms_name']} {money=} {dte=} {pos_share=} {desc['status']} {desc['exposure_max']}"""
+ f"""Skipping: {"a" == "b"} {desc["ms_name"]} {money=} {dte=} {pos_share=} {desc["status"]} {desc["exposure_max"]}"""
)
x = {
@@ -597,10 +455,10 @@
)
}
x = {
- "xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": (
- "xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxx{xx}xxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx"
- ),
+ "xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": "xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxx{xx}xxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx",
}
x = {
- "xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": "xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxx"
+ "xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": (
+ "xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxx"
+ )
}
```
## Ruff Output
@ -1375,7 +1404,7 @@ string_with_escaped_nameescape = "..............................................
string_with_escaped_nameescape = "........................................................................... \\N{LAO KO LA}"
msg = (
lambda x: f"this is a very very very long lambda value {x} that doesn't fit on a single line"
lambda x: f"this is a very very very very long lambda value {x} that doesn't fit on a single line"
)
dict_with_lambda_values = {
@ -1448,6 +1477,20 @@ log.info(
log.info(
f"""Skipping: {"a" == "b"} {desc["ms_name"]} {money=} {dte=} {pos_share=} {desc["status"]} {desc["exposure_max"]}"""
)
x = {
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": (
"xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxx{xx}xxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx"
)
}
x = {
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": "xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxx{xx}xxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx",
}
x = {
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": (
"xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxx"
)
}
```
## Black Output
@ -1963,11 +2006,9 @@ string_with_escaped_nameescape = (
" \\N{LAO KO LA}"
)
msg = (
lambda x: (
f"this is a very very very long lambda value {x} that doesn't fit on a single"
" line"
)
msg = lambda x: (
f"this is a very very very very long lambda value {x} that doesn't fit on a"
" single line"
)
dict_with_lambda_values = {
@ -1992,43 +2033,43 @@ code = (
call(body="%s %s" % (",".join(items), suffix))
log.info(
"Skipping:"
f' {desc["db_id"]=} {desc["ms_name"]} {money=} {dte=} {pos_share=} {desc["status"]=} {desc["exposure_max"]=}'
f'Skipping: {desc["db_id"]=} {desc["ms_name"]} {money=} {dte=} {pos_share=}'
f' {desc["status"]=} {desc["exposure_max"]=}'
)
log.info(
"Skipping:"
f" {desc['db_id']=} {desc['ms_name']} {money=} {dte=} {pos_share=} {desc['status']=} {desc['exposure_max']=}"
f"Skipping: {desc['db_id']=} {desc['ms_name']} {money=} {dte=} {pos_share=}"
f" {desc['status']=} {desc['exposure_max']=}"
)
log.info(
"Skipping:"
f" {desc['db_id']} {foo('bar',x=123)} {'foo' != 'bar'} {(x := 'abc=')} {pos_share=} {desc['status']} {desc['exposure_max']}"
f'Skipping: {desc["db_id"]} {foo("bar",x=123)} {"foo" != "bar"} {(x := "abc=")}'
f' {pos_share=} {desc["status"]} {desc["exposure_max"]}'
)
log.info(
"Skipping:"
f' {desc["db_id"]} {desc["ms_name"]} {money=} {(x := "abc=")=} {pos_share=} {desc["status"]} {desc["exposure_max"]}'
f'Skipping: {desc["db_id"]} {desc["ms_name"]} {money=} {(x := "abc=")=}'
f' {pos_share=} {desc["status"]} {desc["exposure_max"]}'
)
log.info(
"Skipping:"
f' {desc["db_id"]} {foo("bar",x=123)=} {money=} {dte=} {pos_share=} {desc["status"]} {desc["exposure_max"]}'
f'Skipping: {desc["db_id"]} {foo("bar",x=123)=} {money=} {dte=} {pos_share=}'
f' {desc["status"]} {desc["exposure_max"]}'
)
log.info(
"Skipping:"
f' {foo("asdf")=} {desc["ms_name"]} {money=} {dte=} {pos_share=} {desc["status"]} {desc["exposure_max"]}'
f'Skipping: {foo("asdf")=} {desc["ms_name"]} {money=} {dte=} {pos_share=}'
f' {desc["status"]} {desc["exposure_max"]}'
)
log.info(
"Skipping:"
f" {'a' == 'b' == 'c' == 'd'} {desc['ms_name']} {money=} {dte=} {pos_share=} {desc['status']} {desc['exposure_max']}"
f'Skipping: {"a" == "b" == "c" == "d"} {desc["ms_name"]} {money=} {dte=}'
f' {pos_share=} {desc["status"]} {desc["exposure_max"]}'
)
log.info(
"Skipping:"
f' {"a" == "b" == "c" == "d"=} {desc["ms_name"]} {money=} {dte=} {pos_share=} {desc["status"]} {desc["exposure_max"]}'
f'Skipping: {"a" == "b" == "c" == "d"=} {desc["ms_name"]} {money=} {dte=}'
f' {pos_share=} {desc["status"]} {desc["exposure_max"]}'
)
log.info(
@ -2047,4 +2088,18 @@ log.info(
log.info(
f"""Skipping: {'a' == 'b'} {desc['ms_name']} {money=} {dte=} {pos_share=} {desc['status']} {desc['exposure_max']}"""
)
x = {
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": (
"xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxx{xx}xxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx"
)
}
x = {
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": (
"xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxxx{xx}xxx_xxxxx_xxxxxxxxx_xxxxxxxxxxxx_xxxx"
),
}
x = {
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": "xx:xxxxxxxxxxxxxxxxx_xxxxx_xxxxxxx_xxxxxxxxxx"
}
```

View file

@ -1,7 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_long_strings__regression.py
snapshot_kind: text
---
## Input
@ -559,6 +558,7 @@ a_dict = {
}
# Regression test for https://github.com/psf/black/issues/3506.
# Regressed again by https://github.com/psf/black/pull/4498
s = (
"With single quote: ' "
f" {my_dict['foo']}"
@ -684,7 +684,7 @@ s = f'Lorem Ipsum is simply dummy text of the printing and typesetting industry:
+ (
+ "xxxxxxxxxx xxxx xx xxxxxx(%x) xx %x xxxx xx xxx %x.xx"
+ % (len(self) + 1, xxxx.xxxxxxxxxx, xxxx.xxxxxxxxxx)
)
+ )
+ + (
+ " %.3f (%s) to %.3f (%s).\n"
+ % (
@ -693,7 +693,7 @@ s = f'Lorem Ipsum is simply dummy text of the printing and typesetting industry:
+ x,
+ xxxx.xxxxxxxxxxxxxx(xx),
+ )
+ )
)
)
@ -1171,13 +1171,21 @@ s = f'Lorem Ipsum is simply dummy text of the printing and typesetting industry:
)
# Regression test for https://github.com/psf/black/issues/3455.
@@ -674,7 +621,4 @@
@@ -673,14 +620,6 @@
# Regression test for https://github.com/psf/black/issues/3506.
s = f"With single quote: ' {my_dict['foo']} With double quote: \" {my_dict['bar']}"
# Regressed again by https://github.com/psf/black/pull/4498
-s = (
- "With single quote: ' "
- f" {my_dict['foo']}"
- ' With double quote: " '
- f' {my_dict["bar"]}'
-)
+s = f"With single quote: ' {my_dict['foo']} With double quote: \" {my_dict['bar']}"
-s = (
- "Lorem Ipsum is simply dummy text of the printing and typesetting"
- f" industry:'{my_dict['foo']}'"
- f' industry:\'{my_dict["foo"]}\''
-)
+s = f"Lorem Ipsum is simply dummy text of the printing and typesetting industry:'{my_dict['foo']}'"
```
@ -1806,6 +1814,7 @@ a_dict = {
}
# Regression test for https://github.com/psf/black/issues/3506.
# Regressed again by https://github.com/psf/black/pull/4498
s = f"With single quote: ' {my_dict['foo']} With double quote: \" {my_dict['bar']}"
s = f"Lorem Ipsum is simply dummy text of the printing and typesetting industry:'{my_dict['foo']}'"
@ -2488,10 +2497,16 @@ a_dict = {
}
# Regression test for https://github.com/psf/black/issues/3506.
s = f"With single quote: ' {my_dict['foo']} With double quote: \" {my_dict['bar']}"
# Regressed again by https://github.com/psf/black/pull/4498
s = (
"With single quote: ' "
f" {my_dict['foo']}"
' With double quote: " '
f' {my_dict["bar"]}'
)
s = (
"Lorem Ipsum is simply dummy text of the printing and typesetting"
f" industry:'{my_dict['foo']}'"
f' industry:\'{my_dict["foo"]}\''
)
```

View file

@ -1,7 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_multiline_strings.py
snapshot_kind: text
---
## Input
@ -188,6 +187,73 @@ test
assert some_var == expected_result, f"""
expected: {expected_result}
actual: {some_var}"""
def foo():
a = {
xxxx_xxxxxxx.xxxxxx_xxxxxxxxxxxx_xxxxxx_xx_xxx_xxxxxx: {
"xxxxx": """Sxxxxx xxxxxxxxxxxx xxx xxxxx (xxxxxx xxx xxxxxxx)""",
"xxxxxxxx": (
"""Sxxxxxxx xxxxxxxx, xxxxxxx xx xxxxxxxxx
xxxxxxxxxxxxx xxxxxxx xxxxxxxxx xxx-xxxxxxxxxx xxxxxx xx xxx-xxxxxx"""
),
"xxxxxxxx": """Sxxxxxxx xxxxxxxx, xxxxxxx xx xxxxxxxxx
xxxxxxxxxxxxx xxxxxxx xxxxxxxxx xxx-xxxxxxxxxx xxxxxx xx xxx-xxxxxx"""
},
}
xxxx_xxxxxxx.xxxxxx_xxxxxxxxxxxx_xxxxxx_xx_xxx_xxxxxx = {
"xxxxx": """Sxxxxx xxxxxxxxxxxx xxx xxxxx (xxxxxx xxx xxxxxxx)""",
"xxxxxxxx": (
"""Sxxxxxxx xxxxxxxx, xxxxxxx xx xxxxxxxxx
xxxxxxxxxxxxx xxxxxxx xxxxxxxxx xxx-xxxxxxxxxx xxxxxx xx xxx-xxxxxx"""
),
"xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": (
"""
a
a
a
a
a"""
),
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": """
a
a
a
a
a""",
}
a = """
""" if """
""" == """
""" else """
"""
a = """
""" if b else """
"""
a = """
""" if """
""" == """
""" else b
a = b if """
""" == """
""" else """
"""
a = """
""" if b else c
a = c if b else """
"""
a = b if """
""" == """
""" else c
```
## Black Differences
@ -378,6 +444,36 @@ actual: {some_var}"""
assert some_var == expected_result, """
test
@@ -224,10 +267,8 @@
"""Sxxxxxxx xxxxxxxx, xxxxxxx xx xxxxxxxxx
xxxxxxxxxxxxx xxxxxxx xxxxxxxxx xxx-xxxxxxxxxx xxxxxx xx xxx-xxxxxx"""
),
- "xxxxxxxx": (
- """Sxxxxxxx xxxxxxxx, xxxxxxx xx xxxxxxxxx
- xxxxxxxxxxxxx xxxxxxx xxxxxxxxx xxx-xxxxxxxxxx xxxxxx xx xxx-xxxxxx"""
- ),
+ "xxxxxxxx": """Sxxxxxxx xxxxxxxx, xxxxxxx xx xxxxxxxxx
+ xxxxxxxxxxxxx xxxxxxx xxxxxxxxx xxx-xxxxxxxxxx xxxxxx xx xxx-xxxxxx""",
},
}
@@ -246,14 +287,12 @@
a
a"""
),
- "xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": (
- """
+ "xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": """
a
a
a
a
-a"""
- ),
+a""",
}
a = (
```
## Ruff Output
@ -642,6 +738,105 @@ test
assert some_var == expected_result, f"""
expected: {expected_result}
actual: {some_var}"""
def foo():
a = {
xxxx_xxxxxxx.xxxxxx_xxxxxxxxxxxx_xxxxxx_xx_xxx_xxxxxx: {
"xxxxx": """Sxxxxx xxxxxxxxxxxx xxx xxxxx (xxxxxx xxx xxxxxxx)""",
"xxxxxxxx": (
"""Sxxxxxxx xxxxxxxx, xxxxxxx xx xxxxxxxxx
xxxxxxxxxxxxx xxxxxxx xxxxxxxxx xxx-xxxxxxxxxx xxxxxx xx xxx-xxxxxx"""
),
"xxxxxxxx": """Sxxxxxxx xxxxxxxx, xxxxxxx xx xxxxxxxxx
xxxxxxxxxxxxx xxxxxxx xxxxxxxxx xxx-xxxxxxxxxx xxxxxx xx xxx-xxxxxx""",
},
}
xxxx_xxxxxxx.xxxxxx_xxxxxxxxxxxx_xxxxxx_xx_xxx_xxxxxx = {
"xxxxx": """Sxxxxx xxxxxxxxxxxx xxx xxxxx (xxxxxx xxx xxxxxxx)""",
"xxxxxxxx": (
"""Sxxxxxxx xxxxxxxx, xxxxxxx xx xxxxxxxxx
xxxxxxxxxxxxx xxxxxxx xxxxxxxxx xxx-xxxxxxxxxx xxxxxx xx xxx-xxxxxx"""
),
"xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": (
"""
a
a
a
a
a"""
),
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": """
a
a
a
a
a""",
}
a = (
"""
"""
if """
"""
== """
"""
else """
"""
)
a = (
"""
"""
if b
else """
"""
)
a = (
"""
"""
if """
"""
== """
"""
else b
)
a = (
b
if """
"""
== """
"""
else """
"""
)
a = (
"""
"""
if b
else c
)
a = (
c
if b
else """
"""
)
a = (
b
if """
"""
== """
"""
else c
)
```
## Black Output
@ -863,4 +1058,107 @@ test
assert some_var == expected_result, f"""
expected: {expected_result}
actual: {some_var}"""
def foo():
a = {
xxxx_xxxxxxx.xxxxxx_xxxxxxxxxxxx_xxxxxx_xx_xxx_xxxxxx: {
"xxxxx": """Sxxxxx xxxxxxxxxxxx xxx xxxxx (xxxxxx xxx xxxxxxx)""",
"xxxxxxxx": (
"""Sxxxxxxx xxxxxxxx, xxxxxxx xx xxxxxxxxx
xxxxxxxxxxxxx xxxxxxx xxxxxxxxx xxx-xxxxxxxxxx xxxxxx xx xxx-xxxxxx"""
),
"xxxxxxxx": (
"""Sxxxxxxx xxxxxxxx, xxxxxxx xx xxxxxxxxx
xxxxxxxxxxxxx xxxxxxx xxxxxxxxx xxx-xxxxxxxxxx xxxxxx xx xxx-xxxxxx"""
),
},
}
xxxx_xxxxxxx.xxxxxx_xxxxxxxxxxxx_xxxxxx_xx_xxx_xxxxxx = {
"xxxxx": """Sxxxxx xxxxxxxxxxxx xxx xxxxx (xxxxxx xxx xxxxxxx)""",
"xxxxxxxx": (
"""Sxxxxxxx xxxxxxxx, xxxxxxx xx xxxxxxxxx
xxxxxxxxxxxxx xxxxxxx xxxxxxxxx xxx-xxxxxxxxxx xxxxxx xx xxx-xxxxxx"""
),
"xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": (
"""
a
a
a
a
a"""
),
"xx_xxxxx_xxxxxxxxxx_xxxxxxxxx_xx": (
"""
a
a
a
a
a"""
),
}
a = (
"""
"""
if """
"""
== """
"""
else """
"""
)
a = (
"""
"""
if b
else """
"""
)
a = (
"""
"""
if """
"""
== """
"""
else b
)
a = (
b
if """
"""
== """
"""
else """
"""
)
a = (
"""
"""
if b
else c
)
a = (
c
if b
else """
"""
)
a = (
b
if """
"""
== """
"""
else c
)
```

View file

@ -0,0 +1,535 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_remove_multiline_lone_list_item_parens.py
---
## Input
```python
items = [(x for x in [1])]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2"}
if some_var == ""
else {"key": "val"}
)
]
items = [
(
"123456890123457890123468901234567890"
if some_var == "long strings"
else "123467890123467890"
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
and some_var == "long strings"
and {"key": "val"}
)
]
items = [
(
"123456890123457890123468901234567890"
and some_var == "long strings"
and "123467890123467890"
)
]
items = [
(
long_variable_name
and even_longer_variable_name
and yet_another_very_long_variable_name
)
]
# Shouldn't remove trailing commas
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
),
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
and some_var == "long strings"
and {"key": "val"}
),
]
items = [
(
"123456890123457890123468901234567890"
and some_var == "long strings"
and "123467890123467890"
),
]
items = [
(
long_variable_name
and even_longer_variable_name
and yet_another_very_long_variable_name
),
]
# Shouldn't add parentheses
items = [
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
]
items = [{"key1": "val1", "key2": "val2"} if some_var == "" else {"key": "val"}]
# Shouldn't crash with comments
items = [
( # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
) # comment
]
items = [ # comment
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
] # comment
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"} # comment
if some_var == "long strings"
else {"key": "val"}
)
]
items = [ # comment
( # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
) # comment
] # comment
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,30 +1,40 @@
items = [(x for x in [1])]
items = [
- {"key1": "val1", "key2": "val2", "key3": "val3"}
- if some_var == "long strings"
- else {"key": "val"}
+ (
+ {"key1": "val1", "key2": "val2", "key3": "val3"}
+ if some_var == "long strings"
+ else {"key": "val"}
+ )
]
-items = [{"key1": "val1", "key2": "val2"} if some_var == "" else {"key": "val"}]
+items = [({"key1": "val1", "key2": "val2"} if some_var == "" else {"key": "val"})]
items = [
- "123456890123457890123468901234567890"
- if some_var == "long strings"
- else "123467890123467890"
+ (
+ "123456890123457890123468901234567890"
+ if some_var == "long strings"
+ else "123467890123467890"
+ )
]
items = [
- {"key1": "val1", "key2": "val2", "key3": "val3"}
- and some_var == "long strings"
- and {"key": "val"}
+ (
+ {"key1": "val1", "key2": "val2", "key3": "val3"}
+ and some_var == "long strings"
+ and {"key": "val"}
+ )
]
items = [
- "123456890123457890123468901234567890"
- and some_var == "long strings"
- and "123467890123467890"
+ (
+ "123456890123457890123468901234567890"
+ and some_var == "long strings"
+ and "123467890123467890"
+ )
]
items = [
- long_variable_name
- and even_longer_variable_name
- and yet_another_very_long_variable_name
+ (
+ long_variable_name
+ and even_longer_variable_name
+ and yet_another_very_long_variable_name
+ )
]
# Shouldn't remove trailing commas
@@ -66,41 +76,55 @@
items = [{"key1": "val1", "key2": "val2"} if some_var == "" else {"key": "val"}]
# Shouldn't crash with comments
-items = [ # comment
- {"key1": "val1", "key2": "val2", "key3": "val3"}
- if some_var == "long strings"
- else {"key": "val"}
+items = [
+ ( # comment
+ {"key1": "val1", "key2": "val2", "key3": "val3"}
+ if some_var == "long strings"
+ else {"key": "val"}
+ )
]
items = [
- {"key1": "val1", "key2": "val2", "key3": "val3"}
- if some_var == "long strings"
- else {"key": "val"}
-] # comment
+ (
+ {"key1": "val1", "key2": "val2", "key3": "val3"}
+ if some_var == "long strings"
+ else {"key": "val"}
+ ) # comment
+]
items = [ # comment
- {"key1": "val1", "key2": "val2", "key3": "val3"}
- if some_var == "long strings"
- else {"key": "val"}
+ (
+ {"key1": "val1", "key2": "val2", "key3": "val3"}
+ if some_var == "long strings"
+ else {"key": "val"}
+ )
]
items = [
- {"key1": "val1", "key2": "val2", "key3": "val3"}
- if some_var == "long strings"
- else {"key": "val"}
+ (
+ {"key1": "val1", "key2": "val2", "key3": "val3"}
+ if some_var == "long strings"
+ else {"key": "val"}
+ )
] # comment
items = [
- {"key1": "val1", "key2": "val2", "key3": "val3"} # comment
- if some_var == "long strings"
- else {"key": "val"}
+ (
+ {"key1": "val1", "key2": "val2", "key3": "val3"} # comment
+ if some_var == "long strings"
+ else {"key": "val"}
+ )
]
-items = [ # comment # comment
- {"key1": "val1", "key2": "val2", "key3": "val3"}
- if some_var == "long strings"
- else {"key": "val"}
+items = [ # comment
+ ( # comment
+ {"key1": "val1", "key2": "val2", "key3": "val3"}
+ if some_var == "long strings"
+ else {"key": "val"}
+ )
]
items = [
- {"key1": "val1", "key2": "val2", "key3": "val3"}
- if some_var == "long strings"
- else {"key": "val"}
-] # comment # comment
+ (
+ {"key1": "val1", "key2": "val2", "key3": "val3"}
+ if some_var == "long strings"
+ else {"key": "val"}
+ ) # comment
+] # comment
```
## Ruff Output
```python
items = [(x for x in [1])]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [({"key1": "val1", "key2": "val2"} if some_var == "" else {"key": "val"})]
items = [
(
"123456890123457890123468901234567890"
if some_var == "long strings"
else "123467890123467890"
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
and some_var == "long strings"
and {"key": "val"}
)
]
items = [
(
"123456890123457890123468901234567890"
and some_var == "long strings"
and "123467890123467890"
)
]
items = [
(
long_variable_name
and even_longer_variable_name
and yet_another_very_long_variable_name
)
]
# Shouldn't remove trailing commas
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
),
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
and some_var == "long strings"
and {"key": "val"}
),
]
items = [
(
"123456890123457890123468901234567890"
and some_var == "long strings"
and "123467890123467890"
),
]
items = [
(
long_variable_name
and even_longer_variable_name
and yet_another_very_long_variable_name
),
]
# Shouldn't add parentheses
items = [
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
]
items = [{"key1": "val1", "key2": "val2"} if some_var == "" else {"key": "val"}]
# Shouldn't crash with comments
items = [
( # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
) # comment
]
items = [ # comment
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
] # comment
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"} # comment
if some_var == "long strings"
else {"key": "val"}
)
]
items = [ # comment
( # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
) # comment
] # comment
```
## Black Output
```python
items = [(x for x in [1])]
items = [
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
]
items = [{"key1": "val1", "key2": "val2"} if some_var == "" else {"key": "val"}]
items = [
"123456890123457890123468901234567890"
if some_var == "long strings"
else "123467890123467890"
]
items = [
{"key1": "val1", "key2": "val2", "key3": "val3"}
and some_var == "long strings"
and {"key": "val"}
]
items = [
"123456890123457890123468901234567890"
and some_var == "long strings"
and "123467890123467890"
]
items = [
long_variable_name
and even_longer_variable_name
and yet_another_very_long_variable_name
]
# Shouldn't remove trailing commas
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
),
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
and some_var == "long strings"
and {"key": "val"}
),
]
items = [
(
"123456890123457890123468901234567890"
and some_var == "long strings"
and "123467890123467890"
),
]
items = [
(
long_variable_name
and even_longer_variable_name
and yet_another_very_long_variable_name
),
]
# Shouldn't add parentheses
items = [
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
]
items = [{"key1": "val1", "key2": "val2"} if some_var == "" else {"key": "val"}]
# Shouldn't crash with comments
items = [ # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
]
items = [
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
] # comment
items = [ # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
]
items = [
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
] # comment
items = [
{"key1": "val1", "key2": "val2", "key3": "val3"} # comment
if some_var == "long strings"
else {"key": "val"}
]
items = [ # comment # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
]
items = [
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
] # comment # comment
```

View file

@ -0,0 +1,335 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_wrap_comprehension_in.py
---
## Input
```python
[a for graph_path_expression in refined_constraint.condition_as_predicate.variables]
[
a
for graph_path_expression in refined_constraint.condition_as_predicate.variables
]
[
a
for graph_path_expression
in refined_constraint.condition_as_predicate.variables
]
[
a
for graph_path_expression in (
refined_constraint.condition_as_predicate.variables
)
]
[
(foobar_very_long_key, foobar_very_long_value)
for foobar_very_long_key, foobar_very_long_value in foobar_very_long_dictionary.items()
]
# Don't split the `in` if it's not too long
lcomp3 = [
element.split("\n", 1)[0]
for element in collection.select_elements()
# right
if element is not None
]
# Don't remove parens around ternaries
expected = [i for i in (a if b else c)]
# Nested arrays
# First in will not be split because it would still be too long
[[
x
for x in bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
for y in xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
]]
# Multiple comprehensions, only split the second `in`
graph_path_expressions_in_local_constraint_refinements = [
graph_path_expression
for refined_constraint in self._local_constraint_refinements.values()
if refined_constraint is not None
for graph_path_expression in refined_constraint.condition_as_predicate.variables
]
# Dictionary comprehensions
dict_with_really_long_names = {
really_really_long_key_name: an_even_longer_really_really_long_key_value
for really_really_long_key_name, an_even_longer_really_really_long_key_value in really_really_really_long_dict_name.items()
}
{
key_with_super_really_long_name: key_with_super_really_long_name
for key_with_super_really_long_name in dictionary_with_super_really_long_name
}
{
key_with_super_really_long_name: key_with_super_really_long_name
for key_with_super_really_long_name
in dictionary_with_super_really_long_name
}
{
key_with_super_really_long_name: key_with_super_really_long_name
for key in (
dictionary
)
}
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,20 +1,14 @@
[
a
- for graph_path_expression in (
- refined_constraint.condition_as_predicate.variables
- )
+ for graph_path_expression in refined_constraint.condition_as_predicate.variables
]
[
a
- for graph_path_expression in (
- refined_constraint.condition_as_predicate.variables
- )
+ for graph_path_expression in refined_constraint.condition_as_predicate.variables
]
[
a
- for graph_path_expression in (
- refined_constraint.condition_as_predicate.variables
- )
+ for graph_path_expression in refined_constraint.condition_as_predicate.variables
]
[
a
@@ -25,9 +19,7 @@
[
(foobar_very_long_key, foobar_very_long_value)
- for foobar_very_long_key, foobar_very_long_value in (
- foobar_very_long_dictionary.items()
- )
+ for foobar_very_long_key, foobar_very_long_value in foobar_very_long_dictionary.items()
]
# Don't split the `in` if it's not too long
@@ -47,9 +39,7 @@
[
x
for x in bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
- for y in (
- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- )
+ for y in xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
]
]
@@ -58,31 +48,23 @@
graph_path_expression
for refined_constraint in self._local_constraint_refinements.values()
if refined_constraint is not None
- for graph_path_expression in (
- refined_constraint.condition_as_predicate.variables
- )
+ for graph_path_expression in refined_constraint.condition_as_predicate.variables
]
# Dictionary comprehensions
dict_with_really_long_names = {
really_really_long_key_name: an_even_longer_really_really_long_key_value
- for really_really_long_key_name, an_even_longer_really_really_long_key_value in (
- really_really_really_long_dict_name.items()
- )
+ for really_really_long_key_name, an_even_longer_really_really_long_key_value in really_really_really_long_dict_name.items()
}
{
key_with_super_really_long_name: key_with_super_really_long_name
- for key_with_super_really_long_name in (
- dictionary_with_super_really_long_name
- )
+ for key_with_super_really_long_name in dictionary_with_super_really_long_name
}
{
key_with_super_really_long_name: key_with_super_really_long_name
- for key_with_super_really_long_name in (
- dictionary_with_super_really_long_name
- )
+ for key_with_super_really_long_name in dictionary_with_super_really_long_name
}
{
key_with_super_really_long_name: key_with_super_really_long_name
- for key in dictionary
+ for key in (dictionary)
}
```
## Ruff Output
```python
[
a
for graph_path_expression in refined_constraint.condition_as_predicate.variables
]
[
a
for graph_path_expression in refined_constraint.condition_as_predicate.variables
]
[
a
for graph_path_expression in refined_constraint.condition_as_predicate.variables
]
[
a
for graph_path_expression in (
refined_constraint.condition_as_predicate.variables
)
]
[
(foobar_very_long_key, foobar_very_long_value)
for foobar_very_long_key, foobar_very_long_value in foobar_very_long_dictionary.items()
]
# Don't split the `in` if it's not too long
lcomp3 = [
element.split("\n", 1)[0]
for element in collection.select_elements()
# right
if element is not None
]
# Don't remove parens around ternaries
expected = [i for i in (a if b else c)]
# Nested arrays
# First in will not be split because it would still be too long
[
[
x
for x in bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
for y in xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
]
]
# Multiple comprehensions, only split the second `in`
graph_path_expressions_in_local_constraint_refinements = [
graph_path_expression
for refined_constraint in self._local_constraint_refinements.values()
if refined_constraint is not None
for graph_path_expression in refined_constraint.condition_as_predicate.variables
]
# Dictionary comprehensions
dict_with_really_long_names = {
really_really_long_key_name: an_even_longer_really_really_long_key_value
for really_really_long_key_name, an_even_longer_really_really_long_key_value in really_really_really_long_dict_name.items()
}
{
key_with_super_really_long_name: key_with_super_really_long_name
for key_with_super_really_long_name in dictionary_with_super_really_long_name
}
{
key_with_super_really_long_name: key_with_super_really_long_name
for key_with_super_really_long_name in dictionary_with_super_really_long_name
}
{
key_with_super_really_long_name: key_with_super_really_long_name
for key in (dictionary)
}
```
## Black Output
```python
[
a
for graph_path_expression in (
refined_constraint.condition_as_predicate.variables
)
]
[
a
for graph_path_expression in (
refined_constraint.condition_as_predicate.variables
)
]
[
a
for graph_path_expression in (
refined_constraint.condition_as_predicate.variables
)
]
[
a
for graph_path_expression in (
refined_constraint.condition_as_predicate.variables
)
]
[
(foobar_very_long_key, foobar_very_long_value)
for foobar_very_long_key, foobar_very_long_value in (
foobar_very_long_dictionary.items()
)
]
# Don't split the `in` if it's not too long
lcomp3 = [
element.split("\n", 1)[0]
for element in collection.select_elements()
# right
if element is not None
]
# Don't remove parens around ternaries
expected = [i for i in (a if b else c)]
# Nested arrays
# First in will not be split because it would still be too long
[
[
x
for x in bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
for y in (
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
)
]
]
# Multiple comprehensions, only split the second `in`
graph_path_expressions_in_local_constraint_refinements = [
graph_path_expression
for refined_constraint in self._local_constraint_refinements.values()
if refined_constraint is not None
for graph_path_expression in (
refined_constraint.condition_as_predicate.variables
)
]
# Dictionary comprehensions
dict_with_really_long_names = {
really_really_long_key_name: an_even_longer_really_really_long_key_value
for really_really_long_key_name, an_even_longer_really_really_long_key_value in (
really_really_really_long_dict_name.items()
)
}
{
key_with_super_really_long_name: key_with_super_really_long_name
for key_with_super_really_long_name in (
dictionary_with_super_really_long_name
)
}
{
key_with_super_really_long_name: key_with_super_really_long_name
for key_with_super_really_long_name in (
dictionary_with_super_really_long_name
)
}
{
key_with_super_really_long_name: key_with_super_really_long_name
for key in dictionary
}
```

View file

@ -0,0 +1,427 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/remove_except_types_parens.py
---
## Input
```python
# SEE PEP 758 FOR MORE DETAILS
# remains unchanged
try:
pass
except:
pass
# remains unchanged
try:
pass
except ValueError:
pass
try:
pass
except* ValueError:
pass
# parenthesis are removed
try:
pass
except (ValueError):
pass
try:
pass
except* (ValueError):
pass
# parenthesis are removed
try:
pass
except (ValueError) as e:
pass
try:
pass
except* (ValueError) as e:
pass
# remains unchanged
try:
pass
except (ValueError,):
pass
try:
pass
except* (ValueError,):
pass
# remains unchanged
try:
pass
except (ValueError,) as e:
pass
try:
pass
except* (ValueError,) as e:
pass
# remains unchanged
try:
pass
except ValueError, TypeError, KeyboardInterrupt:
pass
try:
pass
except* ValueError, TypeError, KeyboardInterrupt:
pass
# parenthesis are removed
try:
pass
except (ValueError, TypeError, KeyboardInterrupt):
pass
try:
pass
except* (ValueError, TypeError, KeyboardInterrupt):
pass
# parenthesis are not removed
try:
pass
except (ValueError, TypeError, KeyboardInterrupt) as e:
pass
try:
pass
except* (ValueError, TypeError, KeyboardInterrupt) as e:
pass
# parenthesis are removed
try:
pass
except (ValueError if True else TypeError):
pass
try:
pass
except* (ValueError if True else TypeError):
pass
# inner except: parenthesis are removed
# outer except: parenthsis are not removed
try:
try:
pass
except (TypeError, KeyboardInterrupt):
pass
except (ValueError,):
pass
try:
try:
pass
except* (TypeError, KeyboardInterrupt):
pass
except* (ValueError,):
pass
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -74,12 +74,12 @@
# parenthesis are removed
try:
pass
-except ValueError, TypeError, KeyboardInterrupt:
+except (ValueError, TypeError, KeyboardInterrupt):
pass
try:
pass
-except* ValueError, TypeError, KeyboardInterrupt:
+except* (ValueError, TypeError, KeyboardInterrupt):
pass
# parenthesis are not removed
@@ -109,7 +109,7 @@
try:
try:
pass
- except TypeError, KeyboardInterrupt:
+ except (TypeError, KeyboardInterrupt):
pass
except (ValueError,):
pass
@@ -117,7 +117,7 @@
try:
try:
pass
- except* TypeError, KeyboardInterrupt:
+ except* (TypeError, KeyboardInterrupt):
pass
except* (ValueError,):
pass
```
## Ruff Output
```python
# SEE PEP 758 FOR MORE DETAILS
# remains unchanged
try:
pass
except:
pass
# remains unchanged
try:
pass
except ValueError:
pass
try:
pass
except* ValueError:
pass
# parenthesis are removed
try:
pass
except ValueError:
pass
try:
pass
except* ValueError:
pass
# parenthesis are removed
try:
pass
except ValueError as e:
pass
try:
pass
except* ValueError as e:
pass
# remains unchanged
try:
pass
except (ValueError,):
pass
try:
pass
except* (ValueError,):
pass
# remains unchanged
try:
pass
except (ValueError,) as e:
pass
try:
pass
except* (ValueError,) as e:
pass
# remains unchanged
try:
pass
except ValueError, TypeError, KeyboardInterrupt:
pass
try:
pass
except* ValueError, TypeError, KeyboardInterrupt:
pass
# parenthesis are removed
try:
pass
except (ValueError, TypeError, KeyboardInterrupt):
pass
try:
pass
except* (ValueError, TypeError, KeyboardInterrupt):
pass
# parenthesis are not removed
try:
pass
except (ValueError, TypeError, KeyboardInterrupt) as e:
pass
try:
pass
except* (ValueError, TypeError, KeyboardInterrupt) as e:
pass
# parenthesis are removed
try:
pass
except ValueError if True else TypeError:
pass
try:
pass
except* ValueError if True else TypeError:
pass
# inner except: parenthesis are removed
# outer except: parenthsis are not removed
try:
try:
pass
except (TypeError, KeyboardInterrupt):
pass
except (ValueError,):
pass
try:
try:
pass
except* (TypeError, KeyboardInterrupt):
pass
except* (ValueError,):
pass
```
## Black Output
```python
# SEE PEP 758 FOR MORE DETAILS
# remains unchanged
try:
pass
except:
pass
# remains unchanged
try:
pass
except ValueError:
pass
try:
pass
except* ValueError:
pass
# parenthesis are removed
try:
pass
except ValueError:
pass
try:
pass
except* ValueError:
pass
# parenthesis are removed
try:
pass
except ValueError as e:
pass
try:
pass
except* ValueError as e:
pass
# remains unchanged
try:
pass
except (ValueError,):
pass
try:
pass
except* (ValueError,):
pass
# remains unchanged
try:
pass
except (ValueError,) as e:
pass
try:
pass
except* (ValueError,) as e:
pass
# remains unchanged
try:
pass
except ValueError, TypeError, KeyboardInterrupt:
pass
try:
pass
except* ValueError, TypeError, KeyboardInterrupt:
pass
# parenthesis are removed
try:
pass
except ValueError, TypeError, KeyboardInterrupt:
pass
try:
pass
except* ValueError, TypeError, KeyboardInterrupt:
pass
# parenthesis are not removed
try:
pass
except (ValueError, TypeError, KeyboardInterrupt) as e:
pass
try:
pass
except* (ValueError, TypeError, KeyboardInterrupt) as e:
pass
# parenthesis are removed
try:
pass
except ValueError if True else TypeError:
pass
try:
pass
except* ValueError if True else TypeError:
pass
# inner except: parenthesis are removed
# outer except: parenthsis are not removed
try:
try:
pass
except TypeError, KeyboardInterrupt:
pass
except (ValueError,):
pass
try:
try:
pass
except* TypeError, KeyboardInterrupt:
pass
except* (ValueError,):
pass
```

View file

@ -0,0 +1,283 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/remove_lone_list_item_parens.py
---
## Input
```python
items = [(123)]
items = [(True)]
items = [(((((True)))))]
items = [(((((True,)))))]
items = [((((()))))]
items = [(x for x in [1])]
items = {(123)}
items = {(True)}
items = {(((((True)))))}
# Requires `hug_parens_with_braces_and_square_brackets` unstable style to remove parentheses
# around multiline values
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2"}
if some_var == ""
else {"key": "val"}
)
]
# Comments should not cause crashes
items = [
( # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
) # comment
]
items = [ # comment
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
] # comment
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"} # comment
if some_var == "long strings"
else {"key": "val"}
)
]
items = [ # comment
( # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
) # comment
] # comment
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,12 +1,12 @@
-items = [123]
-items = [True]
-items = [True]
-items = [(True,)]
-items = [()]
+items = [(123)]
+items = [(True)]
+items = [(True)]
+items = [((True,))]
+items = [(())]
items = [(x for x in [1])]
-items = {123}
-items = {True}
-items = {True}
+items = {(123)}
+items = {(True)}
+items = {(True)}
# Requires `hug_parens_with_braces_and_square_brackets` unstable style to remove parentheses
# around multiline values
@@ -17,7 +17,7 @@
else {"key": "val"}
)
]
-items = [{"key1": "val1", "key2": "val2"} if some_var == "" else {"key": "val"}]
+items = [({"key1": "val1", "key2": "val2"} if some_var == "" else {"key": "val"})]
# Comments should not cause crashes
items = [
```
## Ruff Output
```python
items = [(123)]
items = [(True)]
items = [(True)]
items = [((True,))]
items = [(())]
items = [(x for x in [1])]
items = {(123)}
items = {(True)}
items = {(True)}
# Requires `hug_parens_with_braces_and_square_brackets` unstable style to remove parentheses
# around multiline values
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [({"key1": "val1", "key2": "val2"} if some_var == "" else {"key": "val"})]
# Comments should not cause crashes
items = [
( # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
) # comment
]
items = [ # comment
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
] # comment
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"} # comment
if some_var == "long strings"
else {"key": "val"}
)
]
items = [ # comment
( # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
) # comment
] # comment
```
## Black Output
```python
items = [123]
items = [True]
items = [True]
items = [(True,)]
items = [()]
items = [(x for x in [1])]
items = {123}
items = {True}
items = {True}
# Requires `hug_parens_with_braces_and_square_brackets` unstable style to remove parentheses
# around multiline values
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [{"key1": "val1", "key2": "val2"} if some_var == "" else {"key": "val"}]
# Comments should not cause crashes
items = [
( # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
) # comment
]
items = [ # comment
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
] # comment
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"} # comment
if some_var == "long strings"
else {"key": "val"}
)
]
items = [ # comment
( # comment
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
)
]
items = [
(
{"key1": "val1", "key2": "val2", "key3": "val3"}
if some_var == "long strings"
else {"key": "val"}
) # comment
] # comment
```

View file

@ -1,7 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/type_param_defaults.py
snapshot_kind: text
---
## Input
@ -25,6 +24,8 @@ def trailing_comma1[T=int,](a: str):
def trailing_comma2[T=int](a: str,):
pass
def weird_syntax[T=lambda: 42, **P=lambda: 43, *Ts=lambda: 44](): pass
```
## Black Differences
@ -32,7 +33,7 @@ def trailing_comma2[T=int](a: str,):
```diff
--- Black
+++ Ruff
@@ -8,20 +8,20 @@
@@ -8,9 +8,9 @@
type D[
*something_that_is_very_very_very_long = *something_that_is_very_very_very_long
] = float
@ -44,35 +45,18 @@ def trailing_comma2[T=int](a: str,):
+)
-def simple[
- T = something_that_is_long
-](short1: int, short2: str, short3: bytes) -> float:
+def simple[T = something_that_is_long](
+ short1: int, short2: str, short3: bytes
+) -> float:
def simple[T = something_that_is_long](
@@ -27,9 +27,7 @@
def trailing_comma1[
T = int,
-](
- a: str,
-):
+](a: str):
pass
-def longer[
- something_that_is_long = something_that_is_long
-](something_that_is_long: something_that_is_long) -> something_that_is_long:
+def longer[something_that_is_long = something_that_is_long](
+ something_that_is_long: something_that_is_long,
+) -> something_that_is_long:
pass
@@ -31,7 +31,7 @@
pass
-def trailing_comma2[
- T = int
-](a: str,):
+def trailing_comma2[T = int](
+ a: str,
+):
pass
```
## Ruff Output
@ -115,6 +99,10 @@ def trailing_comma2[T = int](
a: str,
):
pass
def weird_syntax[T = lambda: 42, **P = lambda: 43, *Ts = lambda: 44]():
pass
```
## Black Output
@ -135,26 +123,32 @@ type something_that_is_long[
] = something_that_is_long
def simple[
T = something_that_is_long
](short1: int, short2: str, short3: bytes) -> float:
def simple[T = something_that_is_long](
short1: int, short2: str, short3: bytes
) -> float:
pass
def longer[
something_that_is_long = something_that_is_long
](something_that_is_long: something_that_is_long) -> something_that_is_long:
def longer[something_that_is_long = something_that_is_long](
something_that_is_long: something_that_is_long,
) -> something_that_is_long:
pass
def trailing_comma1[
T = int,
](a: str):
](
a: str,
):
pass
def trailing_comma2[
T = int
](a: str,):
def trailing_comma2[T = int](
a: str,
):
pass
def weird_syntax[T = lambda: 42, **P = lambda: 43, *Ts = lambda: 44]():
pass
```