Format ExprTuple (#4963)

This implements formatting ExprTuple, including magic trailing comma. I
intentionally didn't change the settings mechanism but just added a
dummy global const flag.

Besides the snapshots, I added custom breaking/joining tests and a
deeply nested test case. The diffs look better than previously, proper
black compatibility depends on parentheses handling.

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
This commit is contained in:
konstin 2023-06-12 14:55:47 +02:00 committed by GitHub
parent 8161757229
commit e586c27590
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 735 additions and 219 deletions

View file

@ -0,0 +1,59 @@
# Non-wrapping parentheses checks
a1 = 1, 2
a2 = (1, 2)
a3 = (1, 2), 3
a4 = ((1, 2), 3)
# Wrapping parentheses checks
b1 = (("Michael", "Ende"), ("Der", "satanarchäolügenialkohöllische", "Wunschpunsch"), ("Beelzebub", "Irrwitzer"), ("Tyrannja", "Vamperl"),)
b2 = ("akjdshflkjahdslkfjlasfdahjlfds", "ljklsadhflakfdajflahfdlajfhafldkjalfj", "ljklsadhflakfdajflahfdlajfhafldkjalf2",)
b3 = ("The", "Night", "of", "Wishes:", "Or", "the", "Satanarchaeolidealcohellish", "Notion", "Potion",)
# Nested wrapping parentheses check
c1 = (("cicero"), ("Qui", "autem,", "si", "maxime", "hoc", "placeat,", "moderatius", "tamen", "id", "uolunt", "fieri,", "difficilem", "quandam", "temperantiam", "postulant", "in", "eo,", "quod", "semel", "admissum", "coerceri", "reprimique", "non", "potest,", "ut", "propemodum", "iustioribus", "utamur", "illis,", "qui", "omnino", "auocent", "a", "philosophia,", "quam", "his,", "qui", "rebus", "infinitis", "modum", "constituant", "in", "reque", "eo", "meliore,", "quo", "maior", "sit,", "mediocritatem", "desiderent."), ("de", "finibus", "bonorum", "et", "malorum"))
# Deeply nested parentheses
d1 = ((("3D",),),)
d2 = (((((((((((((((((((((((((((("¯\_(ツ)_/¯",),),),),),),),),),),),),),),),),),),),),),),),),),),),)
# Join and magic trailing comma
e1 = (
1,
2
)
e2 = (
1,
2,
)
e3 = (
1,
)
e4 = (
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor",
"incididunt"
)
# Empty tuples and comments
f1 = (
# empty
)
f2 = ()
# Comments in other tuples
g1 = ( # a
# b
1, # c
# d
) # e
g2 = ( # a
# b
1, # c
# d
2, # e
# f
) # g
# Ensure the correct number of parentheses
h1 = ((((1, 2))))
h2 = ((((1, "qweiurpoiqwurepqiurpqirpuqoiwrupqoirupqoirupqoiurpqiorupwqiourpqurpqurpqurpqurpqurpqurüqurqpuriq"))))
h3 = 1, "qweiurpoiqwurepqiurpqirpuqoiwrupqoirupqoirupqoiurpqiorupwqiourpqurpqurpqurpqurpqurpqurüqurqpuriq"

View file

@ -1,17 +1,130 @@
use crate::comments::Comments;
use crate::comments::{dangling_node_comments, Comments};
use crate::context::PyFormatContext;
use crate::expression::parentheses::{
default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize,
};
use crate::{not_yet_implemented_custom_text, FormatNodeRule, PyFormatter};
use ruff_formatter::{write, Buffer, FormatResult};
use crate::trivia::Token;
use crate::trivia::{first_non_trivia_token, TokenKind};
use crate::{AsFormat, FormatNodeRule, FormattedIterExt, PyFormatter, USE_MAGIC_TRAILING_COMMA};
use ruff_formatter::formatter::Formatter;
use ruff_formatter::prelude::{
block_indent, group, if_group_breaks, soft_block_indent, soft_line_break_or_space, text,
};
use ruff_formatter::{format_args, write, Buffer, Format, FormatResult};
use ruff_python_ast::prelude::{Expr, Ranged};
use ruff_text_size::TextRange;
use rustpython_parser::ast::ExprTuple;
#[derive(Default)]
pub struct FormatExprTuple;
impl FormatNodeRule<ExprTuple> for FormatExprTuple {
fn fmt_fields(&self, _item: &ExprTuple, f: &mut PyFormatter) -> FormatResult<()> {
write!(f, [not_yet_implemented_custom_text("(1, 2)")])
fn fmt_fields(&self, item: &ExprTuple, f: &mut PyFormatter) -> FormatResult<()> {
let ExprTuple {
range,
elts,
ctx: _,
} = item;
// Handle the edge cases of an empty tuple and a tuple with one element
let last = match &elts[..] {
[] => {
return write!(
f,
[
// An empty tuple always needs parentheses, but does not have a comma
&text("("),
block_indent(&dangling_node_comments(item)),
&text(")"),
]
);
}
[single] => {
return write!(
f,
[group(&format_args![
// A single element tuple always needs parentheses and a trailing comma
&text("("),
soft_block_indent(&format_args![single.format(), &text(",")]),
&text(")"),
])]
);
}
[.., last] => last,
};
let magic_trailing_comma = USE_MAGIC_TRAILING_COMMA
&& matches!(
first_non_trivia_token(last.range().end(), f.context().contents()),
Some(Token {
kind: TokenKind::Comma,
..
})
);
if magic_trailing_comma {
// A magic trailing comma forces us to print in expanded mode since we have more than
// one element
write!(
f,
[
// An expanded group always needs parentheses
&text("("),
block_indent(&ExprSequence::new(elts)),
&text(")"),
]
)?;
} else if is_parenthesized(*range, elts, f) {
// If the tuple has parentheses, keep them. Note that unlike other expr parentheses,
// those are actually part of the range
write!(
f,
[group(&format_args![
// If there were previously parentheses, keep them
&text("("),
soft_block_indent(&ExprSequence::new(elts)),
&text(")"),
])]
)?;
} else {
write!(
f,
[group(&format_args![
// If there were previously no parentheses, add them only if the group breaks
if_group_breaks(&text("(")),
soft_block_indent(&ExprSequence::new(elts)),
if_group_breaks(&text(")")),
])]
)?;
}
Ok(())
}
fn fmt_dangling_comments(&self, _node: &ExprTuple, _f: &mut PyFormatter) -> FormatResult<()> {
// Handled in `fmt_fields`
Ok(())
}
}
#[derive(Debug)]
struct ExprSequence<'a> {
elts: &'a [Expr],
}
impl<'a> ExprSequence<'a> {
const fn new(elts: &'a [Expr]) -> Self {
Self { elts }
}
}
impl Format<PyFormatContext<'_>> for ExprSequence<'_> {
fn fmt(&self, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> {
f.join_with(&format_args!(text(","), soft_line_break_or_space()))
.entries(self.elts.iter().formatted())
.finish()?;
// Black style has a trailing comma on the last entry of an expanded group
write!(f, [if_group_breaks(&text(","))])
}
}
@ -28,3 +141,29 @@ impl NeedsParentheses for ExprTuple {
}
}
}
/// Check if a tuple has already had parentheses in the input
fn is_parenthesized(
tuple_range: TextRange,
elts: &[Expr],
f: &mut Formatter<PyFormatContext<'_>>,
) -> bool {
let parentheses = '(';
let first_char = &f.context().contents()[usize::from(tuple_range.start())..]
.chars()
.next();
let Some(first_char) = first_char else {
return false;
};
if *first_char != parentheses {
return false;
}
// Consider `a = (1, 2), 3`: The first char of the current expr starts is a parentheses, but
// it's not its own but that of its first tuple child. We know that it belongs to the child
// because if it wouldn't, the child would start (at least) a char later
let Some(first_child) = elts.first() else {
return false;
};
first_child.range().start() != tuple_range.start()
}

View file

@ -30,6 +30,10 @@ mod trivia;
include!("../../ruff_formatter/shared_traits.rs");
/// TODO(konstin): hook this up to the settings by replacing `SimpleFormatOptions` with a python
/// specific struct.
pub(crate) const USE_MAGIC_TRAILING_COMMA: bool = true;
/// 'ast is the lifetime of the source code (input), 'buf is the lifetime of the buffer (output)
pub(crate) type PyFormatter<'ast, 'buf> = Formatter<'buf, PyFormatContext<'ast>>;

View file

@ -122,28 +122,25 @@ if True:
- 2,
- 3,
-}
-x = (1,)
+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)}
+c = {1, 2, 3}
+x = (1, 2)
+y = (1, 2)
+nested = {(1, 2), (1, 2)}
+nested_no_trailing_comma = {(1, 2), (1, 2)}
+y = (NOT_IMPLEMENTED_call(),)
+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),
+ "NOT_YET_IMPLEMENTED_STRING",
+ "NOT_YET_IMPLEMENTED_STRING",
+ "NOT_YET_IMPLEMENTED_STRING",
(1, 2, 3),
- "dddddddddddddddddddddddddddddddddddddddd",
+ "NOT_YET_IMPLEMENTED_STRING",
+ "NOT_YET_IMPLEMENTED_STRING",
+ "NOT_YET_IMPLEMENTED_STRING",
+ (1, 2),
+ "NOT_YET_IMPLEMENTED_STRING",
]
-{
@ -161,7 +158,7 @@ if True:
-)
+{NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value}
+{NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value}
+["NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING" % (1, 2)]
+["NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING" % (foo,)]
+x = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value}
+y = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value}
+NOT_YET_IMPLEMENTED_StmtAssert
@ -181,9 +178,8 @@ if True:
-]
+[1, 2, 3]
-division_result_tuple = (6 / 2,)
division_result_tuple = (6 / 2,)
-print("foo %r", (foo.bar,))
+division_result_tuple = (1, 2)
+NOT_IMPLEMENTED_call()
if True:
@ -238,20 +234,20 @@ NOT_YET_IMPLEMENTED_StmtImportFrom
a = {1, 2, 3}
b = {1, 2, 3}
c = {1, 2, 3}
x = (1, 2)
y = (1, 2)
nested = {(1, 2), (1, 2)}
nested_no_trailing_comma = {(1, 2), (1, 2)}
x = (1,)
y = (NOT_IMPLEMENTED_call(),)
nested = {(1, 2, 3), (4, 5, 6)}
nested_no_trailing_comma = {(1, 2, 3), (4, 5, 6)}
nested_long_lines = [
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
(1, 2),
(1, 2, 3),
"NOT_YET_IMPLEMENTED_STRING",
]
{NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value}
{NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value}
["NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING" % (1, 2)]
["NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING" % (foo,)]
x = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value}
y = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value}
NOT_YET_IMPLEMENTED_StmtAssert
@ -262,7 +258,7 @@ NOT_YET_IMPLEMENTED_StmtFor
[1, 2, 3]
division_result_tuple = (1, 2)
division_result_tuple = (6 / 2,)
NOT_IMPLEMENTED_call()
if True:

View file

@ -137,7 +137,7 @@ aaaaaaaaaaaaa, bbbbbbbbb = map(list, map(itertools.chain.from_iterable, zip(*ite
def f(
@@ -49,15 +49,10 @@
@@ -49,10 +49,8 @@
element = 0 # type: int
another_element = 1 # type: float
another_element_with_long_name = 2 # type: int
@ -148,15 +148,9 @@ aaaaaaaaaaaaa, bbbbbbbbb = map(list, map(itertools.chain.from_iterable, zip(*ite
+ another_really_really_long_element_with_a_unnecessarily_long_name_to_describe_what_it_does_enterprise_style = 3 # type: int
+ an_element_with_a_long_value = NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2 # type: bool
- tup = (
- another_element,
- another_really_really_long_element_with_a_unnecessarily_long_name_to_describe_what_it_does_enterprise_style,
- ) # type: Tuple[int, int]
+ tup = (1, 2) # type: Tuple[int, int]
a = (
element
@@ -84,35 +79,22 @@
tup = (
another_element,
@@ -84,35 +82,22 @@
def func(
@ -203,7 +197,7 @@ aaaaaaaaaaaaa, bbbbbbbbb = map(list, map(itertools.chain.from_iterable, zip(*ite
+NOT_IMPLEMENTED_call()
-aaaaaaaaaaaaa, bbbbbbbbb = map(list, map(itertools.chain.from_iterable, zip(*items))) # type: ignore[arg-type]
+(1, 2) = NOT_IMPLEMENTED_call() # type: ignore[arg-type]
+aaaaaaaaaaaaa, bbbbbbbbb = NOT_IMPLEMENTED_call() # type: ignore[arg-type]
```
## Ruff Output
@ -263,7 +257,10 @@ def f(
another_really_really_long_element_with_a_unnecessarily_long_name_to_describe_what_it_does_enterprise_style = 3 # type: int
an_element_with_a_long_value = NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2 # type: bool
tup = (1, 2) # type: Tuple[int, int]
tup = (
another_element,
another_really_really_long_element_with_a_unnecessarily_long_name_to_describe_what_it_does_enterprise_style,
) # type: Tuple[int, int]
a = (
element
@ -308,7 +305,7 @@ AAAAAAAAAAAAA = (
NOT_IMPLEMENTED_call()
(1, 2) = NOT_IMPLEMENTED_call() # type: ignore[arg-type]
aaaaaaaaaaaaa, bbbbbbbbb = NOT_IMPLEMENTED_call() # type: ignore[arg-type]
```
## Black Output

View file

@ -42,8 +42,7 @@ def function(a:int=42):
+NOT_YET_IMPLEMENTED_StmtImportFrom
result = 1 # A simple comment
-result = (1,) # Another one
+result = (1, 2) # Another one
result = (1,) # Another one
result = 1 #  type: ignore
result = 1 # This comment is talking about type: ignore
@ -68,7 +67,7 @@ def function(a:int=42):
NOT_YET_IMPLEMENTED_StmtImportFrom
result = 1 # A simple comment
result = (1, 2) # Another one
result = (1,) # Another one
result = 1 #  type: ignore
result = 1 # This comment is talking about type: ignore

View file

@ -342,8 +342,6 @@ last_call()
-{**a, **b, **c}
-{"2.7", "3.6", "3.7", "3.8", "3.9", ("4.0" if gilectomy else "3.10")}
-({"a": "b"}, (True or False), (+value), "string", b"bytes") or None
-()
-(1,)
+NOT_YET_IMPLEMENTED_ExprUnaryOp
+NOT_YET_IMPLEMENTED_ExprUnaryOp
+NOT_YET_IMPLEMENTED_ExprUnaryOp
@ -377,11 +375,10 @@ last_call()
+ (NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false),
+}
+NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2
+(1, 2)
+(1, 2)
+(1, 2)
()
(1,)
(1, 2)
-(1, 2, 3)
(1, 2, 3)
[]
-[1, 2, 3, 4, 5, 6, 7, 8, 9, (10 or A), (11 or B), (12 or C)]
[
@ -395,11 +392,6 @@ last_call()
- *a,
4,
5,
-]
-[
- 4,
- *a,
- 5,
+ 6,
+ 7,
+ 8,
@ -408,6 +400,11 @@ last_call()
+ (NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2),
+ (NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2),
]
-[
- 4,
- *a,
- 5,
-]
+[1, 2, 3]
+[NOT_YET_IMPLEMENTED_ExprStarred]
+[NOT_YET_IMPLEMENTED_ExprStarred]
@ -541,6 +538,9 @@ last_call()
- int,
- float,
- dict[str, int],
-]
-very_long_variable_name_filters: t.List[
- t.Tuple[str, t.Union[str, t.List[t.Optional[str]]]],
+[
+ 1,
+ 2,
@ -555,9 +555,6 @@ last_call()
+ NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2,
+ NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2,
]
-very_long_variable_name_filters: t.List[
- t.Tuple[str, t.Union[str, t.List[t.Optional[str]]]],
-]
-xxxx_xxxxx_xxxx_xxx: Callable[..., List[SomeClass]] = classmethod( # type: ignore
- sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__)
-)
@ -599,7 +596,7 @@ last_call()
-[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]
(SomeName)
SomeName
-(Good, Bad, Ugly)
(Good, Bad, Ugly)
-(i for i in (1, 2, 3))
-((i**2) for i in (1, 2, 3))
-((i**2) for i, _ in ((1, "a"), (2, "b"), (3, "c")))
@ -614,38 +611,25 @@ last_call()
- "import_session_id": 1,
- **kwargs,
-}
-a = (1,)
-b = (1,)
+(1, 2)
+(i for i in [])
+(i for i in [])
+(i for i in [])
+(i for i in [])
+(1, 2)
+(NOT_YET_IMPLEMENTED_ExprStarred,)
+{NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value}
+a = (1, 2)
+b = (1, 2)
a = (1,)
b = (1,)
c = 1
-d = (1,) + a + (2,)
d = (1,) + a + (2,)
-e = (1,).count(1)
-f = 1, *range(10)
-g = 1, *"ten"
-what_is_up_with_those_new_coord_names = (coord_names + set(vars_to_create)) + set(
- vars_to_remove
+d = (1, 2) + a + (1, 2)
+e = NOT_IMPLEMENTED_call()
+f = (1, 2)
+g = (1, 2)
+what_is_up_with_those_new_coord_names = (
+ (coord_names + NOT_IMPLEMENTED_call())
+ + NOT_IMPLEMENTED_call()
)
-)
-what_is_up_with_those_new_coord_names = (coord_names | set(vars_to_create)) - set(
- vars_to_remove
+what_is_up_with_those_new_coord_names = (
+ (coord_names | NOT_IMPLEMENTED_call())
+ - NOT_IMPLEMENTED_call()
)
-)
-result = (
- session.query(models.Customer.id)
- .filter(
@ -653,7 +637,13 @@ last_call()
- )
- .order_by(models.Customer.id.asc())
- .all()
-)
+e = NOT_IMPLEMENTED_call()
+f = 1, NOT_YET_IMPLEMENTED_ExprStarred
+g = 1, NOT_YET_IMPLEMENTED_ExprStarred
+what_is_up_with_those_new_coord_names = (
+ (coord_names + NOT_IMPLEMENTED_call())
+ + NOT_IMPLEMENTED_call()
)
-result = (
- session.query(models.Customer.id)
- .filter(
@ -663,7 +653,10 @@ last_call()
- models.Customer.id.asc(),
- )
- .all()
-)
+what_is_up_with_those_new_coord_names = (
+ (coord_names | NOT_IMPLEMENTED_call())
+ - NOT_IMPLEMENTED_call()
)
-Ø = set()
-authors.łukasz.say_thanks()
-mapping = {
@ -899,10 +892,10 @@ NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
(NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false),
}
NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2
()
(1,)
(1, 2)
(1, 2)
(1, 2)
(1, 2)
(1, 2, 3)
[]
[
1,
@ -1020,20 +1013,20 @@ NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false
]
(SomeName)
SomeName
(1, 2)
(Good, Bad, Ugly)
(i for i in [])
(i for i in [])
(i for i in [])
(i for i in [])
(1, 2)
(NOT_YET_IMPLEMENTED_ExprStarred,)
{NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value}
a = (1, 2)
b = (1, 2)
a = (1,)
b = (1,)
c = 1
d = (1, 2) + a + (1, 2)
d = (1,) + a + (2,)
e = NOT_IMPLEMENTED_call()
f = (1, 2)
g = (1, 2)
f = 1, NOT_YET_IMPLEMENTED_ExprStarred
g = 1, NOT_YET_IMPLEMENTED_ExprStarred
what_is_up_with_those_new_coord_names = (
(coord_names + NOT_IMPLEMENTED_call())
+ NOT_IMPLEMENTED_call()

View file

@ -101,8 +101,8 @@ def test_calculate_fades():
# one is zero/none
- (0, 4, 0, 0, 10, 0, 0, 6, 10),
- (None, 4, 0, 0, 10, 0, 0, 6, 10),
+ (1, 2),
+ (1, 2),
+ (0, 4, 0, 0, 10, 0, 0, 6, 10),
+ (None, 4, 0, 0, 10, 0, 0, 6, 10),
]
# fmt: on
@ -144,8 +144,8 @@ def verify_fader(test):
def test_calculate_fades():
calcs = [
# one is zero/none
(1, 2),
(1, 2),
(0, 4, 0, 0, 10, 0, 0, 6, 10),
(None, 4, 0, 0, 10, 0, 0, 6, 10),
]
# fmt: on

View file

@ -207,10 +207,10 @@ d={'a':1,
+NOT_YET_IMPLEMENTED_StmtImport
-from third_party import X, Y, Z
-
-from library import some_connection, some_decorator
+NOT_YET_IMPLEMENTED_StmtImportFrom
-from library import some_connection, some_decorator
-
+NOT_YET_IMPLEMENTED_StmtImportFrom
# fmt: off
-from third_party import (X,
@ -281,7 +281,7 @@ d={'a':1,
- assert task._cancel_stack[: len(old_stack)] == old_stack
+def spaces(
+ a=1,
+ b=(1, 2),
+ b=(),
+ c=[],
+ d={NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value},
+ e=True,
@ -296,8 +296,7 @@ d={'a':1,
def spaces_types(
a: int = 1,
- b: tuple = (),
+ b: tuple = (1, 2),
b: tuple = (),
c: list = [],
- d: dict = {},
+ d: dict = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value},
@ -351,7 +350,7 @@ d={'a':1,
# fmt: off
- a , b = *hello
- 'unformatted'
+ (1, 2) = NOT_YET_IMPLEMENTED_ExprStarred
+ a, b = NOT_YET_IMPLEMENTED_ExprStarred
+ "NOT_YET_IMPLEMENTED_STRING"
# fmt: on
@ -463,9 +462,8 @@ d={'a':1,
def single_literal_yapf_disable():
- """Black does not support this."""
- BAZ = {(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)} # yapf: disable
+ "NOT_YET_IMPLEMENTED_STRING"
+ BAZ = {(1, 2), (1, 2), (1, 2)} # yapf: disable
BAZ = {(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)} # yapf: disable
-cfg.rule(
@ -561,7 +559,7 @@ def function_signature_stress_test(
# fmt: on
def spaces(
a=1,
b=(1, 2),
b=(),
c=[],
d={NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value},
e=True,
@ -576,7 +574,7 @@ def spaces(
def spaces_types(
a: int = 1,
b: tuple = (1, 2),
b: tuple = (),
c: list = [],
d: dict = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value},
e: bool = True,
@ -608,7 +606,7 @@ def import_as_names():
def testlist_star_expr():
# fmt: off
(1, 2) = NOT_YET_IMPLEMENTED_ExprStarred
a, b = NOT_YET_IMPLEMENTED_ExprStarred
"NOT_YET_IMPLEMENTED_STRING"
# fmt: on
@ -668,7 +666,7 @@ def long_lines():
def single_literal_yapf_disable():
"NOT_YET_IMPLEMENTED_STRING"
BAZ = {(1, 2), (1, 2), (1, 2)} # yapf: disable
BAZ = {(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)} # yapf: disable
NOT_IMPLEMENTED_call()

View file

@ -25,7 +25,7 @@ f = ["This is a very long line that should be formatted into a clearer line ", "
# fmt: off
-b, c = 1, 2
-d = 6 # fmt: skip
+(1, 2) = (1, 2)
+b, c = 1, 2
+d = 6 # fmt: skip
e = 5
# fmt: on
@ -41,7 +41,7 @@ f = ["This is a very long line that should be formatted into a clearer line ", "
```py
a = 3
# fmt: off
(1, 2) = (1, 2)
b, c = 1, 2
d = 6 # fmt: skip
e = 5
# fmt: on

View file

@ -23,14 +23,13 @@ else:
--- Black
+++ Ruff
@@ -1,9 +1,5 @@
-a, b, c = 3, 4, 5
a, b, c = 3, 4, 5
-if (
- a == 3
- and b != 9 # fmt: skip
- and c is not None
-):
- print("I'm good!")
+(1, 2) = (1, 2)
+if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2:
+ NOT_IMPLEMENTED_call()
else:
@ -41,7 +40,7 @@ else:
## Ruff Output
```py
(1, 2) = (1, 2)
a, b, c = 3, 4, 5
if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2:
NOT_IMPLEMENTED_call()
else:

View file

@ -17,9 +17,8 @@ d = 5
--- Black
+++ Ruff
@@ -1,3 +1,3 @@
-a, b = 1, 2
a, b = 1, 2
-c = 6 # fmt: skip
+(1, 2) = (1, 2)
+c = 6 # fmt: skip
d = 5
```
@ -27,7 +26,7 @@ d = 5
## Ruff Output
```py
(1, 2) = (1, 2)
a, b = 1, 2
c = 6 # fmt: skip
d = 5
```

View file

@ -175,7 +175,7 @@ def __await__(): return (yield)
- assert task._cancel_stack[: len(old_stack)] == old_stack
+def spaces(
+ a=1,
+ b=(1, 2),
+ b=(),
+ c=[],
+ d={NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value},
+ e=True,
@ -190,8 +190,7 @@ def __await__(): return (yield)
def spaces_types(
a: int = 1,
- b: tuple = (),
+ b: tuple = (1, 2),
b: tuple = (),
c: list = [],
- d: dict = {},
+ d: dict = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value},
@ -348,7 +347,7 @@ def function_signature_stress_test(
def spaces(
a=1,
b=(1, 2),
b=(),
c=[],
d={NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value},
e=True,
@ -363,7 +362,7 @@ def spaces(
def spaces_types(
a: int = 1,
b: tuple = (1, 2),
b: tuple = (),
c: list = [],
d: dict = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value},
e: bool = True,

View file

@ -74,19 +74,18 @@ some_module.some_function(
```diff
--- Black
+++ Ruff
@@ -1,69 +1,30 @@
@@ -1,9 +1,7 @@
def f(
a,
):
- d = {
- "key": "value",
- }
- tup = (1,)
+ d = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value}
+ tup = (1, 2)
tup = (1,)
def f2(
@@ -11,10 +9,7 @@
a,
b,
):
@ -94,14 +93,11 @@ some_module.some_function(
- "key": "value",
- "key2": "value2",
- }
- tup = (
- 1,
- 2,
- )
+ d = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value}
+ tup = (1, 2)
tup = (
1,
2,
@@ -24,46 +19,15 @@
def f(
a: int = 1,
):
@ -154,7 +150,7 @@ some_module.some_function(
# The type annotation shouldn't get a trailing comma since that would change its type.
@@ -80,35 +41,16 @@
@@ -80,35 +44,16 @@
pass
@ -203,7 +199,7 @@ def f(
a,
):
d = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value}
tup = (1, 2)
tup = (1,)
def f2(
@ -211,7 +207,10 @@ def f2(
b,
):
d = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value}
tup = (1, 2)
tup = (
1,
2,
)
def f(

View file

@ -96,11 +96,6 @@ return np.divide(
-j = super().name ** 5
-k = [(2**idx, value) for idx, value in pairs]
-l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001)
-m = [([2**63], [1, 2**63])]
-n = count <= 10**5
-o = settings(max_examples=10**6)
-p = {(k, k**2): v**2 for k, v in pairs}
-q = [10**i for i in range(6)]
+a = 5**NOT_YET_IMPLEMENTED_ExprUnaryOp
+b = 5 ** NOT_IMPLEMENTED_call()
+c = NOT_YET_IMPLEMENTED_ExprUnaryOp
@ -113,7 +108,11 @@ return np.divide(
+j = NOT_IMPLEMENTED_call().NOT_IMPLEMENTED_attr ** 5
+k = [i for i in []]
+l = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right
+m = [(1, 2)]
m = [([2**63], [1, 2**63])]
-n = count <= 10**5
-o = settings(max_examples=10**6)
-p = {(k, k**2): v**2 for k, v in pairs}
-q = [10**i for i in range(6)]
+n = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right
+o = NOT_IMPLEMENTED_call()
+p = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict}
@ -132,11 +131,6 @@ return np.divide(
-j = super().name ** 5.0
-k = [(2.0**idx, value) for idx, value in pairs]
-l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001)
-m = [([2.0**63.0], [1.0, 2**63.0])]
-n = count <= 10**5.0
-o = settings(max_examples=10**6.0)
-p = {(k, k**2): v**2.0 for k, v in pairs}
-q = [10.5**i for i in range(6)]
+a = 5.0**NOT_YET_IMPLEMENTED_ExprUnaryOp
+b = 5.0 ** NOT_IMPLEMENTED_call()
+c = NOT_YET_IMPLEMENTED_ExprUnaryOp
@ -149,7 +143,11 @@ return np.divide(
+j = NOT_IMPLEMENTED_call().NOT_IMPLEMENTED_attr ** 5.0
+k = [i for i in []]
+l = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right
+m = [(1, 2)]
m = [([2.0**63.0], [1.0, 2**63.0])]
-n = count <= 10**5.0
-o = settings(max_examples=10**6.0)
-p = {(k, k**2): v**2.0 for k, v in pairs}
-q = [10.5**i for i in range(6)]
+n = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right
+o = NOT_IMPLEMENTED_call()
+p = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict}
@ -201,7 +199,7 @@ i = NOT_IMPLEMENTED_call() ** 5
j = NOT_IMPLEMENTED_call().NOT_IMPLEMENTED_attr ** 5
k = [i for i in []]
l = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right
m = [(1, 2)]
m = [([2**63], [1, 2**63])]
n = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right
o = NOT_IMPLEMENTED_call()
p = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict}
@ -220,7 +218,7 @@ i = NOT_IMPLEMENTED_call() ** 5.0
j = NOT_IMPLEMENTED_call().NOT_IMPLEMENTED_attr ** 5.0
k = [i for i in []]
l = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right
m = [(1, 2)]
m = [([2.0**63.0], [1.0, 2**63.0])]
n = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right
o = NOT_IMPLEMENTED_call()
p = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict}

View file

@ -25,22 +25,15 @@ xxxxxxxxx_yyy_zzzzzzzz[xx.xxxxxx(x_yyy_zzzzzz.xxxxx[0]), x_yyy_zzzzzz.xxxxxx(xxx
```diff
--- Black
+++ Ruff
@@ -2,20 +2,8 @@
# Left hand side fits in a single line but will still be exploded by the
# magic trailing comma.
-(
- first_value,
- (
- m1,
- m2,
- ),
- third_value,
@@ -9,13 +9,8 @@
m2,
),
third_value,
-) = xxxxxx_yyyyyy_zzzzzz_wwwwww_uuuuuuu_vvvvvvvvvvv(
- arg1,
- arg2,
-)
+(1, 2) = NOT_IMPLEMENTED_call()
+) = NOT_IMPLEMENTED_call()
# 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.
@ -57,7 +50,14 @@ xxxxxxxxx_yyy_zzzzzzzz[xx.xxxxxx(x_yyy_zzzzzz.xxxxx[0]), x_yyy_zzzzzz.xxxxxx(xxx
# Left hand side fits in a single line but will still be exploded by the
# magic trailing comma.
(1, 2) = NOT_IMPLEMENTED_call()
(
first_value,
(
m1,
m2,
),
third_value,
) = NOT_IMPLEMENTED_call()
# 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.

View file

@ -114,12 +114,7 @@ def example8():
def example4():
@@ -46,39 +34,15 @@
def example5():
- return ()
+ return (1, 2)
@@ -50,35 +38,11 @@
def example6():
@ -198,7 +193,7 @@ def example4():
def example5():
return (1, 2)
return ()
def example6():

View file

@ -60,7 +60,7 @@ func(
```diff
--- Black
+++ Ruff
@@ -1,25 +1,25 @@
@@ -1,25 +1,30 @@
# We should not remove the trailing comma in a single-element subscript.
-a: tuple[int,]
-b = tuple[int,]
@ -82,8 +82,7 @@ func(
+set_of_types = {NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]}
# Except single element tuples
-small_tuple = (1,)
+small_tuple = (1, 2)
small_tuple = (1,)
# Trailing commas in multiple chained non-nested parens.
-zero(one).two(three).four(five)
@ -93,7 +92,12 @@ func(
+NOT_IMPLEMENTED_call()
-(a, b, c, d) = func1(arg1) and func2(arg2)
+(1, 2) = NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2
+(
+ a,
+ b,
+ c,
+ d,
+) = NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2
-func(argument1, (one, two), argument4, argument5, argument6)
+NOT_IMPLEMENTED_call()
@ -117,14 +121,19 @@ small_set = {1}
set_of_types = {NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]}
# Except single element tuples
small_tuple = (1, 2)
small_tuple = (1,)
# Trailing commas in multiple chained non-nested parens.
NOT_IMPLEMENTED_call()
NOT_IMPLEMENTED_call()
(1, 2) = NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2
(
a,
b,
c,
d,
) = NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2
NOT_IMPLEMENTED_call()
```

View file

@ -76,7 +76,7 @@ x[
```diff
--- Black
+++ Ruff
@@ -1,59 +1,38 @@
@@ -1,59 +1,48 @@
-slice[a.b : c.d]
-slice[d :: d + 1]
-slice[d + 1 :: d]
@ -125,12 +125,22 @@ x[
# These are from PEP-8:
-ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]
-ham[lower:upper], ham[lower:upper:], ham[lower::step]
+(1, 2)
+(1, 2)
+(
+ NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
+ NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
+ NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
+ NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
+ NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
+)
+(
+ NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
+ NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
+ NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
+)
# ham[lower+offset : upper+offset]
-ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]
-ham[lower + offset : upper + offset]
+(1, 2)
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key], NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
+NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
-slice[::, ::]
@ -196,10 +206,20 @@ async def f():
# These are from PEP-8:
(1, 2)
(1, 2)
(
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
)
(
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key],
)
# ham[lower+offset : upper+offset]
(1, 2)
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key], NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]
NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]

View file

@ -33,7 +33,7 @@ def docstring_multiline():
```diff
--- Black
+++ Ruff
@@ -1,20 +1,18 @@
@@ -1,20 +1,36 @@
#!/usr/bin/env python3
-name = "Łukasz"
@ -42,15 +42,33 @@ def docstring_multiline():
-("", "")
-(r"", R"")
+name = "NOT_YET_IMPLEMENTED_STRING"
+(1, 2)
+(1, 2)
+(1, 2)
+(1, 2)
+(NOT_YET_IMPLEMENTED_ExprJoinedStr, NOT_YET_IMPLEMENTED_ExprJoinedStr)
+(b"NOT_YET_IMPLEMENTED_BYTE_STRING", b"NOT_YET_IMPLEMENTED_BYTE_STRING")
+("NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING")
+("NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING")
-(rf"", rf"", Rf"", Rf"", rf"", rf"", Rf"", Rf"")
-(rb"", rb"", Rb"", Rb"", rb"", rb"", Rb"", Rb"")
+(1, 2)
+(1, 2)
+(
+ NOT_YET_IMPLEMENTED_ExprJoinedStr,
+ NOT_YET_IMPLEMENTED_ExprJoinedStr,
+ NOT_YET_IMPLEMENTED_ExprJoinedStr,
+ NOT_YET_IMPLEMENTED_ExprJoinedStr,
+ NOT_YET_IMPLEMENTED_ExprJoinedStr,
+ NOT_YET_IMPLEMENTED_ExprJoinedStr,
+ NOT_YET_IMPLEMENTED_ExprJoinedStr,
+ NOT_YET_IMPLEMENTED_ExprJoinedStr,
+)
+(
+ b"NOT_YET_IMPLEMENTED_BYTE_STRING",
+ b"NOT_YET_IMPLEMENTED_BYTE_STRING",
+ b"NOT_YET_IMPLEMENTED_BYTE_STRING",
+ b"NOT_YET_IMPLEMENTED_BYTE_STRING",
+ b"NOT_YET_IMPLEMENTED_BYTE_STRING",
+ b"NOT_YET_IMPLEMENTED_BYTE_STRING",
+ b"NOT_YET_IMPLEMENTED_BYTE_STRING",
+ b"NOT_YET_IMPLEMENTED_BYTE_STRING",
+)
def docstring_singleline():
@ -71,13 +89,31 @@ def docstring_multiline():
#!/usr/bin/env python3
name = "NOT_YET_IMPLEMENTED_STRING"
(1, 2)
(1, 2)
(1, 2)
(1, 2)
(NOT_YET_IMPLEMENTED_ExprJoinedStr, NOT_YET_IMPLEMENTED_ExprJoinedStr)
(b"NOT_YET_IMPLEMENTED_BYTE_STRING", b"NOT_YET_IMPLEMENTED_BYTE_STRING")
("NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING")
("NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING")
(1, 2)
(1, 2)
(
NOT_YET_IMPLEMENTED_ExprJoinedStr,
NOT_YET_IMPLEMENTED_ExprJoinedStr,
NOT_YET_IMPLEMENTED_ExprJoinedStr,
NOT_YET_IMPLEMENTED_ExprJoinedStr,
NOT_YET_IMPLEMENTED_ExprJoinedStr,
NOT_YET_IMPLEMENTED_ExprJoinedStr,
NOT_YET_IMPLEMENTED_ExprJoinedStr,
NOT_YET_IMPLEMENTED_ExprJoinedStr,
)
(
b"NOT_YET_IMPLEMENTED_BYTE_STRING",
b"NOT_YET_IMPLEMENTED_BYTE_STRING",
b"NOT_YET_IMPLEMENTED_BYTE_STRING",
b"NOT_YET_IMPLEMENTED_BYTE_STRING",
b"NOT_YET_IMPLEMENTED_BYTE_STRING",
b"NOT_YET_IMPLEMENTED_BYTE_STRING",
b"NOT_YET_IMPLEMENTED_BYTE_STRING",
b"NOT_YET_IMPLEMENTED_BYTE_STRING",
)
def docstring_singleline():

View file

@ -42,11 +42,9 @@ assert (
```diff
--- Black
+++ Ruff
@@ -1,58 +1,22 @@
importA
@@ -2,57 +2,21 @@
(
- ()
+ (1, 2)
()
<< 0
- ** 101234234242352525425252352352525234890264906820496920680926538059059209922523523525
+ **101234234242352525425252352352525234890264906820496920680926538059059209922523523525
@ -114,7 +112,7 @@ assert (
```py
importA
(
(1, 2)
()
<< 0
**101234234242352525425252352352525234890264906820496920680926538059059209922523523525
) #

View file

@ -46,7 +46,7 @@ assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx(
```diff
--- Black
+++ Ruff
@@ -1,50 +1,21 @@
@@ -1,50 +1,26 @@
-zero(
- one,
-).two(
@ -67,15 +67,15 @@ assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx(
-func1(arg1).func2(arg1, (one_tuple,)).func3(arg3)
+NOT_IMPLEMENTED_call()
-(
- a,
- b,
- c,
- d,
(
a,
b,
c,
d,
-) = func1(
- arg1
-) and func2(arg2)
+(1, 2) = NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2
+) = NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2
# Example from https://github.com/psf/black/issues/3229
@ -116,7 +116,12 @@ NOT_IMPLEMENTED_call()
# Inner one-element tuple shouldn't explode
NOT_IMPLEMENTED_call()
(1, 2) = NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2
(
a,
b,
c,
d,
) = NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2
# Example from https://github.com/psf/black/issues/3229

View file

@ -20,34 +20,36 @@ this_will_be_wrapped_in_parens, = struct.unpack(b"12345678901234567890")
```diff
--- Black
+++ Ruff
@@ -1,12 +1,7 @@
# This is a standalone comment.
-(
- sdfjklsdfsjldkflkjsf,
- sdfjsdfjlksdljkfsdlkf,
- sdfsdjfklsdfjlksdljkf,
- sdsfsdfjskdflsfsdf,
@@ -4,9 +4,9 @@
sdfjsdfjlksdljkfsdlkf,
sdfsdjfklsdfjlksdljkf,
sdsfsdfjskdflsfsdf,
-) = (1, 2, 3)
+(1, 2) = (1, 2)
+) = 1, 2, 3
# This is as well.
-(this_will_be_wrapped_in_parens,) = struct.unpack(b"12345678901234567890")
+(1, 2) = NOT_IMPLEMENTED_call()
+(this_will_be_wrapped_in_parens,) = NOT_IMPLEMENTED_call()
-(a,) = call()
+(1, 2) = NOT_IMPLEMENTED_call()
+(a,) = NOT_IMPLEMENTED_call()
```
## Ruff Output
```py
# This is a standalone comment.
(1, 2) = (1, 2)
(
sdfjklsdfsjldkflkjsf,
sdfjsdfjlksdljkfsdlkf,
sdfsdjfklsdfjlksdljkf,
sdsfsdfjskdflsfsdf,
) = 1, 2, 3
# This is as well.
(1, 2) = NOT_IMPLEMENTED_call()
(this_will_be_wrapped_in_parens,) = NOT_IMPLEMENTED_call()
(1, 2) = NOT_IMPLEMENTED_call()
(a,) = NOT_IMPLEMENTED_call()
```
## Black Output

View file

@ -86,7 +86,12 @@ aaaaaaaaaaaaaa + [
dddddddddddddddd,
eeeeeee,
]
aaaaaaaaaaaaaa + (1, 2)
aaaaaaaaaaaaaa + (
bbbbbbbbbbbbbbbbbbbbbb,
ccccccccccccccccccccc,
dddddddddddddddd,
eeeeeee,
)
aaaaaaaaaaaaaa + {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value}
aaaaaaaaaaaaaa + {
bbbbbbbbbbbbbbbbbbbbbb,

View file

@ -0,0 +1,267 @@
---
source: crates/ruff_python_formatter/src/lib.rs
expression: snapshot
---
## Input
```py
# Non-wrapping parentheses checks
a1 = 1, 2
a2 = (1, 2)
a3 = (1, 2), 3
a4 = ((1, 2), 3)
# Wrapping parentheses checks
b1 = (("Michael", "Ende"), ("Der", "satanarchäolügenialkohöllische", "Wunschpunsch"), ("Beelzebub", "Irrwitzer"), ("Tyrannja", "Vamperl"),)
b2 = ("akjdshflkjahdslkfjlasfdahjlfds", "ljklsadhflakfdajflahfdlajfhafldkjalfj", "ljklsadhflakfdajflahfdlajfhafldkjalf2",)
b3 = ("The", "Night", "of", "Wishes:", "Or", "the", "Satanarchaeolidealcohellish", "Notion", "Potion",)
# Nested wrapping parentheses check
c1 = (("cicero"), ("Qui", "autem,", "si", "maxime", "hoc", "placeat,", "moderatius", "tamen", "id", "uolunt", "fieri,", "difficilem", "quandam", "temperantiam", "postulant", "in", "eo,", "quod", "semel", "admissum", "coerceri", "reprimique", "non", "potest,", "ut", "propemodum", "iustioribus", "utamur", "illis,", "qui", "omnino", "auocent", "a", "philosophia,", "quam", "his,", "qui", "rebus", "infinitis", "modum", "constituant", "in", "reque", "eo", "meliore,", "quo", "maior", "sit,", "mediocritatem", "desiderent."), ("de", "finibus", "bonorum", "et", "malorum"))
# Deeply nested parentheses
d1 = ((("3D",),),)
d2 = (((((((((((((((((((((((((((("¯\_(ツ)_/¯",),),),),),),),),),),),),),),),),),),),),),),),),),),),)
# Join and magic trailing comma
e1 = (
1,
2
)
e2 = (
1,
2,
)
e3 = (
1,
)
e4 = (
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor",
"incididunt"
)
# Empty tuples and comments
f1 = (
# empty
)
f2 = ()
# Comments in other tuples
g1 = ( # a
# b
1, # c
# d
) # e
g2 = ( # a
# b
1, # c
# d
2, # e
# f
) # g
# Ensure the correct number of parentheses
h1 = ((((1, 2))))
h2 = ((((1, "qweiurpoiqwurepqiurpqirpuqoiwrupqoirupqoirupqoiurpqiorupwqiourpqurpqurpqurpqurpqurpqurüqurqpuriq"))))
h3 = 1, "qweiurpoiqwurepqiurpqirpuqoiwrupqoirupqoirupqoiurpqiorupwqiourpqurpqurpqurpqurpqurpqurüqurqpuriq"
```
## Output
```py
# Non-wrapping parentheses checks
a1 = 1, 2
a2 = (1, 2)
a3 = (1, 2), 3
a4 = ((1, 2), 3)
# Wrapping parentheses checks
b1 = (
("NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING"),
(
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
),
("NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING"),
("NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING"),
)
b2 = (
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
)
b3 = (
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
)
# Nested wrapping parentheses check
c1 = (
("NOT_YET_IMPLEMENTED_STRING"),
(
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
),
(
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
"NOT_YET_IMPLEMENTED_STRING",
),
)
# Deeply nested parentheses
d1 = ((("NOT_YET_IMPLEMENTED_STRING",),),)
d2 = (
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
"NOT_YET_IMPLEMENTED_STRING",
),
),
),
),
),
),
),
),
),
),
),
),
),
),
),
),
),
),
),
),
),
),
),
),
),
),
),
)
# Join and magic trailing comma
e1 = (1, 2)
e2 = (
1,
2,
)
e3 = (1,)
e4 = ("NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING")
# Empty tuples and comments
f1 = (
# empty
)
f2 = ()
# Comments in other tuples
g1 = (
# a
# b
1, # c
# d
) # e
g2 = (
# a
# b
1, # c
# d
2, # e
# f
) # g
# Ensure the correct number of parentheses
h1 = (1, 2)
h2 = (1, "NOT_YET_IMPLEMENTED_STRING")
h3 = 1, "NOT_YET_IMPLEMENTED_STRING"
```