mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-24 05:25:17 +00:00
Update TupleParentheses
usage (#5810)
This commit is contained in:
parent
8a7dcb794b
commit
8eadacda33
7 changed files with 88 additions and 30 deletions
|
@ -53,3 +53,7 @@ selected_choices = [
|
||||||
str(v)
|
str(v)
|
||||||
for vvvvvvvvvvvvvvvvvvvvvvv in value if str(v) not in self.choices.field.empty_values
|
for vvvvvvvvvvvvvvvvvvvvvvv in value if str(v) not in self.choices.field.empty_values
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Tuples with BinOp
|
||||||
|
[i for i in (aaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccc)]
|
||||||
|
[(aaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccc) for i in b]
|
|
@ -49,7 +49,7 @@ impl FormatNodeRule<ExprSubscript> for FormatExprSubscript {
|
||||||
let result = if let Expr::Tuple(tuple) = slice.as_ref() {
|
let result = if let Expr::Tuple(tuple) = slice.as_ref() {
|
||||||
tuple
|
tuple
|
||||||
.format()
|
.format()
|
||||||
.with_options(TupleParentheses::Subscript)
|
.with_options(TupleParentheses::Preserve)
|
||||||
.fmt(f)
|
.fmt(f)
|
||||||
} else {
|
} else {
|
||||||
slice.format().fmt(f)
|
slice.format().fmt(f)
|
||||||
|
|
|
@ -6,29 +6,53 @@ use ruff_formatter::{format_args, write, FormatRuleWithOptions};
|
||||||
use ruff_python_ast::node::AnyNodeRef;
|
use ruff_python_ast::node::AnyNodeRef;
|
||||||
|
|
||||||
use crate::builders::{empty_parenthesized_with_dangling_comments, parenthesize_if_expands};
|
use crate::builders::{empty_parenthesized_with_dangling_comments, parenthesize_if_expands};
|
||||||
use crate::expression::parentheses::{
|
use crate::expression::parentheses::{parenthesized, NeedsParentheses, OptionalParentheses};
|
||||||
parenthesized, NeedsParentheses, OptionalParentheses, Parentheses,
|
|
||||||
};
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Debug, Default)]
|
#[derive(Eq, PartialEq, Debug, Default)]
|
||||||
pub enum TupleParentheses {
|
pub enum TupleParentheses {
|
||||||
/// Black omits parentheses for tuples inside of comprehensions.
|
/// By default tuples with a single element will include parentheses. Tuples with multiple elements
|
||||||
Comprehension,
|
/// will parenthesize if the expression expands. This means that tuples will often *preserve*
|
||||||
|
/// their parentheses, but this differs from `Preserve` in that we may also *introduce*
|
||||||
/// Effectively `None` in `Option<Parentheses>`
|
/// parentheses as well.
|
||||||
#[default]
|
#[default]
|
||||||
Default,
|
Default,
|
||||||
/// Effectively `Some(Parentheses)` in `Option<Parentheses>`
|
|
||||||
Expr(Parentheses),
|
|
||||||
|
|
||||||
/// Black omits parentheses for tuples inside of subscripts except if the tuple is parenthesized
|
/// Handle special cases where parentheses are to be preserved.
|
||||||
/// in the source code.
|
|
||||||
Subscript,
|
|
||||||
|
|
||||||
/// Handle the special case where we remove parentheses even if they were initially present
|
|
||||||
///
|
///
|
||||||
/// Normally, black keeps parentheses, but in the case of loops it formats
|
/// Black omits parentheses for tuples inside subscripts except if the tuple is already
|
||||||
|
/// parenthesized in the source code.
|
||||||
|
/// ```python
|
||||||
|
/// x[a, :]
|
||||||
|
/// x[a, b:]
|
||||||
|
/// x[(a, b):]
|
||||||
|
/// ```
|
||||||
|
Preserve,
|
||||||
|
|
||||||
|
/// Handle the special cases where we don't include parentheses at all.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// Black never formats tuple targets of for loops with parentheses if inside a comprehension.
|
||||||
|
/// For example, tuple targets will always be formatted on the same line, except when an element supports
|
||||||
|
/// line-breaking in an un-parenthesized context.
|
||||||
|
/// ```python
|
||||||
|
/// # Input
|
||||||
|
/// {k: v for x, (k, v) in this_is_a_very_long_variable_which_will_cause_a_trailing_comma_which_breaks_the_comprehension}
|
||||||
|
///
|
||||||
|
/// # Black
|
||||||
|
/// {
|
||||||
|
/// k: v
|
||||||
|
/// for x, (
|
||||||
|
/// k,
|
||||||
|
/// v,
|
||||||
|
/// ) in this_is_a_very_long_variable_which_will_cause_a_trailing_comma_which_breaks_the_comprehension
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
Never,
|
||||||
|
|
||||||
|
/// Handle the special cases where we don't include parentheses if they are not required.
|
||||||
|
///
|
||||||
|
/// Normally, black keeps parentheses, but in the case of for loops it formats
|
||||||
/// ```python
|
/// ```python
|
||||||
/// for (a, b) in x:
|
/// for (a, b) in x:
|
||||||
/// pass
|
/// pass
|
||||||
|
@ -38,9 +62,24 @@ pub enum TupleParentheses {
|
||||||
/// for a, b in x:
|
/// for a, b in x:
|
||||||
/// pass
|
/// pass
|
||||||
/// ```
|
/// ```
|
||||||
/// Black still does use parentheses in this position if the group breaks or magic trailing
|
/// Black still does use parentheses in these positions if the group breaks or magic trailing
|
||||||
/// comma is used.
|
/// comma is used.
|
||||||
StripInsideForLoop,
|
///
|
||||||
|
/// Additional examples:
|
||||||
|
/// ```python
|
||||||
|
/// for (a,) in []:
|
||||||
|
/// pass
|
||||||
|
/// for a, b in []:
|
||||||
|
/// pass
|
||||||
|
/// for a, b in []: # Strips parentheses
|
||||||
|
/// pass
|
||||||
|
/// for (
|
||||||
|
/// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
||||||
|
/// b,
|
||||||
|
/// ) in []:
|
||||||
|
/// pass
|
||||||
|
/// ```
|
||||||
|
NeverPreserve,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -86,7 +125,7 @@ impl FormatNodeRule<ExprTuple> for FormatExprTuple {
|
||||||
.fmt(f);
|
.fmt(f);
|
||||||
}
|
}
|
||||||
[single] => match self.parentheses {
|
[single] => match self.parentheses {
|
||||||
TupleParentheses::Subscript
|
TupleParentheses::Preserve
|
||||||
if !is_parenthesized(*range, elts, f.context().source()) =>
|
if !is_parenthesized(*range, elts, f.context().source()) =>
|
||||||
{
|
{
|
||||||
write!(f, [single.format(), text(",")])
|
write!(f, [single.format(), text(",")])
|
||||||
|
@ -103,19 +142,19 @@ impl FormatNodeRule<ExprTuple> for FormatExprTuple {
|
||||||
// Unlike other expression parentheses, tuple parentheses are part of the range of the
|
// Unlike other expression parentheses, tuple parentheses are part of the range of the
|
||||||
// tuple itself.
|
// tuple itself.
|
||||||
_ if is_parenthesized(*range, elts, f.context().source())
|
_ if is_parenthesized(*range, elts, f.context().source())
|
||||||
&& self.parentheses != TupleParentheses::StripInsideForLoop =>
|
&& self.parentheses != TupleParentheses::NeverPreserve =>
|
||||||
{
|
{
|
||||||
parenthesized("(", &ExprSequence::new(item), ")").fmt(f)
|
parenthesized("(", &ExprSequence::new(item), ")").fmt(f)
|
||||||
}
|
}
|
||||||
_ => match self.parentheses {
|
_ => match self.parentheses {
|
||||||
TupleParentheses::Comprehension => {
|
TupleParentheses::Never => {
|
||||||
let separator =
|
let separator =
|
||||||
format_with(|f| group(&format_args![text(","), space()]).fmt(f));
|
format_with(|f| group(&format_args![text(","), space()]).fmt(f));
|
||||||
f.join_with(separator)
|
f.join_with(separator)
|
||||||
.entries(elts.iter().formatted())
|
.entries(elts.iter().formatted())
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
TupleParentheses::Subscript => group(&ExprSequence::new(item)).fmt(f),
|
TupleParentheses::Preserve => group(&ExprSequence::new(item)).fmt(f),
|
||||||
_ => parenthesize_if_expands(&ExprSequence::new(item)).fmt(f),
|
_ => parenthesize_if_expands(&ExprSequence::new(item)).fmt(f),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ use ruff_python_ast::visitor::preorder::{walk_expr, PreorderVisitor};
|
||||||
|
|
||||||
use crate::builders::parenthesize_if_expands;
|
use crate::builders::parenthesize_if_expands;
|
||||||
use crate::context::NodeLevel;
|
use crate::context::NodeLevel;
|
||||||
use crate::expression::expr_tuple::TupleParentheses;
|
|
||||||
use crate::expression::parentheses::{
|
use crate::expression::parentheses::{
|
||||||
is_expression_parenthesized, optional_parentheses, parenthesized, NeedsParentheses,
|
is_expression_parenthesized, optional_parentheses, parenthesized, NeedsParentheses,
|
||||||
OptionalParentheses, Parentheses, Parenthesize,
|
OptionalParentheses, Parentheses, Parenthesize,
|
||||||
|
@ -91,10 +90,7 @@ impl FormatRule<Expr, PyFormatContext<'_>> for FormatExpr {
|
||||||
Expr::Starred(expr) => expr.format().fmt(f),
|
Expr::Starred(expr) => expr.format().fmt(f),
|
||||||
Expr::Name(expr) => expr.format().fmt(f),
|
Expr::Name(expr) => expr.format().fmt(f),
|
||||||
Expr::List(expr) => expr.format().fmt(f),
|
Expr::List(expr) => expr.format().fmt(f),
|
||||||
Expr::Tuple(expr) => expr
|
Expr::Tuple(expr) => expr.format().fmt(f),
|
||||||
.format()
|
|
||||||
.with_options(TupleParentheses::Expr(parentheses))
|
|
||||||
.fmt(f),
|
|
||||||
Expr::Slice(expr) => expr.format().fmt(f),
|
Expr::Slice(expr) => expr.format().fmt(f),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ impl Format<PyFormatContext<'_>> for ExprTupleWithoutParentheses<'_> {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
Expr::Tuple(expr_tuple) => expr_tuple
|
Expr::Tuple(expr_tuple) => expr_tuple
|
||||||
.format()
|
.format()
|
||||||
.with_options(TupleParentheses::Comprehension)
|
.with_options(TupleParentheses::Never)
|
||||||
.fmt(f),
|
.fmt(f),
|
||||||
other => other.format().fmt(f),
|
other => other.format().fmt(f),
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ impl Format<PyFormatContext<'_>> for ExprTupleWithoutParentheses<'_> {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
Expr::Tuple(expr_tuple) => expr_tuple
|
Expr::Tuple(expr_tuple) => expr_tuple
|
||||||
.format()
|
.format()
|
||||||
.with_options(TupleParentheses::StripInsideForLoop)
|
.with_options(TupleParentheses::NeverPreserve)
|
||||||
.fmt(f),
|
.fmt(f),
|
||||||
other => maybe_parenthesize_expression(other, self.0, Parenthesize::IfBreaks).fmt(f),
|
other => maybe_parenthesize_expression(other, self.0, Parenthesize::IfBreaks).fmt(f),
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,10 @@ selected_choices = [
|
||||||
str(v)
|
str(v)
|
||||||
for vvvvvvvvvvvvvvvvvvvvvvv in value if str(v) not in self.choices.field.empty_values
|
for vvvvvvvvvvvvvvvvvvvvvvv in value if str(v) not in self.choices.field.empty_values
|
||||||
]
|
]
|
||||||
```
|
|
||||||
|
# Tuples with BinOp
|
||||||
|
[i for i in (aaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccc)]
|
||||||
|
[(aaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccc) for i in b]```
|
||||||
|
|
||||||
## Output
|
## Output
|
||||||
```py
|
```py
|
||||||
|
@ -122,6 +125,22 @@ selected_choices = [
|
||||||
for vvvvvvvvvvvvvvvvvvvvvvv in value
|
for vvvvvvvvvvvvvvvvvvvvvvv in value
|
||||||
if str(v) not in self.choices.field.empty_values
|
if str(v) not in self.choices.field.empty_values
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Tuples with BinOp
|
||||||
|
[
|
||||||
|
i
|
||||||
|
for i in (
|
||||||
|
aaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
||||||
|
ccccccccccccccccccccc,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
[
|
||||||
|
(
|
||||||
|
aaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
||||||
|
ccccccccccccccccccccc,
|
||||||
|
)
|
||||||
|
for i in b
|
||||||
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue