Update Black tests (#8901)

This commit is contained in:
Micha Reiser 2023-11-30 09:09:55 +09:00 committed by GitHub
parent 08f3110f1e
commit fd70cd789f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
435 changed files with 21436 additions and 1595 deletions

View file

@ -20,9 +20,10 @@ fn black_compatibility() {
let options_path = input_path.with_extension("options.json");
let options: PyFormatOptions = if let Ok(options_file) = fs::File::open(options_path) {
let options: PyFormatOptions = if let Ok(options_file) = fs::File::open(&options_path) {
let reader = BufReader::new(options_file);
serde_json::from_reader(reader).expect("Options to be a valid Json file")
serde_json::from_reader(reader)
.unwrap_or_else(|_| panic!("Option file {options_path:?} to be a valid Json file"))
} else {
PyFormatOptions::from_extension(input_path)
};
@ -34,7 +35,11 @@ fn black_compatibility() {
)
});
let expected_path = input_path.with_extension("py.expect");
let extension = input_path
.extension()
.expect("Test file to have py or pyi extension")
.to_string_lossy();
let expected_path = input_path.with_extension(format!("{extension}.expect"));
let expected_output = fs::read_to_string(&expected_path)
.unwrap_or_else(|_| panic!("Expected Black output file '{expected_path:?}' to exist"));
@ -106,7 +111,11 @@ fn black_compatibility() {
}
};
insta::glob!("../resources", "test/fixtures/black/**/*.py", test_file);
insta::glob!(
"../resources",
"test/fixtures/black/**/*.{py,pyi}",
test_file
);
}
#[test]

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comment_after_escaped_newline.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/comment_after_escaped_newline.py
---
## Input

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments2.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/comments2.py
---
## Input

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments6.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/comments6.py
---
## Input

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments9.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/comments9.py
---
## Input

View file

@ -0,0 +1,382 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/comments_in_blocks.py
---
## Input
```python
# Test cases from:
# - https://github.com/psf/black/issues/1798
# - https://github.com/psf/black/issues/1499
# - https://github.com/psf/black/issues/1211
# - https://github.com/psf/black/issues/563
(
lambda
# a comment
: None
)
(
lambda:
# b comment
None
)
(
lambda
# a comment
:
# b comment
None
)
[
x
# Let's do this
for
# OK?
x
# Some comment
# And another
in
# One more
y
]
return [
(offers[offer_index], 1.0)
for offer_index, _
# avoid returning any offers that don't match the grammar so
# that the return values here are consistent with what would be
# returned in AcceptValidHeader
in self._parse_and_normalize_offers(offers)
]
from foo import (
bar,
# qux
)
def convert(collection):
# replace all variables by integers
replacement_dict = {
variable: f"{index}"
for index, variable
# 0 is reserved as line terminator
in enumerate(collection.variables(), start=1)
}
{
i: i
for i
# a comment
in range(5)
}
def get_subtree_proof_nodes(
chunk_index_groups: Sequence[Tuple[int, ...], ...],
) -> Tuple[int, ...]:
subtree_node_paths = (
# We take a candidate element from each group and shift it to
# remove the bits that are not common to other group members, then
# we convert it to a tree path that all elements from this group
# have in common.
chunk_index
for chunk_index, bits_to_truncate
# Each group will contain an even "power-of-two" number of# elements.
# This tells us how many tailing bits each element has# which need to
# be truncated to get the group's common prefix.
in ((group[0], (len(group) - 1).bit_length()) for group in chunk_index_groups)
)
return subtree_node_paths
if (
# comment1
a
# comment2
or (
# comment3
(
# comment4
b
)
# comment5
and
# comment6
c
or (
# comment7
d
)
)
):
print("Foo")
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -5,9 +5,9 @@
# - https://github.com/psf/black/issues/563
(
- lambda
+ lambda:
# a comment
- : None
+ None
)
(
@@ -17,9 +17,8 @@
)
(
- lambda
+ lambda:
# a comment
- :
# b comment
None
)
```
## Ruff Output
```python
# Test cases from:
# - https://github.com/psf/black/issues/1798
# - https://github.com/psf/black/issues/1499
# - https://github.com/psf/black/issues/1211
# - https://github.com/psf/black/issues/563
(
lambda:
# a comment
None
)
(
lambda:
# b comment
None
)
(
lambda:
# a comment
# b comment
None
)
[
x
# Let's do this
for
# OK?
x
# Some comment
# And another
in
# One more
y
]
return [
(offers[offer_index], 1.0)
for offer_index, _
# avoid returning any offers that don't match the grammar so
# that the return values here are consistent with what would be
# returned in AcceptValidHeader
in self._parse_and_normalize_offers(offers)
]
from foo import (
bar,
# qux
)
def convert(collection):
# replace all variables by integers
replacement_dict = {
variable: f"{index}"
for index, variable
# 0 is reserved as line terminator
in enumerate(collection.variables(), start=1)
}
{
i: i
for i
# a comment
in range(5)
}
def get_subtree_proof_nodes(
chunk_index_groups: Sequence[Tuple[int, ...], ...],
) -> Tuple[int, ...]:
subtree_node_paths = (
# We take a candidate element from each group and shift it to
# remove the bits that are not common to other group members, then
# we convert it to a tree path that all elements from this group
# have in common.
chunk_index
for chunk_index, bits_to_truncate
# Each group will contain an even "power-of-two" number of# elements.
# This tells us how many tailing bits each element has# which need to
# be truncated to get the group's common prefix.
in ((group[0], (len(group) - 1).bit_length()) for group in chunk_index_groups)
)
return subtree_node_paths
if (
# comment1
a
# comment2
or (
# comment3
(
# comment4
b
)
# comment5
and
# comment6
c
or (
# comment7
d
)
)
):
print("Foo")
```
## Black Output
```python
# Test cases from:
# - https://github.com/psf/black/issues/1798
# - https://github.com/psf/black/issues/1499
# - https://github.com/psf/black/issues/1211
# - https://github.com/psf/black/issues/563
(
lambda
# a comment
: None
)
(
lambda:
# b comment
None
)
(
lambda
# a comment
:
# b comment
None
)
[
x
# Let's do this
for
# OK?
x
# Some comment
# And another
in
# One more
y
]
return [
(offers[offer_index], 1.0)
for offer_index, _
# avoid returning any offers that don't match the grammar so
# that the return values here are consistent with what would be
# returned in AcceptValidHeader
in self._parse_and_normalize_offers(offers)
]
from foo import (
bar,
# qux
)
def convert(collection):
# replace all variables by integers
replacement_dict = {
variable: f"{index}"
for index, variable
# 0 is reserved as line terminator
in enumerate(collection.variables(), start=1)
}
{
i: i
for i
# a comment
in range(5)
}
def get_subtree_proof_nodes(
chunk_index_groups: Sequence[Tuple[int, ...], ...],
) -> Tuple[int, ...]:
subtree_node_paths = (
# We take a candidate element from each group and shift it to
# remove the bits that are not common to other group members, then
# we convert it to a tree path that all elements from this group
# have in common.
chunk_index
for chunk_index, bits_to_truncate
# Each group will contain an even "power-of-two" number of# elements.
# This tells us how many tailing bits each element has# which need to
# be truncated to get the group's common prefix.
in ((group[0], (len(group) - 1).bit_length()) for group in chunk_index_groups)
)
return subtree_node_paths
if (
# comment1
a
# comment2
or (
# comment3
(
# comment4
b
)
# comment5
and
# comment6
c
or (
# comment7
d
)
)
):
print("Foo")
```

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/composition.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/composition.py
---
## Input

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/composition_no_trailing_comma.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/composition_no_trailing_comma.py
---
## Input

View file

@ -0,0 +1,334 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/conditional_expression.py
---
## Input
```python
long_kwargs_single_line = my_function(
foo="test, this is a sample value",
bar=some_long_value_name_foo_bar_baz if some_boolean_variable else some_fallback_value_foo_bar_baz,
baz="hello, this is a another value",
)
multiline_kwargs_indented = my_function(
foo="test, this is a sample value",
bar=some_long_value_name_foo_bar_baz
if some_boolean_variable
else some_fallback_value_foo_bar_baz,
baz="hello, this is a another value",
)
imploding_kwargs = my_function(
foo="test, this is a sample value",
bar=a
if foo
else b,
baz="hello, this is a another value",
)
imploding_line = (
1
if 1 + 1 == 2
else 0
)
exploding_line = "hello this is a slightly long string" if some_long_value_name_foo_bar_baz else "this one is a little shorter"
positional_argument_test(some_long_value_name_foo_bar_baz if some_boolean_variable else some_fallback_value_foo_bar_baz)
def weird_default_argument(x=some_long_value_name_foo_bar_baz
if SOME_CONSTANT
else some_fallback_value_foo_bar_baz):
pass
nested = "hello this is a slightly long string" if (some_long_value_name_foo_bar_baz if
nesting_test_expressions else some_fallback_value_foo_bar_baz) \
else "this one is a little shorter"
generator_expression = (
some_long_value_name_foo_bar_baz if some_boolean_variable else some_fallback_value_foo_bar_baz for some_boolean_variable in some_iterable
)
def limit_offset_sql(self, low_mark, high_mark):
"""Return LIMIT/OFFSET SQL clause."""
limit, offset = self._get_limit_offset_params(low_mark, high_mark)
return " ".join(
sql
for sql in (
"LIMIT %d" % limit if limit else None,
("OFFSET %d" % offset) if offset else None,
)
if sql
)
def something():
clone._iterable_class = (
NamedValuesListIterable
if named
else FlatValuesListIterable
if flat
else ValuesListIterable
)
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,20 +1,16 @@
long_kwargs_single_line = my_function(
foo="test, this is a sample value",
- bar=(
- some_long_value_name_foo_bar_baz
- if some_boolean_variable
- else some_fallback_value_foo_bar_baz
- ),
+ bar=some_long_value_name_foo_bar_baz
+ if some_boolean_variable
+ else some_fallback_value_foo_bar_baz,
baz="hello, this is a another value",
)
multiline_kwargs_indented = my_function(
foo="test, this is a sample value",
- bar=(
- some_long_value_name_foo_bar_baz
- if some_boolean_variable
- else some_fallback_value_foo_bar_baz
- ),
+ bar=some_long_value_name_foo_bar_baz
+ if some_boolean_variable
+ else some_fallback_value_foo_bar_baz,
baz="hello, this is a another value",
)
@@ -40,11 +36,9 @@
def weird_default_argument(
- x=(
- some_long_value_name_foo_bar_baz
- if SOME_CONSTANT
- else some_fallback_value_foo_bar_baz
- ),
+ x=some_long_value_name_foo_bar_baz
+ if SOME_CONSTANT
+ else some_fallback_value_foo_bar_baz,
):
pass
@@ -60,11 +54,9 @@
)
generator_expression = (
- (
- some_long_value_name_foo_bar_baz
- if some_boolean_variable
- else some_fallback_value_foo_bar_baz
- )
+ some_long_value_name_foo_bar_baz
+ if some_boolean_variable
+ else some_fallback_value_foo_bar_baz
for some_boolean_variable in some_iterable
)
@@ -86,5 +78,7 @@
clone._iterable_class = (
NamedValuesListIterable
if named
- else FlatValuesListIterable if flat else ValuesListIterable
+ else FlatValuesListIterable
+ if flat
+ else ValuesListIterable
)
```
## Ruff Output
```python
long_kwargs_single_line = my_function(
foo="test, this is a sample value",
bar=some_long_value_name_foo_bar_baz
if some_boolean_variable
else some_fallback_value_foo_bar_baz,
baz="hello, this is a another value",
)
multiline_kwargs_indented = my_function(
foo="test, this is a sample value",
bar=some_long_value_name_foo_bar_baz
if some_boolean_variable
else some_fallback_value_foo_bar_baz,
baz="hello, this is a another value",
)
imploding_kwargs = my_function(
foo="test, this is a sample value",
bar=a if foo else b,
baz="hello, this is a another value",
)
imploding_line = 1 if 1 + 1 == 2 else 0
exploding_line = (
"hello this is a slightly long string"
if some_long_value_name_foo_bar_baz
else "this one is a little shorter"
)
positional_argument_test(
some_long_value_name_foo_bar_baz
if some_boolean_variable
else some_fallback_value_foo_bar_baz
)
def weird_default_argument(
x=some_long_value_name_foo_bar_baz
if SOME_CONSTANT
else some_fallback_value_foo_bar_baz,
):
pass
nested = (
"hello this is a slightly long string"
if (
some_long_value_name_foo_bar_baz
if nesting_test_expressions
else some_fallback_value_foo_bar_baz
)
else "this one is a little shorter"
)
generator_expression = (
some_long_value_name_foo_bar_baz
if some_boolean_variable
else some_fallback_value_foo_bar_baz
for some_boolean_variable in some_iterable
)
def limit_offset_sql(self, low_mark, high_mark):
"""Return LIMIT/OFFSET SQL clause."""
limit, offset = self._get_limit_offset_params(low_mark, high_mark)
return " ".join(
sql
for sql in (
"LIMIT %d" % limit if limit else None,
("OFFSET %d" % offset) if offset else None,
)
if sql
)
def something():
clone._iterable_class = (
NamedValuesListIterable
if named
else FlatValuesListIterable
if flat
else ValuesListIterable
)
```
## Black Output
```python
long_kwargs_single_line = my_function(
foo="test, this is a sample value",
bar=(
some_long_value_name_foo_bar_baz
if some_boolean_variable
else some_fallback_value_foo_bar_baz
),
baz="hello, this is a another value",
)
multiline_kwargs_indented = my_function(
foo="test, this is a sample value",
bar=(
some_long_value_name_foo_bar_baz
if some_boolean_variable
else some_fallback_value_foo_bar_baz
),
baz="hello, this is a another value",
)
imploding_kwargs = my_function(
foo="test, this is a sample value",
bar=a if foo else b,
baz="hello, this is a another value",
)
imploding_line = 1 if 1 + 1 == 2 else 0
exploding_line = (
"hello this is a slightly long string"
if some_long_value_name_foo_bar_baz
else "this one is a little shorter"
)
positional_argument_test(
some_long_value_name_foo_bar_baz
if some_boolean_variable
else some_fallback_value_foo_bar_baz
)
def weird_default_argument(
x=(
some_long_value_name_foo_bar_baz
if SOME_CONSTANT
else some_fallback_value_foo_bar_baz
),
):
pass
nested = (
"hello this is a slightly long string"
if (
some_long_value_name_foo_bar_baz
if nesting_test_expressions
else some_fallback_value_foo_bar_baz
)
else "this one is a little shorter"
)
generator_expression = (
(
some_long_value_name_foo_bar_baz
if some_boolean_variable
else some_fallback_value_foo_bar_baz
)
for some_boolean_variable in some_iterable
)
def limit_offset_sql(self, low_mark, high_mark):
"""Return LIMIT/OFFSET SQL clause."""
limit, offset = self._get_limit_offset_params(low_mark, high_mark)
return " ".join(
sql
for sql in (
"LIMIT %d" % limit if limit else None,
("OFFSET %d" % offset) if offset else None,
)
if sql
)
def something():
clone._iterable_class = (
NamedValuesListIterable
if named
else FlatValuesListIterable if flat else ValuesListIterable
)
```

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/miscellaneous/docstring_no_string_normalization.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/docstring_no_string_normalization.py
---
## Input

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/expression.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/expression.py
---
## Input

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtonoff.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/fmtonoff.py
---
## Input

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtonoff4.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/fmtonoff4.py
---
## Input

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtonoff5.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/fmtonoff5.py
---
## Input

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtpass_imports.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/fmtpass_imports.py
---
## Input

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip5.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/fmtskip5.py
---
## Input

View file

@ -0,0 +1,608 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/funcdef_return_type_trailing_comma.py
---
## Input
```python
# normal, short, function definition
def foo(a, b) -> tuple[int, float]: ...
# normal, short, function definition w/o return type
def foo(a, b): ...
# no splitting
def foo(a: A, b: B) -> list[p, q]:
pass
# magic trailing comma in param list
def foo(a, b,): ...
# magic trailing comma in nested params in param list
def foo(a, b: tuple[int, float,]): ...
# magic trailing comma in return type, no params
def a() -> tuple[
a,
b,
]: ...
# magic trailing comma in return type, params
def foo(a: A, b: B) -> list[
p,
q,
]:
pass
# magic trailing comma in param list and in return type
def foo(
a: a,
b: b,
) -> list[
a,
a,
]:
pass
# long function definition, param list is longer
def aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(
bbbbbbbbbbbbbbbbbb,
) -> cccccccccccccccccccccccccccccc: ...
# long function definition, return type is longer
# this should maybe split on rhs?
def aaaaaaaaaaaaaaaaa(bbbbbbbbbbbbbbbbbb) -> list[
Ccccccccccccccccccccccccccccccccccccccccccccccccccc, Dddddd
]: ...
# long return type, no param list
def foo() -> list[
Loooooooooooooooooooooooooooooooooooong,
Loooooooooooooooooooong,
Looooooooooooong,
]: ...
# long function name, no param list, no return value
def thiiiiiiiiiiiiiiiiiis_iiiiiiiiiiiiiiiiiiiiiiiiiiiiiis_veeeeeeeeeeeeeeeeeeeeeeery_looooooong():
pass
# long function name, no param list
def thiiiiiiiiiiiiiiiiiis_iiiiiiiiiiiiiiiiiiiiiiiiiiiiiis_veeeeeeeeeeeeeeeeeeeeeeery_looooooong() -> (
list[int, float]
): ...
# long function name, no return value
def thiiiiiiiiiiiiiiiiiis_iiiiiiiiiiiiiiiiiiiiiiiiiiiiiis_veeeeeeeeeeeeeeeeeeeeeeery_looooooong(
a, b
): ...
# unskippable type hint (??)
def foo(a) -> list[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]: # type: ignore
pass
def foo(a) -> list[
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
]: # abpedeifnore
pass
def foo(a, b: list[Bad],): ... # type: ignore
# don't lose any comments (no magic)
def foo( # 1
a, # 2
b) -> list[ # 3
a, # 4
b]: # 5
... # 6
# don't lose any comments (param list magic)
def foo( # 1
a, # 2
b,) -> list[ # 3
a, # 4
b]: # 5
... # 6
# don't lose any comments (return type magic)
def foo( # 1
a, # 2
b) -> list[ # 3
a, # 4
b,]: # 5
... # 6
# don't lose any comments (both magic)
def foo( # 1
a, # 2
b,) -> list[ # 3
a, # 4
b,]: # 5
... # 6
# real life example
def SimplePyFn(
context: hl.GeneratorContext,
buffer_input: Buffer[UInt8, 2],
func_input: Buffer[Int32, 2],
float_arg: Scalar[Float32],
offset: int = 0,
) -> tuple[
Buffer[UInt8, 2],
Buffer[UInt8, 2],
]: ...
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -29,14 +29,18 @@
# magic trailing comma in return type, no params
-def a() -> tuple[
- a,
- b,
-]: ...
+def a() -> (
+ tuple[
+ a,
+ b,
+ ]
+): ...
# magic trailing comma in return type, params
-def foo(a: A, b: B) -> list[
+def foo(
+ a: A, b: B
+) -> list[
p,
q,
]:
@@ -63,16 +67,18 @@
# long function definition, return type is longer
# this should maybe split on rhs?
def aaaaaaaaaaaaaaaaa(
- bbbbbbbbbbbbbbbbbb,
+ bbbbbbbbbbbbbbbbbb
) -> list[Ccccccccccccccccccccccccccccccccccccccccccccccccccc, Dddddd]: ...
# long return type, no param list
-def foo() -> list[
- Loooooooooooooooooooooooooooooooooooong,
- Loooooooooooooooooooong,
- Looooooooooooong,
-]: ...
+def foo() -> (
+ list[
+ Loooooooooooooooooooooooooooooooooooong,
+ Loooooooooooooooooooong,
+ Looooooooooooong,
+ ]
+): ...
# long function name, no param list, no return value
@@ -93,12 +99,16 @@
# unskippable type hint (??)
-def foo(a) -> list[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]: # type: ignore
+def foo(
+ a
+) -> list[
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+]: # type: ignore
pass
def foo(
- a,
+ a
) -> list[
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
]: # abpedeifnore
@@ -112,7 +122,13 @@
# don't lose any comments (no magic)
-def foo(a, b) -> list[a, b]: # 1 # 2 # 3 # 4 # 5
+def foo( # 1
+ a, # 2
+ b,
+) -> list[ # 3
+ a, # 4
+ b,
+]: # 5
... # 6
@@ -120,12 +136,18 @@
def foo( # 1
a, # 2
b,
-) -> list[a, b]: # 3 # 4 # 5
+) -> list[ # 3
+ a, # 4
+ b,
+]: # 5
... # 6
# don't lose any comments (return type magic)
-def foo(a, b) -> list[ # 1 # 2 # 3
+def foo( # 1
+ a, # 2
+ b,
+) -> list[ # 3
a, # 4
b,
]: # 5
```
## Ruff Output
```python
# normal, short, function definition
def foo(a, b) -> tuple[int, float]: ...
# normal, short, function definition w/o return type
def foo(a, b): ...
# no splitting
def foo(a: A, b: B) -> list[p, q]:
pass
# magic trailing comma in param list
def foo(
a,
b,
): ...
# magic trailing comma in nested params in param list
def foo(
a,
b: tuple[
int,
float,
],
): ...
# magic trailing comma in return type, no params
def a() -> (
tuple[
a,
b,
]
): ...
# magic trailing comma in return type, params
def foo(
a: A, b: B
) -> list[
p,
q,
]:
pass
# magic trailing comma in param list and in return type
def foo(
a: a,
b: b,
) -> list[
a,
a,
]:
pass
# long function definition, param list is longer
def aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(
bbbbbbbbbbbbbbbbbb,
) -> cccccccccccccccccccccccccccccc: ...
# long function definition, return type is longer
# this should maybe split on rhs?
def aaaaaaaaaaaaaaaaa(
bbbbbbbbbbbbbbbbbb
) -> list[Ccccccccccccccccccccccccccccccccccccccccccccccccccc, Dddddd]: ...
# long return type, no param list
def foo() -> (
list[
Loooooooooooooooooooooooooooooooooooong,
Loooooooooooooooooooong,
Looooooooooooong,
]
): ...
# long function name, no param list, no return value
def thiiiiiiiiiiiiiiiiiis_iiiiiiiiiiiiiiiiiiiiiiiiiiiiiis_veeeeeeeeeeeeeeeeeeeeeeery_looooooong():
pass
# long function name, no param list
def thiiiiiiiiiiiiiiiiiis_iiiiiiiiiiiiiiiiiiiiiiiiiiiiiis_veeeeeeeeeeeeeeeeeeeeeeery_looooooong() -> (
list[int, float]
): ...
# long function name, no return value
def thiiiiiiiiiiiiiiiiiis_iiiiiiiiiiiiiiiiiiiiiiiiiiiiiis_veeeeeeeeeeeeeeeeeeeeeeery_looooooong(
a, b
): ...
# unskippable type hint (??)
def foo(
a
) -> list[
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
]: # type: ignore
pass
def foo(
a
) -> list[
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
]: # abpedeifnore
pass
def foo(
a,
b: list[Bad],
): ... # type: ignore
# don't lose any comments (no magic)
def foo( # 1
a, # 2
b,
) -> list[ # 3
a, # 4
b,
]: # 5
... # 6
# don't lose any comments (param list magic)
def foo( # 1
a, # 2
b,
) -> list[ # 3
a, # 4
b,
]: # 5
... # 6
# don't lose any comments (return type magic)
def foo( # 1
a, # 2
b,
) -> list[ # 3
a, # 4
b,
]: # 5
... # 6
# don't lose any comments (both magic)
def foo( # 1
a, # 2
b,
) -> list[ # 3
a, # 4
b,
]: # 5
... # 6
# real life example
def SimplePyFn(
context: hl.GeneratorContext,
buffer_input: Buffer[UInt8, 2],
func_input: Buffer[Int32, 2],
float_arg: Scalar[Float32],
offset: int = 0,
) -> tuple[
Buffer[UInt8, 2],
Buffer[UInt8, 2],
]: ...
```
## Black Output
```python
# normal, short, function definition
def foo(a, b) -> tuple[int, float]: ...
# normal, short, function definition w/o return type
def foo(a, b): ...
# no splitting
def foo(a: A, b: B) -> list[p, q]:
pass
# magic trailing comma in param list
def foo(
a,
b,
): ...
# magic trailing comma in nested params in param list
def foo(
a,
b: tuple[
int,
float,
],
): ...
# magic trailing comma in return type, no params
def a() -> tuple[
a,
b,
]: ...
# magic trailing comma in return type, params
def foo(a: A, b: B) -> list[
p,
q,
]:
pass
# magic trailing comma in param list and in return type
def foo(
a: a,
b: b,
) -> list[
a,
a,
]:
pass
# long function definition, param list is longer
def aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(
bbbbbbbbbbbbbbbbbb,
) -> cccccccccccccccccccccccccccccc: ...
# long function definition, return type is longer
# this should maybe split on rhs?
def aaaaaaaaaaaaaaaaa(
bbbbbbbbbbbbbbbbbb,
) -> list[Ccccccccccccccccccccccccccccccccccccccccccccccccccc, Dddddd]: ...
# long return type, no param list
def foo() -> list[
Loooooooooooooooooooooooooooooooooooong,
Loooooooooooooooooooong,
Looooooooooooong,
]: ...
# long function name, no param list, no return value
def thiiiiiiiiiiiiiiiiiis_iiiiiiiiiiiiiiiiiiiiiiiiiiiiiis_veeeeeeeeeeeeeeeeeeeeeeery_looooooong():
pass
# long function name, no param list
def thiiiiiiiiiiiiiiiiiis_iiiiiiiiiiiiiiiiiiiiiiiiiiiiiis_veeeeeeeeeeeeeeeeeeeeeeery_looooooong() -> (
list[int, float]
): ...
# long function name, no return value
def thiiiiiiiiiiiiiiiiiis_iiiiiiiiiiiiiiiiiiiiiiiiiiiiiis_veeeeeeeeeeeeeeeeeeeeeeery_looooooong(
a, b
): ...
# unskippable type hint (??)
def foo(a) -> list[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]: # type: ignore
pass
def foo(
a,
) -> list[
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
]: # abpedeifnore
pass
def foo(
a,
b: list[Bad],
): ... # type: ignore
# don't lose any comments (no magic)
def foo(a, b) -> list[a, b]: # 1 # 2 # 3 # 4 # 5
... # 6
# don't lose any comments (param list magic)
def foo( # 1
a, # 2
b,
) -> list[a, b]: # 3 # 4 # 5
... # 6
# don't lose any comments (return type magic)
def foo(a, b) -> list[ # 1 # 2 # 3
a, # 4
b,
]: # 5
... # 6
# don't lose any comments (both magic)
def foo( # 1
a, # 2
b,
) -> list[ # 3
a, # 4
b,
]: # 5
... # 6
# real life example
def SimplePyFn(
context: hl.GeneratorContext,
buffer_input: Buffer[UInt8, 2],
func_input: Buffer[Int32, 2],
float_arg: Scalar[Float32],
offset: int = 0,
) -> tuple[
Buffer[UInt8, 2],
Buffer[UInt8, 2],
]: ...
```

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/function.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/function.py
---
## Input

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/function2.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/function2.py
---
## Input

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/ignore_pyi.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/ignore_pyi.pyi
---
## Input
@ -22,9 +22,10 @@ def g():
# hi
...
def h():
...
# bye
# FIXME(#8905): Uncomment, leads to unstable formatting
# def h():
# ...
# # bye
```
## Black Differences
@ -32,34 +33,25 @@ def h():
```diff
--- Black
+++ Ruff
@@ -1,18 +1,25 @@
def f(): # type: ignore
...
@@ -3,7 +3,6 @@
+
class x: # some comment
...
-
class y: ... # comment
-class y: ... # comment
+class y:
+ ... # comment
+
+
# whitespace doesn't matter (note the next line has a trailing space and tab)
-class z: ...
+class z:
+ ...
+
def g():
@@ -13,6 +12,7 @@
# hi
...
+
def h():
...
# bye
-def h():
- ...
- # bye
+# FIXME(#8905): Uncomment, leads to unstable formatting
+# def h():
+# ...
+# # bye
```
## Ruff Output
@ -68,28 +60,21 @@ def h():
def f(): # type: ignore
...
class x: # some comment
...
class y:
... # comment
class y: ... # comment
# whitespace doesn't matter (note the next line has a trailing space and tab)
class z:
...
class z: ...
def g():
# hi
...
def h():
...
# bye
# FIXME(#8905): Uncomment, leads to unstable formatting
# def h():
# ...
# # bye
```
## Black Output

View file

@ -0,0 +1,317 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/line_ranges_basic.py
---
## Input
```python
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
def foo1(parameter_1, parameter_2, parameter_3, parameter_4, parameter_5, parameter_6, parameter_7): pass
def foo2(parameter_1, parameter_2, parameter_3, parameter_4, parameter_5, parameter_6, parameter_7): pass
def foo3(parameter_1, parameter_2, parameter_3, parameter_4, parameter_5, parameter_6, parameter_7): pass
def foo4(parameter_1, parameter_2, parameter_3, parameter_4, parameter_5, parameter_6, parameter_7): pass
# Adding some unformated code covering a wide range of syntaxes.
if True:
# Incorrectly indented prefix comments.
pass
import typing
from typing import (
Any ,
)
class MyClass( object): # Trailing comment with extra leading space.
#NOTE: The following indentation is incorrect:
@decor( 1 * 3 )
def my_func( arg):
pass
try: # Trailing comment with extra leading space.
for i in range(10): # Trailing comment with extra leading space.
while condition:
if something:
then_something( )
elif something_else:
then_something_else( )
except ValueError as e:
unformatted( )
finally:
unformatted( )
async def test_async_unformatted( ): # Trailing comment with extra leading space.
async for i in some_iter( unformatted ): # Trailing comment with extra leading space.
await asyncio.sleep( 1 )
async with some_context( unformatted ):
print( "unformatted" )
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,7 +1,17 @@
-# flags: --line-ranges=5-6
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
-def foo1(parameter_1, parameter_2, parameter_3, parameter_4, parameter_5, parameter_6, parameter_7): pass
+def foo1(
+ parameter_1,
+ parameter_2,
+ parameter_3,
+ parameter_4,
+ parameter_5,
+ parameter_6,
+ parameter_7,
+):
+ pass
+
+
def foo2(
parameter_1,
parameter_2,
@@ -26,38 +36,52 @@
pass
-def foo4(parameter_1, parameter_2, parameter_3, parameter_4, parameter_5, parameter_6, parameter_7): pass
+def foo4(
+ parameter_1,
+ parameter_2,
+ parameter_3,
+ parameter_4,
+ parameter_5,
+ parameter_6,
+ parameter_7,
+):
+ pass
+
# Adding some unformated code covering a wide range of syntaxes.
if True:
- # Incorrectly indented prefix comments.
- pass
+ # Incorrectly indented prefix comments.
+ pass
+
+import typing
+from typing import (
+ Any,
+)
+
+
+class MyClass(object): # Trailing comment with extra leading space.
+ # NOTE: The following indentation is incorrect:
+ @decor(1 * 3)
+ def my_func(arg):
+ pass
-import typing
-from typing import (
- Any ,
- )
-class MyClass( object): # Trailing comment with extra leading space.
- #NOTE: The following indentation is incorrect:
- @decor( 1 * 3 )
- def my_func( arg):
- pass
-try: # Trailing comment with extra leading space.
- for i in range(10): # Trailing comment with extra leading space.
- while condition:
- if something:
- then_something( )
- elif something_else:
- then_something_else( )
-except ValueError as e:
- unformatted( )
+try: # Trailing comment with extra leading space.
+ for i in range(10): # Trailing comment with extra leading space.
+ while condition:
+ if something:
+ then_something()
+ elif something_else:
+ then_something_else()
+except ValueError as e:
+ unformatted()
finally:
- unformatted( )
+ unformatted()
+
-async def test_async_unformatted( ): # Trailing comment with extra leading space.
- async for i in some_iter( unformatted ): # Trailing comment with extra leading space.
- await asyncio.sleep( 1 )
- async with some_context( unformatted ):
- print( "unformatted" )
+async def test_async_unformatted(): # Trailing comment with extra leading space.
+ async for i in some_iter(unformatted): # Trailing comment with extra leading space.
+ await asyncio.sleep(1)
+ async with some_context(unformatted):
+ print("unformatted")
```
## Ruff Output
```python
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
def foo1(
parameter_1,
parameter_2,
parameter_3,
parameter_4,
parameter_5,
parameter_6,
parameter_7,
):
pass
def foo2(
parameter_1,
parameter_2,
parameter_3,
parameter_4,
parameter_5,
parameter_6,
parameter_7,
):
pass
def foo3(
parameter_1,
parameter_2,
parameter_3,
parameter_4,
parameter_5,
parameter_6,
parameter_7,
):
pass
def foo4(
parameter_1,
parameter_2,
parameter_3,
parameter_4,
parameter_5,
parameter_6,
parameter_7,
):
pass
# Adding some unformated code covering a wide range of syntaxes.
if True:
# Incorrectly indented prefix comments.
pass
import typing
from typing import (
Any,
)
class MyClass(object): # Trailing comment with extra leading space.
# NOTE: The following indentation is incorrect:
@decor(1 * 3)
def my_func(arg):
pass
try: # Trailing comment with extra leading space.
for i in range(10): # Trailing comment with extra leading space.
while condition:
if something:
then_something()
elif something_else:
then_something_else()
except ValueError as e:
unformatted()
finally:
unformatted()
async def test_async_unformatted(): # Trailing comment with extra leading space.
async for i in some_iter(unformatted): # Trailing comment with extra leading space.
await asyncio.sleep(1)
async with some_context(unformatted):
print("unformatted")
```
## Black Output
```python
# flags: --line-ranges=5-6
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
def foo1(parameter_1, parameter_2, parameter_3, parameter_4, parameter_5, parameter_6, parameter_7): pass
def foo2(
parameter_1,
parameter_2,
parameter_3,
parameter_4,
parameter_5,
parameter_6,
parameter_7,
):
pass
def foo3(
parameter_1,
parameter_2,
parameter_3,
parameter_4,
parameter_5,
parameter_6,
parameter_7,
):
pass
def foo4(parameter_1, parameter_2, parameter_3, parameter_4, parameter_5, parameter_6, parameter_7): pass
# Adding some unformated code covering a wide range of syntaxes.
if True:
# Incorrectly indented prefix comments.
pass
import typing
from typing import (
Any ,
)
class MyClass( object): # Trailing comment with extra leading space.
#NOTE: The following indentation is incorrect:
@decor( 1 * 3 )
def my_func( arg):
pass
try: # Trailing comment with extra leading space.
for i in range(10): # Trailing comment with extra leading space.
while condition:
if something:
then_something( )
elif something_else:
then_something_else( )
except ValueError as e:
unformatted( )
finally:
unformatted( )
async def test_async_unformatted( ): # Trailing comment with extra leading space.
async for i in some_iter( unformatted ): # Trailing comment with extra leading space.
await asyncio.sleep( 1 )
async with some_context( unformatted ):
print( "unformatted" )
```

View file

@ -0,0 +1,79 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/line_ranges_diff_edge_case.py
---
## Input
```python
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
# Reproducible example for https://github.com/psf/black/issues/4033.
# This can be fixed in the future if we use a better diffing algorithm, or make Black
# perform formatting in a single pass.
print ( "format me" )
print ( "format me" )
print ( "format me" )
print ( "format me" )
print ( "format me" )
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,4 +1,3 @@
-# flags: --line-ranges=10-11
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
@@ -6,8 +5,8 @@
# This can be fixed in the future if we use a better diffing algorithm, or make Black
# perform formatting in a single pass.
-print ( "format me" )
print("format me")
print("format me")
print("format me")
print("format me")
+print("format me")
```
## Ruff Output
```python
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
# Reproducible example for https://github.com/psf/black/issues/4033.
# This can be fixed in the future if we use a better diffing algorithm, or make Black
# perform formatting in a single pass.
print("format me")
print("format me")
print("format me")
print("format me")
print("format me")
```
## Black Output
```python
# flags: --line-ranges=10-11
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
# Reproducible example for https://github.com/psf/black/issues/4033.
# This can be fixed in the future if we use a better diffing algorithm, or make Black
# perform formatting in a single pass.
print ( "format me" )
print("format me")
print("format me")
print("format me")
print("format me")
```

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/line_ranges_fmt_off.py
---
## Input
```python
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
# fmt: off
import os
def myfunc( ): # Intentionally unformatted.
pass
# fmt: on
def myfunc( ): # This will not be reformatted.
print( {"also won't be reformatted"} )
# fmt: off
def myfunc( ): # This will not be reformatted.
print( {"also won't be reformatted"} )
def myfunc( ): # This will not be reformatted.
print( {"also won't be reformatted"} )
# fmt: on
def myfunc( ): # This will be reformatted.
print( {"this will be reformatted"} )
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,4 +1,3 @@
-# flags: --line-ranges=7-7 --line-ranges=17-23
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
@@ -9,8 +8,10 @@
# fmt: on
-def myfunc( ): # This will not be reformatted.
- print( {"also won't be reformatted"} )
+def myfunc(): # This will not be reformatted.
+ print({"also won't be reformatted"})
+
+
# fmt: off
def myfunc( ): # This will not be reformatted.
print( {"also won't be reformatted"} )
```
## Ruff Output
```python
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
# fmt: off
import os
def myfunc( ): # Intentionally unformatted.
pass
# fmt: on
def myfunc(): # This will not be reformatted.
print({"also won't be reformatted"})
# fmt: off
def myfunc( ): # This will not be reformatted.
print( {"also won't be reformatted"} )
def myfunc( ): # This will not be reformatted.
print( {"also won't be reformatted"} )
# fmt: on
def myfunc(): # This will be reformatted.
print({"this will be reformatted"})
```
## Black Output
```python
# flags: --line-ranges=7-7 --line-ranges=17-23
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
# fmt: off
import os
def myfunc( ): # Intentionally unformatted.
pass
# fmt: on
def myfunc( ): # This will not be reformatted.
print( {"also won't be reformatted"} )
# fmt: off
def myfunc( ): # This will not be reformatted.
print( {"also won't be reformatted"} )
def myfunc( ): # This will not be reformatted.
print( {"also won't be reformatted"} )
# fmt: on
def myfunc(): # This will be reformatted.
print({"this will be reformatted"})
```

View file

@ -0,0 +1,74 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/line_ranges_fmt_off_decorator.py
---
## Input
```python
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
# Regression test for an edge case involving decorators and fmt: off/on.
class MyClass:
# fmt: off
@decorator ( )
# fmt: on
def method():
print ( "str" )
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,12 +1,10 @@
-# flags: --line-ranges=12-12
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
# Regression test for an edge case involving decorators and fmt: off/on.
class MyClass:
-
# fmt: off
@decorator ( )
# fmt: on
def method():
- print("str")
+ print ( "str" )
```
## Ruff Output
```python
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
# Regression test for an edge case involving decorators and fmt: off/on.
class MyClass:
# fmt: off
@decorator ( )
# fmt: on
def method():
print ( "str" )
```
## Black Output
```python
# flags: --line-ranges=12-12
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
# Regression test for an edge case involving decorators and fmt: off/on.
class MyClass:
# fmt: off
@decorator ( )
# fmt: on
def method():
print("str")
```

View file

@ -0,0 +1,93 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/line_ranges_fmt_off_overlap.py
---
## Input
```python
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
def myfunc( ): # This will not be reformatted.
print( {"also won't be reformatted"} )
# fmt: off
def myfunc( ): # This will not be reformatted.
print( {"also won't be reformatted"} )
def myfunc( ): # This will not be reformatted.
print( {"also won't be reformatted"} )
# fmt: on
def myfunc( ): # This will be reformatted.
print( {"this will be reformatted"} )
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,10 +1,11 @@
-# flags: --line-ranges=11-17
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
-def myfunc( ): # This will not be reformatted.
- print( {"also won't be reformatted"} )
+def myfunc(): # This will not be reformatted.
+ print({"also won't be reformatted"})
+
+
# fmt: off
def myfunc( ): # This will not be reformatted.
print( {"also won't be reformatted"} )
```
## Ruff Output
```python
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
def myfunc(): # This will not be reformatted.
print({"also won't be reformatted"})
# fmt: off
def myfunc( ): # This will not be reformatted.
print( {"also won't be reformatted"} )
def myfunc( ): # This will not be reformatted.
print( {"also won't be reformatted"} )
# fmt: on
def myfunc(): # This will be reformatted.
print({"this will be reformatted"})
```
## Black Output
```python
# flags: --line-ranges=11-17
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
def myfunc( ): # This will not be reformatted.
print( {"also won't be reformatted"} )
# fmt: off
def myfunc( ): # This will not be reformatted.
print( {"also won't be reformatted"} )
def myfunc( ): # This will not be reformatted.
print( {"also won't be reformatted"} )
# fmt: on
def myfunc(): # This will be reformatted.
print({"this will be reformatted"})
```

View file

@ -0,0 +1,72 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/line_ranges_indentation.py
---
## Input
```python
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
if cond1:
print("first")
if cond2:
print("second")
else:
print("else")
if another_cond:
print("will not be changed")
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,4 +1,3 @@
-# flags: --line-ranges=5-5
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
if cond1:
@@ -9,4 +8,4 @@
print("else")
if another_cond:
- print("will not be changed")
+ print("will not be changed")
```
## Ruff Output
```python
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
if cond1:
print("first")
if cond2:
print("second")
else:
print("else")
if another_cond:
print("will not be changed")
```
## Black Output
```python
# flags: --line-ranges=5-5
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
if cond1:
print("first")
if cond2:
print("second")
else:
print("else")
if another_cond:
print("will not be changed")
```

View file

@ -0,0 +1,77 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/line_ranges_two_passes.py
---
## Input
```python
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
# This is a specific case for Black's two-pass formatting behavior in `format_str`.
# The second pass must respect the line ranges before the first pass.
def restrict_to_this_line(arg1,
arg2,
arg3):
print ( "This should not be formatted." )
print ( "Note that in the second pass, the original line range 9-11 will cover these print lines.")
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,4 +1,3 @@
-# flags: --line-ranges=9-11
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
@@ -7,5 +6,7 @@
def restrict_to_this_line(arg1, arg2, arg3):
- print ( "This should not be formatted." )
- print ( "Note that in the second pass, the original line range 9-11 will cover these print lines.")
+ print("This should not be formatted.")
+ print(
+ "Note that in the second pass, the original line range 9-11 will cover these print lines."
+ )
```
## Ruff Output
```python
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
# This is a specific case for Black's two-pass formatting behavior in `format_str`.
# The second pass must respect the line ranges before the first pass.
def restrict_to_this_line(arg1, arg2, arg3):
print("This should not be formatted.")
print(
"Note that in the second pass, the original line range 9-11 will cover these print lines."
)
```
## Black Output
```python
# flags: --line-ranges=9-11
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
# This is a specific case for Black's two-pass formatting behavior in `format_str`.
# The second pass must respect the line ranges before the first pass.
def restrict_to_this_line(arg1, arg2, arg3):
print ( "This should not be formatted." )
print ( "Note that in the second pass, the original line range 9-11 will cover these print lines.")
```

View file

@ -0,0 +1,60 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/line_ranges_unwrapping.py
---
## Input
```python
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
alist = [
1, 2
]
adict = {
"key" : "value"
}
func_call (
arg = value
)
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,4 +1,3 @@
-# flags: --line-ranges=5-5 --line-ranges=9-9 --line-ranges=13-13
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
alist = [1, 2]
```
## Ruff Output
```python
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
alist = [1, 2]
adict = {"key": "value"}
func_call(arg=value)
```
## Black Output
```python
# flags: --line-ranges=5-5 --line-ranges=9-9 --line-ranges=13-13
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
# flag above as it's formatting specifically these lines.
alist = [1, 2]
adict = {"key": "value"}
func_call(arg=value)
```

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/miscellaneous/long_strings_flag_disabled.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/long_strings_flag_disabled.py
---
## Input

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/multiline_consecutive_open_parentheses_ignore.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/multiline_consecutive_open_parentheses_ignore.py
---
## Input

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/nested_stub.pyi
---
## Input
```python
import sys
class Outer:
class InnerStub: ...
outer_attr_after_inner_stub: int
class Inner:
inner_attr: int
outer_attr: int
if sys.version_info > (3, 7):
if sys.platform == "win32":
assignment = 1
def function_definition(self): ...
def f1(self) -> str: ...
if sys.platform != "win32":
def function_definition(self): ...
assignment = 1
def f2(self) -> str: ...
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,7 +1,9 @@
import sys
+
class Outer:
class InnerStub: ...
+
outer_attr_after_inner_stub: int
class Inner:
@@ -9,14 +11,19 @@
outer_attr: int
+
if sys.version_info > (3, 7):
if sys.platform == "win32":
assignment = 1
+
def function_definition(self): ...
def f1(self) -> str: ...
+
if sys.platform != "win32":
+
def function_definition(self): ...
+
assignment = 1
def f2(self) -> str: ...
```
## Ruff Output
```python
import sys
class Outer:
class InnerStub: ...
outer_attr_after_inner_stub: int
class Inner:
inner_attr: int
outer_attr: int
if sys.version_info > (3, 7):
if sys.platform == "win32":
assignment = 1
def function_definition(self): ...
def f1(self) -> str: ...
if sys.platform != "win32":
def function_definition(self): ...
assignment = 1
def f2(self) -> str: ...
```
## Black Output
```python
import sys
class Outer:
class InnerStub: ...
outer_attr_after_inner_stub: int
class Inner:
inner_attr: int
outer_attr: int
if sys.version_info > (3, 7):
if sys.platform == "win32":
assignment = 1
def function_definition(self): ...
def f1(self) -> str: ...
if sys.platform != "win32":
def function_definition(self): ...
assignment = 1
def f2(self) -> str: ...
```

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/py_310/pattern_matching_style.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/pattern_matching_style.py
---
## Input

View file

@ -0,0 +1,370 @@
---
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
---
## Input
```python
# This has always worked
z= Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong
# "AnnAssign"s now also work
z: Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong
z: (Short
| Short2
| Short3
| Short4)
z: (int)
z: ((int))
z: Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong = 7
z: (Short
| Short2
| Short3
| Short4) = 8
z: (int) = 2.3
z: ((int)) = foo()
# In case I go for not enforcing parantheses, this might get improved at the same time
x = (
z
== 9999999999999999999999999999999999999999
| 9999999999999999999999999999999999999999
| 9999999999999999999999999999999999999999
| 9999999999999999999999999999999999999999,
y
== 9999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999,
)
x = (
z == (9999999999999999999999999999999999999999
| 9999999999999999999999999999999999999999
| 9999999999999999999999999999999999999999
| 9999999999999999999999999999999999999999),
y == (9999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999),
)
# handle formatting of "tname"s in parameter list
# remove unnecessary paren
def foo(i: (int)) -> None: ...
# this is a syntax error in the type annotation according to mypy, but it's not invalid *python* code, so make sure we don't mess with it and make it so.
def foo(i: (int,)) -> None: ...
def foo(
i: int,
x: Loooooooooooooooooooooooong
| Looooooooooooooooong
| Looooooooooooooooooooong
| Looooooong,
*,
s: str,
) -> None:
pass
@app.get("/path/")
async def foo(
q: str
| None = Query(None, title="Some long title", description="Some long description")
):
pass
def f(
max_jobs: int
| None = Option(
None, help="Maximum number of jobs to launch. And some additional text."
),
another_option: bool = False
):
...
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -7,26 +7,16 @@
)
# "AnnAssign"s now also work
-z: (
- Loooooooooooooooooooooooong
- | Loooooooooooooooooooooooong
- | Loooooooooooooooooooooooong
- | Loooooooooooooooooooooooong
-)
-z: Short | Short2 | Short3 | Short4
-z: int
-z: int
+z: Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong
+z: (Short | Short2 | Short3 | Short4)
+z: (int)
+z: (int)
-z: (
- Loooooooooooooooooooooooong
- | Loooooooooooooooooooooooong
- | Loooooooooooooooooooooooong
- | Loooooooooooooooooooooooong
-) = 7
-z: Short | Short2 | Short3 | Short4 = 8
-z: int = 2.3
-z: int = foo()
+z: Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong = 7
+z: (Short | Short2 | Short3 | Short4) = 8
+z: (int) = 2.3
+z: (int) = foo()
# In case I go for not enforcing parantheses, this might get improved at the same time
x = (
@@ -63,7 +53,7 @@
# remove unnecessary paren
-def foo(i: int) -> None: ...
+def foo(i: (int)) -> None: ...
# this is a syntax error in the type annotation according to mypy, but it's not invalid *python* code, so make sure we don't mess with it and make it so.
@@ -72,12 +62,10 @@
def foo(
i: int,
- x: (
- Loooooooooooooooooooooooong
- | Looooooooooooooooong
- | Looooooooooooooooooooong
- | Looooooong
- ),
+ x: Loooooooooooooooooooooooong
+ | Looooooooooooooooong
+ | Looooooooooooooooooooong
+ | Looooooong,
*,
s: str,
) -> None:
@@ -88,7 +76,7 @@
async def foo(
q: str | None = Query(
None, title="Some long title", description="Some long description"
- )
+ ),
):
pass
```
## Ruff Output
```python
# This has always worked
z = (
Loooooooooooooooooooooooong
| Loooooooooooooooooooooooong
| Loooooooooooooooooooooooong
| Loooooooooooooooooooooooong
)
# "AnnAssign"s now also work
z: Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong
z: (Short | Short2 | Short3 | Short4)
z: (int)
z: (int)
z: Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong = 7
z: (Short | Short2 | Short3 | Short4) = 8
z: (int) = 2.3
z: (int) = foo()
# In case I go for not enforcing parantheses, this might get improved at the same time
x = (
z
== 9999999999999999999999999999999999999999
| 9999999999999999999999999999999999999999
| 9999999999999999999999999999999999999999
| 9999999999999999999999999999999999999999,
y
== 9999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999,
)
x = (
z
== (
9999999999999999999999999999999999999999
| 9999999999999999999999999999999999999999
| 9999999999999999999999999999999999999999
| 9999999999999999999999999999999999999999
),
y
== (
9999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999
),
)
# handle formatting of "tname"s in parameter list
# remove unnecessary paren
def foo(i: (int)) -> None: ...
# this is a syntax error in the type annotation according to mypy, but it's not invalid *python* code, so make sure we don't mess with it and make it so.
def foo(i: (int,)) -> None: ...
def foo(
i: int,
x: Loooooooooooooooooooooooong
| Looooooooooooooooong
| Looooooooooooooooooooong
| Looooooong,
*,
s: str,
) -> None:
pass
@app.get("/path/")
async def foo(
q: str | None = Query(
None, title="Some long title", description="Some long description"
),
):
pass
def f(
max_jobs: int | None = Option(
None, help="Maximum number of jobs to launch. And some additional text."
),
another_option: bool = False,
): ...
```
## Black Output
```python
# This has always worked
z = (
Loooooooooooooooooooooooong
| Loooooooooooooooooooooooong
| Loooooooooooooooooooooooong
| Loooooooooooooooooooooooong
)
# "AnnAssign"s now also work
z: (
Loooooooooooooooooooooooong
| Loooooooooooooooooooooooong
| Loooooooooooooooooooooooong
| Loooooooooooooooooooooooong
)
z: Short | Short2 | Short3 | Short4
z: int
z: int
z: (
Loooooooooooooooooooooooong
| Loooooooooooooooooooooooong
| Loooooooooooooooooooooooong
| Loooooooooooooooooooooooong
) = 7
z: Short | Short2 | Short3 | Short4 = 8
z: int = 2.3
z: int = foo()
# In case I go for not enforcing parantheses, this might get improved at the same time
x = (
z
== 9999999999999999999999999999999999999999
| 9999999999999999999999999999999999999999
| 9999999999999999999999999999999999999999
| 9999999999999999999999999999999999999999,
y
== 9999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999,
)
x = (
z
== (
9999999999999999999999999999999999999999
| 9999999999999999999999999999999999999999
| 9999999999999999999999999999999999999999
| 9999999999999999999999999999999999999999
),
y
== (
9999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999
),
)
# handle formatting of "tname"s in parameter list
# remove unnecessary paren
def foo(i: int) -> None: ...
# this is a syntax error in the type annotation according to mypy, but it's not invalid *python* code, so make sure we don't mess with it and make it so.
def foo(i: (int,)) -> None: ...
def foo(
i: int,
x: (
Loooooooooooooooooooooooong
| Looooooooooooooooong
| Looooooooooooooooooooong
| Looooooong
),
*,
s: str,
) -> None:
pass
@app.get("/path/")
async def foo(
q: str | None = Query(
None, title="Some long title", description="Some long description"
)
):
pass
def f(
max_jobs: int | None = Option(
None, help="Maximum number of jobs to launch. And some additional text."
),
another_option: bool = False,
): ...
```

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/py_310/pep_572_py310.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/pep_572_py310.py
---
## Input

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/py_38/pep_572_remove_parens.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/pep_572_remove_parens.py
---
## Input

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/miscellaneous/power_op_newline.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/power_op_newline.py
---
## Input

View file

@ -0,0 +1,218 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_allow_empty_first_line_in_special_cases.py
---
## Input
```python
def foo():
"""
Docstring
"""
# Here we go
if x:
# This is also now fine
a = 123
else:
# But not necessary
a = 123
if y:
while True:
"""
Long comment here
"""
a = 123
if z:
for _ in range(100):
a = 123
else:
try:
# this should be ok
a = 123
except:
"""also this"""
a = 123
def bar():
if x:
a = 123
def baz():
# OK
if x:
a = 123
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -5,7 +5,6 @@
# Here we go
if x:
-
# This is also now fine
a = 123
@@ -14,38 +13,30 @@
a = 123
if y:
-
while True:
-
"""
Long comment here
"""
a = 123
if z:
-
for _ in range(100):
a = 123
else:
-
try:
-
# this should be ok
a = 123
except:
-
"""also this"""
a = 123
def bar():
-
if x:
a = 123
def baz():
-
# OK
if x:
a = 123
```
## Ruff Output
```python
def foo():
"""
Docstring
"""
# Here we go
if x:
# This is also now fine
a = 123
else:
# But not necessary
a = 123
if y:
while True:
"""
Long comment here
"""
a = 123
if z:
for _ in range(100):
a = 123
else:
try:
# this should be ok
a = 123
except:
"""also this"""
a = 123
def bar():
if x:
a = 123
def baz():
# OK
if x:
a = 123
```
## Black Output
```python
def foo():
"""
Docstring
"""
# Here we go
if x:
# This is also now fine
a = 123
else:
# But not necessary
a = 123
if y:
while True:
"""
Long comment here
"""
a = 123
if z:
for _ in range(100):
a = 123
else:
try:
# this should be ok
a = 123
except:
"""also this"""
a = 123
def bar():
if x:
a = 123
def baz():
# OK
if x:
a = 123
```

View file

@ -0,0 +1,219 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_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
)
# long arguments
normal_name = normal_function_name(
"but with super long string arguments that on their own exceed the line limit so there's no way it can ever fit",
"eggs with spam and eggs and spam with eggs with spam and eggs and spam with eggs with spam and eggs and spam with eggs",
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it=0,
)
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
```
## 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
)
@@ -35,10 +29,8 @@
)
# long arguments
normal_name = normal_function_name(
- "but with super long string arguments that on their own exceed the line limit so"
- " there's no way it can ever fit",
- "eggs with spam and eggs and spam with eggs with spam and eggs and spam with eggs"
- " with spam and eggs and spam with eggs",
+ "but with super long string arguments that on their own exceed the line limit so there's no way it can ever fit",
+ "eggs with spam and eggs and spam with eggs with spam and eggs and spam with eggs with spam and eggs and spam with eggs",
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it=0,
)
string_variable_name = "a string that is waaaaaaaayyyyyyyy too long, even in parens, there's nothing you can do" # noqa
```
## 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
)
)
# long arguments
normal_name = normal_function_name(
"but with super long string arguments that on their own exceed the line limit so there's no way it can ever fit",
"eggs with spam and eggs and spam with eggs with spam and eggs and spam with eggs with spam and eggs and spam with eggs",
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it=0,
)
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,
)
```
## 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
)
)
# long arguments
normal_name = normal_function_name(
"but with super long string arguments that on their own exceed the line limit so"
" there's no way it can ever fit",
"eggs with spam and eggs and spam with eggs with spam and eggs and spam with eggs"
" with spam and eggs and spam with eggs",
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it=0,
)
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,
)
```

View file

@ -0,0 +1,600 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_comments7.py
---
## Input
```python
from .config import (
Any,
Bool,
ConfigType,
ConfigTypeAttributes,
Int,
Path,
# String,
# resolve_to_config_type,
# DEFAULT_TYPE_ATTRIBUTES,
)
from .config import (
Any,
Bool,
ConfigType,
ConfigTypeAttributes,
Int,
no_comma_here_yet
# and some comments,
# resolve_to_config_type,
# DEFAULT_TYPE_ATTRIBUTES,
)
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
MyLovelyCompanyTeamProjectComponent # NOT DRY
)
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
MyLovelyCompanyTeamProjectComponent as component # DRY
)
result = 1 # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
result = (
1 # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
)
result = (
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # aaa
)
result = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # aaa
def func():
c = call(
0.0123,
0.0456,
0.0789,
0.0123,
0.0789,
a[-1], # type: ignore
)
c = call(
0.0123,
0.0456,
0.0789,
0.0123,
0.0789,
a[-1] # type: ignore
)
c = call(
0.0123,
0.0456,
0.0789,
0.0123,
0.0456,
0.0789,
0.0123,
0.0456,
0.0789,
a[-1] # type: ignore
)
# The type: ignore exception only applies to line length, not
# other types of formatting.
c = call(
"aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", # type: ignore
"aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa"
)
class C:
@pytest.mark.parametrize(
("post_data", "message"),
[
# metadata_version errors.
(
{},
"None is an invalid value for Metadata-Version. Error: This field is"
" required. see"
" https://packaging.python.org/specifications/core-metadata"
),
(
{"metadata_version": "-1"},
"'-1' is an invalid value for Metadata-Version. Error: Unknown Metadata"
" Version see"
" https://packaging.python.org/specifications/core-metadata"
),
# name errors.
(
{"metadata_version": "1.2"},
"'' is an invalid value for Name. Error: This field is required. see"
" https://packaging.python.org/specifications/core-metadata"
),
(
{"metadata_version": "1.2", "name": "foo-"},
"'foo-' is an invalid value for Name. Error: Must start and end with a"
" letter or numeral and contain only ascii numeric and '.', '_' and"
" '-'. see https://packaging.python.org/specifications/core-metadata"
),
# version errors.
(
{"metadata_version": "1.2", "name": "example"},
"'' is an invalid value for Version. Error: This field is required. see"
" https://packaging.python.org/specifications/core-metadata"
),
(
{"metadata_version": "1.2", "name": "example", "version": "dog"},
"'dog' is an invalid value for Version. Error: Must start and end with"
" a letter or numeral and contain only ascii numeric and '.', '_' and"
" '-'. see https://packaging.python.org/specifications/core-metadata"
)
]
)
def test_fails_invalid_post_data(
self, pyramid_config, db_request, post_data, message
):
...
square = Square(4) # type: Optional[Square]
# Regression test for https://github.com/psf/black/issues/3756.
[
(
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
),
]
[
( # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
),
]
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -34,13 +34,9 @@
result = 1 # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-result = ( # aaa
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
-)
+result = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # aaa
-result = ( # aaa
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
-)
+result = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # aaa
def func():
@@ -52,12 +48,19 @@
0.0789,
a[-1], # type: ignore
)
- c = call(0.0123, 0.0456, 0.0789, 0.0123, 0.0789, a[-1]) # type: ignore
c = call(
0.0123,
0.0456,
0.0789,
0.0123,
+ 0.0789,
+ a[-1], # type: ignore
+ )
+ c = call(
+ 0.0123,
+ 0.0456,
+ 0.0789,
+ 0.0123,
0.0456,
0.0789,
0.0123,
@@ -91,53 +94,39 @@
# metadata_version errors.
(
{},
- (
- "None is an invalid value for Metadata-Version. Error: This field"
- " is required. see"
- " https://packaging.python.org/specifications/core-metadata"
- ),
+ "None is an invalid value for Metadata-Version. Error: This field is"
+ " required. see"
+ " https://packaging.python.org/specifications/core-metadata",
),
(
{"metadata_version": "-1"},
- (
- "'-1' is an invalid value for Metadata-Version. Error: Unknown"
- " Metadata Version see"
- " https://packaging.python.org/specifications/core-metadata"
- ),
+ "'-1' is an invalid value for Metadata-Version. Error: Unknown Metadata"
+ " Version see"
+ " https://packaging.python.org/specifications/core-metadata",
),
# name errors.
(
{"metadata_version": "1.2"},
- (
- "'' is an invalid value for Name. Error: This field is required."
- " see https://packaging.python.org/specifications/core-metadata"
- ),
+ "'' is an invalid value for Name. Error: This field is required. see"
+ " https://packaging.python.org/specifications/core-metadata",
),
(
{"metadata_version": "1.2", "name": "foo-"},
- (
- "'foo-' is an invalid value for Name. Error: Must start and end"
- " with a letter or numeral and contain only ascii numeric and '.',"
- " '_' and '-'. see"
- " https://packaging.python.org/specifications/core-metadata"
- ),
+ "'foo-' is an invalid value for Name. Error: Must start and end with a"
+ " letter or numeral and contain only ascii numeric and '.', '_' and"
+ " '-'. see https://packaging.python.org/specifications/core-metadata",
),
# version errors.
(
{"metadata_version": "1.2", "name": "example"},
- (
- "'' is an invalid value for Version. Error: This field is required."
- " see https://packaging.python.org/specifications/core-metadata"
- ),
+ "'' is an invalid value for Version. Error: This field is required. see"
+ " https://packaging.python.org/specifications/core-metadata",
),
(
{"metadata_version": "1.2", "name": "example", "version": "dog"},
- (
- "'dog' is an invalid value for Version. Error: Must start and end"
- " with a letter or numeral and contain only ascii numeric and '.',"
- " '_' and '-'. see"
- " https://packaging.python.org/specifications/core-metadata"
- ),
+ "'dog' is an invalid value for Version. Error: Must start and end with"
+ " a letter or numeral and contain only ascii numeric and '.', '_' and"
+ " '-'. see https://packaging.python.org/specifications/core-metadata",
),
],
)
@@ -150,8 +139,8 @@
# Regression test for https://github.com/psf/black/issues/3756.
[
- ( # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ (
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
),
]
[
```
## Ruff Output
```python
from .config import (
Any,
Bool,
ConfigType,
ConfigTypeAttributes,
Int,
Path,
# String,
# resolve_to_config_type,
# DEFAULT_TYPE_ATTRIBUTES,
)
from .config import (
Any,
Bool,
ConfigType,
ConfigTypeAttributes,
Int,
no_comma_here_yet,
# and some comments,
# resolve_to_config_type,
# DEFAULT_TYPE_ATTRIBUTES,
)
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
MyLovelyCompanyTeamProjectComponent, # NOT DRY
)
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
MyLovelyCompanyTeamProjectComponent as component, # DRY
)
result = 1 # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
result = 1 # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
result = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # aaa
result = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # aaa
def func():
c = call(
0.0123,
0.0456,
0.0789,
0.0123,
0.0789,
a[-1], # type: ignore
)
c = call(
0.0123,
0.0456,
0.0789,
0.0123,
0.0789,
a[-1], # type: ignore
)
c = call(
0.0123,
0.0456,
0.0789,
0.0123,
0.0456,
0.0789,
0.0123,
0.0456,
0.0789,
a[-1], # type: ignore
)
# The type: ignore exception only applies to line length, not
# other types of formatting.
c = call(
"aaaaaaaa",
"aaaaaaaa",
"aaaaaaaa",
"aaaaaaaa",
"aaaaaaaa",
"aaaaaaaa", # type: ignore
"aaaaaaaa",
"aaaaaaaa",
"aaaaaaaa",
"aaaaaaaa",
"aaaaaaaa",
"aaaaaaaa",
)
class C:
@pytest.mark.parametrize(
("post_data", "message"),
[
# metadata_version errors.
(
{},
"None is an invalid value for Metadata-Version. Error: This field is"
" required. see"
" https://packaging.python.org/specifications/core-metadata",
),
(
{"metadata_version": "-1"},
"'-1' is an invalid value for Metadata-Version. Error: Unknown Metadata"
" Version see"
" https://packaging.python.org/specifications/core-metadata",
),
# name errors.
(
{"metadata_version": "1.2"},
"'' is an invalid value for Name. Error: This field is required. see"
" https://packaging.python.org/specifications/core-metadata",
),
(
{"metadata_version": "1.2", "name": "foo-"},
"'foo-' is an invalid value for Name. Error: Must start and end with a"
" letter or numeral and contain only ascii numeric and '.', '_' and"
" '-'. see https://packaging.python.org/specifications/core-metadata",
),
# version errors.
(
{"metadata_version": "1.2", "name": "example"},
"'' is an invalid value for Version. Error: This field is required. see"
" https://packaging.python.org/specifications/core-metadata",
),
(
{"metadata_version": "1.2", "name": "example", "version": "dog"},
"'dog' is an invalid value for Version. Error: Must start and end with"
" a letter or numeral and contain only ascii numeric and '.', '_' and"
" '-'. see https://packaging.python.org/specifications/core-metadata",
),
],
)
def test_fails_invalid_post_data(
self, pyramid_config, db_request, post_data, message
): ...
square = Square(4) # type: Optional[Square]
# Regression test for https://github.com/psf/black/issues/3756.
[
(
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
),
]
[
( # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
),
]
```
## Black Output
```python
from .config import (
Any,
Bool,
ConfigType,
ConfigTypeAttributes,
Int,
Path,
# String,
# resolve_to_config_type,
# DEFAULT_TYPE_ATTRIBUTES,
)
from .config import (
Any,
Bool,
ConfigType,
ConfigTypeAttributes,
Int,
no_comma_here_yet,
# and some comments,
# resolve_to_config_type,
# DEFAULT_TYPE_ATTRIBUTES,
)
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
MyLovelyCompanyTeamProjectComponent, # NOT DRY
)
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
MyLovelyCompanyTeamProjectComponent as component, # DRY
)
result = 1 # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
result = 1 # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
result = ( # aaa
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
)
result = ( # aaa
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
)
def func():
c = call(
0.0123,
0.0456,
0.0789,
0.0123,
0.0789,
a[-1], # type: ignore
)
c = call(0.0123, 0.0456, 0.0789, 0.0123, 0.0789, a[-1]) # type: ignore
c = call(
0.0123,
0.0456,
0.0789,
0.0123,
0.0456,
0.0789,
0.0123,
0.0456,
0.0789,
a[-1], # type: ignore
)
# The type: ignore exception only applies to line length, not
# other types of formatting.
c = call(
"aaaaaaaa",
"aaaaaaaa",
"aaaaaaaa",
"aaaaaaaa",
"aaaaaaaa",
"aaaaaaaa", # type: ignore
"aaaaaaaa",
"aaaaaaaa",
"aaaaaaaa",
"aaaaaaaa",
"aaaaaaaa",
"aaaaaaaa",
)
class C:
@pytest.mark.parametrize(
("post_data", "message"),
[
# metadata_version errors.
(
{},
(
"None is an invalid value for Metadata-Version. Error: This field"
" is required. see"
" https://packaging.python.org/specifications/core-metadata"
),
),
(
{"metadata_version": "-1"},
(
"'-1' is an invalid value for Metadata-Version. Error: Unknown"
" Metadata Version see"
" https://packaging.python.org/specifications/core-metadata"
),
),
# name errors.
(
{"metadata_version": "1.2"},
(
"'' is an invalid value for Name. Error: This field is required."
" see https://packaging.python.org/specifications/core-metadata"
),
),
(
{"metadata_version": "1.2", "name": "foo-"},
(
"'foo-' is an invalid value for Name. Error: Must start and end"
" with a letter or numeral and contain only ascii numeric and '.',"
" '_' and '-'. see"
" https://packaging.python.org/specifications/core-metadata"
),
),
# version errors.
(
{"metadata_version": "1.2", "name": "example"},
(
"'' is an invalid value for Version. Error: This field is required."
" see https://packaging.python.org/specifications/core-metadata"
),
),
(
{"metadata_version": "1.2", "name": "example", "version": "dog"},
(
"'dog' is an invalid value for Version. Error: Must start and end"
" with a letter or numeral and contain only ascii numeric and '.',"
" '_' and '-'. see"
" https://packaging.python.org/specifications/core-metadata"
),
),
],
)
def test_fails_invalid_post_data(
self, pyramid_config, db_request, post_data, message
): ...
square = Square(4) # type: Optional[Square]
# Regression test for https://github.com/psf/black/issues/3756.
[
( # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
),
]
[
( # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
),
]
```

View file

@ -0,0 +1,342 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_context_managers_39.py
---
## Input
```python
with \
make_context_manager1() as cm1, \
make_context_manager2() as cm2, \
make_context_manager3() as cm3, \
make_context_manager4() as cm4 \
:
pass
# Leading comment
with \
make_context_manager1() as cm1, \
make_context_manager2(), \
make_context_manager3() as cm3, \
make_context_manager4() \
:
pass
with \
new_new_new1() as cm1, \
new_new_new2() \
:
pass
with (
new_new_new1() as cm1,
new_new_new2()
):
pass
# Leading comment.
with (
# First comment.
new_new_new1() as cm1,
# Second comment.
new_new_new2()
# Last comment.
):
pass
with \
this_is_a_very_long_call(looong_arg1=looong_value1, looong_arg2=looong_value2) as cm1, \
this_is_a_very_long_call(looong_arg1=looong_value1, looong_arg2=looong_value2, looong_arg3=looong_value3, looong_arg4=looong_value4) as cm2 \
:
pass
with mock.patch.object(
self.my_runner, "first_method", autospec=True
) as mock_run_adb, mock.patch.object(
self.my_runner, "second_method", autospec=True, return_value="foo"
):
pass
with xxxxxxxx.some_kind_of_method(
some_argument=[
"first",
"second",
"third",
]
).another_method() as cmd:
pass
async def func():
async with \
make_context_manager1() as cm1, \
make_context_manager2() as cm2, \
make_context_manager3() as cm3, \
make_context_manager4() as cm4 \
:
pass
async with some_function(
argument1, argument2, argument3="some_value"
) as some_cm, some_other_function(
argument1, argument2, argument3="some_value"
):
pass
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,19 +1,9 @@
-with (
- make_context_manager1() as cm1,
- make_context_manager2() as cm2,
- make_context_manager3() as cm3,
- make_context_manager4() as cm4,
-):
+with make_context_manager1() as cm1, make_context_manager2() as cm2, make_context_manager3() as cm3, make_context_manager4() as cm4:
pass
# Leading comment
-with (
- make_context_manager1() as cm1,
- make_context_manager2(),
- make_context_manager3() as cm3,
- make_context_manager4(),
-):
+with make_context_manager1() as cm1, make_context_manager2(), make_context_manager3() as cm3, make_context_manager4():
pass
@@ -36,25 +26,21 @@
pass
-with (
- this_is_a_very_long_call(
- looong_arg1=looong_value1, looong_arg2=looong_value2
- ) as cm1,
- this_is_a_very_long_call(
- looong_arg1=looong_value1,
- looong_arg2=looong_value2,
- looong_arg3=looong_value3,
- looong_arg4=looong_value4,
- ) as cm2,
-):
+with this_is_a_very_long_call(
+ looong_arg1=looong_value1, looong_arg2=looong_value2
+) as cm1, this_is_a_very_long_call(
+ looong_arg1=looong_value1,
+ looong_arg2=looong_value2,
+ looong_arg3=looong_value3,
+ looong_arg4=looong_value4,
+) as cm2:
pass
-with (
- mock.patch.object(self.my_runner, "first_method", autospec=True) as mock_run_adb,
- mock.patch.object(
- self.my_runner, "second_method", autospec=True, return_value="foo"
- ),
+with mock.patch.object(
+ self.my_runner, "first_method", autospec=True
+) as mock_run_adb, mock.patch.object(
+ self.my_runner, "second_method", autospec=True, return_value="foo"
):
pass
@@ -70,16 +56,10 @@
async def func():
- async with (
- make_context_manager1() as cm1,
- make_context_manager2() as cm2,
- make_context_manager3() as cm3,
- make_context_manager4() as cm4,
- ):
+ async with make_context_manager1() as cm1, make_context_manager2() as cm2, make_context_manager3() as cm3, make_context_manager4() as cm4:
pass
- async with (
- some_function(argument1, argument2, argument3="some_value") as some_cm,
- some_other_function(argument1, argument2, argument3="some_value"),
- ):
+ async with some_function(
+ argument1, argument2, argument3="some_value"
+ ) as some_cm, some_other_function(argument1, argument2, argument3="some_value"):
pass
```
## Ruff Output
```python
with make_context_manager1() as cm1, make_context_manager2() as cm2, make_context_manager3() as cm3, make_context_manager4() as cm4:
pass
# Leading comment
with make_context_manager1() as cm1, make_context_manager2(), make_context_manager3() as cm3, make_context_manager4():
pass
with new_new_new1() as cm1, new_new_new2():
pass
with new_new_new1() as cm1, new_new_new2():
pass
# Leading comment.
with (
# First comment.
new_new_new1() as cm1,
# Second comment.
new_new_new2(),
# Last comment.
):
pass
with this_is_a_very_long_call(
looong_arg1=looong_value1, looong_arg2=looong_value2
) as cm1, this_is_a_very_long_call(
looong_arg1=looong_value1,
looong_arg2=looong_value2,
looong_arg3=looong_value3,
looong_arg4=looong_value4,
) as cm2:
pass
with mock.patch.object(
self.my_runner, "first_method", autospec=True
) as mock_run_adb, mock.patch.object(
self.my_runner, "second_method", autospec=True, return_value="foo"
):
pass
with xxxxxxxx.some_kind_of_method(
some_argument=[
"first",
"second",
"third",
]
).another_method() as cmd:
pass
async def func():
async with make_context_manager1() as cm1, make_context_manager2() as cm2, make_context_manager3() as cm3, make_context_manager4() as cm4:
pass
async with some_function(
argument1, argument2, argument3="some_value"
) as some_cm, some_other_function(argument1, argument2, argument3="some_value"):
pass
```
## Black Output
```python
with (
make_context_manager1() as cm1,
make_context_manager2() as cm2,
make_context_manager3() as cm3,
make_context_manager4() as cm4,
):
pass
# Leading comment
with (
make_context_manager1() as cm1,
make_context_manager2(),
make_context_manager3() as cm3,
make_context_manager4(),
):
pass
with new_new_new1() as cm1, new_new_new2():
pass
with new_new_new1() as cm1, new_new_new2():
pass
# Leading comment.
with (
# First comment.
new_new_new1() as cm1,
# Second comment.
new_new_new2(),
# Last comment.
):
pass
with (
this_is_a_very_long_call(
looong_arg1=looong_value1, looong_arg2=looong_value2
) as cm1,
this_is_a_very_long_call(
looong_arg1=looong_value1,
looong_arg2=looong_value2,
looong_arg3=looong_value3,
looong_arg4=looong_value4,
) as cm2,
):
pass
with (
mock.patch.object(self.my_runner, "first_method", autospec=True) as mock_run_adb,
mock.patch.object(
self.my_runner, "second_method", autospec=True, return_value="foo"
),
):
pass
with xxxxxxxx.some_kind_of_method(
some_argument=[
"first",
"second",
"third",
]
).another_method() as cmd:
pass
async def func():
async with (
make_context_manager1() as cm1,
make_context_manager2() as cm2,
make_context_manager3() as cm3,
make_context_manager4() as cm4,
):
pass
async with (
some_function(argument1, argument2, argument3="some_value") as some_cm,
some_other_function(argument1, argument2, argument3="some_value"),
):
pass
```

View file

@ -0,0 +1,79 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_context_managers_autodetect_310.py
---
## Input
```python
# This file uses pattern matching introduced in Python 3.10.
match http_code:
case 404:
print("Not found")
with \
make_context_manager1() as cm1, \
make_context_manager2() as cm2, \
make_context_manager3() as cm3, \
make_context_manager4() as cm4 \
:
pass
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -6,10 +6,5 @@
print("Not found")
-with (
- make_context_manager1() as cm1,
- make_context_manager2() as cm2,
- make_context_manager3() as cm3,
- make_context_manager4() as cm4,
-):
+with make_context_manager1() as cm1, make_context_manager2() as cm2, make_context_manager3() as cm3, make_context_manager4() as cm4:
pass
```
## Ruff Output
```python
# This file uses pattern matching introduced in Python 3.10.
match http_code:
case 404:
print("Not found")
with make_context_manager1() as cm1, make_context_manager2() as cm2, make_context_manager3() as cm3, make_context_manager4() as cm4:
pass
```
## Black Output
```python
# This file uses pattern matching introduced in Python 3.10.
match http_code:
case 404:
print("Not found")
with (
make_context_manager1() as cm1,
make_context_manager2() as cm2,
make_context_manager3() as cm3,
make_context_manager4() as cm4,
):
pass
```

View file

@ -0,0 +1,82 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_context_managers_autodetect_311.py
---
## Input
```python
# This file uses except* clause in Python 3.11.
try:
some_call()
except* Error as e:
pass
with \
make_context_manager1() as cm1, \
make_context_manager2() as cm2, \
make_context_manager3() as cm3, \
make_context_manager4() as cm4 \
:
pass
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -7,10 +7,5 @@
pass
-with (
- make_context_manager1() as cm1,
- make_context_manager2() as cm2,
- make_context_manager3() as cm3,
- make_context_manager4() as cm4,
-):
+with make_context_manager1() as cm1, make_context_manager2() as cm2, make_context_manager3() as cm3, make_context_manager4() as cm4:
pass
```
## Ruff Output
```python
# This file uses except* clause in Python 3.11.
try:
some_call()
except* Error as e:
pass
with make_context_manager1() as cm1, make_context_manager2() as cm2, make_context_manager3() as cm3, make_context_manager4() as cm4:
pass
```
## Black Output
```python
# This file uses except* clause in Python 3.11.
try:
some_call()
except* Error as e:
pass
with (
make_context_manager1() as cm1,
make_context_manager2() as cm2,
make_context_manager3() as cm3,
make_context_manager4() as cm4,
):
pass
```

View file

@ -0,0 +1,81 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_context_managers_autodetect_39.py
---
## Input
```python
# This file uses parenthesized context managers introduced in Python 3.9.
with \
make_context_manager1() as cm1, \
make_context_manager2() as cm2, \
make_context_manager3() as cm3, \
make_context_manager4() as cm4 \
:
pass
with (
new_new_new1() as cm1,
new_new_new2()
):
pass
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,12 +1,7 @@
# This file uses parenthesized context managers introduced in Python 3.9.
-with (
- make_context_manager1() as cm1,
- make_context_manager2() as cm2,
- make_context_manager3() as cm3,
- make_context_manager4() as cm4,
-):
+with make_context_manager1() as cm1, make_context_manager2() as cm2, make_context_manager3() as cm3, make_context_manager4() as cm4:
pass
```
## Ruff Output
```python
# This file uses parenthesized context managers introduced in Python 3.9.
with make_context_manager1() as cm1, make_context_manager2() as cm2, make_context_manager3() as cm3, make_context_manager4() as cm4:
pass
with new_new_new1() as cm1, new_new_new2():
pass
```
## Black Output
```python
# This file uses parenthesized context managers introduced in Python 3.9.
with (
make_context_manager1() as cm1,
make_context_manager2() as cm2,
make_context_manager3() as cm3,
make_context_manager4() as cm4,
):
pass
with new_new_new1() as cm1, new_new_new2():
pass
```

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/miscellaneous/docstring_preview_no_string_normalization.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_docstring_no_string_normalization.py
---
## Input

View file

@ -0,0 +1,231 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_dummy_implementations.py
---
## Input
```python
from typing import NoReturn, Protocol, Union, overload
def dummy(a): ...
def other(b): ...
@overload
def a(arg: int) -> int: ...
@overload
def a(arg: str) -> str: ...
@overload
def a(arg: object) -> NoReturn: ...
def a(arg: Union[int, str, object]) -> Union[int, str]:
if not isinstance(arg, (int, str)):
raise TypeError
return arg
class Proto(Protocol):
def foo(self, a: int) -> int:
...
def bar(self, b: str) -> str: ...
def baz(self, c: bytes) -> str:
...
def dummy_two():
...
@dummy
def dummy_three():
...
def dummy_four():
...
@overload
def b(arg: int) -> int: ...
@overload
def b(arg: str) -> str: ...
@overload
def b(arg: object) -> NoReturn: ...
def b(arg: Union[int, str, object]) -> Union[int, str]:
if not isinstance(arg, (int, str)):
raise TypeError
return arg
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -2,15 +2,23 @@
def dummy(a): ...
+
+
def other(b): ...
@overload
def a(arg: int) -> int: ...
+
+
@overload
def a(arg: str) -> str: ...
+
+
@overload
def a(arg: object) -> NoReturn: ...
+
+
def a(arg: Union[int, str, object]) -> Union[int, str]:
if not isinstance(arg, (int, str)):
raise TypeError
@@ -21,10 +29,13 @@
def foo(self, a: int) -> int: ...
def bar(self, b: str) -> str: ...
+
def baz(self, c: bytes) -> str: ...
def dummy_two(): ...
+
+
@dummy
def dummy_three(): ...
@@ -38,6 +49,8 @@
@overload
def b(arg: str) -> str: ...
+
+
@overload
def b(arg: object) -> NoReturn: ...
```
## Ruff Output
```python
from typing import NoReturn, Protocol, Union, overload
def dummy(a): ...
def other(b): ...
@overload
def a(arg: int) -> int: ...
@overload
def a(arg: str) -> str: ...
@overload
def a(arg: object) -> NoReturn: ...
def a(arg: Union[int, str, object]) -> Union[int, str]:
if not isinstance(arg, (int, str)):
raise TypeError
return arg
class Proto(Protocol):
def foo(self, a: int) -> int: ...
def bar(self, b: str) -> str: ...
def baz(self, c: bytes) -> str: ...
def dummy_two(): ...
@dummy
def dummy_three(): ...
def dummy_four(): ...
@overload
def b(arg: int) -> int: ...
@overload
def b(arg: str) -> str: ...
@overload
def b(arg: object) -> NoReturn: ...
def b(arg: Union[int, str, object]) -> Union[int, str]:
if not isinstance(arg, (int, str)):
raise TypeError
return arg
```
## Black Output
```python
from typing import NoReturn, Protocol, Union, overload
def dummy(a): ...
def other(b): ...
@overload
def a(arg: int) -> int: ...
@overload
def a(arg: str) -> str: ...
@overload
def a(arg: object) -> NoReturn: ...
def a(arg: Union[int, str, object]) -> Union[int, str]:
if not isinstance(arg, (int, str)):
raise TypeError
return arg
class Proto(Protocol):
def foo(self, a: int) -> int: ...
def bar(self, b: str) -> str: ...
def baz(self, c: bytes) -> str: ...
def dummy_two(): ...
@dummy
def dummy_three(): ...
def dummy_four(): ...
@overload
def b(arg: int) -> int: ...
@overload
def b(arg: str) -> str: ...
@overload
def b(arg: object) -> NoReturn: ...
def b(arg: Union[int, str, object]) -> Union[int, str]:
if not isinstance(arg, (int, str)):
raise TypeError
return arg
```

View file

@ -0,0 +1,446 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_form_feeds.py
---
## Input
```python
# Warning! This file contains form feeds (ASCII 0x0C, often represented by \f or ^L).
# These may be invisible in your editor: ensure you can see them before making changes here.
# There's one at the start that'll get stripped
# Comment and statement processing is different enough that we'll test variations of both
# contexts here
#
#
#
#
#
#
#
#
#
#
\
#
pass
pass
pass
pass
pass
pass
pass
pass
pass
pass
pass
# form feed after a dedent
def foo():
pass
pass
# form feeds are prohibited inside blocks, or on a line with nonwhitespace
def bar( a = 1 ,b : bool = False ) :
pass
class Baz:
def __init__(self):
pass
def something(self):
pass
#
pass
pass #
a = 1
#
pass
a = 1
a = [
]
# as internal whitespace of a comment is allowed but why
"form feed literal in a string is okay "
# form feeds at the very end get removed.
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -5,62 +5,62 @@
# Comment and statement processing is different enough that we'll test variations of both
# contexts here
-
+
#
-
+
#
-
+
#
-
+
#
-
+
#
-
+
#
-
+
#
-
+
#
-
+
#
-
+
#
#
pass
-
+
pass
-
+
pass
-
+
pass
-
+
pass
-
+
pass
-
+
pass
-
+
pass
-
+
pass
-
+
pass
-
+
pass
@@ -68,7 +68,7 @@
def foo():
pass
-
+
pass
@@ -84,7 +84,7 @@
def something(self):
pass
-
+
#
pass
pass #
```
## Ruff Output
```python
# Warning! This file contains form feeds (ASCII 0x0C, often represented by \f or ^L).
# These may be invisible in your editor: ensure you can see them before making changes here.
# There's one at the start that'll get stripped
# Comment and statement processing is different enough that we'll test variations of both
# contexts here
#
#
#
#
#
#
#
#
#
#
#
pass
pass
pass
pass
pass
pass
pass
pass
pass
pass
pass
# form feed after a dedent
def foo():
pass
pass
# form feeds are prohibited inside blocks, or on a line with nonwhitespace
def bar(a=1, b: bool = False):
pass
class Baz:
def __init__(self):
pass
def something(self):
pass
#
pass
pass #
a = 1
#
pass
a = 1
a = []
# as internal whitespace of a comment is allowed but why
"form feed literal in a string is okay "
# form feeds at the very end get removed.
```
## Black Output
```python
# Warning! This file contains form feeds (ASCII 0x0C, often represented by \f or ^L).
# These may be invisible in your editor: ensure you can see them before making changes here.
# There's one at the start that'll get stripped
# Comment and statement processing is different enough that we'll test variations of both
# contexts here
#
#
#
#
#
#
#
#
#
#
#
pass
pass
pass
pass
pass
pass
pass
pass
pass
pass
pass
# form feed after a dedent
def foo():
pass
pass
# form feeds are prohibited inside blocks, or on a line with nonwhitespace
def bar(a=1, b: bool = False):
pass
class Baz:
def __init__(self):
pass
def something(self):
pass
#
pass
pass #
a = 1
#
pass
a = 1
a = []
# as internal whitespace of a comment is allowed but why
"form feed literal in a string is okay "
# form feeds at the very end get removed.
```

View file

@ -0,0 +1,97 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_format_unicode_escape_seq.py
---
## Input
```python
x = "\x1F"
x = "\\x1B"
x = "\\\x1B"
x = "\U0001F60E"
x = "\u0001F60E"
x = r"\u0001F60E"
x = "don't format me"
x = "\xA3"
x = "\u2717"
x = "\uFaCe"
x = "\N{ox}\N{OX}"
x = "\N{lAtIn smaLL letteR x}"
x = "\N{CYRILLIC small LETTER BYELORUSSIAN-UKRAINIAN I}"
x = b"\x1Fdon't byte"
x = rb"\x1Fdon't format"
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,15 +1,15 @@
-x = "\x1f"
+x = "\x1F"
x = "\\x1B"
-x = "\\\x1b"
-x = "\U0001f60e"
+x = "\\\x1B"
+x = "\U0001F60E"
x = "\u0001F60E"
x = r"\u0001F60E"
x = "don't format me"
-x = "\xa3"
+x = "\xA3"
x = "\u2717"
-x = "\uface"
-x = "\N{OX}\N{OX}"
-x = "\N{LATIN SMALL LETTER X}"
-x = "\N{CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I}"
-x = b"\x1fdon't byte"
+x = "\uFaCe"
+x = "\N{ox}\N{OX}"
+x = "\N{lAtIn smaLL letteR x}"
+x = "\N{CYRILLIC small LETTER BYELORUSSIAN-UKRAINIAN I}"
+x = b"\x1Fdon't byte"
x = rb"\x1Fdon't format"
```
## Ruff Output
```python
x = "\x1F"
x = "\\x1B"
x = "\\\x1B"
x = "\U0001F60E"
x = "\u0001F60E"
x = r"\u0001F60E"
x = "don't format me"
x = "\xA3"
x = "\u2717"
x = "\uFaCe"
x = "\N{ox}\N{OX}"
x = "\N{lAtIn smaLL letteR x}"
x = "\N{CYRILLIC small LETTER BYELORUSSIAN-UKRAINIAN I}"
x = b"\x1Fdon't byte"
x = rb"\x1Fdon't format"
```
## Black Output
```python
x = "\x1f"
x = "\\x1B"
x = "\\\x1b"
x = "\U0001f60e"
x = "\u0001F60E"
x = r"\u0001F60E"
x = "don't format me"
x = "\xa3"
x = "\u2717"
x = "\uface"
x = "\N{OX}\N{OX}"
x = "\N{LATIN SMALL LETTER X}"
x = "\N{CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I}"
x = b"\x1fdon't byte"
x = rb"\x1Fdon't format"
```

View file

@ -0,0 +1,201 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_long_dict_values.py
---
## Input
```python
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",
}
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':
xxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxx(
xxxxxxxxxxxxxx={
'x':
xxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxx(
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=(
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(
xxxxxxxxxxxxx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx={
'x': x.xx,
'x': x.x,
}))))
}),
}
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,32 +1,26 @@
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"
- ),
+ "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",
}
my_dict = {
- "a key in my dict": (
- a_very_long_variable * and_a_very_long_function_call() / 100000.0
- )
+ "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
- )
+ "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")
- )
+ "a key in my dict": MyClass.some_attribute.first_call()
+ .second_call()
+ .third_call(some_args="some value")
}
{
```
## Ruff Output
```python
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",
}
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": xxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxx(
xxxxxxxxxxxxxx={
"x": xxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxx(
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=(
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(
xxxxxxxxxxxxx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx={
"x": x.xx,
"x": x.x,
}
)
)
)
)
}
),
}
```
## Black Output
```python
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"
),
}
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": xxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxx(
xxxxxxxxxxxxxx={
"x": xxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxx(
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=(
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(
xxxxxxxxxxxxx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx={
"x": x.xx,
"x": x.x,
}
)
)
)
)
}
),
}
```

View file

@ -0,0 +1,75 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_long_strings__east_asian_width.py
---
## Input
```python
# The following strings do not have not-so-many chars, but are long enough
# when these are rendered in a monospace font (if the renderer respects
# Unicode East Asian Width properties).
hangul = '코드포인트 수는 적으나 실제 터미널이나 에디터에서 렌더링될 땐 너무 길어서 줄바꿈이 필요한 문자열'
hanzi = '中文測試:代碼點數量少,但在真正的終端模擬器或編輯器中呈現時太長,因此需要換行的字符串。'
japanese = 'コードポイントの数は少ないが、実際の端末エミュレータやエディタでレンダリングされる時は長すぎる為、改行が要る文字列'
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,16 +1,6 @@
# The following strings do not have not-so-many chars, but are long enough
# when these are rendered in a monospace font (if the renderer respects
# Unicode East Asian Width properties).
-hangul = (
- "코드포인트 수는 적으나 실제 터미널이나 에디터에서 렌더링될 땐 너무 길어서 줄바꿈이"
- " 필요한 문자열"
-)
-hanzi = (
- "中文測試:代碼點數量少,但在真正的終端模擬器或編輯器中呈現時太長,"
- "因此需要換行的字符串。"
-)
-japanese = (
- "コードポイントの数は少ないが、"
- "実際の端末エミュレータやエディタでレンダリングされる時は長すぎる為、"
- "改行が要る文字列"
-)
+hangul = "코드포인트 수는 적으나 실제 터미널이나 에디터에서 렌더링될 땐 너무 길어서 줄바꿈이 필요한 문자열"
+hanzi = "中文測試:代碼點數量少,但在真正的終端模擬器或編輯器中呈現時太長,因此需要換行的字符串。"
+japanese = "コードポイントの数は少ないが、実際の端末エミュレータやエディタでレンダリングされる時は長すぎる為、改行が要る文字列"
```
## Ruff Output
```python
# The following strings do not have not-so-many chars, but are long enough
# when these are rendered in a monospace font (if the renderer respects
# Unicode East Asian Width properties).
hangul = "코드포인트 수는 적으나 실제 터미널이나 에디터에서 렌더링될 땐 너무 길어서 줄바꿈이 필요한 문자열"
hanzi = "中文測試:代碼點數量少,但在真正的終端模擬器或編輯器中呈現時太長,因此需要換行的字符串。"
japanese = "コードポイントの数は少ないが、実際の端末エミュレータやエディタでレンダリングされる時は長すぎる為、改行が要る文字列"
```
## Black Output
```python
# The following strings do not have not-so-many chars, but are long enough
# when these are rendered in a monospace font (if the renderer respects
# Unicode East Asian Width properties).
hangul = (
"코드포인트 수는 적으나 실제 터미널이나 에디터에서 렌더링될 땐 너무 길어서 줄바꿈이"
" 필요한 문자열"
)
hanzi = (
"中文測試:代碼點數量少,但在真正的終端模擬器或編輯器中呈現時太長,"
"因此需要換行的字符串。"
)
japanese = (
"コードポイントの数は少ないが、"
"実際の端末エミュレータやエディタでレンダリングされる時は長すぎる為、"
"改行が要る文字列"
)
```

View file

@ -0,0 +1,340 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_long_strings__edge_case.py
---
## Input
```python
some_variable = "This string is long but not so long that it needs to be split just yet"
some_variable = 'This string is long but not so long that it needs to be split just yet'
some_variable = "This string is long, just long enough that it needs to be split, u get?"
some_variable = 'This string is long, just long enough that it needs to be split, u get?'
some_variable = "This string is long, just long enough that it needs to be split, u get? So we stay"
some_variable = 'This string is long, just long enough that it needs to be split, u get? So we stay'
some_variable = "This string is long, just long enough that it needs to be split, u get? So we split"
some_variable = 'This string is long, just long enough that it needs to be split, u get? So we split'
some_variable = "This string is long but not so long that it needs hahahah toooooo be so greatttt {} that I just can't think of any more good words to say about it at alll".format("ha")
some_variable = "This string is long but not so long that it needs hahahah toooooo be so greatttt {} that I just can't think of any more good words to say about it at allll".format("ha")
some_variable = "This string is long but not so long that it needs hahahah toooooo be so greatttt {} that I just can't think of any more good words to say about it at alllllllllll".format("ha")
some_variable = "This string is long but not so long that it needs hahahah toooooo be so greatttt {} that I just can't think of any more good words to say about it at allllllllllll".format("ha")
some_variable = "This is a long string that will end with a method that is not calleddd".format
addition_inside_tuple = (
some_string_inside_a_variable
+ "Some string that is just long enough to cause a split to take place.............",
xyz,
"Some really long string that needs to get split eventually but I'm running out of things to say" + some_string_inside_a_variable
)
addition_inside_tuple = (
some_string_inside_a_variable
+ "Some string that is just long enough to cause a split to take place.............."
)
return "Hi there. This is areally really reallllly long string that needs to be split!!!"
ternary_expression = (
"Short String"
if some_condition
else "This is a really long string that will eventually need to be split right here."
)
return f'{x}/b/c/d/d/d/dadfjsadjsaidoaisjdsfjaofjdfijaidfjaodfjaoifjodjafojdoajaaaaaaaaaaa'
return f'{x}/b/c/d/d/d/dadfjsadjsaidoaisjdsfjaofjdfijaidfjaodfjaoifjodjafojdoajaaaaaaaaaaaa'
assert str(result) == "This long string should be split at some point right close to or around hereeeeeee"
assert str(result) < "This long string should be split at some point right close to or around hereeeeee"
assert "A format string: %s" % "This long string should be split at some point right close to or around hereeeeeee" != result
msg += "This long string should be wrapped in parens at some point right around hereeeee"
msg += "This long string should be split at some point right close to or around hereeeeeeee"
msg += "This long string should not be split at any point ever since it is just righttt"
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -12,51 +12,33 @@
some_variable = (
"This string is long, just long enough that it needs to be split, u get? So we stay"
)
-some_variable = (
- "This string is long, just long enough that it needs to be split, u get? So we"
- " split"
-)
-some_variable = (
- "This string is long, just long enough that it needs to be split, u get? So we"
- " split"
-)
-some_variable = (
- "This string is long but not so long that it needs hahahah toooooo be so greatttt"
- " {} that I just can't think of any more good words to say about it at alll".format(
- "ha"
- )
+some_variable = "This string is long, just long enough that it needs to be split, u get? So we split"
+some_variable = "This string is long, just long enough that it needs to be split, u get? So we split"
+some_variable = "This string is long but not so long that it needs hahahah toooooo be so greatttt {} that I just can't think of any more good words to say about it at alll".format(
+ "ha"
)
-some_variable = (
- "This string is long but not so long that it needs hahahah toooooo be so greatttt"
- " {} that I just can't think of any more good words to say about it at allll"
- .format("ha")
+some_variable = "This string is long but not so long that it needs hahahah toooooo be so greatttt {} that I just can't think of any more good words to say about it at allll".format(
+ "ha"
)
-some_variable = (
- "This string is long but not so long that it needs hahahah toooooo be so greatttt"
- " {} that I just can't think of any more good words to say about it at alllllllllll"
- .format("ha")
+some_variable = "This string is long but not so long that it needs hahahah toooooo be so greatttt {} that I just can't think of any more good words to say about it at alllllllllll".format(
+ "ha"
)
-some_variable = (
- "This string is long but not so long that it needs hahahah toooooo be so greatttt"
- " {} that I just can't think of any more good words to say about it at"
- " allllllllllll".format("ha")
+some_variable = "This string is long but not so long that it needs hahahah toooooo be so greatttt {} that I just can't think of any more good words to say about it at allllllllllll".format(
+ "ha"
)
some_variable = (
"This is a long string that will end with a method that is not calleddd".format
)
addition_inside_tuple = (
some_string_inside_a_variable
- + "Some string that is just long enough to cause a split to take"
- " place.............",
+ + "Some string that is just long enough to cause a split to take place.............",
xyz,
- "Some really long string that needs to get split eventually but I'm running out of"
- " things to say"
+ "Some really long string that needs to get split eventually but I'm running out of things to say"
+ some_string_inside_a_variable,
)
addition_inside_tuple = (
some_string_inside_a_variable
- + "Some string that is just long enough to cause a split to take"
- " place.............."
+ + "Some string that is just long enough to cause a split to take place.............."
)
return (
"Hi there. This is areally really reallllly long string that needs to be split!!!"
@@ -64,9 +46,7 @@
ternary_expression = (
"Short String"
if some_condition
- else (
- "This is a really long string that will eventually need to be split right here."
- )
+ else "This is a really long string that will eventually need to be split right here."
)
return (
f"{x}/b/c/d/d/d/dadfjsadjsaidoaisjdsfjaofjdfijaidfjaodfjaoifjodjafojdoajaaaaaaaaaaa"
@@ -74,25 +54,19 @@
return f"{x}/b/c/d/d/d/dadfjsadjsaidoaisjdsfjaofjdfijaidfjaodfjaoifjodjafojdoajaaaaaaaaaaaa"
assert (
str(result)
- == "This long string should be split at some point right close to or around"
- " hereeeeeee"
+ == "This long string should be split at some point right close to or around hereeeeeee"
)
assert (
str(result)
- < "This long string should be split at some point right close to or around"
- " hereeeeee"
+ < "This long string should be split at some point right close to or around hereeeeee"
)
assert (
"A format string: %s"
- % "This long string should be split at some point right close to or around"
- " hereeeeeee"
+ % "This long string should be split at some point right close to or around hereeeeeee"
!= result
)
msg += (
"This long string should be wrapped in parens at some point right around hereeeee"
)
-msg += (
- "This long string should be split at some point right close to or around"
- " hereeeeeeee"
-)
+msg += "This long string should be split at some point right close to or around hereeeeeeee"
msg += "This long string should not be split at any point ever since it is just righttt"
```
## Ruff Output
```python
some_variable = "This string is long but not so long that it needs to be split just yet"
some_variable = "This string is long but not so long that it needs to be split just yet"
some_variable = (
"This string is long, just long enough that it needs to be split, u get?"
)
some_variable = (
"This string is long, just long enough that it needs to be split, u get?"
)
some_variable = (
"This string is long, just long enough that it needs to be split, u get? So we stay"
)
some_variable = (
"This string is long, just long enough that it needs to be split, u get? So we stay"
)
some_variable = "This string is long, just long enough that it needs to be split, u get? So we split"
some_variable = "This string is long, just long enough that it needs to be split, u get? So we split"
some_variable = "This string is long but not so long that it needs hahahah toooooo be so greatttt {} that I just can't think of any more good words to say about it at alll".format(
"ha"
)
some_variable = "This string is long but not so long that it needs hahahah toooooo be so greatttt {} that I just can't think of any more good words to say about it at allll".format(
"ha"
)
some_variable = "This string is long but not so long that it needs hahahah toooooo be so greatttt {} that I just can't think of any more good words to say about it at alllllllllll".format(
"ha"
)
some_variable = "This string is long but not so long that it needs hahahah toooooo be so greatttt {} that I just can't think of any more good words to say about it at allllllllllll".format(
"ha"
)
some_variable = (
"This is a long string that will end with a method that is not calleddd".format
)
addition_inside_tuple = (
some_string_inside_a_variable
+ "Some string that is just long enough to cause a split to take place.............",
xyz,
"Some really long string that needs to get split eventually but I'm running out of things to say"
+ some_string_inside_a_variable,
)
addition_inside_tuple = (
some_string_inside_a_variable
+ "Some string that is just long enough to cause a split to take place.............."
)
return (
"Hi there. This is areally really reallllly long string that needs to be split!!!"
)
ternary_expression = (
"Short String"
if some_condition
else "This is a really long string that will eventually need to be split right here."
)
return (
f"{x}/b/c/d/d/d/dadfjsadjsaidoaisjdsfjaofjdfijaidfjaodfjaoifjodjafojdoajaaaaaaaaaaa"
)
return f"{x}/b/c/d/d/d/dadfjsadjsaidoaisjdsfjaofjdfijaidfjaodfjaoifjodjafojdoajaaaaaaaaaaaa"
assert (
str(result)
== "This long string should be split at some point right close to or around hereeeeeee"
)
assert (
str(result)
< "This long string should be split at some point right close to or around hereeeeee"
)
assert (
"A format string: %s"
% "This long string should be split at some point right close to or around hereeeeeee"
!= result
)
msg += (
"This long string should be wrapped in parens at some point right around hereeeee"
)
msg += "This long string should be split at some point right close to or around hereeeeeeee"
msg += "This long string should not be split at any point ever since it is just righttt"
```
## Black Output
```python
some_variable = "This string is long but not so long that it needs to be split just yet"
some_variable = "This string is long but not so long that it needs to be split just yet"
some_variable = (
"This string is long, just long enough that it needs to be split, u get?"
)
some_variable = (
"This string is long, just long enough that it needs to be split, u get?"
)
some_variable = (
"This string is long, just long enough that it needs to be split, u get? So we stay"
)
some_variable = (
"This string is long, just long enough that it needs to be split, u get? So we stay"
)
some_variable = (
"This string is long, just long enough that it needs to be split, u get? So we"
" split"
)
some_variable = (
"This string is long, just long enough that it needs to be split, u get? So we"
" split"
)
some_variable = (
"This string is long but not so long that it needs hahahah toooooo be so greatttt"
" {} that I just can't think of any more good words to say about it at alll".format(
"ha"
)
)
some_variable = (
"This string is long but not so long that it needs hahahah toooooo be so greatttt"
" {} that I just can't think of any more good words to say about it at allll"
.format("ha")
)
some_variable = (
"This string is long but not so long that it needs hahahah toooooo be so greatttt"
" {} that I just can't think of any more good words to say about it at alllllllllll"
.format("ha")
)
some_variable = (
"This string is long but not so long that it needs hahahah toooooo be so greatttt"
" {} that I just can't think of any more good words to say about it at"
" allllllllllll".format("ha")
)
some_variable = (
"This is a long string that will end with a method that is not calleddd".format
)
addition_inside_tuple = (
some_string_inside_a_variable
+ "Some string that is just long enough to cause a split to take"
" place.............",
xyz,
"Some really long string that needs to get split eventually but I'm running out of"
" things to say"
+ some_string_inside_a_variable,
)
addition_inside_tuple = (
some_string_inside_a_variable
+ "Some string that is just long enough to cause a split to take"
" place.............."
)
return (
"Hi there. This is areally really reallllly long string that needs to be split!!!"
)
ternary_expression = (
"Short String"
if some_condition
else (
"This is a really long string that will eventually need to be split right here."
)
)
return (
f"{x}/b/c/d/d/d/dadfjsadjsaidoaisjdsfjaofjdfijaidfjaodfjaoifjodjafojdoajaaaaaaaaaaa"
)
return f"{x}/b/c/d/d/d/dadfjsadjsaidoaisjdsfjaofjdfijaidfjaodfjaoifjodjafojdoajaaaaaaaaaaaa"
assert (
str(result)
== "This long string should be split at some point right close to or around"
" hereeeeeee"
)
assert (
str(result)
< "This long string should be split at some point right close to or around"
" hereeeeee"
)
assert (
"A format string: %s"
% "This long string should be split at some point right close to or around"
" hereeeeeee"
!= result
)
msg += (
"This long string should be wrapped in parens at some point right around hereeeee"
)
msg += (
"This long string should be split at some point right close to or around"
" hereeeeeeee"
)
msg += "This long string should not be split at any point ever since it is just righttt"
```

View file

@ -0,0 +1,115 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_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",
+ 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

@ -0,0 +1,923 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_multiline_strings.py
---
## Input
```python
"""cow
say""",
call(3, "dogsay", textwrap.dedent("""dove
coo""" % "cowabunga"))
call(3, "dogsay", textwrap.dedent("""dove
coo""" % "cowabunga"))
call(3, textwrap.dedent("""cow
moo""" % "cowabunga"), "dogsay")
call(3, "dogsay", textwrap.dedent("""crow
caw""" % "cowabunga"),)
call(3, textwrap.dedent("""cat
meow""" % "cowabunga"), {"dog", "say"})
call(3, {"dog", "say"}, textwrap.dedent("""horse
neigh""" % "cowabunga"))
call(3, {"dog", "say"}, textwrap.dedent("""pig
oink""" % "cowabunga"),)
textwrap.dedent("""A one-line triple-quoted string.""")
textwrap.dedent("""A two-line triple-quoted string
since it goes to the next line.""")
textwrap.dedent("""A three-line triple-quoted string
that not only goes to the next line
but also goes one line beyond.""")
textwrap.dedent("""\
A triple-quoted string
actually leveraging the textwrap.dedent functionality
that ends in a trailing newline,
representing e.g. file contents.
""")
path.write_text(textwrap.dedent("""\
A triple-quoted string
actually leveraging the textwrap.dedent functionality
that ends in a trailing newline,
representing e.g. file contents.
"""))
path.write_text(textwrap.dedent("""\
A triple-quoted string
actually leveraging the textwrap.dedent functionality
that ends in a trailing newline,
representing e.g. {config_filename} file contents.
""".format("config_filename", config_filename)))
# Another use case
data = yaml.load("""\
a: 1
b: 2
""")
data = yaml.load("""\
a: 1
b: 2
""",)
data = yaml.load(
"""\
a: 1
b: 2
"""
)
MULTILINE = """
foo
""".replace("\n", "")
generated_readme = lambda project_name: """
{}
<Add content here!>
""".strip().format(project_name)
parser.usage += """
Custom extra help summary.
Extra test:
- with
- bullets
"""
def get_stuff(cr, value):
# original
cr.execute("""
SELECT whatever
FROM some_table t
WHERE id = %s
""", [value])
return cr.fetchone()
def get_stuff(cr, value):
# preferred
cr.execute(
"""
SELECT whatever
FROM some_table t
WHERE id = %s
""",
[value],
)
return cr.fetchone()
call(arg1, arg2, """
short
""", arg3=True)
test_vectors = [
"one-liner\n",
"two\nliner\n",
"""expressed
as a three line
mulitline string""",
]
_wat = re.compile(
r"""
regex
""",
re.MULTILINE | re.VERBOSE,
)
dis_c_instance_method = """\
%3d 0 LOAD_FAST 1 (x)
2 LOAD_CONST 1 (1)
4 COMPARE_OP 2 (==)
6 LOAD_FAST 0 (self)
8 STORE_ATTR 0 (x)
10 LOAD_CONST 0 (None)
12 RETURN_VALUE
""" % (_C.__init__.__code__.co_firstlineno + 1,)
path.write_text(textwrap.dedent("""\
A triple-quoted string
actually {verb} the textwrap.dedent functionality
that ends in a trailing newline,
representing e.g. {file_type} file contents.
""".format(verb="using", file_type="test")))
{"""cow
moos"""}
["""cow
moos"""]
["""cow
moos""", """dog
woofs
and
barks"""]
def dastardly_default_value(
cow: String = json.loads("""this
is
quite
the
dastadardly
value!"""),
**kwargs,
):
pass
print(f"""
This {animal}
moos and barks
{animal} say
""")
msg = f"""The arguments {bad_arguments} were passed in.
Please use `--build-option` instead,
`--global-option` is reserved to flags like `--verbose` or `--quiet`.
"""
this_will_become_one_line = (
"a"
"b"
"c"
)
this_will_stay_on_three_lines = (
"a" # comment
"b"
"c"
)
this_will_also_become_one_line = ( # comment
"a"
"b"
"c"
)
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,95 +1,138 @@
-"""cow
+(
+ """cow
say""",
+)
call(
3,
"dogsay",
- textwrap.dedent("""dove
- coo""" % "cowabunga"),
+ textwrap.dedent(
+ """dove
+ coo"""
+ % "cowabunga"
+ ),
)
call(
3,
"dogsay",
- textwrap.dedent("""dove
-coo""" % "cowabunga"),
+ textwrap.dedent(
+ """dove
+coo"""
+ % "cowabunga"
+ ),
)
call(
3,
- textwrap.dedent("""cow
- moo""" % "cowabunga"),
+ textwrap.dedent(
+ """cow
+ moo"""
+ % "cowabunga"
+ ),
"dogsay",
)
call(
3,
"dogsay",
- textwrap.dedent("""crow
- caw""" % "cowabunga"),
+ textwrap.dedent(
+ """crow
+ caw"""
+ % "cowabunga"
+ ),
)
call(
3,
- textwrap.dedent("""cat
- meow""" % "cowabunga"),
+ textwrap.dedent(
+ """cat
+ meow"""
+ % "cowabunga"
+ ),
{"dog", "say"},
)
call(
3,
{"dog", "say"},
- textwrap.dedent("""horse
- neigh""" % "cowabunga"),
+ textwrap.dedent(
+ """horse
+ neigh"""
+ % "cowabunga"
+ ),
)
call(
3,
{"dog", "say"},
- textwrap.dedent("""pig
- oink""" % "cowabunga"),
+ textwrap.dedent(
+ """pig
+ oink"""
+ % "cowabunga"
+ ),
)
textwrap.dedent("""A one-line triple-quoted string.""")
-textwrap.dedent("""A two-line triple-quoted string
-since it goes to the next line.""")
-textwrap.dedent("""A three-line triple-quoted string
+textwrap.dedent(
+ """A two-line triple-quoted string
+since it goes to the next line."""
+)
+textwrap.dedent(
+ """A three-line triple-quoted string
that not only goes to the next line
-but also goes one line beyond.""")
-textwrap.dedent("""\
+but also goes one line beyond."""
+)
+textwrap.dedent(
+ """\
A triple-quoted string
actually leveraging the textwrap.dedent functionality
that ends in a trailing newline,
representing e.g. file contents.
-""")
-path.write_text(textwrap.dedent("""\
+"""
+)
+path.write_text(
+ textwrap.dedent(
+ """\
A triple-quoted string
actually leveraging the textwrap.dedent functionality
that ends in a trailing newline,
representing e.g. file contents.
-"""))
-path.write_text(textwrap.dedent("""\
+"""
+ )
+)
+path.write_text(
+ textwrap.dedent(
+ """\
A triple-quoted string
actually leveraging the textwrap.dedent functionality
that ends in a trailing newline,
representing e.g. {config_filename} file contents.
-""".format("config_filename", config_filename)))
+""".format("config_filename", config_filename)
+ )
+)
# Another use case
-data = yaml.load("""\
+data = yaml.load(
+ """\
a: 1
b: 2
-""")
+"""
+)
data = yaml.load(
"""\
a: 1
b: 2
""",
)
-data = yaml.load("""\
+data = yaml.load(
+ """\
a: 1
b: 2
-""")
+"""
+)
MULTILINE = """
foo
""".replace("\n", "")
-generated_readme = lambda project_name: """
+generated_readme = (
+ lambda project_name: """
{}
<Add content here!>
""".strip().format(project_name)
+)
parser.usage += """
Custom extra help summary.
@@ -156,16 +199,24 @@
10 LOAD_CONST 0 (None)
12 RETURN_VALUE
""" % (_C.__init__.__code__.co_firstlineno + 1,)
-path.write_text(textwrap.dedent("""\
+path.write_text(
+ textwrap.dedent(
+ """\
A triple-quoted string
actually {verb} the textwrap.dedent functionality
that ends in a trailing newline,
representing e.g. {file_type} file contents.
-""".format(verb="using", file_type="test")))
-{"""cow
-moos"""}
-["""cow
-moos"""]
+""".format(verb="using", file_type="test")
+ )
+)
+{
+ """cow
+moos"""
+}
+[
+ """cow
+moos"""
+]
[
"""cow
moos""",
@@ -177,28 +228,32 @@
def dastardly_default_value(
- cow: String = json.loads("""this
+ cow: String = json.loads(
+ """this
is
quite
the
dastadardly
-value!"""),
+value!"""
+ ),
**kwargs,
):
pass
-print(f"""
+print(
+ f"""
This {animal}
moos and barks
{animal} say
-""")
+"""
+)
msg = f"""The arguments {bad_arguments} were passed in.
Please use `--build-option` instead,
`--global-option` is reserved to flags like `--verbose` or `--quiet`.
"""
-this_will_become_one_line = "abc"
+this_will_become_one_line = "a" "b" "c"
this_will_stay_on_three_lines = (
"a" # comment
@@ -206,4 +261,6 @@
"c"
)
-this_will_also_become_one_line = "abc" # comment
+this_will_also_become_one_line = ( # comment
+ "a" "b" "c"
+)
```
## Ruff Output
```python
(
"""cow
say""",
)
call(
3,
"dogsay",
textwrap.dedent(
"""dove
coo"""
% "cowabunga"
),
)
call(
3,
"dogsay",
textwrap.dedent(
"""dove
coo"""
% "cowabunga"
),
)
call(
3,
textwrap.dedent(
"""cow
moo"""
% "cowabunga"
),
"dogsay",
)
call(
3,
"dogsay",
textwrap.dedent(
"""crow
caw"""
% "cowabunga"
),
)
call(
3,
textwrap.dedent(
"""cat
meow"""
% "cowabunga"
),
{"dog", "say"},
)
call(
3,
{"dog", "say"},
textwrap.dedent(
"""horse
neigh"""
% "cowabunga"
),
)
call(
3,
{"dog", "say"},
textwrap.dedent(
"""pig
oink"""
% "cowabunga"
),
)
textwrap.dedent("""A one-line triple-quoted string.""")
textwrap.dedent(
"""A two-line triple-quoted string
since it goes to the next line."""
)
textwrap.dedent(
"""A three-line triple-quoted string
that not only goes to the next line
but also goes one line beyond."""
)
textwrap.dedent(
"""\
A triple-quoted string
actually leveraging the textwrap.dedent functionality
that ends in a trailing newline,
representing e.g. file contents.
"""
)
path.write_text(
textwrap.dedent(
"""\
A triple-quoted string
actually leveraging the textwrap.dedent functionality
that ends in a trailing newline,
representing e.g. file contents.
"""
)
)
path.write_text(
textwrap.dedent(
"""\
A triple-quoted string
actually leveraging the textwrap.dedent functionality
that ends in a trailing newline,
representing e.g. {config_filename} file contents.
""".format("config_filename", config_filename)
)
)
# Another use case
data = yaml.load(
"""\
a: 1
b: 2
"""
)
data = yaml.load(
"""\
a: 1
b: 2
""",
)
data = yaml.load(
"""\
a: 1
b: 2
"""
)
MULTILINE = """
foo
""".replace("\n", "")
generated_readme = (
lambda project_name: """
{}
<Add content here!>
""".strip().format(project_name)
)
parser.usage += """
Custom extra help summary.
Extra test:
- with
- bullets
"""
def get_stuff(cr, value):
# original
cr.execute(
"""
SELECT whatever
FROM some_table t
WHERE id = %s
""",
[value],
)
return cr.fetchone()
def get_stuff(cr, value):
# preferred
cr.execute(
"""
SELECT whatever
FROM some_table t
WHERE id = %s
""",
[value],
)
return cr.fetchone()
call(
arg1,
arg2,
"""
short
""",
arg3=True,
)
test_vectors = [
"one-liner\n",
"two\nliner\n",
"""expressed
as a three line
mulitline string""",
]
_wat = re.compile(
r"""
regex
""",
re.MULTILINE | re.VERBOSE,
)
dis_c_instance_method = """\
%3d 0 LOAD_FAST 1 (x)
2 LOAD_CONST 1 (1)
4 COMPARE_OP 2 (==)
6 LOAD_FAST 0 (self)
8 STORE_ATTR 0 (x)
10 LOAD_CONST 0 (None)
12 RETURN_VALUE
""" % (_C.__init__.__code__.co_firstlineno + 1,)
path.write_text(
textwrap.dedent(
"""\
A triple-quoted string
actually {verb} the textwrap.dedent functionality
that ends in a trailing newline,
representing e.g. {file_type} file contents.
""".format(verb="using", file_type="test")
)
)
{
"""cow
moos"""
}
[
"""cow
moos"""
]
[
"""cow
moos""",
"""dog
woofs
and
barks""",
]
def dastardly_default_value(
cow: String = json.loads(
"""this
is
quite
the
dastadardly
value!"""
),
**kwargs,
):
pass
print(
f"""
This {animal}
moos and barks
{animal} say
"""
)
msg = f"""The arguments {bad_arguments} were passed in.
Please use `--build-option` instead,
`--global-option` is reserved to flags like `--verbose` or `--quiet`.
"""
this_will_become_one_line = "a" "b" "c"
this_will_stay_on_three_lines = (
"a" # comment
"b"
"c"
)
this_will_also_become_one_line = ( # comment
"a" "b" "c"
)
```
## Black Output
```python
"""cow
say""",
call(
3,
"dogsay",
textwrap.dedent("""dove
coo""" % "cowabunga"),
)
call(
3,
"dogsay",
textwrap.dedent("""dove
coo""" % "cowabunga"),
)
call(
3,
textwrap.dedent("""cow
moo""" % "cowabunga"),
"dogsay",
)
call(
3,
"dogsay",
textwrap.dedent("""crow
caw""" % "cowabunga"),
)
call(
3,
textwrap.dedent("""cat
meow""" % "cowabunga"),
{"dog", "say"},
)
call(
3,
{"dog", "say"},
textwrap.dedent("""horse
neigh""" % "cowabunga"),
)
call(
3,
{"dog", "say"},
textwrap.dedent("""pig
oink""" % "cowabunga"),
)
textwrap.dedent("""A one-line triple-quoted string.""")
textwrap.dedent("""A two-line triple-quoted string
since it goes to the next line.""")
textwrap.dedent("""A three-line triple-quoted string
that not only goes to the next line
but also goes one line beyond.""")
textwrap.dedent("""\
A triple-quoted string
actually leveraging the textwrap.dedent functionality
that ends in a trailing newline,
representing e.g. file contents.
""")
path.write_text(textwrap.dedent("""\
A triple-quoted string
actually leveraging the textwrap.dedent functionality
that ends in a trailing newline,
representing e.g. file contents.
"""))
path.write_text(textwrap.dedent("""\
A triple-quoted string
actually leveraging the textwrap.dedent functionality
that ends in a trailing newline,
representing e.g. {config_filename} file contents.
""".format("config_filename", config_filename)))
# Another use case
data = yaml.load("""\
a: 1
b: 2
""")
data = yaml.load(
"""\
a: 1
b: 2
""",
)
data = yaml.load("""\
a: 1
b: 2
""")
MULTILINE = """
foo
""".replace("\n", "")
generated_readme = lambda project_name: """
{}
<Add content here!>
""".strip().format(project_name)
parser.usage += """
Custom extra help summary.
Extra test:
- with
- bullets
"""
def get_stuff(cr, value):
# original
cr.execute(
"""
SELECT whatever
FROM some_table t
WHERE id = %s
""",
[value],
)
return cr.fetchone()
def get_stuff(cr, value):
# preferred
cr.execute(
"""
SELECT whatever
FROM some_table t
WHERE id = %s
""",
[value],
)
return cr.fetchone()
call(
arg1,
arg2,
"""
short
""",
arg3=True,
)
test_vectors = [
"one-liner\n",
"two\nliner\n",
"""expressed
as a three line
mulitline string""",
]
_wat = re.compile(
r"""
regex
""",
re.MULTILINE | re.VERBOSE,
)
dis_c_instance_method = """\
%3d 0 LOAD_FAST 1 (x)
2 LOAD_CONST 1 (1)
4 COMPARE_OP 2 (==)
6 LOAD_FAST 0 (self)
8 STORE_ATTR 0 (x)
10 LOAD_CONST 0 (None)
12 RETURN_VALUE
""" % (_C.__init__.__code__.co_firstlineno + 1,)
path.write_text(textwrap.dedent("""\
A triple-quoted string
actually {verb} the textwrap.dedent functionality
that ends in a trailing newline,
representing e.g. {file_type} file contents.
""".format(verb="using", file_type="test")))
{"""cow
moos"""}
["""cow
moos"""]
[
"""cow
moos""",
"""dog
woofs
and
barks""",
]
def dastardly_default_value(
cow: String = json.loads("""this
is
quite
the
dastadardly
value!"""),
**kwargs,
):
pass
print(f"""
This {animal}
moos and barks
{animal} say
""")
msg = f"""The arguments {bad_arguments} were passed in.
Please use `--build-option` instead,
`--global-option` is reserved to flags like `--verbose` or `--quiet`.
"""
this_will_become_one_line = "abc"
this_will_stay_on_three_lines = (
"a" # comment
"b"
"c"
)
this_will_also_become_one_line = "abc" # comment
```

View file

@ -0,0 +1,134 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_no_blank_line_before_docstring.py
---
## 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...
"""
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -3,10 +3,12 @@
class LineBeforeDocstring:
+
"""Please move me up"""
class EvenIfThereIsAMethodAfter:
+
"""I'm the docstring"""
def method(self):
@@ -14,10 +16,12 @@
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...
```
## 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...
"""
```
## 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...
"""
```

View file

@ -0,0 +1,104 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_pattern_matching_trailing_comma.py
---
## Input
```python
match maybe, multiple:
case perhaps, 5:
pass
case perhaps, 6,:
pass
match more := (than, one), indeed,:
case _, (5, 6):
pass
case [[5], (6)], [7],:
pass
case _:
pass
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -8,13 +8,16 @@
pass
-match more := (than, one), indeed,:
+match (
+ more := (than, one),
+ indeed,
+):
case _, (5, 6):
pass
- case (
+ case [
[[5], (6)],
[7],
- ):
+ ]:
pass
case _:
pass
```
## Ruff Output
```python
match maybe, multiple:
case perhaps, 5:
pass
case (
perhaps,
6,
):
pass
match (
more := (than, one),
indeed,
):
case _, (5, 6):
pass
case [
[[5], (6)],
[7],
]:
pass
case _:
pass
```
## Black Output
```python
match maybe, multiple:
case perhaps, 5:
pass
case (
perhaps,
6,
):
pass
match more := (than, one), indeed,:
case _, (5, 6):
pass
case (
[[5], (6)],
[7],
):
pass
case _:
pass
```

View file

@ -0,0 +1,38 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_pep_572.py
---
## Input
```python
x[(a:=0):]
x[:(a:=0)]
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,2 +1,2 @@
-x[(a := 0):]
-x[:(a := 0)]
+x[(a := 0) :]
+x[: (a := 0)]
```
## Ruff Output
```python
x[(a := 0) :]
x[: (a := 0)]
```
## Black Output
```python
x[(a := 0):]
x[:(a := 0)]
```

View file

@ -0,0 +1,99 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_percent_precedence.py
---
## Input
```python
("" % a) ** 2
("" % a)[0]
("" % a)()
("" % a).b
2 * ("" % a)
2 @ ("" % a)
2 / ("" % a)
2 // ("" % a)
2 % ("" % a)
+("" % a)
b + ("" % a)
-("" % a)
b - ("" % a)
b + -("" % a)
~("" % a)
2 ** ("" % a)
await ("" % a)
b[("" % a)]
b(("" % a))
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -9,9 +9,9 @@
2 // ("" % a)
2 % ("" % a)
+("" % a)
-b + "" % a
+b + ("" % a)
-("" % a)
-b - "" % a
+b - ("" % a)
b + -("" % a)
~("" % a)
2 ** ("" % a)
```
## Ruff Output
```python
("" % a) ** 2
("" % a)[0]
("" % a)()
("" % a).b
2 * ("" % a)
2 @ ("" % a)
2 / ("" % a)
2 // ("" % a)
2 % ("" % a)
+("" % a)
b + ("" % a)
-("" % a)
b - ("" % a)
b + -("" % a)
~("" % a)
2 ** ("" % a)
await ("" % a)
b[("" % a)]
b(("" % a))
```
## Black Output
```python
("" % a) ** 2
("" % a)[0]
("" % a)()
("" % a).b
2 * ("" % a)
2 @ ("" % a)
2 / ("" % a)
2 // ("" % a)
2 % ("" % a)
+("" % a)
b + "" % a
-("" % a)
b - "" % a
b + -("" % a)
~("" % a)
2 ** ("" % a)
await ("" % a)
b[("" % a)]
b(("" % a))
```

View file

@ -0,0 +1,354 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_power_op_spacing.py
---
## Input
```python
a = 1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1
b = 1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1
c = 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1
d = 1**1 ** 1**1 ** 1**1 ** 1**1 ** 1**1**1 ** 1 ** 1**1 ** 1**1**1**1**1 ** 1 ** 1**1**1 **1**1** 1 ** 1 ** 1
e = 𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟
f = 𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟
a = 1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0
b = 1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0
c = 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0
d = 1.0**1.0 ** 1.0**1.0 ** 1.0**1.0 ** 1.0**1.0 ** 1.0**1.0**1.0 ** 1.0 ** 1.0**1.0 ** 1.0**1.0**1.0
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,83 +1,83 @@
a = 1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1
b = (
1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
- ** 1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
+ **1
)
c = 1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1
d = 1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1
e = 𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟
f = (
𨉟
- ** 𨉟
- ** 𨉟
- ** 𨉟
- ** 𨉟
- ** 𨉟
- ** 𨉟
- ** 𨉟
- ** 𨉟
- ** 𨉟
- ** 𨉟
- ** 𨉟
- ** 𨉟
- ** 𨉟
- ** 𨉟
- ** 𨉟
- ** 𨉟
- ** 𨉟
- ** 𨉟
- ** 𨉟
- ** 𨉟
- ** 𨉟
+ **𨉟
+ **𨉟
+ **𨉟
+ **𨉟
+ **𨉟
+ **𨉟
+ **𨉟
+ **𨉟
+ **𨉟
+ **𨉟
+ **𨉟
+ **𨉟
+ **𨉟
+ **𨉟
+ **𨉟
+ **𨉟
+ **𨉟
+ **𨉟
+ **𨉟
+ **𨉟
+ **𨉟
)
a = 1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0
b = (
1.0
- ** 1.0
- ** 1.0
- ** 1.0
- ** 1.0
- ** 1.0
- ** 1.0
- ** 1.0
- ** 1.0
- ** 1.0
- ** 1.0
- ** 1.0
- ** 1.0
- ** 1.0
- ** 1.0
- ** 1.0
- ** 1.0
- ** 1.0
+ **1.0
+ **1.0
+ **1.0
+ **1.0
+ **1.0
+ **1.0
+ **1.0
+ **1.0
+ **1.0
+ **1.0
+ **1.0
+ **1.0
+ **1.0
+ **1.0
+ **1.0
+ **1.0
+ **1.0
)
c = 1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0
d = 1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0
```
## Ruff Output
```python
a = 1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1
b = (
1
**1
**1
**1
**1
**1
**1
**1
**1
**1
**1
**1
**1
**1
**1
**1
**1
**1
**1
**1
**1
**1
**1
**1
**1
**1
**1
**1
**1
)
c = 1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1
d = 1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1
e = 𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟
f = (
𨉟
**𨉟
**𨉟
**𨉟
**𨉟
**𨉟
**𨉟
**𨉟
**𨉟
**𨉟
**𨉟
**𨉟
**𨉟
**𨉟
**𨉟
**𨉟
**𨉟
**𨉟
**𨉟
**𨉟
**𨉟
**𨉟
)
a = 1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0
b = (
1.0
**1.0
**1.0
**1.0
**1.0
**1.0
**1.0
**1.0
**1.0
**1.0
**1.0
**1.0
**1.0
**1.0
**1.0
**1.0
**1.0
**1.0
)
c = 1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0
d = 1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0
```
## Black Output
```python
a = 1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1
b = (
1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
)
c = 1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1
d = 1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1
e = 𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟
f = (
𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
)
a = 1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0
b = (
1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
)
c = 1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0
d = 1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0
```

View file

@ -0,0 +1,457 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_prefer_rhs_split.py
---
## Input
```python
first_item, second_item = (
some_looooooooong_module.some_looooooooooooooong_function_name(
first_argument, second_argument, third_argument
)
)
some_dict["with_a_long_key"] = (
some_looooooooong_module.some_looooooooooooooong_function_name(
first_argument, second_argument, third_argument
)
)
# Make sure it works when the RHS only has one pair of (optional) parens.
first_item, second_item = (
some_looooooooong_module.SomeClass.some_looooooooooooooong_variable_name
)
some_dict["with_a_long_key"] = (
some_looooooooong_module.SomeClass.some_looooooooooooooong_variable_name
)
# Make sure chaining assignments work.
first_item, second_item, third_item, forth_item = m["everything"] = (
some_looooooooong_module.some_looooooooooooooong_function_name(
first_argument, second_argument, third_argument
)
)
# Make sure when the RHS's first split at the non-optional paren fits,
# we split there instead of the outer RHS optional paren.
first_item, second_item = some_looooooooong_module.some_loooooog_function_name(
first_argument, second_argument, third_argument
)
(
first_item,
second_item,
third_item,
forth_item,
fifth_item,
last_item_very_loooooong,
) = some_looooooooong_module.some_looooooooooooooong_function_name(
first_argument, second_argument, third_argument
)
(
first_item,
second_item,
third_item,
forth_item,
fifth_item,
last_item_very_loooooong,
) = everything = some_looooong_function_name(
first_argument, second_argument, third_argument
)
# Make sure unsplittable type ignore won't be moved.
some_kind_of_table[some_key] = util.some_function( # type: ignore # noqa: E501
some_arg
).intersection(pk_cols)
some_kind_of_table[
some_key
] = lambda obj: obj.some_long_named_method() # type: ignore # noqa: E501
some_kind_of_table[
some_key # type: ignore # noqa: E501
] = lambda obj: obj.some_long_named_method()
# 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
# Right side of assignment contains un-nested pairs of inner parens.
some_kind_of_instance.some_kind_of_map[a_key] = (
isinstance(some_var, SomeClass)
and table.something_and_something != table.something_else
) or (
isinstance(some_other_var, BaseClass) and table.something != table.some_other_thing
)
# Multiple targets
a = b = (
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
)
a = b = c = d = e = f = g = (
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
) = i = j = (
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
)
a = (
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
) = c
a = (
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
) = (
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
) = ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,29 +1,31 @@
-first_item, second_item = (
- some_looooooooong_module.some_looooooooooooooong_function_name(
- first_argument, second_argument, third_argument
- )
+(
+ first_item,
+ second_item,
+) = some_looooooooong_module.some_looooooooooooooong_function_name(
+ first_argument, second_argument, third_argument
)
-some_dict["with_a_long_key"] = (
- some_looooooooong_module.some_looooooooooooooong_function_name(
- first_argument, second_argument, third_argument
- )
+some_dict[
+ "with_a_long_key"
+] = some_looooooooong_module.some_looooooooooooooong_function_name(
+ first_argument, second_argument, third_argument
)
# Make sure it works when the RHS only has one pair of (optional) parens.
-first_item, second_item = (
- some_looooooooong_module.SomeClass.some_looooooooooooooong_variable_name
-)
+(
+ first_item,
+ second_item,
+) = some_looooooooong_module.SomeClass.some_looooooooooooooong_variable_name
-some_dict["with_a_long_key"] = (
- some_looooooooong_module.SomeClass.some_looooooooooooooong_variable_name
-)
+some_dict[
+ "with_a_long_key"
+] = some_looooooooong_module.SomeClass.some_looooooooooooooong_variable_name
# Make sure chaining assignments work.
-first_item, second_item, third_item, forth_item = m["everything"] = (
- some_looooooooong_module.some_looooooooooooooong_function_name(
- first_argument, second_argument, third_argument
- )
+first_item, second_item, third_item, forth_item = m[
+ "everything"
+] = some_looooooooong_module.some_looooooooooooooong_function_name(
+ first_argument, second_argument, third_argument
)
# Make sure when the RHS's first split at the non-optional paren fits,
@@ -60,9 +62,7 @@
some_arg
).intersection(pk_cols)
-some_kind_of_table[
- some_key
-] = lambda obj: obj.some_long_named_method() # type: ignore # noqa: E501
+some_kind_of_table[some_key] = lambda obj: obj.some_long_named_method() # type: ignore # noqa: E501
some_kind_of_table[
some_key # type: ignore # noqa: E501
@@ -85,15 +85,29 @@
)
# Multiple targets
-a = b = (
- ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-)
+a = (
+ b
+) = ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-a = b = c = d = e = f = g = (
+a = (
+ b
+) = (
+ c
+) = (
+ d
+) = (
+ e
+) = (
+ f
+) = (
+ g
+) = (
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
-) = i = j = (
- kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
-)
+) = (
+ i
+) = (
+ j
+) = kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
a = (
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
```
## Ruff Output
```python
(
first_item,
second_item,
) = some_looooooooong_module.some_looooooooooooooong_function_name(
first_argument, second_argument, third_argument
)
some_dict[
"with_a_long_key"
] = some_looooooooong_module.some_looooooooooooooong_function_name(
first_argument, second_argument, third_argument
)
# Make sure it works when the RHS only has one pair of (optional) parens.
(
first_item,
second_item,
) = some_looooooooong_module.SomeClass.some_looooooooooooooong_variable_name
some_dict[
"with_a_long_key"
] = some_looooooooong_module.SomeClass.some_looooooooooooooong_variable_name
# Make sure chaining assignments work.
first_item, second_item, third_item, forth_item = m[
"everything"
] = some_looooooooong_module.some_looooooooooooooong_function_name(
first_argument, second_argument, third_argument
)
# Make sure when the RHS's first split at the non-optional paren fits,
# we split there instead of the outer RHS optional paren.
first_item, second_item = some_looooooooong_module.some_loooooog_function_name(
first_argument, second_argument, third_argument
)
(
first_item,
second_item,
third_item,
forth_item,
fifth_item,
last_item_very_loooooong,
) = some_looooooooong_module.some_looooooooooooooong_function_name(
first_argument, second_argument, third_argument
)
(
first_item,
second_item,
third_item,
forth_item,
fifth_item,
last_item_very_loooooong,
) = everything = some_looooong_function_name(
first_argument, second_argument, third_argument
)
# Make sure unsplittable type ignore won't be moved.
some_kind_of_table[some_key] = util.some_function( # type: ignore # noqa: E501
some_arg
).intersection(pk_cols)
some_kind_of_table[some_key] = lambda obj: obj.some_long_named_method() # type: ignore # noqa: E501
some_kind_of_table[
some_key # type: ignore # noqa: E501
] = lambda obj: obj.some_long_named_method()
# 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
# Right side of assignment contains un-nested pairs of inner parens.
some_kind_of_instance.some_kind_of_map[a_key] = (
isinstance(some_var, SomeClass)
and table.something_and_something != table.something_else
) or (
isinstance(some_other_var, BaseClass) and table.something != table.some_other_thing
)
# Multiple targets
a = (
b
) = ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
a = (
b
) = (
c
) = (
d
) = (
e
) = (
f
) = (
g
) = (
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
) = (
i
) = (
j
) = kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
a = (
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
) = c
a = (
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
) = (
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
) = ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
```
## Black Output
```python
first_item, second_item = (
some_looooooooong_module.some_looooooooooooooong_function_name(
first_argument, second_argument, third_argument
)
)
some_dict["with_a_long_key"] = (
some_looooooooong_module.some_looooooooooooooong_function_name(
first_argument, second_argument, third_argument
)
)
# Make sure it works when the RHS only has one pair of (optional) parens.
first_item, second_item = (
some_looooooooong_module.SomeClass.some_looooooooooooooong_variable_name
)
some_dict["with_a_long_key"] = (
some_looooooooong_module.SomeClass.some_looooooooooooooong_variable_name
)
# Make sure chaining assignments work.
first_item, second_item, third_item, forth_item = m["everything"] = (
some_looooooooong_module.some_looooooooooooooong_function_name(
first_argument, second_argument, third_argument
)
)
# Make sure when the RHS's first split at the non-optional paren fits,
# we split there instead of the outer RHS optional paren.
first_item, second_item = some_looooooooong_module.some_loooooog_function_name(
first_argument, second_argument, third_argument
)
(
first_item,
second_item,
third_item,
forth_item,
fifth_item,
last_item_very_loooooong,
) = some_looooooooong_module.some_looooooooooooooong_function_name(
first_argument, second_argument, third_argument
)
(
first_item,
second_item,
third_item,
forth_item,
fifth_item,
last_item_very_loooooong,
) = everything = some_looooong_function_name(
first_argument, second_argument, third_argument
)
# Make sure unsplittable type ignore won't be moved.
some_kind_of_table[some_key] = util.some_function( # type: ignore # noqa: E501
some_arg
).intersection(pk_cols)
some_kind_of_table[
some_key
] = lambda obj: obj.some_long_named_method() # type: ignore # noqa: E501
some_kind_of_table[
some_key # type: ignore # noqa: E501
] = lambda obj: obj.some_long_named_method()
# 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
# Right side of assignment contains un-nested pairs of inner parens.
some_kind_of_instance.some_kind_of_map[a_key] = (
isinstance(some_var, SomeClass)
and table.something_and_something != table.something_else
) or (
isinstance(some_other_var, BaseClass) and table.something != table.some_other_thing
)
# Multiple targets
a = b = (
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
)
a = b = c = d = e = f = g = (
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
) = i = j = (
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
)
a = (
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
) = c
a = (
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
) = (
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
) = ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
```

View file

@ -0,0 +1,75 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_return_annotation_brackets_string.py
---
## Input
```python
# Long string example
def frobnicate() -> "ThisIsTrulyUnreasonablyExtremelyLongClassName | list[ThisIsTrulyUnreasonablyExtremelyLongClassName]":
pass
# splitting the string breaks if there's any parameters
def frobnicate(a) -> "ThisIsTrulyUnreasonablyExtremelyLongClassName | list[ThisIsTrulyUnreasonablyExtremelyLongClassName]":
pass
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,13 +1,12 @@
# Long string example
def frobnicate() -> (
- "ThisIsTrulyUnreasonablyExtremelyLongClassName |"
- " list[ThisIsTrulyUnreasonablyExtremelyLongClassName]"
+ "ThisIsTrulyUnreasonablyExtremelyLongClassName | list[ThisIsTrulyUnreasonablyExtremelyLongClassName]"
):
pass
# splitting the string breaks if there's any parameters
def frobnicate(
- a,
+ a
) -> "ThisIsTrulyUnreasonablyExtremelyLongClassName | list[ThisIsTrulyUnreasonablyExtremelyLongClassName]":
pass
```
## Ruff Output
```python
# Long string example
def frobnicate() -> (
"ThisIsTrulyUnreasonablyExtremelyLongClassName | list[ThisIsTrulyUnreasonablyExtremelyLongClassName]"
):
pass
# splitting the string breaks if there's any parameters
def frobnicate(
a
) -> "ThisIsTrulyUnreasonablyExtremelyLongClassName | list[ThisIsTrulyUnreasonablyExtremelyLongClassName]":
pass
```
## Black Output
```python
# Long string example
def frobnicate() -> (
"ThisIsTrulyUnreasonablyExtremelyLongClassName |"
" list[ThisIsTrulyUnreasonablyExtremelyLongClassName]"
):
pass
# splitting the string breaks if there's any parameters
def frobnicate(
a,
) -> "ThisIsTrulyUnreasonablyExtremelyLongClassName | list[ThisIsTrulyUnreasonablyExtremelyLongClassName]":
pass
```

View file

@ -0,0 +1,64 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/preview_single_line_format_skip_with_multiple_comments.py
---
## Input
```python
foo = 123 # fmt: skip # noqa: E501 # pylint
bar = (
123 ,
( 1 + 5 ) # pylint # fmt:skip
)
baz = "a" + "b" # pylint; fmt: skip; noqa: E501
skip_will_not_work = "a" + "b" # pylint fmt:skip
skip_will_not_work2 = "a" + "b" # some text; fmt:skip happens to be part of it
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,8 +1,8 @@
-foo = 123 # fmt: skip # noqa: E501 # pylint
+foo = 123 # fmt: skip # noqa: E501 # pylint
bar = (
- 123 ,
- ( 1 + 5 ) # pylint # fmt:skip
+ 123,
+ (1 + 5), # pylint # fmt:skip
)
-baz = "a" + "b" # pylint; fmt: skip; noqa: E501
+baz = "a" + "b" # pylint; fmt: skip; noqa: E501
skip_will_not_work = "a" + "b" # pylint fmt:skip
skip_will_not_work2 = "a" + "b" # some text; fmt:skip happens to be part of it
```
## Ruff Output
```python
foo = 123 # fmt: skip # noqa: E501 # pylint
bar = (
123,
(1 + 5), # pylint # fmt:skip
)
baz = "a" + "b" # pylint; fmt: skip; noqa: E501
skip_will_not_work = "a" + "b" # pylint fmt:skip
skip_will_not_work2 = "a" + "b" # some text; fmt:skip happens to be part of it
```
## Black Output
```python
foo = 123 # fmt: skip # noqa: E501 # pylint
bar = (
123 ,
( 1 + 5 ) # pylint # fmt:skip
)
baz = "a" + "b" # pylint; fmt: skip; noqa: E501
skip_will_not_work = "a" + "b" # pylint fmt:skip
skip_will_not_work2 = "a" + "b" # some text; fmt:skip happens to be part of it
```

View file

@ -0,0 +1,89 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/raw_docstring.py
---
## Input
```python
class C:
r"""Raw"""
def f():
r"""Raw"""
class SingleQuotes:
r'''Raw'''
class UpperCaseR:
R"""Raw"""
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,4 +1,5 @@
class C:
+
r"""Raw"""
@@ -7,8 +8,9 @@
class SingleQuotes:
- r'''Raw'''
+ r"""Raw"""
+
class UpperCaseR:
R"""Raw"""
```
## Ruff Output
```python
class C:
r"""Raw"""
def f():
r"""Raw"""
class SingleQuotes:
r"""Raw"""
class UpperCaseR:
R"""Raw"""
```
## Black Output
```python
class C:
r"""Raw"""
def f():
r"""Raw"""
class SingleQuotes:
r'''Raw'''
class UpperCaseR:
R"""Raw"""
```

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/remove_await_parens.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/remove_await_parens.py
---
## Input
@ -86,6 +86,15 @@ async def main():
async def main():
await (yield)
async def main():
await (a ** b)
await (a[b] ** c)
await (a ** b[c])
await ((a + b) ** (c + d))
await (a + b)
await (a[b])
await (a[b ** c])
```
## Black Differences
@ -213,6 +222,16 @@ async def main():
async def main():
await (yield)
async def main():
await (a**b)
await (a[b] ** c)
await (a ** b[c])
await ((a + b) ** (c + d))
await (a + b)
await a[b]
await a[b**c]
```
## Black Output
@ -311,6 +330,16 @@ async def main():
async def main():
await (yield)
async def main():
await (a**b)
await (a[b] ** c)
await (a ** b[c])
await ((a + b) ** (c + d))
await (a + b)
await a[b]
await a[b**c]
```

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/remove_except_parens.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/remove_except_parens.py
---
## Input

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/remove_for_brackets.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/remove_for_brackets.py
---
## Input

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/return_annotation_brackets.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/return_annotation_brackets.py
---
## Input
@ -93,6 +93,11 @@ def foo() -> tuple[loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
# Magic trailing comma example
def foo() -> tuple[int, int, int,]:
return 2
# Magic trailing comma example, with params
# this is broken - the trailing comma is transferred to the param list. Fixed in preview
def foo(a,b) -> tuple[int, int, int,]:
return 2
```
## Black Differences
@ -122,6 +127,17 @@ def foo() -> tuple[int, int, int,]:
return 2 * a
@@ -124,5 +132,9 @@
# this is broken - the trailing comma is transferred to the param list. Fixed in preview
def foo(
a, b
-) -> tuple[int, int, int,]:
+) -> tuple[
+ int,
+ int,
+ int,
+]:
return 2
```
## Ruff Output
@ -255,6 +271,18 @@ def foo() -> (
]
):
return 2
# Magic trailing comma example, with params
# this is broken - the trailing comma is transferred to the param list. Fixed in preview
def foo(
a, b
) -> tuple[
int,
int,
int,
]:
return 2
```
## Black Output
@ -380,6 +408,14 @@ def foo() -> (
]
):
return 2
# Magic trailing comma example, with params
# this is broken - the trailing comma is transferred to the param list. Fixed in preview
def foo(
a, b
) -> tuple[int, int, int,]:
return 2
```

View file

@ -0,0 +1,288 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/stub.pyi
---
## Input
```python
X: int
def f(): ...
class D:
...
class C:
...
class B:
this_lack_of_newline_should_be_kept: int
def b(self) -> None: ...
but_this_newline_should_also_be_kept: int
class A:
attr: int
attr2: str
def f(self) -> int:
...
def g(self) -> str: ...
def g():
...
def h(): ...
if sys.version_info >= (3, 8):
class E:
def f(self): ...
class F:
def f(self): ...
class G: ...
class H: ...
else:
class I: ...
class J: ...
def f(): ...
class K:
def f(self): ...
def f(): ...
class Nested:
class dirty: ...
class little: ...
class secret:
def who_has_to_know(self): ...
def verse(self): ...
class Conditional:
def f(self): ...
if sys.version_info >= (3, 8):
def g(self): ...
else:
def g(self): ...
def h(self): ...
def i(self): ...
if sys.version_info >= (3, 8):
def j(self): ...
def k(self): ...
if sys.version_info >= (3, 8):
class A: ...
class B: ...
class C:
def l(self): ...
def m(self): ...
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -24,31 +24,24 @@
if sys.version_info >= (3, 8):
class E:
def f(self): ...
-
class F:
def f(self): ...
-
class G: ...
class H: ...
-
else:
class I: ...
class J: ...
-
def f(): ...
class K:
def f(self): ...
-
def f(): ...
class Nested:
class dirty: ...
class little: ...
-
class secret:
def who_has_to_know(self): ...
-
def verse(self): ...
class Conditional:
@@ -57,17 +50,14 @@
def g(self): ...
else:
def g(self): ...
-
def h(self): ...
def i(self): ...
if sys.version_info >= (3, 8):
def j(self): ...
-
def k(self): ...
if sys.version_info >= (3, 8):
class A: ...
class B: ...
-
class C:
def l(self): ...
def m(self): ...
```
## Ruff Output
```python
X: int
def f(): ...
class D: ...
class C: ...
class B:
this_lack_of_newline_should_be_kept: int
def b(self) -> None: ...
but_this_newline_should_also_be_kept: int
class A:
attr: int
attr2: str
def f(self) -> int: ...
def g(self) -> str: ...
def g(): ...
def h(): ...
if sys.version_info >= (3, 8):
class E:
def f(self): ...
class F:
def f(self): ...
class G: ...
class H: ...
else:
class I: ...
class J: ...
def f(): ...
class K:
def f(self): ...
def f(): ...
class Nested:
class dirty: ...
class little: ...
class secret:
def who_has_to_know(self): ...
def verse(self): ...
class Conditional:
def f(self): ...
if sys.version_info >= (3, 8):
def g(self): ...
else:
def g(self): ...
def h(self): ...
def i(self): ...
if sys.version_info >= (3, 8):
def j(self): ...
def k(self): ...
if sys.version_info >= (3, 8):
class A: ...
class B: ...
class C:
def l(self): ...
def m(self): ...
```
## Black Output
```python
X: int
def f(): ...
class D: ...
class C: ...
class B:
this_lack_of_newline_should_be_kept: int
def b(self) -> None: ...
but_this_newline_should_also_be_kept: int
class A:
attr: int
attr2: str
def f(self) -> int: ...
def g(self) -> str: ...
def g(): ...
def h(): ...
if sys.version_info >= (3, 8):
class E:
def f(self): ...
class F:
def f(self): ...
class G: ...
class H: ...
else:
class I: ...
class J: ...
def f(): ...
class K:
def f(self): ...
def f(): ...
class Nested:
class dirty: ...
class little: ...
class secret:
def who_has_to_know(self): ...
def verse(self): ...
class Conditional:
def f(self): ...
if sys.version_info >= (3, 8):
def g(self): ...
else:
def g(self): ...
def h(self): ...
def i(self): ...
if sys.version_info >= (3, 8):
def j(self): ...
def k(self): ...
if sys.version_info >= (3, 8):
class A: ...
class B: ...
class C:
def l(self): ...
def m(self): ...
```

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/torture.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/torture.py
---
## Input

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/trailing_commas_in_leading_parts.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/trailing_commas_in_leading_parts.py
---
## Input

View file

@ -1,6 +1,6 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/tupleassign.py
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/tupleassign.py
---
## Input

View file

@ -1,624 +0,0 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/miscellaneous/decorators.py
---
## Input
```python
# This file doesn't use the standard decomposition.
# Decorator syntax test cases are separated by double # comments.
# Those before the 'output' comment are valid under the old syntax.
# Those after the 'ouput' comment require PEP614 relaxed syntax.
# Do not remove the double # separator before the first test case, it allows
# the comment before the test case to be ignored.
##
@decorator
def f():
...
##
@decorator()
def f():
...
##
@decorator(arg)
def f():
...
##
@decorator(kwarg=0)
def f():
...
##
@decorator(*args)
def f():
...
##
@decorator(**kwargs)
def f():
...
##
@decorator(*args, **kwargs)
def f():
...
##
@decorator(*args, **kwargs,)
def f():
...
##
@dotted.decorator
def f():
...
##
@dotted.decorator(arg)
def f():
...
##
@dotted.decorator(kwarg=0)
def f():
...
##
@dotted.decorator(*args)
def f():
...
##
@dotted.decorator(**kwargs)
def f():
...
##
@dotted.decorator(*args, **kwargs)
def f():
...
##
@dotted.decorator(*args, **kwargs,)
def f():
...
##
@double.dotted.decorator
def f():
...
##
@double.dotted.decorator(arg)
def f():
...
##
@double.dotted.decorator(kwarg=0)
def f():
...
##
@double.dotted.decorator(*args)
def f():
...
##
@double.dotted.decorator(**kwargs)
def f():
...
##
@double.dotted.decorator(*args, **kwargs)
def f():
...
##
@double.dotted.decorator(*args, **kwargs,)
def f():
...
##
@_(sequence["decorator"])
def f():
...
##
@eval("sequence['decorator']")
def f():
...
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -1,29 +1,206 @@
+# This file doesn't use the standard decomposition.
+# Decorator syntax test cases are separated by double # comments.
+# Those before the 'output' comment are valid under the old syntax.
+# Those after the 'ouput' comment require PEP614 relaxed syntax.
+# Do not remove the double # separator before the first test case, it allows
+# the comment before the test case to be ignored.
+
+##
+
+
+@decorator
+def f():
+ ...
+
+
+##
+
+
+@decorator()
+def f():
+ ...
+
+
+##
+
+
+@decorator(arg)
+def f():
+ ...
+
+
+##
+
+
+@decorator(kwarg=0)
+def f():
+ ...
+
+
+##
+
+
+@decorator(*args)
+def f():
+ ...
+
+
##
-@decorator()()
+
+@decorator(**kwargs)
def f():
...
+
##
-@(decorator)
+
+@decorator(*args, **kwargs)
def f():
...
+
##
-@sequence["decorator"]
+
+@decorator(
+ *args,
+ **kwargs,
+)
def f():
...
+
##
-@decorator[List[str]]
+
+@dotted.decorator
def f():
...
+
##
-@var := decorator
+
+@dotted.decorator(arg)
+def f():
+ ...
+
+
+##
+
+
+@dotted.decorator(kwarg=0)
+def f():
+ ...
+
+
+##
+
+
+@dotted.decorator(*args)
+def f():
+ ...
+
+
+##
+
+
+@dotted.decorator(**kwargs)
+def f():
+ ...
+
+
+##
+
+
+@dotted.decorator(*args, **kwargs)
+def f():
+ ...
+
+
+##
+
+
+@dotted.decorator(
+ *args,
+ **kwargs,
+)
+def f():
+ ...
+
+
+##
+
+
+@double.dotted.decorator
+def f():
+ ...
+
+
+##
+
+
+@double.dotted.decorator(arg)
+def f():
+ ...
+
+
+##
+
+
+@double.dotted.decorator(kwarg=0)
+def f():
+ ...
+
+
+##
+
+
+@double.dotted.decorator(*args)
+def f():
+ ...
+
+
+##
+
+
+@double.dotted.decorator(**kwargs)
+def f():
+ ...
+
+
+##
+
+
+@double.dotted.decorator(*args, **kwargs)
+def f():
+ ...
+
+
+##
+
+
+@double.dotted.decorator(
+ *args,
+ **kwargs,
+)
+def f():
+ ...
+
+
+##
+
+
+@_(sequence["decorator"])
+def f():
+ ...
+
+
+##
+
+
+@eval("sequence['decorator']")
def f():
...
```
## Ruff Output
```python
# This file doesn't use the standard decomposition.
# Decorator syntax test cases are separated by double # comments.
# Those before the 'output' comment are valid under the old syntax.
# Those after the 'ouput' comment require PEP614 relaxed syntax.
# Do not remove the double # separator before the first test case, it allows
# the comment before the test case to be ignored.
##
@decorator
def f():
...
##
@decorator()
def f():
...
##
@decorator(arg)
def f():
...
##
@decorator(kwarg=0)
def f():
...
##
@decorator(*args)
def f():
...
##
@decorator(**kwargs)
def f():
...
##
@decorator(*args, **kwargs)
def f():
...
##
@decorator(
*args,
**kwargs,
)
def f():
...
##
@dotted.decorator
def f():
...
##
@dotted.decorator(arg)
def f():
...
##
@dotted.decorator(kwarg=0)
def f():
...
##
@dotted.decorator(*args)
def f():
...
##
@dotted.decorator(**kwargs)
def f():
...
##
@dotted.decorator(*args, **kwargs)
def f():
...
##
@dotted.decorator(
*args,
**kwargs,
)
def f():
...
##
@double.dotted.decorator
def f():
...
##
@double.dotted.decorator(arg)
def f():
...
##
@double.dotted.decorator(kwarg=0)
def f():
...
##
@double.dotted.decorator(*args)
def f():
...
##
@double.dotted.decorator(**kwargs)
def f():
...
##
@double.dotted.decorator(*args, **kwargs)
def f():
...
##
@double.dotted.decorator(
*args,
**kwargs,
)
def f():
...
##
@_(sequence["decorator"])
def f():
...
##
@eval("sequence['decorator']")
def f():
...
```
## Black Output
```python
##
@decorator()()
def f():
...
##
@(decorator)
def f():
...
##
@sequence["decorator"]
def f():
...
##
@decorator[List[str]]
def f():
...
##
@var := decorator
def f():
...
```

View file

@ -5,7 +5,6 @@ input_file: crates/ruff_python_formatter/resources/test/fixtures/black/miscellan
## Input
```python
# flags: --pyi
from typing import Union
@bird
@ -43,8 +42,7 @@ def eggs() -> Union[str, int]: ...
```diff
--- Black
+++ Ruff
@@ -1,32 +1,59 @@
+# flags: --pyi
@@ -1,32 +1,58 @@
from typing import Union
+
@ -69,13 +67,13 @@ def eggs() -> Union[str, int]: ...
- def BMethod(self, arg: List[str]) -> None: ...
+ def BMethod(self, arg: List[str]) -> None:
+ ...
+
+
+class C:
+ ...
-class C: ...
+class C:
+ ...
+
+
@hmm
-class D: ...
+class D:
@ -120,7 +118,6 @@ def eggs() -> Union[str, int]: ...
## Ruff Output
```python
# flags: --pyi
from typing import Union

View file

@ -0,0 +1,128 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/miscellaneous/force_pyi.pyi
---
## Input
```python
from typing import Union
@bird
def zoo(): ...
class A: ...
@bar
class B:
def BMethod(self) -> None: ...
@overload
def BMethod(self, arg : List[str]) -> None: ...
class C: ...
@hmm
class D: ...
class E: ...
@baz
def foo() -> None:
...
class F (A , C): ...
def spam() -> None: ...
@overload
def spam(arg: str) -> str: ...
var : int = 1
def eggs() -> Union[str, int]: ...
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -15,7 +15,6 @@
@hmm
class D: ...
-
class E: ...
@baz
```
## Ruff Output
```python
from typing import Union
@bird
def zoo(): ...
class A: ...
@bar
class B:
def BMethod(self) -> None: ...
@overload
def BMethod(self, arg: List[str]) -> None: ...
class C: ...
@hmm
class D: ...
class E: ...
@baz
def foo() -> None: ...
class F(A, C): ...
def spam() -> None: ...
@overload
def spam(arg: str) -> str: ...
var: int = 1
def eggs() -> Union[str, int]: ...
```
## Black Output
```python
from typing import Union
@bird
def zoo(): ...
class A: ...
@bar
class B:
def BMethod(self) -> None: ...
@overload
def BMethod(self, arg: List[str]) -> None: ...
class C: ...
@hmm
class D: ...
class E: ...
@baz
def foo() -> None: ...
class F(A, C): ...
def spam() -> None: ...
@overload
def spam(arg: str) -> str: ...
var: int = 1
def eggs() -> Union[str, int]: ...
```

View file

@ -1,420 +0,0 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/py_310/pattern_matching_extras.py
---
## Input
```python
import match
match something:
case [a as b]:
print(b)
case [a as b, c, d, e as f]:
print(f)
case Point(a as b):
print(b)
case Point(int() as x, int() as y):
print(x, y)
match = 1
case: int = re.match(something)
match re.match(case):
case type("match", match):
pass
case match:
pass
def func(match: case, case: match) -> case:
match Something():
case func(match, case):
...
case another:
...
match maybe, multiple:
case perhaps, 5:
pass
case perhaps, 6,:
pass
match more := (than, one), indeed,:
case _, (5, 6):
pass
case [[5], (6)], [7],:
pass
case _:
pass
match a, *b, c:
case [*_]:
assert "seq" == _
case {}:
assert "map" == b
match match(
case,
match(
match, case, match, looooooooooooooooooooooooooooooooooooong, match, case, match
),
case,
):
case case(
match=case,
case=re.match(
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong
),
):
pass
case [a as match]:
pass
case case:
pass
match match:
case case:
pass
match a, *b(), c:
case d, *f, g:
pass
match something:
case {
"key": key as key_1,
"password": PASS.ONE | PASS.TWO | PASS.THREE as password,
}:
pass
case {"maybe": something(complicated as this) as that}:
pass
match something:
case 1 as a:
pass
case 2 as b, 3 as c:
pass
case 4 as d, (5 as e), (6 | 7 as g), *h:
pass
match bar1:
case Foo(aa=Callable() as aa, bb=int()):
print(bar1.aa, bar1.bb)
case _:
print("no match", "\n")
match bar1:
case Foo(
normal=x, perhaps=[list, {"x": d, "y": 1.0}] as y, otherwise=something, q=t as u
):
pass
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -32,14 +32,23 @@
match maybe, multiple:
case perhaps, 5:
pass
- case perhaps, 6,:
+ case (
+ perhaps,
+ 6,
+ ):
pass
-match more := (than, one), indeed,:
+match (
+ more := (than, one),
+ indeed,
+):
case _, (5, 6):
pass
- case [[5], (6)], [7],:
+ case [
+ [[5], (6)],
+ [7],
+ ]:
pass
case _:
pass
```
## Ruff Output
```python
import match
match something:
case [a as b]:
print(b)
case [a as b, c, d, e as f]:
print(f)
case Point(a as b):
print(b)
case Point(int() as x, int() as y):
print(x, y)
match = 1
case: int = re.match(something)
match re.match(case):
case type("match", match):
pass
case match:
pass
def func(match: case, case: match) -> case:
match Something():
case func(match, case):
...
case another:
...
match maybe, multiple:
case perhaps, 5:
pass
case (
perhaps,
6,
):
pass
match (
more := (than, one),
indeed,
):
case _, (5, 6):
pass
case [
[[5], (6)],
[7],
]:
pass
case _:
pass
match a, *b, c:
case [*_]:
assert "seq" == _
case {}:
assert "map" == b
match match(
case,
match(
match, case, match, looooooooooooooooooooooooooooooooooooong, match, case, match
),
case,
):
case case(
match=case,
case=re.match(
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong
),
):
pass
case [a as match]:
pass
case case:
pass
match match:
case case:
pass
match a, *b(), c:
case d, *f, g:
pass
match something:
case {
"key": key as key_1,
"password": PASS.ONE | PASS.TWO | PASS.THREE as password,
}:
pass
case {"maybe": something(complicated as this) as that}:
pass
match something:
case 1 as a:
pass
case 2 as b, 3 as c:
pass
case 4 as d, (5 as e), (6 | 7 as g), *h:
pass
match bar1:
case Foo(aa=Callable() as aa, bb=int()):
print(bar1.aa, bar1.bb)
case _:
print("no match", "\n")
match bar1:
case Foo(
normal=x, perhaps=[list, {"x": d, "y": 1.0}] as y, otherwise=something, q=t as u
):
pass
```
## Black Output
```python
import match
match something:
case [a as b]:
print(b)
case [a as b, c, d, e as f]:
print(f)
case Point(a as b):
print(b)
case Point(int() as x, int() as y):
print(x, y)
match = 1
case: int = re.match(something)
match re.match(case):
case type("match", match):
pass
case match:
pass
def func(match: case, case: match) -> case:
match Something():
case func(match, case):
...
case another:
...
match maybe, multiple:
case perhaps, 5:
pass
case perhaps, 6,:
pass
match more := (than, one), indeed,:
case _, (5, 6):
pass
case [[5], (6)], [7],:
pass
case _:
pass
match a, *b, c:
case [*_]:
assert "seq" == _
case {}:
assert "map" == b
match match(
case,
match(
match, case, match, looooooooooooooooooooooooooooooooooooong, match, case, match
),
case,
):
case case(
match=case,
case=re.match(
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong
),
):
pass
case [a as match]:
pass
case case:
pass
match match:
case case:
pass
match a, *b(), c:
case d, *f, g:
pass
match something:
case {
"key": key as key_1,
"password": PASS.ONE | PASS.TWO | PASS.THREE as password,
}:
pass
case {"maybe": something(complicated as this) as that}:
pass
match something:
case 1 as a:
pass
case 2 as b, 3 as c:
pass
case 4 as d, (5 as e), (6 | 7 as g), *h:
pass
match bar1:
case Foo(aa=Callable() as aa, bb=int()):
print(bar1.aa, bar1.bb)
case _:
print("no match", "\n")
match bar1:
case Foo(
normal=x, perhaps=[list, {"x": d, "y": 1.0}] as y, otherwise=something, q=t as u
):
pass
```

View file

@ -1,184 +0,0 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/docstring_preview.py
---
## Input
```python
def docstring_almost_at_line_limit():
"""long docstring.................................................................
"""
def docstring_almost_at_line_limit_with_prefix():
f"""long docstring................................................................
"""
def mulitline_docstring_almost_at_line_limit():
"""long docstring.................................................................
..................................................................................
"""
def mulitline_docstring_almost_at_line_limit_with_prefix():
f"""long docstring................................................................
..................................................................................
"""
def docstring_at_line_limit():
"""long docstring................................................................"""
def docstring_at_line_limit_with_prefix():
f"""long docstring..............................................................."""
def multiline_docstring_at_line_limit():
"""first line-----------------------------------------------------------------------
second line----------------------------------------------------------------------"""
def multiline_docstring_at_line_limit_with_prefix():
f"""first line----------------------------------------------------------------------
second line----------------------------------------------------------------------"""
def single_quote_docstring_over_line_limit():
"We do not want to put the closing quote on a new line as that is invalid (see GH-3141)."
def single_quote_docstring_over_line_limit2():
'We do not want to put the closing quote on a new line as that is invalid (see GH-3141).'
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -3,7 +3,8 @@
def docstring_almost_at_line_limit_with_prefix():
- f"""long docstring................................................................"""
+ f"""long docstring................................................................
+ """
def mulitline_docstring_almost_at_line_limit():
```
## Ruff Output
```python
def docstring_almost_at_line_limit():
"""long docstring................................................................."""
def docstring_almost_at_line_limit_with_prefix():
f"""long docstring................................................................
"""
def mulitline_docstring_almost_at_line_limit():
"""long docstring.................................................................
..................................................................................
"""
def mulitline_docstring_almost_at_line_limit_with_prefix():
f"""long docstring................................................................
..................................................................................
"""
def docstring_at_line_limit():
"""long docstring................................................................"""
def docstring_at_line_limit_with_prefix():
f"""long docstring..............................................................."""
def multiline_docstring_at_line_limit():
"""first line-----------------------------------------------------------------------
second line----------------------------------------------------------------------"""
def multiline_docstring_at_line_limit_with_prefix():
f"""first line----------------------------------------------------------------------
second line----------------------------------------------------------------------"""
def single_quote_docstring_over_line_limit():
"We do not want to put the closing quote on a new line as that is invalid (see GH-3141)."
def single_quote_docstring_over_line_limit2():
"We do not want to put the closing quote on a new line as that is invalid (see GH-3141)."
```
## Black Output
```python
def docstring_almost_at_line_limit():
"""long docstring................................................................."""
def docstring_almost_at_line_limit_with_prefix():
f"""long docstring................................................................"""
def mulitline_docstring_almost_at_line_limit():
"""long docstring.................................................................
..................................................................................
"""
def mulitline_docstring_almost_at_line_limit_with_prefix():
f"""long docstring................................................................
..................................................................................
"""
def docstring_at_line_limit():
"""long docstring................................................................"""
def docstring_at_line_limit_with_prefix():
f"""long docstring..............................................................."""
def multiline_docstring_at_line_limit():
"""first line-----------------------------------------------------------------------
second line----------------------------------------------------------------------"""
def multiline_docstring_at_line_limit_with_prefix():
f"""first line----------------------------------------------------------------------
second line----------------------------------------------------------------------"""
def single_quote_docstring_over_line_limit():
"We do not want to put the closing quote on a new line as that is invalid (see GH-3141)."
def single_quote_docstring_over_line_limit2():
"We do not want to put the closing quote on a new line as that is invalid (see GH-3141)."
```