format ExprListComp (#5600)

Co-authored-by: Micha Reiser <micha@reiser.io>
This commit is contained in:
David Szotten 2023-07-11 07:35:51 +01:00 committed by GitHub
parent 987111f5fb
commit 1782fb8c30
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 489 additions and 128 deletions

View file

@ -0,0 +1,32 @@
[i for i in []]
[i for i in [1,]]
[
a # a
for # for
c # c
in # in
e # e
]
[
# above a
a # a
# above for
for # for
# above c
c # c
# above in
in # in
# above e
e # e
# above if
if # if
# above f
f # f
# above if2
if # if2
# above g
g # g
]

View file

@ -38,6 +38,7 @@ pub(super) fn place_comment<'a>(
handle_slice_comments, handle_slice_comments,
handle_attribute_comment, handle_attribute_comment,
handle_expr_if_comment, handle_expr_if_comment,
handle_comprehension_comment,
handle_trailing_expression_starred_star_end_of_line_comment, handle_trailing_expression_starred_star_end_of_line_comment,
]; ];
for handler in HANDLERS { for handler in HANDLERS {
@ -1244,6 +1245,137 @@ fn find_only_token_in_range(range: TextRange, locator: &Locator, token_kind: Tok
token token
} }
// Handle comments inside comprehensions, e.g.
//
// ```python
// [
// a
// for # dangling on the comprehension
// b
// # dangling on the comprehension
// in # dangling on comprehension.iter
// # leading on the iter
// c
// # dangling on comprehension.if.n
// if # dangling on comprehension.if.n
// d
// ]
// ```
fn handle_comprehension_comment<'a>(
comment: DecoratedComment<'a>,
locator: &Locator,
) -> CommentPlacement<'a> {
let AnyNodeRef::Comprehension(comprehension) = comment.enclosing_node() else {
return CommentPlacement::Default(comment);
};
let is_own_line = comment.line_position().is_own_line();
// Comments between the `for` and target
// ```python
// [
// a
// for # attache as dangling on the comprehension
// b in c
// ]
// ```
if comment.slice().end() < comprehension.target.range().start() {
return if is_own_line {
// own line comments are correctly assigned as leading the target
CommentPlacement::Default(comment)
} else {
// after the `for`
CommentPlacement::dangling(comment.enclosing_node(), comment)
};
}
let in_token = find_only_token_in_range(
TextRange::new(
comprehension.target.range().end(),
comprehension.iter.range().start(),
),
locator,
TokenKind::In,
);
// Comments between the target and the `in`
// ```python
// [
// a for b
// # attach as dangling on the target
// # (to be rendered as leading on the "in")
// in c
// ]
// ```
if comment.slice().start() < in_token.start() {
// attach as dangling comments on the target
// (to be rendered as leading on the "in")
return if is_own_line {
CommentPlacement::dangling(comment.enclosing_node(), comment)
} else {
// correctly trailing on the target
CommentPlacement::Default(comment)
};
}
// Comments between the `in` and the iter
// ```python
// [
// a for b
// in # attach as dangling on the iter
// c
// ]
// ```
if comment.slice().start() < comprehension.iter.range().start() {
return if is_own_line {
CommentPlacement::Default(comment)
} else {
// after the `in` but same line, turn into trailing on the `in` token
CommentPlacement::dangling((&comprehension.iter).into(), comment)
};
}
let mut last_end = comprehension.iter.range().end();
for if_node in &comprehension.ifs {
// ```python
// [
// a
// for
// c
// in
// e
// # above if <-- find these own-line between previous and `if` token
// if # if <-- find these end-of-line between `if` and if node (`f`)
// # above f <-- already correctly assigned as leading `f`
// f # f <-- already correctly assigned as trailing `f`
// # above if2
// if # if2
// # above g
// g # g
// ]
// ```
let if_token = find_only_token_in_range(
TextRange::new(last_end, if_node.range().start()),
locator,
TokenKind::If,
);
if is_own_line {
if last_end < comment.slice().start() && comment.slice().start() < if_token.start() {
return CommentPlacement::dangling((if_node).into(), comment);
}
} else {
if if_token.start() < comment.slice().start()
&& comment.slice().start() < if_node.range().start()
{
return CommentPlacement::dangling((if_node).into(), comment);
}
}
last_end = if_node.range().end();
}
CommentPlacement::Default(comment)
}
/// Returns `true` if `right` is `Some` and `left` and `right` are referentially equal. /// Returns `true` if `right` is `Some` and `left` and `right` are referentially equal.
fn are_same_optional<'a, T>(left: AnyNodeRef, right: Option<T>) -> bool fn are_same_optional<'a, T>(left: AnyNodeRef, right: Option<T>) -> bool
where where

View file

@ -1,20 +1,41 @@
use crate::comments::Comments; use crate::comments::Comments;
use crate::expression::parentheses::{ use crate::expression::parentheses::{
default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize, default_expression_needs_parentheses, parenthesized, NeedsParentheses, Parentheses,
Parenthesize,
}; };
use crate::{not_yet_implemented_custom_text, FormatNodeRule, PyFormatter}; use crate::prelude::*;
use ruff_formatter::{write, Buffer, FormatResult}; use crate::AsFormat;
use crate::{FormatNodeRule, PyFormatter};
use ruff_formatter::{format_args, write, Buffer, FormatResult};
use rustpython_parser::ast::ExprListComp; use rustpython_parser::ast::ExprListComp;
#[derive(Default)] #[derive(Default)]
pub struct FormatExprListComp; pub struct FormatExprListComp;
impl FormatNodeRule<ExprListComp> for FormatExprListComp { impl FormatNodeRule<ExprListComp> for FormatExprListComp {
fn fmt_fields(&self, _item: &ExprListComp, f: &mut PyFormatter) -> FormatResult<()> { fn fmt_fields(&self, item: &ExprListComp, f: &mut PyFormatter) -> FormatResult<()> {
let ExprListComp {
range: _,
elt,
generators,
} = item;
let joined = format_with(|f| {
f.join_with(soft_line_break_or_space())
.entries(generators.iter().formatted())
.finish()
});
write!( write!(
f, f,
[not_yet_implemented_custom_text( [parenthesized(
"[NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []]" "[",
&format_args!(
group(&elt.format()),
soft_line_break_or_space(),
group(&joined)
),
"]"
)] )]
) )
} }

View file

@ -1,12 +1,87 @@
use crate::{not_yet_implemented, FormatNodeRule, PyFormatter}; use crate::comments::{leading_comments, trailing_comments};
use ruff_formatter::{write, Buffer, FormatResult}; use crate::prelude::*;
use rustpython_parser::ast::Comprehension; use crate::AsFormat;
use crate::{FormatNodeRule, PyFormatter};
use ruff_formatter::{format_args, write, Buffer, FormatResult};
use rustpython_parser::ast::{Comprehension, Ranged};
#[derive(Default)] #[derive(Default)]
pub struct FormatComprehension; pub struct FormatComprehension;
impl FormatNodeRule<Comprehension> for FormatComprehension { impl FormatNodeRule<Comprehension> for FormatComprehension {
fn fmt_fields(&self, item: &Comprehension, f: &mut PyFormatter) -> FormatResult<()> { fn fmt_fields(&self, item: &Comprehension, f: &mut PyFormatter) -> FormatResult<()> {
write!(f, [not_yet_implemented(item)]) let Comprehension {
range: _,
target,
iter,
ifs,
is_async,
} = item;
let comments = f.context().comments().clone();
if *is_async {
write!(f, [text("async"), space()])?;
}
let dangling_item_comments = comments.dangling_comments(item);
let (before_target_comments, before_in_comments) = dangling_item_comments.split_at(
dangling_item_comments
.partition_point(|comment| comment.slice().end() < target.range().start()),
);
let trailing_in_comments = comments.dangling_comments(iter);
write!(
f,
[
text("for"),
trailing_comments(before_target_comments),
group(&format_args!(
soft_line_break_or_space(),
target.format(),
soft_line_break_or_space(),
leading_comments(before_in_comments),
text("in"),
trailing_comments(trailing_in_comments),
soft_line_break_or_space(),
iter.format(),
)),
]
)?;
if !ifs.is_empty() {
let joined = format_with(|f| {
let mut joiner = f.join_with(soft_line_break_or_space());
for if_case in ifs {
let dangling_if_comments = comments.dangling_comments(if_case);
let (own_line_if_comments, end_of_line_if_comments) = dangling_if_comments
.split_at(
dangling_if_comments
.partition_point(|comment| comment.line_position().is_own_line()),
);
joiner.entry(&group(&format_args!(
leading_comments(own_line_if_comments),
text("if"),
trailing_comments(end_of_line_if_comments),
soft_line_break_or_space(),
if_case.format(),
)));
}
joiner.finish()
});
write!(f, [soft_line_break_or_space(), group(&joined)])?;
}
Ok(())
}
fn fmt_dangling_comments(
&self,
_node: &Comprehension,
_f: &mut PyFormatter,
) -> FormatResult<()> {
// dangling comments are formatted as part of fmt_fields
Ok(())
} }
} }

View file

@ -42,7 +42,7 @@ def make_arange(n):
```diff ```diff
--- Black --- Black
+++ Ruff +++ Ruff
@@ -2,29 +2,21 @@ @@ -2,29 +2,27 @@
def f(): def f():
@ -60,13 +60,16 @@ def make_arange(n):
async def func(): async def func():
if test: if test:
- out_batched = [ out_batched = [
- i i
- async for i in aitertools._async_map( - async for i in aitertools._async_map(
- self.async_inc, arange(8), batch_size=3 - self.async_inc, arange(8), batch_size=3
- ) - )
- ] + async for
+ out_batched = [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] + i
+ in
+ aitertools._async_map(self.async_inc, arange(8), batch_size=3)
]
def awaited_generator_value(n): def awaited_generator_value(n):
@ -95,7 +98,13 @@ def g():
async def func(): async def func():
if test: if test:
out_batched = [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] out_batched = [
i
async for
i
in
aitertools._async_map(self.async_inc, arange(8), batch_size=3)
]
def awaited_generator_value(n): def awaited_generator_value(n):

View file

@ -59,7 +59,7 @@ while x := f(x):
```diff ```diff
--- Black --- Black
+++ Ruff +++ Ruff
@@ -2,10 +2,10 @@ @@ -2,7 +2,7 @@
(a := a) (a := a)
if (match := pattern.search(data)) is None: if (match := pattern.search(data)) is None:
pass pass
@ -67,11 +67,7 @@ while x := f(x):
+if (match := pattern.search(data)): +if (match := pattern.search(data)):
pass pass
[y := f(x), y**2, y**3] [y := f(x), y**2, y**3]
-filtered_data = [y for x in data if (y := f(x)) is None] filtered_data = [y for x in data if (y := f(x)) is None]
+filtered_data = [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []]
(y := f(x))
y0 = (y1 := f(x))
foo(x=(y := f(x)))
@@ -19,10 +19,10 @@ @@ -19,10 +19,10 @@
pass pass
@ -122,7 +118,7 @@ if (match := pattern.search(data)) is None:
if (match := pattern.search(data)): if (match := pattern.search(data)):
pass pass
[y := f(x), y**2, y**3] [y := f(x), y**2, y**3]
filtered_data = [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] filtered_data = [y for x in data if (y := f(x)) is None]
(y := f(x)) (y := f(x))
y0 = (y1 := f(x)) y0 = (y1 := f(x))
foo(x=(y := f(x))) foo(x=(y := f(x)))

View file

@ -224,36 +224,43 @@ instruction()#comment with bad spacing
if ( if (
self._proc is not None self._proc is not None
# has the child process finished? # has the child process finished?
@@ -114,25 +122,9 @@ @@ -115,7 +123,12 @@
# yup
arg3=True, arg3=True,
) )
- lcomp = [ lcomp = [
- element for element in collection if element is not None # yup # yup # right - element for element in collection if element is not None # yup # yup # right
- ] + element # yup
- lcomp2 = [ + for
- # hello + element
- element + in
- # yup + collection # yup
- for element in collection + if element is not None # right
- # right ]
lcomp2 = [
# hello
@@ -123,7 +136,9 @@
# yup
for element in collection
# right
- if element is not None - if element is not None
- ] + if
- lcomp3 = [ + element
- # This one is actually too long to fit in a single line. + is not None
- element.split("\n", 1)[0] ]
- # yup lcomp3 = [
- for element in collection.select_elements() # This one is actually too long to fit in a single line.
- # right @@ -131,7 +146,9 @@
# yup
for element in collection.select_elements()
# right
- if element is not None - if element is not None
- ] + if
+ lcomp = [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] + element
+ lcomp2 = [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] + is not None
+ lcomp3 = [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] ]
while True: while True:
if False: if False:
continue @@ -143,7 +160,10 @@
@@ -143,7 +135,10 @@
# let's return # let's return
return Node( return Node(
syms.simple_stmt, syms.simple_stmt,
@ -265,7 +272,7 @@ instruction()#comment with bad spacing
) )
@@ -158,7 +153,11 @@ @@ -158,7 +178,11 @@
class Test: class Test:
def _init_host(self, parsed) -> None: def _init_host(self, parsed) -> None:
@ -407,9 +414,34 @@ short
# yup # yup
arg3=True, arg3=True,
) )
lcomp = [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] lcomp = [
lcomp2 = [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] element # yup
lcomp3 = [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] for
element
in
collection # yup
if element is not None # right
]
lcomp2 = [
# hello
element
# yup
for element in collection
# right
if
element
is not None
]
lcomp3 = [
# This one is actually too long to fit in a single line.
element.split("\n", 1)[0]
# yup
for element in collection.select_elements()
# right
if
element
is not None
]
while True: while True:
if False: if False:
continue continue

View file

@ -60,22 +60,17 @@ def func():
```diff ```diff
--- Black --- Black
+++ Ruff +++ Ruff
@@ -6,14 +6,7 @@ @@ -12,7 +12,9 @@
x = """ # yup
a really long string for element in collection.select_elements()
""" # right
- lcomp3 = [
- # This one is actually too long to fit in a single line.
- element.split("\n", 1)[0]
- # yup
- for element in collection.select_elements()
- # right
- if element is not None - if element is not None
- ] + if
+ lcomp3 = [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] + element
+ is not None
]
# Capture each of the exceptions in the MultiError along with each of their causes and contexts # Capture each of the exceptions in the MultiError along with each of their causes and contexts
if isinstance(exc_value, MultiError): if isinstance(exc_value, MultiError):
embedded = []
``` ```
## Ruff Output ## Ruff Output
@ -89,7 +84,16 @@ def func():
x = """ x = """
a really long string a really long string
""" """
lcomp3 = [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] lcomp3 = [
# This one is actually too long to fit in a single line.
element.split("\n", 1)[0]
# yup
for element in collection.select_elements()
# right
if
element
is not None
]
# Capture each of the exceptions in the MultiError along with each of their causes and contexts # Capture each of the exceptions in the MultiError along with each of their causes and contexts
if isinstance(exc_value, MultiError): if isinstance(exc_value, MultiError):
embedded = [] embedded = []

View file

@ -324,10 +324,14 @@ last_call()
-{(i**2) 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"))} -{(i**2) for i, _ in ((1, "a"), (2, "b"), (3, "c"))}
-{((i**2) + j) for i in (1, 2, 3) for j in (1, 2, 3)} -{((i**2) + j) for i in (1, 2, 3) for j in (1, 2, 3)}
-[i for i in (1, 2, 3)] +{NOT_IMPLEMENTED_set_value for value in NOT_IMPLEMENTED_set}
-[(i**2) for i in (1, 2, 3)] +{NOT_IMPLEMENTED_set_value for value in NOT_IMPLEMENTED_set}
-[(i**2) for i, _ in ((1, "a"), (2, "b"), (3, "c"))] +{NOT_IMPLEMENTED_set_value for value in NOT_IMPLEMENTED_set}
-[((i**2) + j) for i in (1, 2, 3) for j in (1, 2, 3)] +{NOT_IMPLEMENTED_set_value for value in NOT_IMPLEMENTED_set}
[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"))]
[((i**2) + j) for i in (1, 2, 3) for j in (1, 2, 3)]
-{i: 0 for i in (1, 2, 3)} -{i: 0 for i in (1, 2, 3)}
-{i: j for i, j in ((1, "a"), (2, "b"), (3, "c"))} -{i: j for i, j in ((1, "a"), (2, "b"), (3, "c"))}
-{a: b * 2 for a, b in dictionary.items()} -{a: b * 2 for a, b in dictionary.items()}
@ -336,14 +340,6 @@ last_call()
- k: v - k: v
- for k, v in this_is_a_very_long_variable_which_will_cause_a_trailing_comma_which_breaks_the_comprehension - for k, v in this_is_a_very_long_variable_which_will_cause_a_trailing_comma_which_breaks_the_comprehension
-} -}
+{NOT_IMPLEMENTED_set_value for value in NOT_IMPLEMENTED_set}
+{NOT_IMPLEMENTED_set_value for value in NOT_IMPLEMENTED_set}
+{NOT_IMPLEMENTED_set_value for value in NOT_IMPLEMENTED_set}
+{NOT_IMPLEMENTED_set_value for value in NOT_IMPLEMENTED_set}
+[NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []]
+[NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []]
+[NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []]
+[NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []]
+{NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict} +{NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict}
+{NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict} +{NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict}
+{NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict} +{NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict}
@ -369,9 +365,6 @@ last_call()
- int, - int,
- float, - float,
- dict[str, int], - dict[str, int],
-]
-very_long_variable_name_filters: t.List[
- t.Tuple[str, t.Union[str, t.List[t.Optional[str]]]],
+ ( + (
+ str, + str,
+ int, + int,
@ -379,6 +372,9 @@ last_call()
+ dict[str, int], + dict[str, int],
+ ) + )
] ]
-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 -xxxx_xxxxx_xxxx_xxx: Callable[..., List[SomeClass]] = classmethod( # type: ignore
- sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__) - sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__)
-) -)
@ -433,10 +429,11 @@ last_call()
(*starred,) (*starred,)
{ {
"id": "1", "id": "1",
@@ -208,24 +202,14 @@ @@ -207,25 +201,15 @@
)
what_is_up_with_those_new_coord_names = (coord_names | set(vars_to_create)) - set( what_is_up_with_those_new_coord_names = (coord_names | set(vars_to_create)) - set(
vars_to_remove vars_to_remove
) -)
-result = ( -result = (
- session.query(models.Customer.id) - session.query(models.Customer.id)
- .filter( - .filter(
@ -444,7 +441,7 @@ last_call()
- ) - )
- .order_by(models.Customer.id.asc()) - .order_by(models.Customer.id.asc())
- .all() - .all()
-) )
-result = ( -result = (
- session.query(models.Customer.id) - session.query(models.Customer.id)
- .filter( - .filter(
@ -645,10 +642,10 @@ str or None if (1 if True else 2) else str or bytes or None
{NOT_IMPLEMENTED_set_value for value in NOT_IMPLEMENTED_set} {NOT_IMPLEMENTED_set_value for value in NOT_IMPLEMENTED_set}
{NOT_IMPLEMENTED_set_value for value in NOT_IMPLEMENTED_set} {NOT_IMPLEMENTED_set_value for value in NOT_IMPLEMENTED_set}
{NOT_IMPLEMENTED_set_value for value in NOT_IMPLEMENTED_set} {NOT_IMPLEMENTED_set_value for value in NOT_IMPLEMENTED_set}
[NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] [i for i in (1, 2, 3)]
[NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] [(i**2) for i in (1, 2, 3)]
[NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] [(i**2) for i, _ in ((1, "a"), (2, "b"), (3, "c"))]
[NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] [((i**2) + j) for i in (1, 2, 3) for j in (1, 2, 3)]
{NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict} {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict}
{NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict} {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict}
{NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict} {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict}

View file

@ -75,7 +75,7 @@ return np.divide(
```diff ```diff
--- Black --- Black
+++ Ruff +++ Ruff
@@ -15,38 +15,38 @@ @@ -15,7 +15,7 @@
b = 5 ** f() b = 5 ** f()
c = -(5**2) c = -(5**2)
d = 5 ** f["hi"] d = 5 ** f["hi"]
@ -84,21 +84,16 @@ return np.divide(
f = f() ** 5 f = f() ** 5
g = a.b**c.d g = a.b**c.d
h = 5 ** funcs.f() h = 5 ** funcs.f()
i = funcs.f() ** 5 @@ -26,7 +26,7 @@
j = super().name ** 5
-k = [(2**idx, value) for idx, value in pairs]
+k = [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []]
l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001)
m = [([2**63], [1, 2**63])] m = [([2**63], [1, 2**63])]
n = count <= 10**5 n = count <= 10**5
o = settings(max_examples=10**6) o = settings(max_examples=10**6)
-p = {(k, k**2): v**2 for k, v in pairs} -p = {(k, k**2): v**2 for k, v in pairs}
-q = [10**i for i in range(6)]
+p = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict} +p = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict}
+q = [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] q = [10**i for i in range(6)]
r = x**y r = x**y
a = 5.0**~4.0 @@ -34,7 +34,7 @@
b = 5.0 ** f() b = 5.0 ** f()
c = -(5.0**2.0) c = -(5.0**2.0)
d = 5.0 ** f["hi"] d = 5.0 ** f["hi"]
@ -107,21 +102,15 @@ return np.divide(
f = f() ** 5.0 f = f() ** 5.0
g = a.b**c.d g = a.b**c.d
h = 5.0 ** funcs.f() h = 5.0 ** funcs.f()
i = funcs.f() ** 5.0 @@ -45,7 +45,7 @@
j = super().name ** 5.0
-k = [(2.0**idx, value) for idx, value in pairs]
+k = [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []]
l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001)
m = [([2.0**63.0], [1.0, 2**63.0])] m = [([2.0**63.0], [1.0, 2**63.0])]
n = count <= 10**5.0 n = count <= 10**5.0
o = settings(max_examples=10**6.0) o = settings(max_examples=10**6.0)
-p = {(k, k**2): v**2.0 for k, v in pairs} -p = {(k, k**2): v**2.0 for k, v in pairs}
-q = [10.5**i for i in range(6)]
+p = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict} +p = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict}
+q = [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] q = [10.5**i for i in range(6)]
# WE SHOULD DEFINITELY NOT EAT THESE COMMENTS (https://github.com/psf/black/issues/2873)
@@ -55,9 +55,11 @@ @@ -55,9 +55,11 @@
view.variance, # type: ignore[union-attr] view.variance, # type: ignore[union-attr]
view.sum_of_weights, # type: ignore[union-attr] view.sum_of_weights, # type: ignore[union-attr]
@ -164,13 +153,13 @@ g = a.b**c.d
h = 5 ** funcs.f() h = 5 ** funcs.f()
i = funcs.f() ** 5 i = funcs.f() ** 5
j = super().name ** 5 j = super().name ** 5
k = [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] k = [(2**idx, value) for idx, value in pairs]
l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001) l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001)
m = [([2**63], [1, 2**63])] m = [([2**63], [1, 2**63])]
n = count <= 10**5 n = count <= 10**5
o = settings(max_examples=10**6) o = settings(max_examples=10**6)
p = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict} p = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict}
q = [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] q = [10**i for i in range(6)]
r = x**y r = x**y
a = 5.0**~4.0 a = 5.0**~4.0
@ -183,13 +172,13 @@ g = a.b**c.d
h = 5.0 ** funcs.f() h = 5.0 ** funcs.f()
i = funcs.f() ** 5.0 i = funcs.f() ** 5.0
j = super().name ** 5.0 j = super().name ** 5.0
k = [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] k = [(2.0**idx, value) for idx, value in pairs]
l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001) l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001)
m = [([2.0**63.0], [1.0, 2**63.0])] m = [([2.0**63.0], [1.0, 2**63.0])]
n = count <= 10**5.0 n = count <= 10**5.0
o = settings(max_examples=10**6.0) o = settings(max_examples=10**6.0)
p = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict} p = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict}
q = [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] q = [10.5**i for i in range(6)]
# WE SHOULD DEFINITELY NOT EAT THESE COMMENTS (https://github.com/psf/black/issues/2873) # WE SHOULD DEFINITELY NOT EAT THESE COMMENTS (https://github.com/psf/black/issues/2873)

View file

@ -43,7 +43,7 @@ ham[lower + offset : upper + offset]
```diff ```diff
--- Black --- Black
+++ Ruff +++ Ruff
@@ -4,28 +4,34 @@ @@ -4,19 +4,21 @@
slice[d::d] slice[d::d]
slice[0] slice[0]
slice[-1] slice[-1]
@ -68,19 +68,11 @@ ham[lower + offset : upper + offset]
+slice[ +slice[
+ (NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []) : x + (NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []) : x
+] +]
+slice[ +slice[ :: [i for i in range(42)]]
+ :: [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []]
+]
async def f(): async def f():
- slice[await x : [i async for i in arange(42)] : 42] @@ -27,5 +29,5 @@
+ slice[
+ await x : [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] : 42
+ ]
# These are from PEP-8:
ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:] 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] ham[lower:upper], ham[lower:upper:], ham[lower::step]
# ham[lower+offset : upper+offset] # ham[lower+offset : upper+offset]
@ -112,15 +104,11 @@ slice[not so_simple : 1 < val <= 10]
slice[ slice[
(NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []) : x (NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []) : x
] ]
slice[ slice[ :: [i for i in range(42)]]
:: [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []]
]
async def f(): async def f():
slice[ slice[await x : [i async for i in arange(42)] : 42]
await x : [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] : 42
]
# These are from PEP-8: # These are from PEP-8:

View file

@ -277,10 +277,10 @@ aaaaaaaaaaaaaa + {
dddddddddddddddd, dddddddddddddddd,
eeeeeee, eeeeeee,
} }
( aaaaaaaaaaaaaa + [
aaaaaaaaaaaaaa a
+ [NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []] for x in bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
) ]
( (
aaaaaaaaaaaaaa aaaaaaaaaaaaaa
+ (NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in []) + (NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in [])

View file

@ -0,0 +1,86 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/list_comp.py
---
## Input
```py
[i for i in []]
[i for i in [1,]]
[
a # a
for # for
c # c
in # in
e # e
]
[
# above a
a # a
# above for
for # for
# above c
c # c
# above in
in # in
# above e
e # e
# above if
if # if
# above f
f # f
# above if2
if # if2
# above g
g # g
]
```
## Output
```py
[i for i in []]
[
i
for
i
in
[
1,
]
]
[
a # a
for # for
c # c
in # in
e # e
]
[
# above a
a # a
# above for
for # for
# above c
c # c
# above in
in # in
# above e
e # e
# above if
if # if
# above f
f # f
# above if2
if # if2
# above g
g # g
]
```