Update TupleParentheses usage (#5810)

This commit is contained in:
Chris Pryer 2023-07-24 10:44:36 -04:00 committed by GitHub
parent 8a7dcb794b
commit 8eadacda33
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 88 additions and 30 deletions

View file

@ -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]

View file

@ -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)

View file

@ -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),
}, },
} }

View file

@ -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),
}); });

View file

@ -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),
} }

View file

@ -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),
} }

View file

@ -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
]
``` ```