Compare commits

...

2 Commits

Author SHA1 Message Date
Micha Reiser
d3e160dcb7 Indent expanded binary expressions 2024-02-14 18:53:11 +01:00
Micha Reiser
003851b54c Beautify 2024-02-14 18:10:38 +01:00
65 changed files with 2935 additions and 822 deletions

View File

@@ -1,8 +1,9 @@
use crate::format_element::PrintMode;
use crate::{GroupId, TextSize};
use std::cell::Cell;
use std::num::NonZeroU8;
use crate::format_element::PrintMode;
use crate::{GroupId, TextSize};
/// A Tag marking the start and end of some content to which some special formatting should be applied.
///
/// Tags always come in pairs of a start and an end tag and the styling defined by this tag
@@ -99,6 +100,10 @@ pub enum Tag {
}
impl Tag {
pub const fn align(count: NonZeroU8) -> Tag {
Tag::StartAlign(Align(count))
}
/// Returns `true` if `self` is any start tag.
pub const fn is_start(&self) -> bool {
matches!(

View File

@@ -13,10 +13,11 @@ use ruff_text_size::{Ranged, TextRange};
use crate::comments::{leading_comments, trailing_comments, Comments, SourceComment};
use crate::expression::parentheses::{
in_parentheses_only_group, in_parentheses_only_if_group_breaks,
in_parentheses_only_soft_line_break, in_parentheses_only_soft_line_break_or_space,
is_expression_parenthesized, write_in_parentheses_only_group_end_tag,
write_in_parentheses_only_group_start_tag, Parentheses,
in_parentheses_only_group, in_parentheses_only_if_group_breaks, in_parentheses_only_indent_end,
in_parentheses_only_indent_start, in_parentheses_only_soft_line_break,
in_parentheses_only_soft_line_break_or_space, is_expression_parenthesized,
write_in_parentheses_only_group_end_tag, write_in_parentheses_only_group_start_tag,
Parentheses,
};
use crate::expression::OperatorPrecedence;
use crate::prelude::*;
@@ -287,7 +288,7 @@ impl Format<PyFormatContext<'_>> for BinaryLike<'_> {
let flat_binary = self.flatten(&comments, f.context().source());
if self.is_bool_op() {
return in_parentheses_only_group(&&*flat_binary).fmt(f);
return in_parentheses_only_group(&flat_binary).fmt(f);
}
let source = f.context().source();
@@ -481,7 +482,7 @@ impl Format<PyFormatContext<'_>> for BinaryLike<'_> {
// Finish the group that wraps all implicit concatenated strings
write_in_parentheses_only_group_end_tag(f);
} else {
in_parentheses_only_group(&&*flat_binary).fmt(f)?;
in_parentheses_only_group(&flat_binary).fmt(f)?;
}
Ok(())
@@ -527,6 +528,12 @@ impl<'a> Deref for FlatBinaryExpression<'a> {
}
}
impl Format<PyFormatContext<'_>> for FlatBinaryExpression<'_> {
fn fmt(&self, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> {
Format::fmt(&**self, f)
}
}
/// Binary chain represented as a flat vector where operands are stored at even indices and operators
/// add odd indices.
///
@@ -642,7 +649,7 @@ impl<'a> FlatBinaryExpressionSlice<'a> {
}
/// Formats a binary chain slice by inserting soft line breaks before the lowest-precedence operators.
/// In other words: It splits the line before by the lowest precedence operators (and it either splits
/// In other words: It splits the line before the lowest precedence operators (and it either splits
/// all of them or none). For example, the lowest precedence operator for `a + b * c + d` is the `+` operator.
/// The expression either gets formatted as `a + b * c + d` if it fits on the line or as
/// ```python
@@ -678,9 +685,11 @@ impl Format<PyFormatContext<'_>> for FlatBinaryExpressionSlice<'_> {
let mut last_operator: Option<OperatorIndex> = None;
let lowest_precedence = self.lowest_precedence();
let lowest_precedence_operators = self
.operators()
.filter(|(_, operator)| operator.precedence() == lowest_precedence);
for (index, operator_part) in self.operators() {
if operator_part.precedence() == lowest_precedence {
for (index, operator_part) in lowest_precedence_operators {
let left = self.between_operators(last_operator, index);
let right = self.after_operator(index);
@@ -701,6 +710,10 @@ impl Format<PyFormatContext<'_>> for FlatBinaryExpressionSlice<'_> {
_ => in_parentheses_only_group(&left).fmt(f)?,
}
if last_operator.is_none() {
in_parentheses_only_indent_start().fmt(f)?;
}
if let Some(trailing) = left.last_operand().trailing_binary_comments() {
trailing_comments(trailing).fmt(f)?;
}
@@ -731,7 +744,6 @@ impl Format<PyFormatContext<'_>> for FlatBinaryExpressionSlice<'_> {
last_operator = Some(index);
}
}
// Format the last right side
// SAFETY: It is guaranteed that the slice contains at least a operand, operator, operand sequence or:
@@ -745,9 +757,11 @@ impl Format<PyFormatContext<'_>> for FlatBinaryExpressionSlice<'_> {
}
match &right.0 {
[OperandOrOperator::Operand(operand)] => operand.fmt(f),
_ => in_parentheses_only_group(&right).fmt(f),
[OperandOrOperator::Operand(operand)] => operand.fmt(f)?,
_ => in_parentheses_only_group(&right).fmt(f)?,
}
in_parentheses_only_indent_end().fmt(f)
}
}

View File

@@ -379,6 +379,42 @@ where
})
}
pub(super) fn in_parentheses_only_indent_start<'a>() -> impl Format<PyFormatContext<'a>> {
format_with(|f: &mut PyFormatter| {
match f.context().node_level() {
NodeLevel::TopLevel(_) | NodeLevel::CompoundStatement | NodeLevel::Expression(None) => {
// no-op, not parenthesized
}
NodeLevel::Expression(Some(parentheses_id)) => f.write_element(FormatElement::Tag(
Tag::StartIndentIfGroupBreaks(parentheses_id),
)),
NodeLevel::ParenthesizedExpression => {
f.write_element(FormatElement::Tag(Tag::StartIndent))
}
}
Ok(())
})
}
pub(super) fn in_parentheses_only_indent_end<'a>() -> impl Format<PyFormatContext<'a>> {
format_with(|f: &mut PyFormatter| {
match f.context().node_level() {
NodeLevel::TopLevel(_) | NodeLevel::CompoundStatement | NodeLevel::Expression(None) => {
// no-op, not parenthesized
}
NodeLevel::Expression(Some(_)) => {
f.write_element(FormatElement::Tag(Tag::EndIndentIfGroupBreaks))
}
NodeLevel::ParenthesizedExpression => {
f.write_element(FormatElement::Tag(Tag::EndIndent))
}
}
Ok(())
})
}
/// Format comments inside empty parentheses, brackets or curly braces.
///
/// Empty `()`, `[]` and `{}` are special because there can be dangling comments, and they can be in

View File

@@ -0,0 +1,314 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/collections.py
---
## Input
```python
import core, time, a
from . import A, B, C
# keeps existing trailing comma
from foo import (
bar,
)
# also keeps existing structure
from foo import (
baz,
qux,
)
# `as` works as well
from foo import (
xyzzy as magic,
)
a = {1,2,3,}
b = {
1,2,
3}
c = {
1,
2,
3,
}
x = 1,
y = narf(),
nested = {(1,2,3),(4,5,6),}
nested_no_trailing_comma = {(1,2,3),(4,5,6)}
nested_long_lines = ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "cccccccccccccccccccccccccccccccccccccccc", (1, 2, 3), "dddddddddddddddddddddddddddddddddddddddd"]
{"oneple": (1,),}
{"oneple": (1,)}
['ls', 'lsoneple/%s' % (foo,)]
x = {"oneple": (1,)}
y = {"oneple": (1,),}
assert False, ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa wraps %s" % bar)
# looping over a 1-tuple should also not get wrapped
for x in (1,):
pass
for (x,) in (1,), (2,), (3,):
pass
[1, 2, 3,]
division_result_tuple = (6/2,)
print("foo %r", (foo.bar,))
if True:
IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING = (
Config.IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING
| {pylons.controllers.WSGIController}
)
if True:
ec2client.get_waiter('instance_stopped').wait(
InstanceIds=[instance.id],
WaiterConfig={
'Delay': 5,
})
ec2client.get_waiter("instance_stopped").wait(
InstanceIds=[instance.id],
WaiterConfig={"Delay": 5,},
)
ec2client.get_waiter("instance_stopped").wait(
InstanceIds=[instance.id], WaiterConfig={"Delay": 5,},
)
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -54,7 +54,7 @@
}
assert False, (
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa wraps %s"
- % bar
+ % bar
)
# looping over a 1-tuple should also not get wrapped
@@ -75,7 +75,7 @@
if True:
IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING = (
Config.IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING
- | {pylons.controllers.WSGIController}
+ | {pylons.controllers.WSGIController}
)
if True:
```
## Ruff Output
```python
import core, time, a
from . import A, B, C
# keeps existing trailing comma
from foo import (
bar,
)
# also keeps existing structure
from foo import (
baz,
qux,
)
# `as` works as well
from foo import (
xyzzy as magic,
)
a = {
1,
2,
3,
}
b = {1, 2, 3}
c = {
1,
2,
3,
}
x = (1,)
y = (narf(),)
nested = {
(1, 2, 3),
(4, 5, 6),
}
nested_no_trailing_comma = {(1, 2, 3), (4, 5, 6)}
nested_long_lines = [
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"cccccccccccccccccccccccccccccccccccccccc",
(1, 2, 3),
"dddddddddddddddddddddddddddddddddddddddd",
]
{
"oneple": (1,),
}
{"oneple": (1,)}
["ls", "lsoneple/%s" % (foo,)]
x = {"oneple": (1,)}
y = {
"oneple": (1,),
}
assert False, (
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa wraps %s"
% bar
)
# looping over a 1-tuple should also not get wrapped
for x in (1,):
pass
for (x,) in (1,), (2,), (3,):
pass
[
1,
2,
3,
]
division_result_tuple = (6 / 2,)
print("foo %r", (foo.bar,))
if True:
IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING = (
Config.IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING
| {pylons.controllers.WSGIController}
)
if True:
ec2client.get_waiter("instance_stopped").wait(
InstanceIds=[instance.id],
WaiterConfig={
"Delay": 5,
},
)
ec2client.get_waiter("instance_stopped").wait(
InstanceIds=[instance.id],
WaiterConfig={
"Delay": 5,
},
)
ec2client.get_waiter("instance_stopped").wait(
InstanceIds=[instance.id],
WaiterConfig={
"Delay": 5,
},
)
```
## Black Output
```python
import core, time, a
from . import A, B, C
# keeps existing trailing comma
from foo import (
bar,
)
# also keeps existing structure
from foo import (
baz,
qux,
)
# `as` works as well
from foo import (
xyzzy as magic,
)
a = {
1,
2,
3,
}
b = {1, 2, 3}
c = {
1,
2,
3,
}
x = (1,)
y = (narf(),)
nested = {
(1, 2, 3),
(4, 5, 6),
}
nested_no_trailing_comma = {(1, 2, 3), (4, 5, 6)}
nested_long_lines = [
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"cccccccccccccccccccccccccccccccccccccccc",
(1, 2, 3),
"dddddddddddddddddddddddddddddddddddddddd",
]
{
"oneple": (1,),
}
{"oneple": (1,)}
["ls", "lsoneple/%s" % (foo,)]
x = {"oneple": (1,)}
y = {
"oneple": (1,),
}
assert False, (
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa wraps %s"
% bar
)
# looping over a 1-tuple should also not get wrapped
for x in (1,):
pass
for (x,) in (1,), (2,), (3,):
pass
[
1,
2,
3,
]
division_result_tuple = (6 / 2,)
print("foo %r", (foo.bar,))
if True:
IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING = (
Config.IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING
| {pylons.controllers.WSGIController}
)
if True:
ec2client.get_waiter("instance_stopped").wait(
InstanceIds=[instance.id],
WaiterConfig={
"Delay": 5,
},
)
ec2client.get_waiter("instance_stopped").wait(
InstanceIds=[instance.id],
WaiterConfig={
"Delay": 5,
},
)
ec2client.get_waiter("instance_stopped").wait(
InstanceIds=[instance.id],
WaiterConfig={
"Delay": 5,
},
)
```

View File

@@ -192,7 +192,7 @@ instruction()#comment with bad spacing
children[0],
body,
children[-1], # type: ignore
@@ -72,7 +76,11 @@
@@ -72,14 +76,18 @@
body,
parameters.children[-1], # )2
]
@@ -204,7 +204,19 @@ instruction()#comment with bad spacing
+ ] # type: ignore
if (
self._proc is not None
# has the child process finished?
- # has the child process finished?
- and self._returncode is None
- # the child process has finished, but the
- # transport hasn't been notified yet?
- and self._proc.poll() is None
+ # has the child process finished?
+ and self._returncode is None
+ # the child process has finished, but the
+ # transport hasn't been notified yet?
+ and self._proc.poll() is None
):
pass
# no newline before or after
@@ -115,7 +123,9 @@
arg3=True,
)
@@ -228,7 +240,16 @@ instruction()#comment with bad spacing
)
@@ -158,7 +171,10 @@
@@ -151,14 +164,17 @@
[
CONFIG_FILE,
]
- + SHARED_CONFIG_FILES
- + USER_CONFIG_FILES
+ + SHARED_CONFIG_FILES
+ + USER_CONFIG_FILES
) # type: Final
class Test:
def _init_host(self, parsed) -> None:

View File

@@ -141,6 +141,23 @@ aaaaaaaaaaaaa, bbbbbbbbb = map(list, map(itertools.chain.from_iterable, zip(*ite
an_element_with_a_long_value = calls() or more_calls() and more() # type: bool
tup = (
@@ -61,11 +59,11 @@
a = (
element
- + another_element
- + another_element_with_long_name
- + element
- + another_element
- + another_element_with_long_name
+ + another_element
+ + another_element_with_long_name
+ + element
+ + another_element
+ + another_element_with_long_name
) # type: int
@@ -100,7 +98,13 @@
)

View File

@@ -146,6 +146,40 @@ if (
# b comment
None
)
@@ -92,20 +91,20 @@
# comment1
a
# comment2
- or (
- # comment3
- (
- # comment4
- b
- )
- # comment5
- and
- # comment6
- c
or (
- # comment7
- d
+ # comment3
+ (
+ # comment4
+ b
+ )
+ # comment5
+ and
+ # comment6
+ c
+ or (
+ # comment7
+ d
+ )
)
- )
):
print("Foo")
```
## Ruff Output

View File

@@ -193,6 +193,26 @@ class C:
```diff
--- Black
+++ Ruff
@@ -22,8 +22,8 @@
if (
# Rule 1
i % 2 == 0
- # Rule 2
- and i % 3 == 0
+ # Rule 2
+ and i % 3 == 0
):
while (
# Just a comment
@@ -41,7 +41,7 @@
)
return (
'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s'
- % (test.name, test.filename, lineno, lname, err)
+ % (test.name, test.filename, lineno, lname, err)
)
def omitting_trailers(self) -> None:
@@ -110,19 +110,20 @@
value, is_going_to_be="too long to fit in a single line", srsly=True
), "Not what we expected"
@@ -227,7 +247,7 @@ class C:
assert expected(
value, is_going_to_be="too long to fit in a single line", srsly=True
@@ -161,9 +162,7 @@
@@ -161,21 +162,19 @@
8 STORE_ATTR 0 (x)
10 LOAD_CONST 0 (None)
12 RETURN_VALUE
@@ -238,6 +258,29 @@ class C:
assert (
expectedexpectedexpectedexpectedexpectedexpectedexpectedexpectedexpect
- == {
- key1: value1,
- key2: value2,
- key3: value3,
- key4: value4,
- key5: value5,
- key6: value6,
- key7: value7,
- key8: value8,
- key9: value9,
- }
+ == {
+ key1: value1,
+ key2: value2,
+ key3: value3,
+ key4: value4,
+ key5: value5,
+ key6: value6,
+ key7: value7,
+ key8: value8,
+ key9: value9,
+ }
)
```
## Ruff Output

View File

@@ -193,6 +193,26 @@ class C:
```diff
--- Black
+++ Ruff
@@ -22,8 +22,8 @@
if (
# Rule 1
i % 2 == 0
- # Rule 2
- and i % 3 == 0
+ # Rule 2
+ and i % 3 == 0
):
while (
# Just a comment
@@ -41,7 +41,7 @@
)
return (
'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s'
- % (test.name, test.filename, lineno, lname, err)
+ % (test.name, test.filename, lineno, lname, err)
)
def omitting_trailers(self) -> None:
@@ -110,19 +110,20 @@
value, is_going_to_be="too long to fit in a single line", srsly=True
), "Not what we expected"
@@ -227,7 +247,7 @@ class C:
assert expected(
value, is_going_to_be="too long to fit in a single line", srsly=True
@@ -161,9 +162,7 @@
@@ -161,21 +162,19 @@
8 STORE_ATTR 0 (x)
10 LOAD_CONST 0 (None)
12 RETURN_VALUE
@@ -238,6 +258,29 @@ class C:
assert (
expectedexpectedexpectedexpectedexpectedexpectedexpectedexpectedexpect
- == {
- key1: value1,
- key2: value2,
- key3: value3,
- key4: value4,
- key5: value5,
- key6: value6,
- key7: value7,
- key8: value8,
- key9: value9,
- }
+ == {
+ key1: value1,
+ key2: value2,
+ key3: value3,
+ key4: value4,
+ key5: value5,
+ key6: value6,
+ key7: value7,
+ key8: value8,
+ key9: value9,
+ }
)
```
## Ruff Output

View File

@@ -275,6 +275,131 @@ last_call()
) # note: no trailing comma pre-3.6
call(*gidgets[:2])
call(a, *gidgets[:2])
@@ -277,95 +277,95 @@
pass
a = (
aaaa.bbbb.cccc.dddd.eeee.ffff.gggg.hhhh.iiii.jjjj.kkkk.llll.mmmm.nnnn.oooo.pppp
- in qqqq.rrrr.ssss.tttt.uuuu.vvvv.xxxx.yyyy.zzzz
+ in qqqq.rrrr.ssss.tttt.uuuu.vvvv.xxxx.yyyy.zzzz
)
a = (
aaaa.bbbb.cccc.dddd.eeee.ffff.gggg.hhhh.iiii.jjjj.kkkk.llll.mmmm.nnnn.oooo.pppp
- not in qqqq.rrrr.ssss.tttt.uuuu.vvvv.xxxx.yyyy.zzzz
+ not in qqqq.rrrr.ssss.tttt.uuuu.vvvv.xxxx.yyyy.zzzz
)
a = (
aaaa.bbbb.cccc.dddd.eeee.ffff.gggg.hhhh.iiii.jjjj.kkkk.llll.mmmm.nnnn.oooo.pppp
- is qqqq.rrrr.ssss.tttt.uuuu.vvvv.xxxx.yyyy.zzzz
+ is qqqq.rrrr.ssss.tttt.uuuu.vvvv.xxxx.yyyy.zzzz
)
a = (
aaaa.bbbb.cccc.dddd.eeee.ffff.gggg.hhhh.iiii.jjjj.kkkk.llll.mmmm.nnnn.oooo.pppp
- is not qqqq.rrrr.ssss.tttt.uuuu.vvvv.xxxx.yyyy.zzzz
+ is not qqqq.rrrr.ssss.tttt.uuuu.vvvv.xxxx.yyyy.zzzz
)
if (
threading.current_thread() != threading.main_thread()
- and threading.current_thread() != threading.main_thread()
- or signal.getsignal(signal.SIGINT) != signal.default_int_handler
+ and threading.current_thread() != threading.main_thread()
+ or signal.getsignal(signal.SIGINT) != signal.default_int_handler
):
return True
if (
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
):
return True
if (
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- & aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ & aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
):
return True
if (
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
):
return True
if (
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
):
return True
if (
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
):
return True
if (
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- / aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ / aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
):
return True
if (
~aaaa.a + aaaa.b - aaaa.c * aaaa.d / aaaa.e
- | aaaa.f & aaaa.g % aaaa.h ^ aaaa.i << aaaa.k >> aaaa.l**aaaa.m // aaaa.n
+ | aaaa.f & aaaa.g % aaaa.h ^ aaaa.i << aaaa.k >> aaaa.l**aaaa.m // aaaa.n
):
return True
if (
~aaaaaaaa.a + aaaaaaaa.b - aaaaaaaa.c @ aaaaaaaa.d / aaaaaaaa.e
- | aaaaaaaa.f & aaaaaaaa.g % aaaaaaaa.h
- ^ aaaaaaaa.i << aaaaaaaa.k >> aaaaaaaa.l**aaaaaaaa.m // aaaaaaaa.n
+ | aaaaaaaa.f & aaaaaaaa.g % aaaaaaaa.h
+ ^ aaaaaaaa.i << aaaaaaaa.k >> aaaaaaaa.l**aaaaaaaa.m // aaaaaaaa.n
):
return True
if (
~aaaaaaaaaaaaaaaa.a
- + aaaaaaaaaaaaaaaa.b
- - aaaaaaaaaaaaaaaa.c * aaaaaaaaaaaaaaaa.d @ aaaaaaaaaaaaaaaa.e
- | aaaaaaaaaaaaaaaa.f & aaaaaaaaaaaaaaaa.g % aaaaaaaaaaaaaaaa.h
- ^ aaaaaaaaaaaaaaaa.i
- << aaaaaaaaaaaaaaaa.k
- >> aaaaaaaaaaaaaaaa.l**aaaaaaaaaaaaaaaa.m // aaaaaaaaaaaaaaaa.n
+ + aaaaaaaaaaaaaaaa.b
+ - aaaaaaaaaaaaaaaa.c * aaaaaaaaaaaaaaaa.d @ aaaaaaaaaaaaaaaa.e
+ | aaaaaaaaaaaaaaaa.f & aaaaaaaaaaaaaaaa.g % aaaaaaaaaaaaaaaa.h
+ ^ aaaaaaaaaaaaaaaa.i
+ << aaaaaaaaaaaaaaaa.k
+ >> aaaaaaaaaaaaaaaa.l**aaaaaaaaaaaaaaaa.m // aaaaaaaaaaaaaaaa.n
):
return True
(
aaaaaaaaaaaaaaaa
- + aaaaaaaaaaaaaaaa
- - aaaaaaaaaaaaaaaa
- * (aaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaa)
- / (aaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaa)
+ + aaaaaaaaaaaaaaaa
+ - aaaaaaaaaaaaaaaa
+ * (aaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaa)
+ / (aaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaa)
)
aaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaa
(
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- >> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- << aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ >> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ << aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
)
bbbb >> bbbb * bbbb
(
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- ^ bbbb.a & aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- ^ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ ^ bbbb.a & aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ ^ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
)
last_call()
# standalone comment at ENDMARKER
```
## Ruff Output

View File

@@ -110,6 +110,15 @@ elif unformatted:
},
)
@@ -19,7 +18,7 @@
"-la",
]
# fmt: on
- + path,
+ + path,
check=True,
)
@@ -82,6 +81,6 @@
if x:
return x

View File

@@ -21,15 +21,17 @@ else:
```diff
--- Black
+++ Ruff
@@ -1,7 +1,7 @@
@@ -1,8 +1,8 @@
a, b, c = 3, 4, 5
if (
a == 3
- and b != 9 # fmt: skip
- and c is not None
+ and b != 9 # fmt: skip
and c is not None
+ and c is not None
):
print("I'm good!")
else:
```
## Ruff Output

View File

@@ -0,0 +1,343 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/function_trailing_comma.py
---
## Input
```python
def f(a,):
d = {'key': 'value',}
tup = (1,)
def f2(a,b,):
d = {'key': 'value', 'key2': 'value2',}
tup = (1,2,)
def f(a:int=1,):
call(arg={'explode': 'this',})
call2(arg=[1,2,3],)
x = {
"a": 1,
"b": 2,
}["a"]
if a == {"a": 1,"b": 2,"c": 3,"d": 4,"e": 5,"f": 6,"g": 7,"h": 8,}["a"]:
pass
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set[
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
]:
json = {"k": {"k2": {"k3": [1,]}}}
# The type annotation shouldn't get a trailing comma since that would change its type.
# Relevant bug report: https://github.com/psf/black/issues/2381.
def some_function_with_a_really_long_name() -> (
returning_a_deeply_nested_import_of_a_type_i_suppose
):
pass
def some_method_with_a_really_long_name(very_long_parameter_so_yeah: str, another_long_parameter: int) -> (
another_case_of_returning_a_deeply_nested_import_of_a_type_i_suppose_cause_why_not
):
pass
def func() -> (
also_super_long_type_annotation_that_may_cause_an_AST_related_crash_in_black(this_shouldn_t_get_a_trailing_comma_too)
):
pass
def func() -> ((also_super_long_type_annotation_that_may_cause_an_AST_related_crash_in_black(
this_shouldn_t_get_a_trailing_comma_too
))
):
pass
# Make sure inner one-element tuple won't explode
some_module.some_function(
argument1, (one_element_tuple,), argument4, argument5, argument6
)
# Inner trailing comma causes outer to explode
some_module.some_function(
argument1, (one, two,), argument4, argument5, argument6
)
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -38,16 +38,16 @@
}["a"]
if (
a
- == {
- "a": 1,
- "b": 2,
- "c": 3,
- "d": 4,
- "e": 5,
- "f": 6,
- "g": 7,
- "h": 8,
- }["a"]
+ == {
+ "a": 1,
+ "b": 2,
+ "c": 3,
+ "d": 4,
+ "e": 5,
+ "f": 6,
+ "g": 7,
+ "h": 8,
+ }["a"]
):
pass
```
## Ruff Output
```python
def f(
a,
):
d = {
"key": "value",
}
tup = (1,)
def f2(
a,
b,
):
d = {
"key": "value",
"key2": "value2",
}
tup = (
1,
2,
)
def f(
a: int = 1,
):
call(
arg={
"explode": "this",
}
)
call2(
arg=[1, 2, 3],
)
x = {
"a": 1,
"b": 2,
}["a"]
if (
a
== {
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
"f": 6,
"g": 7,
"h": 8,
}["a"]
):
pass
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (
Set["xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]
):
json = {
"k": {
"k2": {
"k3": [
1,
]
}
}
}
# The type annotation shouldn't get a trailing comma since that would change its type.
# Relevant bug report: https://github.com/psf/black/issues/2381.
def some_function_with_a_really_long_name() -> (
returning_a_deeply_nested_import_of_a_type_i_suppose
):
pass
def some_method_with_a_really_long_name(
very_long_parameter_so_yeah: str, another_long_parameter: int
) -> another_case_of_returning_a_deeply_nested_import_of_a_type_i_suppose_cause_why_not:
pass
def func() -> (
also_super_long_type_annotation_that_may_cause_an_AST_related_crash_in_black(
this_shouldn_t_get_a_trailing_comma_too
)
):
pass
def func() -> (
also_super_long_type_annotation_that_may_cause_an_AST_related_crash_in_black(
this_shouldn_t_get_a_trailing_comma_too
)
):
pass
# Make sure inner one-element tuple won't explode
some_module.some_function(
argument1, (one_element_tuple,), argument4, argument5, argument6
)
# Inner trailing comma causes outer to explode
some_module.some_function(
argument1,
(
one,
two,
),
argument4,
argument5,
argument6,
)
```
## Black Output
```python
def f(
a,
):
d = {
"key": "value",
}
tup = (1,)
def f2(
a,
b,
):
d = {
"key": "value",
"key2": "value2",
}
tup = (
1,
2,
)
def f(
a: int = 1,
):
call(
arg={
"explode": "this",
}
)
call2(
arg=[1, 2, 3],
)
x = {
"a": 1,
"b": 2,
}["a"]
if (
a
== {
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
"f": 6,
"g": 7,
"h": 8,
}["a"]
):
pass
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (
Set["xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]
):
json = {
"k": {
"k2": {
"k3": [
1,
]
}
}
}
# The type annotation shouldn't get a trailing comma since that would change its type.
# Relevant bug report: https://github.com/psf/black/issues/2381.
def some_function_with_a_really_long_name() -> (
returning_a_deeply_nested_import_of_a_type_i_suppose
):
pass
def some_method_with_a_really_long_name(
very_long_parameter_so_yeah: str, another_long_parameter: int
) -> another_case_of_returning_a_deeply_nested_import_of_a_type_i_suppose_cause_why_not:
pass
def func() -> (
also_super_long_type_annotation_that_may_cause_an_AST_related_crash_in_black(
this_shouldn_t_get_a_trailing_comma_too
)
):
pass
def func() -> (
also_super_long_type_annotation_that_may_cause_an_AST_related_crash_in_black(
this_shouldn_t_get_a_trailing_comma_too
)
):
pass
# Make sure inner one-element tuple won't explode
some_module.some_function(
argument1, (one_element_tuple,), argument4, argument5, argument6
)
# Inner trailing comma causes outer to explode
some_module.some_function(
argument1,
(
one,
two,
),
argument4,
argument5,
argument6,
)
```

View File

@@ -0,0 +1,227 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/import_spacing.py
---
## Input
```python
"""The asyncio package, tracking PEP 3156."""
# flake8: noqa
from logging import (
WARNING
)
from logging import (
ERROR,
)
import sys
# This relies on each of the submodules having an __all__ variable.
from .base_events import *
from .coroutines import *
from .events import * # comment here
from .futures import *
from .locks import * # comment here
from .protocols import *
from ..runners import * # comment here
from ..queues import *
from ..streams import *
from some_library import (
Just, Enough, Libraries, To, Fit, In, This, Nice, Split, Which, We, No, Longer, Use
)
from name_of_a_company.extremely_long_project_name.component.ttypes import CuteLittleServiceHandlerFactoryyy
from name_of_a_company.extremely_long_project_name.extremely_long_component_name.ttypes import *
from .a.b.c.subprocess import *
from . import (tasks)
from . import (A, B, C)
from . import SomeVeryLongNameAndAllOfItsAdditionalLetters1, \
SomeVeryLongNameAndAllOfItsAdditionalLetters2
__all__ = (
base_events.__all__
+ coroutines.__all__
+ events.__all__
+ futures.__all__
+ locks.__all__
+ protocols.__all__
+ runners.__all__
+ queues.__all__
+ streams.__all__
+ tasks.__all__
)
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -52,13 +52,13 @@
__all__ = (
base_events.__all__
- + coroutines.__all__
- + events.__all__
- + futures.__all__
- + locks.__all__
- + protocols.__all__
- + runners.__all__
- + queues.__all__
- + streams.__all__
- + tasks.__all__
+ + coroutines.__all__
+ + events.__all__
+ + futures.__all__
+ + locks.__all__
+ + protocols.__all__
+ + runners.__all__
+ + queues.__all__
+ + streams.__all__
+ + tasks.__all__
)
```
## Ruff Output
```python
"""The asyncio package, tracking PEP 3156."""
# flake8: noqa
from logging import WARNING
from logging import (
ERROR,
)
import sys
# This relies on each of the submodules having an __all__ variable.
from .base_events import *
from .coroutines import *
from .events import * # comment here
from .futures import *
from .locks import * # comment here
from .protocols import *
from ..runners import * # comment here
from ..queues import *
from ..streams import *
from some_library import (
Just,
Enough,
Libraries,
To,
Fit,
In,
This,
Nice,
Split,
Which,
We,
No,
Longer,
Use,
)
from name_of_a_company.extremely_long_project_name.component.ttypes import (
CuteLittleServiceHandlerFactoryyy,
)
from name_of_a_company.extremely_long_project_name.extremely_long_component_name.ttypes import *
from .a.b.c.subprocess import *
from . import tasks
from . import A, B, C
from . import (
SomeVeryLongNameAndAllOfItsAdditionalLetters1,
SomeVeryLongNameAndAllOfItsAdditionalLetters2,
)
__all__ = (
base_events.__all__
+ coroutines.__all__
+ events.__all__
+ futures.__all__
+ locks.__all__
+ protocols.__all__
+ runners.__all__
+ queues.__all__
+ streams.__all__
+ tasks.__all__
)
```
## Black Output
```python
"""The asyncio package, tracking PEP 3156."""
# flake8: noqa
from logging import WARNING
from logging import (
ERROR,
)
import sys
# This relies on each of the submodules having an __all__ variable.
from .base_events import *
from .coroutines import *
from .events import * # comment here
from .futures import *
from .locks import * # comment here
from .protocols import *
from ..runners import * # comment here
from ..queues import *
from ..streams import *
from some_library import (
Just,
Enough,
Libraries,
To,
Fit,
In,
This,
Nice,
Split,
Which,
We,
No,
Longer,
Use,
)
from name_of_a_company.extremely_long_project_name.component.ttypes import (
CuteLittleServiceHandlerFactoryyy,
)
from name_of_a_company.extremely_long_project_name.extremely_long_component_name.ttypes import *
from .a.b.c.subprocess import *
from . import tasks
from . import A, B, C
from . import (
SomeVeryLongNameAndAllOfItsAdditionalLetters1,
SomeVeryLongNameAndAllOfItsAdditionalLetters2,
)
__all__ = (
base_events.__all__
+ coroutines.__all__
+ events.__all__
+ futures.__all__
+ locks.__all__
+ protocols.__all__
+ runners.__all__
+ queues.__all__
+ streams.__all__
+ tasks.__all__
)
```

View File

@@ -304,7 +304,52 @@ long_unmergable_string_with_pragma = (
```diff
--- Black
+++ Ruff
@@ -165,13 +165,9 @@
@@ -40,11 +40,11 @@
sooo="soooo", x=2
),
"A %s %s"
- % (
- "formatted",
- "string",
- ): "This is a really really really long string that has to go inside of a dictionary. It is %s bad (#%d)."
- % ("soooo", 2),
+ % (
+ "formatted",
+ "string",
+ ): "This is a really really really long string that has to go inside of a dictionary. It is %s bad (#%d)."
+ % ("soooo", 2),
}
func_with_keywords(
@@ -123,7 +123,7 @@
old_fmt_string1 = (
"While we are on the topic of %s, we should also note that old-style formatting must also be preserved, since some %s still uses it."
- % ("formatting", "code")
+ % ("formatting", "code")
)
old_fmt_string2 = "This is a %s %s %s %s" % (
@@ -135,12 +135,12 @@
old_fmt_string3 = (
"Whereas only the strings after the percent sign were long in the last example, this example uses a long initial string as well. This is another %s %s %s %s"
- % (
- "really really really really really",
- "old",
- "way to format strings!",
- "Use f-strings instead!",
- )
+ % (
+ "really really really really really",
+ "old",
+ "way to format strings!",
+ "Use f-strings instead!",
+ )
)
fstring = f"f-strings definitely make things more {difficult} than they need to be for {{black}}. But boy they sure are handy. The problem is that some lines will need to have the 'f' whereas others do not. This {line}, for example, needs one."
@@ -165,36 +165,32 @@
triple_quote_string = """This is a really really really long triple quote string assignment and it should not be touched."""
@@ -320,6 +365,50 @@ long_unmergable_string_with_pragma = (
"formatting"
)
assert some_type_of_boolean_expression, (
"Followed by a really really really long string that is used to provide context to the AssertionError exception, which uses dynamic string %s."
- % "formatting"
+ % "formatting"
)
assert some_type_of_boolean_expression, (
"Followed by a really really really long string that is used to provide context to the AssertionError exception, which uses dynamic %s %s."
- % ("string", "formatting")
+ % ("string", "formatting")
)
some_function_call(
"With a reallly generic name and with a really really long string that is, at some point down the line, "
- + added
- + " to a variable and then added to another string."
+ + added
+ + " to a variable and then added to another string."
)
some_function_call(
"With a reallly generic name and with a really really long string that is, at some point down the line, "
- + added
- + " to a variable and then added to another string. But then what happens when the final string is also supppppperrrrr long?! Well then that second (realllllllly long) string should be split too.",
+ + added
+ + " to a variable and then added to another string. But then what happens when the final string is also supppppperrrrr long?! Well then that second (realllllllly long) string should be split too.",
"and a second argument",
and_a_third,
)
@@ -249,10 +245,10 @@
annotated_variable: Final = (
"This is a large "
- + STRING
- + " that has been "
- + CONCATENATED
- + "using the '+' operator."
+ + STRING
+ + " that has been "
+ + CONCATENATED
+ + "using the '+' operator."
)
annotated_variable: Final = "This is a large string that has a type annotation attached to it. A type annotation should NOT stop a long string from being wrapped."
annotated_variable: Literal[
```
## Ruff Output

View File

@@ -95,7 +95,96 @@ def f(
```diff
--- Black
+++ Ruff
@@ -63,7 +63,7 @@
@@ -1,17 +1,17 @@
# This has always worked
z = (
Loooooooooooooooooooooooong
- | Loooooooooooooooooooooooong
- | Loooooooooooooooooooooooong
- | Loooooooooooooooooooooooong
+ | Loooooooooooooooooooooooong
+ | Loooooooooooooooooooooooong
+ | Loooooooooooooooooooooooong
)
# "AnnAssign"s now also work
z: (
Loooooooooooooooooooooooong
- | Loooooooooooooooooooooooong
- | Loooooooooooooooooooooooong
- | Loooooooooooooooooooooooong
+ | Loooooooooooooooooooooooong
+ | Loooooooooooooooooooooooong
+ | Loooooooooooooooooooooooong
)
z: Short | Short2 | Short3 | Short4
z: int
@@ -20,9 +20,9 @@
z: (
Loooooooooooooooooooooooong
- | Loooooooooooooooooooooooong
- | Loooooooooooooooooooooooong
- | Loooooooooooooooooooooooong
+ | Loooooooooooooooooooooooong
+ | Loooooooooooooooooooooooong
+ | Loooooooooooooooooooooooong
) = 7
z: Short | Short2 | Short3 | Short4 = 8
z: int = 2.3
@@ -31,39 +31,39 @@
# In case I go for not enforcing parantheses, this might get improved at the same time
x = (
z
- == 9999999999999999999999999999999999999999
- | 9999999999999999999999999999999999999999
- | 9999999999999999999999999999999999999999
- | 9999999999999999999999999999999999999999,
+ == 9999999999999999999999999999999999999999
+ | 9999999999999999999999999999999999999999
+ | 9999999999999999999999999999999999999999
+ | 9999999999999999999999999999999999999999,
y
- == 9999999999999999999999999999999999999999
- + 9999999999999999999999999999999999999999
- + 9999999999999999999999999999999999999999
- + 9999999999999999999999999999999999999999,
+ == 9999999999999999999999999999999999999999
+ + 9999999999999999999999999999999999999999
+ + 9999999999999999999999999999999999999999
+ + 9999999999999999999999999999999999999999,
)
x = (
z
- == (
- 9999999999999999999999999999999999999999
- | 9999999999999999999999999999999999999999
- | 9999999999999999999999999999999999999999
- | 9999999999999999999999999999999999999999
- ),
+ == (
+ 9999999999999999999999999999999999999999
+ | 9999999999999999999999999999999999999999
+ | 9999999999999999999999999999999999999999
+ | 9999999999999999999999999999999999999999
+ ),
y
- == (
- 9999999999999999999999999999999999999999
- + 9999999999999999999999999999999999999999
- + 9999999999999999999999999999999999999999
- + 9999999999999999999999999999999999999999
- ),
+ == (
+ 9999999999999999999999999999999999999999
+ + 9999999999999999999999999999999999999999
+ + 9999999999999999999999999999999999999999
+ + 9999999999999999999999999999999999999999
+ ),
)
# handle formatting of "tname"s in parameter list
# remove unnecessary paren
@@ -110,13 +199,11 @@ def f(
i: int,
- x: (
- Loooooooooooooooooooooooong
- | Looooooooooooooooong
- | Looooooooooooooooooooong
+ x: Loooooooooooooooooooooooong
| Looooooooooooooooong
| Looooooooooooooooooooong
- | Looooooong
- ),
+ x: Loooooooooooooooooooooooong
+ | Looooooooooooooooong
+ | Looooooooooooooooooooong
+ | Looooooong,
*,
s: str,

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/pep_604.py
---
## Input
```python
def some_very_long_name_function() -> my_module.Asdf | my_module.AnotherType | my_module.YetAnotherType | None:
pass
def some_very_long_name_function() -> my_module.Asdf | my_module.AnotherType | my_module.YetAnotherType | my_module.EvenMoreType | None:
pass
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -6,9 +6,9 @@
def some_very_long_name_function() -> (
my_module.Asdf
- | my_module.AnotherType
- | my_module.YetAnotherType
- | my_module.EvenMoreType
- | None
+ | my_module.AnotherType
+ | my_module.YetAnotherType
+ | my_module.EvenMoreType
+ | None
):
pass
```
## Ruff Output
```python
def some_very_long_name_function() -> (
my_module.Asdf | my_module.AnotherType | my_module.YetAnotherType | None
):
pass
def some_very_long_name_function() -> (
my_module.Asdf
| my_module.AnotherType
| my_module.YetAnotherType
| my_module.EvenMoreType
| None
):
pass
```
## Black Output
```python
def some_very_long_name_function() -> (
my_module.Asdf | my_module.AnotherType | my_module.YetAnotherType | None
):
pass
def some_very_long_name_function() -> (
my_module.Asdf
| my_module.AnotherType
| my_module.YetAnotherType
| my_module.EvenMoreType
| None
):
pass
```

View File

@@ -13,11 +13,13 @@ importA;()<<0**0#
```diff
--- Black
+++ Ruff
@@ -2,5 +2,5 @@
@@ -1,6 +1,6 @@
importA
(
()
<< 0
- << 0
- ** 0
+ << 0
+ **0
) #
```

View File

@@ -92,14 +92,11 @@ class Random:
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
* and_a_very_long_function_call()
* and_another_long_func()
/ 100000.0
- )
}
my_dict = {

View File

@@ -626,18 +626,25 @@ log.info(f"""Skipping: {'a' == 'b'} {desc['ms_name']} {money=} {dte=} {pos_share
)
old_fmt_string2 = "This is a %s %s %s %s" % (
@@ -271,8 +201,7 @@
@@ -271,36 +201,23 @@
)
old_fmt_string3 = (
- "Whereas only the strings after the percent sign were long in the last example,"
- " this example uses a long initial string as well. This is another %s %s %s %s"
- % (
- "really really really really really",
- "old",
- "way to format strings!",
- "Use f-strings instead!",
- )
+ "Whereas only the strings after the percent sign were long in the last example, this example uses a long initial string as well. This is another %s %s %s %s"
% (
"really really really really really",
"old",
@@ -281,26 +210,14 @@
)
+ % (
+ "really really really really really",
+ "old",
+ "way to format strings!",
+ "Use f-strings instead!",
+ )
)
-fstring = (
@@ -694,26 +701,30 @@ log.info(f"""Skipping: {'a' == 'b'} {desc['ms_name']} {money=} {dte=} {pos_share
assert some_type_of_boolean_expression, (
- "Followed by a really really really long string that is used to provide context to"
- " the AssertionError exception, which uses dynamic %s %s."
- % ("string", "formatting")
+ "Followed by a really really really long string that is used to provide context to the AssertionError exception, which uses dynamic %s %s."
% ("string", "formatting")
+ % ("string", "formatting")
)
some_function_call(
- "With a reallly generic name and with a really really long string that is, at some"
- " point down the line, "
- + added
- + " to a variable and then added to another string."
+ "With a reallly generic name and with a really really long string that is, at some point down the line, "
+ added
+ " to a variable and then added to another string."
+ + added
+ + " to a variable and then added to another string."
)
some_function_call(
- "With a reallly generic name and with a really really long string that is, at some"
- " point down the line, "
+ "With a reallly generic name and with a really really long string that is, at some point down the line, "
+ added
- + added
- + " to a variable and then added to another string. But then what happens when the"
- " final string is also supppppperrrrr long?! Well then that second (realllllllly"
- " long) string should be split too.",
+ "With a reallly generic name and with a really really long string that is, at some point down the line, "
+ + added
+ + " to a variable and then added to another string. But then what happens when the final string is also supppppperrrrr long?! Well then that second (realllllllly long) string should be split too.",
"and a second argument",
and_a_third,
@@ -772,7 +783,7 @@ log.info(f"""Skipping: {'a' == 'b'} {desc['ms_name']} {money=} {dte=} {pos_share
x,
y,
z,
@@ -397,7 +306,7 @@
@@ -397,61 +306,38 @@
func_with_bad_parens(
x,
y,
@@ -781,14 +792,21 @@ log.info(f"""Skipping: {'a' == 'b'} {desc['ms_name']} {money=} {dte=} {pos_share
z,
)
@@ -408,50 +317,27 @@
+ CONCATENATED
+ "using the '+' operator."
)
annotated_variable: Final = (
"This is a large "
- + STRING
- + " that has been "
- + CONCATENATED
- + "using the '+' operator."
-)
-annotated_variable: Final = (
- "This is a large string that has a type annotation attached to it. A type"
- " annotation should NOT stop a long string from being wrapped."
-)
+ + STRING
+ + " that has been "
+ + CONCATENATED
+ + "using the '+' operator."
)
+annotated_variable: Final = "This is a large string that has a type annotation attached to it. A type annotation should NOT stop a long string from being wrapped."
annotated_variable: Literal["fakse_literal"] = (
- "This is a large string that has a type annotation attached to it. A type"
@@ -910,14 +928,15 @@ log.info(f"""Skipping: {'a' == 'b'} {desc['ms_name']} {money=} {dte=} {pos_share
- + ", \n".join(
- " (%r, self.%s, visitor.%s)" % (attrname, attrname, visit_name)
- for attrname, visit_name in names
- )
- + "\n ]\n"
+ (" return [\n")
+ + (
+ ", \n".join(
+ " (%r, self.%s, visitor.%s)" % (attrname, attrname, visit_name)
+ for attrname, visit_name in names
+ )
)
- + "\n ]\n"
+ )
+ + ("\n ]\n")
)

View File

@@ -103,8 +103,9 @@ msg += "This long string should not be split at any point ever since it is just
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,
+ "Some really long string that needs to get split eventually but I'm running out of things to say"
+ some_string_inside_a_variable,
+ + some_string_inside_a_variable,
)
addition_inside_tuple = (
some_string_inside_a_variable
@@ -143,8 +144,9 @@ msg += "This long string should not be split at any point ever since it is just
"A format string: %s"
- % "This long string should be split at some point right close to or around"
- " hereeeeeee"
- != result
+ % "This long string should be split at some point right close to or around hereeeeeee"
!= result
+ != result
)
msg += (
"This long string should be wrapped in parens at some point right around hereeeee"

View File

@@ -689,7 +689,7 @@ s = f'Lorem Ipsum is simply dummy text of the printing and typesetting industry:
+ (
+ "xxxxxxxxxx xxxx xx xxxxxx(%x) xx %x xxxx xx xxx %x.xx"
+ % (len(self) + 1, xxxx.xxxxxxxxxx, xxxx.xxxxxxxxxx)
+ )
)
+ + (
+ " %.3f (%s) to %.3f (%s).\n"
+ % (
@@ -698,7 +698,7 @@ s = f'Lorem Ipsum is simply dummy text of the printing and typesetting industry:
+ x,
+ xxxx.xxxxxxxxxxxxxx(xx),
+ )
)
+ )
)
@@ -832,7 +832,7 @@ s = f'Lorem Ipsum is simply dummy text of the printing and typesetting industry:
some_commented_string = ( # This comment stays at the top.
"This string is long but not so long that it needs hahahah toooooo be so greatttt"
@@ -279,36 +280,25 @@
@@ -279,37 +280,26 @@
)
lpar_and_rpar_have_comments = func_call( # LPAR Comment
@@ -852,32 +852,33 @@ s = f'Lorem Ipsum is simply dummy text of the printing and typesetting industry:
- f" {'' if ID is None else ID} | perl -nE 'print if /^{field}:/'"
-)
+cmd_fstring = f"sudo -E deluge-console info --detailed --sort-reverse=time_added {'' if ID is None else ID} | perl -nE 'print if /^{field}:/'"
+
+cmd_fstring = f"sudo -E deluge-console info --detailed --sort-reverse=time_added {'{{}}' if ID is None else ID} | perl -nE 'print if /^{field}:/'"
-cmd_fstring = (
- "sudo -E deluge-console info --detailed --sort-reverse=time_added"
- f" {'{{}}' if ID is None else ID} | perl -nE 'print if /^{field}:/'"
-)
+cmd_fstring = f"sudo -E deluge-console info --detailed --sort-reverse=time_added {'{{}}' if ID is None else ID} | perl -nE 'print if /^{field}:/'"
+cmd_fstring = f"sudo -E deluge-console info --detailed --sort-reverse=time_added {{'' if ID is None else ID}} | perl -nE 'print if /^{field}:/'"
-cmd_fstring = (
- "sudo -E deluge-console info --detailed --sort-reverse=time_added {'' if ID is"
- f" None else ID}} | perl -nE 'print if /^{field}:/'"
-)
+cmd_fstring = f"sudo -E deluge-console info --detailed --sort-reverse=time_added {{'' if ID is None else ID}} | perl -nE 'print if /^{field}:/'"
+fstring = f"This string really doesn't need to be an {{{{fstring}}}}, but this one most certainly, absolutely {does}."
+
fstring = (
- "This string really doesn't need to be an {{fstring}}, but this one most"
- f" certainly, absolutely {does}."
+ f"We have to remember to escape {braces}." " Like {these}." f" But not {this}."
)
-
-fstring = f"We have to remember to escape {braces}. Like {{these}}. But not {this}."
-fstring = f"We have to remember to escape {braces}. Like {{these}}. But not {this}."
-
class A:
@@ -364,10 +354,7 @@
class B:
@@ -364,11 +354,8 @@
def foo():
if not hasattr(module, name):
raise ValueError(
@@ -885,10 +886,12 @@ s = f'Lorem Ipsum is simply dummy text of the printing and typesetting industry:
- " serialize things like inner classes. Please move the object into"
- " the main module body to use migrations.\nFor more information,"
- " see https://docs.djangoproject.com/en/%s/topics/migrations/#serializing-values"
- % (name, module_name, get_docs_version())
+ "Could not find object %s in %s.\nPlease note that you cannot serialize things like inner classes. Please move the object into the main module body to use migrations.\nFor more information, see https://docs.djangoproject.com/en/%s/topics/migrations/#serializing-values"
% (name, module_name, get_docs_version())
+ % (name, module_name, get_docs_version())
)
@@ -382,23 +369,19 @@
class Step(StepBase):
@@ -931,6 +934,15 @@ s = f'Lorem Ipsum is simply dummy text of the printing and typesetting industry:
)
@@ -423,7 +406,7 @@
def G():
assert (
c_float(val[0][0] / val[0][1]).value
- == c_float(value[0][0] / value[0][1]).value
+ == c_float(value[0][0] / value[0][1]).value
), "%s didn't roundtrip" % tag
@@ -432,9 +415,7 @@
assert xxxxxxx_xxxx in [
x.xxxxx.xxxxxx.xxxxx.xxxxxx,

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

@@ -129,6 +129,15 @@ a = (
some_kind_of_table[
some_key # type: ignore # noqa: E501
@@ -79,7 +77,7 @@
# 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
+ and table.something_and_something != table.something_else
) or (
isinstance(some_other_var, BaseClass) and table.something != table.some_other_thing
)
```
## Ruff Output

View File

@@ -127,6 +127,24 @@ def foo(a,b) -> tuple[int, int, int,]:
return 2 * a
@@ -45,7 +53,7 @@
def foo() -> (
intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds
- | intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds
+ | intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds
):
return 2
@@ -64,7 +72,7 @@
c: int,
) -> (
intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds
- | intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds
+ | intsdfsafafafdfdsasdfsfsdfasdfafdsafdfdsfasdskdsdsfdsafdsafsdfdasfffsfdsfdsafafhdskfhdsfjdslkfdlfsdkjhsdfjkdshfkljds
):
return 2
@@ -124,5 +132,9 @@
# this is broken - the trailing comma is transferred to the param list. Fixed in preview
def foo(

View File

@@ -41,11 +41,13 @@ assert (
```diff
--- Black
+++ Ruff
@@ -2,7 +2,7 @@
@@ -1,8 +1,8 @@
importA
(
()
<< 0
- << 0
- ** 101234234242352525425252352352525234890264906820496920680926538059059209922523523525
+ << 0
+ **101234234242352525425252352352525234890264906820496920680926538059059209922523523525
) #

View File

@@ -0,0 +1,129 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/trailing_comma_optional_parens1.py
---
## Input
```python
if e1234123412341234.winerror not in (_winapi.ERROR_SEM_TIMEOUT,
_winapi.ERROR_PIPE_BUSY) or _check_timeout(t):
pass
if x:
if y:
new_id = max(Vegetable.objects.order_by('-id')[0].id,
Mineral.objects.order_by('-id')[0].id) + 1
class X:
def get_help_text(self):
return ngettext(
"Your password must contain at least %(min_length)d character.",
"Your password must contain at least %(min_length)d characters.",
self.min_length,
) % {'min_length': self.min_length}
class A:
def b(self):
if self.connection.mysql_is_mariadb and (
10,
4,
3,
) < self.connection.mysql_version < (10, 5, 2):
pass
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -11,7 +11,7 @@
Vegetable.objects.order_by("-id")[0].id,
Mineral.objects.order_by("-id")[0].id,
)
- + 1
+ + 1
)
```
## Ruff Output
```python
if e1234123412341234.winerror not in (
_winapi.ERROR_SEM_TIMEOUT,
_winapi.ERROR_PIPE_BUSY,
) or _check_timeout(t):
pass
if x:
if y:
new_id = (
max(
Vegetable.objects.order_by("-id")[0].id,
Mineral.objects.order_by("-id")[0].id,
)
+ 1
)
class X:
def get_help_text(self):
return ngettext(
"Your password must contain at least %(min_length)d character.",
"Your password must contain at least %(min_length)d characters.",
self.min_length,
) % {"min_length": self.min_length}
class A:
def b(self):
if self.connection.mysql_is_mariadb and (
10,
4,
3,
) < self.connection.mysql_version < (10, 5, 2):
pass
```
## Black Output
```python
if e1234123412341234.winerror not in (
_winapi.ERROR_SEM_TIMEOUT,
_winapi.ERROR_PIPE_BUSY,
) or _check_timeout(t):
pass
if x:
if y:
new_id = (
max(
Vegetable.objects.order_by("-id")[0].id,
Mineral.objects.order_by("-id")[0].id,
)
+ 1
)
class X:
def get_help_text(self):
return ngettext(
"Your password must contain at least %(min_length)d character.",
"Your password must contain at least %(min_length)d characters.",
self.min_length,
) % {"min_length": self.min_length}
class A:
def b(self):
if self.connection.mysql_is_mariadb and (
10,
4,
3,
) < self.connection.mysql_version < (10, 5, 2):
pass
```

View File

@@ -0,0 +1,59 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/trailing_comma_optional_parens3.py
---
## Input
```python
if True:
if True:
if True:
return _(
"qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweas "
+ "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwegqweasdzxcqweasdzxc.",
"qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwe",
) % {"reported_username": reported_username, "report_reason": report_reason}
```
## Black Differences
```diff
--- Black
+++ Ruff
@@ -3,6 +3,6 @@
if True:
return _(
"qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweas "
- + "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwegqweasdzxcqweasdzxc.",
+ + "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwegqweasdzxcqweasdzxc.",
"qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwe",
) % {"reported_username": reported_username, "report_reason": report_reason}
```
## Ruff Output
```python
if True:
if True:
if True:
return _(
"qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweas "
+ "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwegqweasdzxcqweasdzxc.",
"qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwe",
) % {"reported_username": reported_username, "report_reason": report_reason}
```
## Black Output
```python
if True:
if True:
if True:
return _(
"qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweas "
+ "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwegqweasdzxcqweasdzxc.",
"qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwe",
) % {"reported_username": reported_username, "report_reason": report_reason}
```

View File

@@ -56,7 +56,12 @@ assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx(
# Example from https://github.com/psf/black/issues/3229
@@ -43,8 +41,6 @@
@@ -39,12 +37,10 @@
# https://github.com/psf/black/pull/3370 causes an infinite recursion.
assert (
long_module.long_class.long_func().another_func()
- == long_module.long_class.long_func()["some_key"].another_func(arg1)
+ == long_module.long_class.long_func()["some_key"].another_func(arg1)
)
# Regression test for https://github.com/psf/black/issues/3414.

View File

@@ -504,7 +504,10 @@ aaaaaaaaaaaaaa + {
# But only for expressions that have a statement parent.
not (
aaaaaaaaaaaaaa
+ {a for x in bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb}
+ {
a
for x in bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
}
)
[
a

View File

@@ -348,7 +348,10 @@ if True:
to_fields is None
or
# Reference to primary key.
(None in to_fields and (reference_field is None or reference_field.primary_key))
(
None in to_fields
and (reference_field is None or reference_field.primary_key)
)
or
# Reference to field.
reference_field_name in to_fields

View File

@@ -531,7 +531,22 @@ def double(
) -> (
int
| list[
int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int
int,
int,
int,
int,
int,
int,
int,
int,
int,
int,
int,
int,
int,
int,
int,
int,
] # Hello
):
pass