mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-26 20:10:09 +00:00
Respect magic trailing comma for set expression (#5782)
<!-- Thank you for contributing to Ruff! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? - Does this pull request include references to any relevant issues? --> ## Summary This PR uses the `join_comma_separated` builder for formatting set expressions to ensure the formatting preserves magic commas, if the setting is enabled. <!-- What's the purpose of the change? What does it do, and why? --> ## Test Plan See the fixed black tests <!-- How was it tested? -->
This commit is contained in:
parent
fa4855e6fe
commit
df2efe81c8
2 changed files with 8 additions and 319 deletions
|
@ -1,9 +1,10 @@
|
||||||
|
use rustpython_parser::ast::{ExprSet, Ranged};
|
||||||
|
|
||||||
|
use ruff_python_ast::node::AnyNodeRef;
|
||||||
|
|
||||||
use crate::expression::parentheses::{parenthesized, NeedsParentheses, OptionalParentheses};
|
use crate::expression::parentheses::{parenthesized, NeedsParentheses, OptionalParentheses};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::FormatNodeRule;
|
use crate::FormatNodeRule;
|
||||||
use ruff_formatter::format_args;
|
|
||||||
use ruff_python_ast::node::AnyNodeRef;
|
|
||||||
use rustpython_parser::ast::ExprSet;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FormatExprSet;
|
pub struct FormatExprSet;
|
||||||
|
@ -14,13 +15,13 @@ impl FormatNodeRule<ExprSet> for FormatExprSet {
|
||||||
// That would be a dict expression
|
// That would be a dict expression
|
||||||
assert!(!elts.is_empty());
|
assert!(!elts.is_empty());
|
||||||
// Avoid second mutable borrow of f
|
// Avoid second mutable borrow of f
|
||||||
let joined = format_with(|f| {
|
let joined = format_with(|f: &mut PyFormatter| {
|
||||||
f.join_with(format_args!(text(","), soft_line_break_or_space()))
|
f.join_comma_separated(item.end())
|
||||||
.entries(elts.iter().formatted())
|
.nodes(elts.iter())
|
||||||
.finish()
|
.finish()
|
||||||
});
|
});
|
||||||
|
|
||||||
parenthesized("{", &format_args![joined, if_group_breaks(&text(","))], "}").fmt(f)
|
parenthesized("{", &joined, "}").fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,312 +0,0 @@
|
||||||
---
|
|
||||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
|
||||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/collections.py
|
|
||||||
---
|
|
||||||
## Input
|
|
||||||
|
|
||||||
```py
|
|
||||||
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
|
|
||||||
@@ -18,23 +18,12 @@
|
|
||||||
xyzzy as magic,
|
|
||||||
)
|
|
||||||
|
|
||||||
-a = {
|
|
||||||
- 1,
|
|
||||||
- 2,
|
|
||||||
- 3,
|
|
||||||
-}
|
|
||||||
+a = {1, 2, 3}
|
|
||||||
b = {1, 2, 3}
|
|
||||||
-c = {
|
|
||||||
- 1,
|
|
||||||
- 2,
|
|
||||||
- 3,
|
|
||||||
-}
|
|
||||||
+c = {1, 2, 3}
|
|
||||||
x = (1,)
|
|
||||||
y = (narf(),)
|
|
||||||
-nested = {
|
|
||||||
- (1, 2, 3),
|
|
||||||
- (4, 5, 6),
|
|
||||||
-}
|
|
||||||
+nested = {(1, 2, 3), (4, 5, 6)}
|
|
||||||
nested_no_trailing_comma = {(1, 2, 3), (4, 5, 6)}
|
|
||||||
nested_long_lines = [
|
|
||||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
||||||
```
|
|
||||||
|
|
||||||
## Ruff Output
|
|
||||||
|
|
||||||
```py
|
|
||||||
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
|
|
||||||
|
|
||||||
```py
|
|
||||||
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,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue