mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-26 11:59:10 +00:00
parent
a95deec00f
commit
424b720c19
62 changed files with 1799 additions and 3890 deletions
|
@ -37,7 +37,6 @@ for node_line in node_lines:
|
||||||
# `FStringLiteralElement`, `FStringFormatSpec` and `FStringExpressionElement` are handled by the `FString`
|
# `FStringLiteralElement`, `FStringFormatSpec` and `FStringExpressionElement` are handled by the `FString`
|
||||||
# implementation.
|
# implementation.
|
||||||
if node in (
|
if node in (
|
||||||
"FString",
|
|
||||||
"FStringLiteralElement",
|
"FStringLiteralElement",
|
||||||
"FStringExpressionElement",
|
"FStringExpressionElement",
|
||||||
"FStringFormatSpec",
|
"FStringFormatSpec",
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"preview": "enabled"
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -1,5 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"preview": "enabled"
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -1,11 +1,9 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"quote_style": "preserve",
|
"quote_style": "preserve"
|
||||||
"preview": "enabled"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"quote_style": "preserve",
|
"quote_style": "preserve",
|
||||||
"preview": "enabled",
|
|
||||||
"target_version": "py312"
|
"target_version": "py312"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"preview": "enabled",
|
|
||||||
"source_type": "Stub"
|
"source_type": "Stub"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"preview": "enabled"
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -1,15 +1,14 @@
|
||||||
use ruff_python_ast::{AnyNodeRef, ExprFString, StringLike};
|
use ruff_python_ast::{AnyNodeRef, ExprFString, StringLike};
|
||||||
use ruff_text_size::TextSlice;
|
|
||||||
|
|
||||||
use crate::expression::parentheses::{
|
use crate::expression::parentheses::{
|
||||||
in_parentheses_only_group, NeedsParentheses, OptionalParentheses,
|
in_parentheses_only_group, NeedsParentheses, OptionalParentheses,
|
||||||
};
|
};
|
||||||
use crate::other::f_string::{FStringLayout, FormatFString};
|
use crate::other::f_string::FStringLayout;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::string::implicit::{
|
use crate::string::implicit::{
|
||||||
FormatImplicitConcatenatedString, FormatImplicitConcatenatedStringFlat,
|
FormatImplicitConcatenatedString, FormatImplicitConcatenatedStringFlat,
|
||||||
};
|
};
|
||||||
use crate::string::{Quoting, StringLikeExtensions};
|
use crate::string::StringLikeExtensions;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FormatExprFString;
|
pub struct FormatExprFString;
|
||||||
|
@ -23,7 +22,7 @@ impl FormatNodeRule<ExprFString> for FormatExprFString {
|
||||||
// [`ruff_python_ast::FStringValue::single`] constructor.
|
// [`ruff_python_ast::FStringValue::single`] constructor.
|
||||||
let f_string = f_string_part.as_f_string().unwrap();
|
let f_string = f_string_part.as_f_string().unwrap();
|
||||||
|
|
||||||
FormatFString::new(f_string, f_string_quoting(item, f.context().source())).fmt(f)
|
f_string.format().fmt(f)
|
||||||
} else {
|
} else {
|
||||||
// Always join fstrings that aren't parenthesized and thus, are always on a single line.
|
// Always join fstrings that aren't parenthesized and thus, are always on a single line.
|
||||||
if !f.context().node_level().is_parenthesized() {
|
if !f.context().node_level().is_parenthesized() {
|
||||||
|
@ -58,28 +57,3 @@ impl NeedsParentheses for ExprFString {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn f_string_quoting(f_string: &ExprFString, source: &str) -> Quoting {
|
|
||||||
let unprefixed = source
|
|
||||||
.slice(f_string)
|
|
||||||
.trim_start_matches(|c| c != '"' && c != '\'');
|
|
||||||
let triple_quoted = unprefixed.starts_with(r#"""""#) || unprefixed.starts_with(r"'''");
|
|
||||||
|
|
||||||
if f_string
|
|
||||||
.value
|
|
||||||
.elements()
|
|
||||||
.filter_map(|element| element.as_expression())
|
|
||||||
.any(|expression| {
|
|
||||||
let string_content = source.slice(expression);
|
|
||||||
if triple_quoted {
|
|
||||||
string_content.contains(r#"""""#) || string_content.contains("'''")
|
|
||||||
} else {
|
|
||||||
string_content.contains(['"', '\''])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
{
|
|
||||||
Quoting::Preserve
|
|
||||||
} else {
|
|
||||||
Quoting::CanChange
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ use crate::expression::parentheses::{
|
||||||
};
|
};
|
||||||
use crate::expression::CallChainLayout;
|
use crate::expression::CallChainLayout;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::preview::is_empty_parameters_no_unnecessary_parentheses_around_return_value_enabled;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FormatExprSubscript {
|
pub struct FormatExprSubscript {
|
||||||
|
@ -108,13 +107,14 @@ impl NeedsParentheses for ExprSubscript {
|
||||||
if function.returns.as_deref().is_some_and(|returns| {
|
if function.returns.as_deref().is_some_and(|returns| {
|
||||||
AnyNodeRef::ptr_eq(returns.into(), self.into())
|
AnyNodeRef::ptr_eq(returns.into(), self.into())
|
||||||
}) {
|
}) {
|
||||||
if is_empty_parameters_no_unnecessary_parentheses_around_return_value_enabled(context) &&
|
if function.parameters.is_empty()
|
||||||
function.parameters.is_empty() && !context.comments().has(&*function.parameters) {
|
&& !context.comments().has(&*function.parameters)
|
||||||
|
{
|
||||||
// Apply the `optional_parentheses` layout when the subscript
|
// Apply the `optional_parentheses` layout when the subscript
|
||||||
// is in a return type position of a function without parameters.
|
// is in a return type position of a function without parameters.
|
||||||
// This ensures the subscript is parenthesized if it has a very
|
// This ensures the subscript is parenthesized if it has a very
|
||||||
// long name that goes over the line length limit.
|
// long name that goes over the line length limit.
|
||||||
return OptionalParentheses::Multiline
|
return OptionalParentheses::Multiline;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't use the best fitting layout for return type annotation because it results in the
|
// Don't use the best fitting layout for return type annotation because it results in the
|
||||||
|
|
|
@ -19,10 +19,7 @@ use crate::expression::parentheses::{
|
||||||
OptionalParentheses, Parentheses, Parenthesize,
|
OptionalParentheses, Parentheses, Parenthesize,
|
||||||
};
|
};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::preview::{
|
use crate::preview::is_hug_parens_with_braces_and_square_brackets_enabled;
|
||||||
is_empty_parameters_no_unnecessary_parentheses_around_return_value_enabled,
|
|
||||||
is_f_string_formatting_enabled, is_hug_parens_with_braces_and_square_brackets_enabled,
|
|
||||||
};
|
|
||||||
|
|
||||||
mod binary_like;
|
mod binary_like;
|
||||||
pub(crate) mod expr_attribute;
|
pub(crate) mod expr_attribute;
|
||||||
|
@ -388,18 +385,12 @@ impl Format<PyFormatContext<'_>> for MaybeParenthesizeExpression<'_> {
|
||||||
// is parenthesized. Unless, it's the `Parenthesize::IfBreaksParenthesizedNested` layout
|
// is parenthesized. Unless, it's the `Parenthesize::IfBreaksParenthesizedNested` layout
|
||||||
// where parenthesizing nested `maybe_parenthesized_expression` is explicitly desired.
|
// where parenthesizing nested `maybe_parenthesized_expression` is explicitly desired.
|
||||||
_ if f.context().node_level().is_parenthesized() => {
|
_ if f.context().node_level().is_parenthesized() => {
|
||||||
if !is_empty_parameters_no_unnecessary_parentheses_around_return_value_enabled(
|
return if matches!(parenthesize, Parenthesize::IfBreaksParenthesizedNested) {
|
||||||
f.context(),
|
parenthesize_if_expands(&expression.format().with_options(Parentheses::Never))
|
||||||
) {
|
.with_indent(!is_expression_huggable(expression, f.context()))
|
||||||
OptionalParentheses::Never
|
.fmt(f)
|
||||||
} else if matches!(parenthesize, Parenthesize::IfBreaksParenthesizedNested) {
|
|
||||||
return parenthesize_if_expands(
|
|
||||||
&expression.format().with_options(Parentheses::Never),
|
|
||||||
)
|
|
||||||
.with_indent(!is_expression_huggable(expression, f.context()))
|
|
||||||
.fmt(f);
|
|
||||||
} else {
|
} else {
|
||||||
return expression.format().with_options(Parentheses::Never).fmt(f);
|
expression.format().with_options(Parentheses::Never).fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
needs_parentheses => needs_parentheses,
|
needs_parentheses => needs_parentheses,
|
||||||
|
@ -409,13 +400,12 @@ impl Format<PyFormatContext<'_>> for MaybeParenthesizeExpression<'_> {
|
||||||
|
|
||||||
match needs_parentheses {
|
match needs_parentheses {
|
||||||
OptionalParentheses::Multiline => match parenthesize {
|
OptionalParentheses::Multiline => match parenthesize {
|
||||||
Parenthesize::IfBreaksParenthesized | Parenthesize::IfBreaksParenthesizedNested if !is_empty_parameters_no_unnecessary_parentheses_around_return_value_enabled(f.context()) => {
|
|
||||||
parenthesize_if_expands(&unparenthesized).fmt(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
Parenthesize::IfRequired => unparenthesized.fmt(f),
|
Parenthesize::IfRequired => unparenthesized.fmt(f),
|
||||||
|
|
||||||
Parenthesize::Optional | Parenthesize::IfBreaks | Parenthesize::IfBreaksParenthesized | Parenthesize::IfBreaksParenthesizedNested => {
|
Parenthesize::Optional
|
||||||
|
| Parenthesize::IfBreaks
|
||||||
|
| Parenthesize::IfBreaksParenthesized
|
||||||
|
| Parenthesize::IfBreaksParenthesizedNested => {
|
||||||
if can_omit_optional_parentheses(expression, f.context()) {
|
if can_omit_optional_parentheses(expression, f.context()) {
|
||||||
optional_parentheses(&unparenthesized).fmt(f)
|
optional_parentheses(&unparenthesized).fmt(f)
|
||||||
} else {
|
} else {
|
||||||
|
@ -424,9 +414,6 @@ impl Format<PyFormatContext<'_>> for MaybeParenthesizeExpression<'_> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
OptionalParentheses::BestFit => match parenthesize {
|
OptionalParentheses::BestFit => match parenthesize {
|
||||||
Parenthesize::IfBreaksParenthesized | Parenthesize::IfBreaksParenthesizedNested if !is_empty_parameters_no_unnecessary_parentheses_around_return_value_enabled(f.context()) =>
|
|
||||||
parenthesize_if_expands(&unparenthesized).fmt(f),
|
|
||||||
|
|
||||||
Parenthesize::IfBreaksParenthesized | Parenthesize::IfBreaksParenthesizedNested => {
|
Parenthesize::IfBreaksParenthesized | Parenthesize::IfBreaksParenthesizedNested => {
|
||||||
// Can-omit layout is relevant for `"abcd".call`. We don't want to add unnecessary
|
// Can-omit layout is relevant for `"abcd".call`. We don't want to add unnecessary
|
||||||
// parentheses in this case.
|
// parentheses in this case.
|
||||||
|
@ -454,15 +441,11 @@ impl Format<PyFormatContext<'_>> for MaybeParenthesizeExpression<'_> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
OptionalParentheses::Never => match parenthesize {
|
OptionalParentheses::Never => match parenthesize {
|
||||||
Parenthesize::IfBreaksParenthesized | Parenthesize::IfBreaksParenthesizedNested if !is_empty_parameters_no_unnecessary_parentheses_around_return_value_enabled(f.context()) => {
|
Parenthesize::Optional
|
||||||
parenthesize_if_expands(&unparenthesized)
|
| Parenthesize::IfBreaks
|
||||||
.with_indent(!is_expression_huggable(expression, f.context()))
|
| Parenthesize::IfRequired
|
||||||
.fmt(f)
|
| Parenthesize::IfBreaksParenthesized
|
||||||
}
|
| Parenthesize::IfBreaksParenthesizedNested => unparenthesized.fmt(f),
|
||||||
|
|
||||||
Parenthesize::Optional | Parenthesize::IfBreaks | Parenthesize::IfRequired | Parenthesize::IfBreaksParenthesized | Parenthesize::IfBreaksParenthesizedNested => {
|
|
||||||
unparenthesized.fmt(f)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
OptionalParentheses::Always => {
|
OptionalParentheses::Always => {
|
||||||
|
@ -766,32 +749,6 @@ impl<'input> CanOmitOptionalParenthesesVisitor<'input> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr::StringLiteral(ast::ExprStringLiteral { value, .. })
|
|
||||||
if value.is_implicit_concatenated() =>
|
|
||||||
{
|
|
||||||
if !is_f_string_formatting_enabled(self.context) {
|
|
||||||
self.update_max_precedence(OperatorPrecedence::String);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Expr::BytesLiteral(ast::ExprBytesLiteral { value, .. })
|
|
||||||
if value.is_implicit_concatenated() =>
|
|
||||||
{
|
|
||||||
if !is_f_string_formatting_enabled(self.context) {
|
|
||||||
self.update_max_precedence(OperatorPrecedence::String);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Expr::FString(ast::ExprFString { value, .. }) if value.is_implicit_concatenated() => {
|
|
||||||
if !is_f_string_formatting_enabled(self.context) {
|
|
||||||
self.update_max_precedence(OperatorPrecedence::String);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Non terminal nodes that don't have a termination token.
|
// Non terminal nodes that don't have a termination token.
|
||||||
Expr::Named(_) | Expr::Generator(_) | Expr::Tuple(_) => {}
|
Expr::Named(_) | Expr::Generator(_) | Expr::Tuple(_) => {}
|
||||||
|
|
||||||
|
@ -1193,8 +1150,6 @@ enum OperatorPrecedence {
|
||||||
BitwiseXor,
|
BitwiseXor,
|
||||||
BitwiseOr,
|
BitwiseOr,
|
||||||
Comparator,
|
Comparator,
|
||||||
// Implicit string concatenation
|
|
||||||
String,
|
|
||||||
BooleanOperation,
|
BooleanOperation,
|
||||||
Conditional,
|
Conditional,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2935,6 +2935,34 @@ impl<'ast> IntoFormat<PyFormatContext<'ast>> for ast::TypeParamParamSpec {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FormatRule<ast::FString, PyFormatContext<'_>> for crate::other::f_string::FormatFString {
|
||||||
|
#[inline]
|
||||||
|
fn fmt(&self, node: &ast::FString, f: &mut PyFormatter) -> FormatResult<()> {
|
||||||
|
FormatNodeRule::<ast::FString>::fmt(self, node, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> AsFormat<PyFormatContext<'ast>> for ast::FString {
|
||||||
|
type Format<'a> = FormatRefWithRule<
|
||||||
|
'a,
|
||||||
|
ast::FString,
|
||||||
|
crate::other::f_string::FormatFString,
|
||||||
|
PyFormatContext<'ast>,
|
||||||
|
>;
|
||||||
|
fn format(&self) -> Self::Format<'_> {
|
||||||
|
FormatRefWithRule::new(self, crate::other::f_string::FormatFString::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> IntoFormat<PyFormatContext<'ast>> for ast::FString {
|
||||||
|
type Format = FormatOwnedWithRule<
|
||||||
|
ast::FString,
|
||||||
|
crate::other::f_string::FormatFString,
|
||||||
|
PyFormatContext<'ast>,
|
||||||
|
>;
|
||||||
|
fn into_format(self) -> Self::Format {
|
||||||
|
FormatOwnedWithRule::new(self, crate::other::f_string::FormatFString::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FormatRule<ast::StringLiteral, PyFormatContext<'_>>
|
impl FormatRule<ast::StringLiteral, PyFormatContext<'_>>
|
||||||
for crate::other::string_literal::FormatStringLiteral
|
for crate::other::string_literal::FormatStringLiteral
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,6 @@ use crate::comments::{leading_comments, trailing_comments};
|
||||||
use crate::expression::expr_tuple::TupleParentheses;
|
use crate::expression::expr_tuple::TupleParentheses;
|
||||||
use crate::expression::parentheses::is_expression_parenthesized;
|
use crate::expression::parentheses::is_expression_parenthesized;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::preview::is_comprehension_leading_expression_comments_same_line_enabled;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FormatComprehension;
|
pub struct FormatComprehension;
|
||||||
|
@ -36,14 +35,12 @@ impl FormatNodeRule<Comprehension> for FormatComprehension {
|
||||||
// )
|
// )
|
||||||
// ]
|
// ]
|
||||||
// ```
|
// ```
|
||||||
let will_be_parenthesized =
|
let will_be_parenthesized = self.preserve_parentheses
|
||||||
is_comprehension_leading_expression_comments_same_line_enabled(f.context())
|
&& is_expression_parenthesized(
|
||||||
&& self.preserve_parentheses
|
self.expression.into(),
|
||||||
&& is_expression_parenthesized(
|
f.context().comments().ranges(),
|
||||||
self.expression.into(),
|
f.context().source(),
|
||||||
f.context().comments().ranges(),
|
);
|
||||||
f.context().source(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if has_leading_comments && !will_be_parenthesized {
|
if has_leading_comments && !will_be_parenthesized {
|
||||||
soft_line_break_or_space().fmt(f)
|
soft_line_break_or_space().fmt(f)
|
||||||
|
|
|
@ -4,8 +4,7 @@ use ruff_source_file::LineRanges;
|
||||||
use ruff_text_size::Ranged;
|
use ruff_text_size::Ranged;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::preview::is_f_string_formatting_enabled;
|
use crate::string::{StringNormalizer, StringQuotes};
|
||||||
use crate::string::{Quoting, StringNormalizer, StringQuotes};
|
|
||||||
|
|
||||||
use super::f_string_element::FormatFStringElement;
|
use super::f_string_element::FormatFStringElement;
|
||||||
|
|
||||||
|
@ -13,66 +12,25 @@ use super::f_string_element::FormatFStringElement;
|
||||||
///
|
///
|
||||||
/// For example, this would be used to format the f-string part in `"foo" f"bar {x}"`
|
/// For example, this would be used to format the f-string part in `"foo" f"bar {x}"`
|
||||||
/// or the standalone f-string in `f"foo {x} bar"`.
|
/// or the standalone f-string in `f"foo {x} bar"`.
|
||||||
pub(crate) struct FormatFString<'a> {
|
#[derive(Default)]
|
||||||
value: &'a FString,
|
pub struct FormatFString;
|
||||||
/// The quoting of an f-string. This is determined by the parent node
|
|
||||||
/// (f-string expression) and is required to format an f-string correctly.
|
|
||||||
quoting: Quoting,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> FormatFString<'a> {
|
impl FormatNodeRule<FString> for FormatFString {
|
||||||
pub(crate) fn new(value: &'a FString, quoting: Quoting) -> Self {
|
fn fmt_fields(&self, item: &FString, f: &mut PyFormatter) -> FormatResult<()> {
|
||||||
Self { value, quoting }
|
let normalizer = StringNormalizer::from_context(f.context());
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Format<PyFormatContext<'_>> for FormatFString<'_> {
|
let string_kind = normalizer.choose_quotes(item.into()).flags();
|
||||||
fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> {
|
|
||||||
// If the preview style is enabled, make the decision on what quotes to use locally for each
|
|
||||||
// f-string instead of globally for the entire f-string expression.
|
|
||||||
let quoting = if is_f_string_formatting_enabled(f.context()) {
|
|
||||||
Quoting::CanChange
|
|
||||||
} else {
|
|
||||||
self.quoting
|
|
||||||
};
|
|
||||||
|
|
||||||
let normalizer = StringNormalizer::from_context(f.context()).with_quoting(quoting);
|
|
||||||
|
|
||||||
// If f-string formatting is disabled (not in preview), then we will
|
|
||||||
// fall back to the previous behavior of normalizing the f-string.
|
|
||||||
if !is_f_string_formatting_enabled(f.context()) {
|
|
||||||
let result = normalizer.normalize(self.value.into()).fmt(f);
|
|
||||||
let comments = f.context().comments();
|
|
||||||
self.value.elements.iter().for_each(|value| {
|
|
||||||
comments.mark_verbatim_node_comments_formatted(value.into());
|
|
||||||
// Above method doesn't mark the trailing comments of the f-string elements
|
|
||||||
// as formatted, so we need to do it manually. For example,
|
|
||||||
//
|
|
||||||
// ```python
|
|
||||||
// f"""foo {
|
|
||||||
// x:.3f
|
|
||||||
// # comment
|
|
||||||
// }"""
|
|
||||||
// ```
|
|
||||||
for trailing_comment in comments.trailing(value) {
|
|
||||||
trailing_comment.mark_formatted();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
let string_kind = normalizer.choose_quotes(self.value.into()).flags();
|
|
||||||
|
|
||||||
let context = FStringContext::new(
|
let context = FStringContext::new(
|
||||||
string_kind,
|
string_kind,
|
||||||
FStringLayout::from_f_string(self.value, f.context().source()),
|
FStringLayout::from_f_string(item, f.context().source()),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Starting prefix and quote
|
// Starting prefix and quote
|
||||||
let quotes = StringQuotes::from(string_kind);
|
let quotes = StringQuotes::from(string_kind);
|
||||||
write!(f, [string_kind.prefix(), quotes])?;
|
write!(f, [string_kind.prefix(), quotes])?;
|
||||||
|
|
||||||
for element in &self.value.elements {
|
for element in &item.elements {
|
||||||
FormatFStringElement::new(element, context).fmt(f)?;
|
FormatFStringElement::new(element, context).fmt(f)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,8 +61,7 @@ impl<'a> FormatFStringLiteralElement<'a> {
|
||||||
impl Format<PyFormatContext<'_>> for FormatFStringLiteralElement<'_> {
|
impl Format<PyFormatContext<'_>> for FormatFStringLiteralElement<'_> {
|
||||||
fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> {
|
fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> {
|
||||||
let literal_content = f.context().source().slice(self.element);
|
let literal_content = f.context().source().slice(self.element);
|
||||||
let normalized =
|
let normalized = normalize_string(literal_content, 0, self.fstring_flags, false);
|
||||||
normalize_string(literal_content, 0, self.fstring_flags, false, false, true);
|
|
||||||
match &normalized {
|
match &normalized {
|
||||||
Cow::Borrowed(_) => source_text_slice(self.element.range()).fmt(f),
|
Cow::Borrowed(_) => source_text_slice(self.element.range()).fmt(f),
|
||||||
Cow::Owned(normalized) => text(normalized).fmt(f),
|
Cow::Owned(normalized) => text(normalized).fmt(f),
|
||||||
|
|
|
@ -1,15 +1,10 @@
|
||||||
use ruff_formatter::{write, FormatRuleWithOptions};
|
use ruff_formatter::{format_args, write, FormatRuleWithOptions};
|
||||||
use ruff_python_ast::AstNode;
|
|
||||||
use ruff_python_ast::MatchCase;
|
use ruff_python_ast::MatchCase;
|
||||||
|
|
||||||
use crate::builders::parenthesize_if_expands;
|
|
||||||
use crate::expression::maybe_parenthesize_expression;
|
use crate::expression::maybe_parenthesize_expression;
|
||||||
use crate::expression::parentheses::{
|
use crate::expression::parentheses::Parenthesize;
|
||||||
NeedsParentheses, OptionalParentheses, Parentheses, Parenthesize,
|
|
||||||
};
|
|
||||||
use crate::pattern::maybe_parenthesize_pattern;
|
use crate::pattern::maybe_parenthesize_pattern;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::preview::is_match_case_parentheses_enabled;
|
|
||||||
use crate::statement::clause::{clause_body, clause_header, ClauseHeader};
|
use crate::statement::clause::{clause_body, clause_header, ClauseHeader};
|
||||||
use crate::statement::suite::SuiteKind;
|
use crate::statement::suite::SuiteKind;
|
||||||
|
|
||||||
|
@ -39,42 +34,12 @@ impl FormatNodeRule<MatchCase> for FormatMatchCase {
|
||||||
let comments = f.context().comments().clone();
|
let comments = f.context().comments().clone();
|
||||||
let dangling_item_comments = comments.dangling(item);
|
let dangling_item_comments = comments.dangling(item);
|
||||||
|
|
||||||
let format_pattern = format_with(|f| {
|
|
||||||
if is_match_case_parentheses_enabled(f.context()) {
|
|
||||||
maybe_parenthesize_pattern(pattern, item).fmt(f)
|
|
||||||
} else {
|
|
||||||
let has_comments =
|
|
||||||
comments.has_leading(pattern) || comments.has_trailing_own_line(pattern);
|
|
||||||
|
|
||||||
if has_comments {
|
|
||||||
pattern.format().with_options(Parentheses::Always).fmt(f)
|
|
||||||
} else {
|
|
||||||
match pattern.needs_parentheses(item.as_any_node_ref(), f.context()) {
|
|
||||||
OptionalParentheses::Multiline => parenthesize_if_expands(
|
|
||||||
&pattern.format().with_options(Parentheses::Never),
|
|
||||||
)
|
|
||||||
.fmt(f),
|
|
||||||
OptionalParentheses::Always => {
|
|
||||||
pattern.format().with_options(Parentheses::Always).fmt(f)
|
|
||||||
}
|
|
||||||
OptionalParentheses::Never | OptionalParentheses::BestFit => {
|
|
||||||
pattern.format().with_options(Parentheses::Never).fmt(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let format_guard = guard.as_deref().map(|guard| {
|
let format_guard = guard.as_deref().map(|guard| {
|
||||||
format_with(|f| {
|
format_with(|f| {
|
||||||
write!(f, [space(), token("if"), space()])?;
|
write!(f, [space(), token("if"), space()])?;
|
||||||
|
|
||||||
if is_match_case_parentheses_enabled(f.context()) {
|
maybe_parenthesize_expression(guard, item, Parenthesize::IfBreaksParenthesized)
|
||||||
maybe_parenthesize_expression(guard, item, Parenthesize::IfBreaksParenthesized)
|
.fmt(f)
|
||||||
.fmt(f)
|
|
||||||
} else {
|
|
||||||
guard.format().fmt(f)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -84,9 +49,12 @@ impl FormatNodeRule<MatchCase> for FormatMatchCase {
|
||||||
clause_header(
|
clause_header(
|
||||||
ClauseHeader::MatchCase(item),
|
ClauseHeader::MatchCase(item),
|
||||||
dangling_item_comments,
|
dangling_item_comments,
|
||||||
&format_with(|f| {
|
&format_args![
|
||||||
write!(f, [token("case"), space(), format_pattern, format_guard])
|
token("case"),
|
||||||
}),
|
space(),
|
||||||
|
maybe_parenthesize_pattern(pattern, item),
|
||||||
|
format_guard
|
||||||
|
],
|
||||||
),
|
),
|
||||||
clause_body(
|
clause_body(
|
||||||
body,
|
body,
|
||||||
|
|
|
@ -2,8 +2,7 @@ use ruff_formatter::FormatRuleWithOptions;
|
||||||
use ruff_python_ast::StringLiteral;
|
use ruff_python_ast::StringLiteral;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::preview::is_f_string_implicit_concatenated_string_literal_quotes_enabled;
|
use crate::string::{docstring, StringNormalizer};
|
||||||
use crate::string::{docstring, Quoting, StringNormalizer};
|
|
||||||
use crate::QuoteStyle;
|
use crate::QuoteStyle;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -28,12 +27,6 @@ pub enum StringLiteralKind {
|
||||||
String,
|
String,
|
||||||
/// A string literal used as a docstring.
|
/// A string literal used as a docstring.
|
||||||
Docstring,
|
Docstring,
|
||||||
/// A string literal that is implicitly concatenated with an f-string. This
|
|
||||||
/// makes the overall expression an f-string whose quoting detection comes
|
|
||||||
/// from the parent node (f-string expression).
|
|
||||||
#[deprecated]
|
|
||||||
#[allow(private_interfaces)]
|
|
||||||
InImplicitlyConcatenatedFString(Quoting),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StringLiteralKind {
|
impl StringLiteralKind {
|
||||||
|
@ -41,26 +34,6 @@ impl StringLiteralKind {
|
||||||
pub(crate) const fn is_docstring(self) -> bool {
|
pub(crate) const fn is_docstring(self) -> bool {
|
||||||
matches!(self, StringLiteralKind::Docstring)
|
matches!(self, StringLiteralKind::Docstring)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the quoting to be used for this string literal.
|
|
||||||
fn quoting(self, context: &PyFormatContext) -> Quoting {
|
|
||||||
match self {
|
|
||||||
StringLiteralKind::String | StringLiteralKind::Docstring => Quoting::CanChange,
|
|
||||||
#[allow(deprecated)]
|
|
||||||
StringLiteralKind::InImplicitlyConcatenatedFString(quoting) => {
|
|
||||||
// Allow string literals to pick the "optimal" quote character
|
|
||||||
// even if any other fstring in the implicit concatenation uses an expression
|
|
||||||
// containing a quote character.
|
|
||||||
// TODO: Remove StringLiteralKind::InImplicitlyConcatenatedFString when promoting
|
|
||||||
// this style to stable and remove the layout from `AnyStringPart::String`.
|
|
||||||
if is_f_string_implicit_concatenated_string_literal_quotes_enabled(context) {
|
|
||||||
Quoting::CanChange
|
|
||||||
} else {
|
|
||||||
quoting
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FormatNodeRule<StringLiteral> for FormatStringLiteral {
|
impl FormatNodeRule<StringLiteral> for FormatStringLiteral {
|
||||||
|
@ -75,7 +48,6 @@ impl FormatNodeRule<StringLiteral> for FormatStringLiteral {
|
||||||
};
|
};
|
||||||
|
|
||||||
let normalized = StringNormalizer::from_context(f.context())
|
let normalized = StringNormalizer::from_context(f.context())
|
||||||
.with_quoting(self.layout.quoting(f.context()))
|
|
||||||
.with_preferred_quote_style(quote_style)
|
.with_preferred_quote_style(quote_style)
|
||||||
.normalize(item.into());
|
.normalize(item.into());
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,7 @@ use crate::expression::parentheses::{
|
||||||
is_expression_parenthesized, parenthesized, Parentheses, Parenthesize,
|
is_expression_parenthesized, parenthesized, Parentheses, Parenthesize,
|
||||||
};
|
};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::preview::{
|
use crate::preview::is_with_single_target_parentheses_enabled;
|
||||||
is_with_single_item_pre_39_enabled, is_with_single_target_parentheses_enabled,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum WithItemLayout {
|
pub enum WithItemLayout {
|
||||||
|
@ -154,9 +152,7 @@ impl FormatNodeRule<WithItem> for FormatWithItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
WithItemLayout::Python38OrOlder { single } => {
|
WithItemLayout::Python38OrOlder { single } => {
|
||||||
let parenthesize = if (single && is_with_single_item_pre_39_enabled(f.context()))
|
let parenthesize = if single || is_parenthesized {
|
||||||
|| is_parenthesized
|
|
||||||
{
|
|
||||||
Parenthesize::IfBreaks
|
Parenthesize::IfBreaks
|
||||||
} else {
|
} else {
|
||||||
Parenthesize::IfRequired
|
Parenthesize::IfRequired
|
||||||
|
|
|
@ -14,7 +14,6 @@ use crate::expression::parentheses::{
|
||||||
optional_parentheses, parenthesized, NeedsParentheses, OptionalParentheses, Parentheses,
|
optional_parentheses, parenthesized, NeedsParentheses, OptionalParentheses, Parentheses,
|
||||||
};
|
};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::preview::is_join_implicit_concatenated_string_enabled;
|
|
||||||
|
|
||||||
pub(crate) mod pattern_arguments;
|
pub(crate) mod pattern_arguments;
|
||||||
pub(crate) mod pattern_keyword;
|
pub(crate) mod pattern_keyword;
|
||||||
|
@ -227,7 +226,7 @@ pub(crate) fn can_pattern_omit_optional_parentheses(
|
||||||
pattern: &Pattern,
|
pattern: &Pattern,
|
||||||
context: &PyFormatContext,
|
context: &PyFormatContext,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut visitor = CanOmitOptionalParenthesesVisitor::new(context);
|
let mut visitor = CanOmitOptionalParenthesesVisitor::default();
|
||||||
visitor.visit_pattern(pattern, context);
|
visitor.visit_pattern(pattern, context);
|
||||||
|
|
||||||
if !visitor.any_parenthesized_expressions {
|
if !visitor.any_parenthesized_expressions {
|
||||||
|
@ -272,32 +271,16 @@ pub(crate) fn can_pattern_omit_optional_parentheses(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Default)]
|
||||||
struct CanOmitOptionalParenthesesVisitor<'input> {
|
struct CanOmitOptionalParenthesesVisitor<'input> {
|
||||||
max_precedence: OperatorPrecedence,
|
max_precedence: OperatorPrecedence,
|
||||||
max_precedence_count: usize,
|
max_precedence_count: usize,
|
||||||
any_parenthesized_expressions: bool,
|
any_parenthesized_expressions: bool,
|
||||||
join_implicit_concatenated_strings: bool,
|
|
||||||
last: Option<&'input Pattern>,
|
last: Option<&'input Pattern>,
|
||||||
first: First<'input>,
|
first: First<'input>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CanOmitOptionalParenthesesVisitor<'a> {
|
impl<'a> CanOmitOptionalParenthesesVisitor<'a> {
|
||||||
fn new(context: &PyFormatContext) -> Self {
|
|
||||||
Self {
|
|
||||||
max_precedence: OperatorPrecedence::default(),
|
|
||||||
max_precedence_count: 0,
|
|
||||||
any_parenthesized_expressions: false,
|
|
||||||
// TODO: Derive default for `CanOmitOptionalParenthesesVisitor` when removing the `join_implicit_concatenated_strings`
|
|
||||||
// preview style.
|
|
||||||
join_implicit_concatenated_strings: is_join_implicit_concatenated_string_enabled(
|
|
||||||
context,
|
|
||||||
),
|
|
||||||
last: None,
|
|
||||||
first: First::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_pattern(&mut self, pattern: &'a Pattern, context: &PyFormatContext) {
|
fn visit_pattern(&mut self, pattern: &'a Pattern, context: &PyFormatContext) {
|
||||||
match pattern {
|
match pattern {
|
||||||
Pattern::MatchSequence(_) | Pattern::MatchMapping(_) => {
|
Pattern::MatchSequence(_) | Pattern::MatchMapping(_) => {
|
||||||
|
@ -305,27 +288,11 @@ impl<'a> CanOmitOptionalParenthesesVisitor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Pattern::MatchValue(value) => match &*value.value {
|
Pattern::MatchValue(value) => match &*value.value {
|
||||||
Expr::StringLiteral(string) => {
|
Expr::StringLiteral(_) |
|
||||||
if !self.join_implicit_concatenated_strings {
|
Expr::BytesLiteral(_) |
|
||||||
self.update_max_precedence(OperatorPrecedence::String, string.value.len());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Expr::BytesLiteral(bytes) => {
|
|
||||||
if !self.join_implicit_concatenated_strings {
|
|
||||||
self.update_max_precedence(OperatorPrecedence::String, bytes.value.len());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// F-strings are allowed according to python's grammar but fail with a syntax error at runtime.
|
// F-strings are allowed according to python's grammar but fail with a syntax error at runtime.
|
||||||
// That's why we need to support them for formatting.
|
// That's why we need to support them for formatting.
|
||||||
Expr::FString(string) => {
|
Expr::FString(_) |
|
||||||
if !self.join_implicit_concatenated_strings {
|
|
||||||
self.update_max_precedence(
|
|
||||||
OperatorPrecedence::String,
|
|
||||||
string.value.as_slice().len(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Expr::NumberLiteral(_) | Expr::Attribute(_) | Expr::UnaryOp(_) => {
|
Expr::NumberLiteral(_) | Expr::Attribute(_) | Expr::UnaryOp(_) => {
|
||||||
// require no state update other than visit_pattern does.
|
// require no state update other than visit_pattern does.
|
||||||
}
|
}
|
||||||
|
@ -397,8 +364,6 @@ enum OperatorPrecedence {
|
||||||
None,
|
None,
|
||||||
Additive,
|
Additive,
|
||||||
Or,
|
Or,
|
||||||
// Implicit string concatenation
|
|
||||||
String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default)]
|
#[derive(Copy, Clone, Debug, Default)]
|
||||||
|
|
|
@ -5,7 +5,6 @@ use ruff_python_ast::PatternMatchAs;
|
||||||
use crate::comments::dangling_comments;
|
use crate::comments::dangling_comments;
|
||||||
use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses};
|
use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::preview::is_match_case_parentheses_enabled;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FormatPatternMatchAs;
|
pub struct FormatPatternMatchAs;
|
||||||
|
@ -55,16 +54,12 @@ impl NeedsParentheses for PatternMatchAs {
|
||||||
fn needs_parentheses(
|
fn needs_parentheses(
|
||||||
&self,
|
&self,
|
||||||
_parent: AnyNodeRef,
|
_parent: AnyNodeRef,
|
||||||
context: &PyFormatContext,
|
_context: &PyFormatContext,
|
||||||
) -> OptionalParentheses {
|
) -> OptionalParentheses {
|
||||||
if is_match_case_parentheses_enabled(context) {
|
if self.name.is_some() {
|
||||||
if self.name.is_some() {
|
|
||||||
OptionalParentheses::Multiline
|
|
||||||
} else {
|
|
||||||
OptionalParentheses::BestFit
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
OptionalParentheses::Multiline
|
OptionalParentheses::Multiline
|
||||||
|
} else {
|
||||||
|
OptionalParentheses::BestFit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ use crate::expression::parentheses::{
|
||||||
OptionalParentheses,
|
OptionalParentheses,
|
||||||
};
|
};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::preview::is_match_case_parentheses_enabled;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FormatPatternMatchOr;
|
pub struct FormatPatternMatchOr;
|
||||||
|
@ -43,11 +42,7 @@ impl FormatNodeRule<PatternMatchOr> for FormatPatternMatchOr {
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|
||||||
if is_match_case_parentheses_enabled(f.context()) {
|
in_parentheses_only_group(&inner).fmt(f)
|
||||||
in_parentheses_only_group(&inner).fmt(f)
|
|
||||||
} else {
|
|
||||||
inner.fmt(f)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ use ruff_python_ast::{PatternMatchSingleton, Singleton};
|
||||||
|
|
||||||
use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses};
|
use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::preview::is_match_case_parentheses_enabled;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FormatPatternMatchSingleton;
|
pub struct FormatPatternMatchSingleton;
|
||||||
|
@ -22,12 +21,8 @@ impl NeedsParentheses for PatternMatchSingleton {
|
||||||
fn needs_parentheses(
|
fn needs_parentheses(
|
||||||
&self,
|
&self,
|
||||||
_parent: AnyNodeRef,
|
_parent: AnyNodeRef,
|
||||||
context: &PyFormatContext,
|
_context: &PyFormatContext,
|
||||||
) -> OptionalParentheses {
|
) -> OptionalParentheses {
|
||||||
if is_match_case_parentheses_enabled(context) {
|
OptionalParentheses::BestFit
|
||||||
OptionalParentheses::BestFit
|
|
||||||
} else {
|
|
||||||
OptionalParentheses::Never
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ use ruff_python_ast::PatternMatchValue;
|
||||||
|
|
||||||
use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses, Parentheses};
|
use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses, Parentheses};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::preview::is_match_case_parentheses_enabled;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FormatPatternMatchValue;
|
pub struct FormatPatternMatchValue;
|
||||||
|
@ -21,10 +20,6 @@ impl NeedsParentheses for PatternMatchValue {
|
||||||
parent: AnyNodeRef,
|
parent: AnyNodeRef,
|
||||||
context: &PyFormatContext,
|
context: &PyFormatContext,
|
||||||
) -> OptionalParentheses {
|
) -> OptionalParentheses {
|
||||||
if is_match_case_parentheses_enabled(context) {
|
self.value.needs_parentheses(parent, context)
|
||||||
self.value.needs_parentheses(parent, context)
|
|
||||||
} else {
|
|
||||||
OptionalParentheses::Never
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,65 +14,6 @@ pub(crate) const fn is_hug_parens_with_braces_and_square_brackets_enabled(
|
||||||
context.is_preview()
|
context.is_preview()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the [`f-string formatting`](https://github.com/astral-sh/ruff/issues/7594) preview style is enabled.
|
|
||||||
/// WARNING: This preview style depends on `is_f_string_implicit_concatenated_string_literal_quotes_enabled`.
|
|
||||||
/// TODO: Remove `Quoting` when promoting this preview style and convert `FormatStringPart` etc. regular `FormatWithRule` implementations.
|
|
||||||
/// TODO: Remove `format_f_string` from `normalize_string` when promoting this preview style.
|
|
||||||
pub(crate) fn is_f_string_formatting_enabled(context: &PyFormatContext) -> bool {
|
|
||||||
context.is_preview()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See [#13539](https://github.com/astral-sh/ruff/pull/13539)
|
|
||||||
/// Remove `Quoting` when stabilizing this preview style.
|
|
||||||
pub(crate) fn is_f_string_implicit_concatenated_string_literal_quotes_enabled(
|
|
||||||
context: &PyFormatContext,
|
|
||||||
) -> bool {
|
|
||||||
context.is_preview()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn is_with_single_item_pre_39_enabled(context: &PyFormatContext) -> bool {
|
|
||||||
context.is_preview()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See [#12282](https://github.com/astral-sh/ruff/pull/12282).
|
|
||||||
pub(crate) fn is_comprehension_leading_expression_comments_same_line_enabled(
|
|
||||||
context: &PyFormatContext,
|
|
||||||
) -> bool {
|
|
||||||
context.is_preview()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See [#9447](https://github.com/astral-sh/ruff/issues/9447)
|
|
||||||
pub(crate) fn is_empty_parameters_no_unnecessary_parentheses_around_return_value_enabled(
|
|
||||||
context: &PyFormatContext,
|
|
||||||
) -> bool {
|
|
||||||
context.is_preview()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See [#6933](https://github.com/astral-sh/ruff/issues/6933).
|
|
||||||
/// This style also covers the black preview styles `remove_redundant_guard_parens` and `parens_for_long_if_clauses_in_case_block `.
|
|
||||||
/// WARNING: This preview style depends on `is_empty_parameters_no_unnecessary_parentheses_around_return_value_enabled`
|
|
||||||
/// because it relies on the new semantic of `IfBreaksParenthesized`.
|
|
||||||
pub(crate) fn is_match_case_parentheses_enabled(context: &PyFormatContext) -> bool {
|
|
||||||
context.is_preview()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This preview style fixes a bug with the docstring's `line-length` calculation when using the `dynamic` mode.
|
|
||||||
/// The new style now respects the indent **inside** the docstring and reduces the `line-length` accordingly
|
|
||||||
/// so that the docstring's code block fits into the global line-length setting.
|
|
||||||
pub(crate) fn is_docstring_code_block_in_docstring_indent_enabled(
|
|
||||||
context: &PyFormatContext,
|
|
||||||
) -> bool {
|
|
||||||
context.is_preview()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if implicitly concatenated strings should be joined if they all fit on a single line.
|
|
||||||
/// See [#9457](https://github.com/astral-sh/ruff/issues/9457)
|
|
||||||
/// WARNING: This preview style depends on `is_empty_parameters_no_unnecessary_parentheses_around_return_value_enabled`
|
|
||||||
/// because it relies on the new semantic of `IfBreaksParenthesized`.
|
|
||||||
pub(crate) fn is_join_implicit_concatenated_string_enabled(context: &PyFormatContext) -> bool {
|
|
||||||
context.is_preview()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if the bugfix for single-with items with a trailing comment targeting Python 3.9 or newer is enabled.
|
/// Returns `true` if the bugfix for single-with items with a trailing comment targeting Python 3.9 or newer is enabled.
|
||||||
///
|
///
|
||||||
/// See [#14001](https://github.com/astral-sh/ruff/issues/14001)
|
/// See [#14001](https://github.com/astral-sh/ruff/issues/14001)
|
||||||
|
|
|
@ -3,10 +3,8 @@ use ruff_formatter::write;
|
||||||
use ruff_python_ast::StmtAssert;
|
use ruff_python_ast::StmtAssert;
|
||||||
|
|
||||||
use crate::comments::SourceComment;
|
use crate::comments::SourceComment;
|
||||||
|
|
||||||
use crate::expression::maybe_parenthesize_expression;
|
use crate::expression::maybe_parenthesize_expression;
|
||||||
use crate::expression::parentheses::Parenthesize;
|
use crate::expression::parentheses::Parenthesize;
|
||||||
use crate::preview::is_join_implicit_concatenated_string_enabled;
|
|
||||||
use crate::{has_skip_comment, prelude::*};
|
use crate::{has_skip_comment, prelude::*};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -30,18 +28,12 @@ impl FormatNodeRule<StmtAssert> for FormatStmtAssert {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if let Some(msg) = msg {
|
if let Some(msg) = msg {
|
||||||
let parenthesize = if is_join_implicit_concatenated_string_enabled(f.context()) {
|
|
||||||
Parenthesize::IfBreaksParenthesized
|
|
||||||
} else {
|
|
||||||
Parenthesize::IfBreaks
|
|
||||||
};
|
|
||||||
|
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
[
|
[
|
||||||
token(","),
|
token(","),
|
||||||
space(),
|
space(),
|
||||||
maybe_parenthesize_expression(msg, item, parenthesize),
|
maybe_parenthesize_expression(msg, item, Parenthesize::IfBreaksParenthesized),
|
||||||
]
|
]
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use ruff_formatter::{format_args, write, FormatError, RemoveSoftLinesBuffer};
|
use ruff_formatter::{format_args, write, FormatError, RemoveSoftLinesBuffer};
|
||||||
use ruff_python_ast::{
|
use ruff_python_ast::{
|
||||||
AnyNodeRef, Expr, ExprAttribute, ExprCall, FStringPart, Operator, StmtAssign, StringLike,
|
AnyNodeRef, Expr, ExprAttribute, ExprCall, FString, FStringPart, Operator, StmtAssign,
|
||||||
TypeParams,
|
StringLike, TypeParams,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::builders::parenthesize_if_expands;
|
use crate::builders::parenthesize_if_expands;
|
||||||
|
@ -9,7 +9,6 @@ use crate::comments::{
|
||||||
trailing_comments, Comments, LeadingDanglingTrailingComments, SourceComment,
|
trailing_comments, Comments, LeadingDanglingTrailingComments, SourceComment,
|
||||||
};
|
};
|
||||||
use crate::context::{NodeLevel, WithNodeLevel};
|
use crate::context::{NodeLevel, WithNodeLevel};
|
||||||
use crate::expression::expr_f_string::f_string_quoting;
|
|
||||||
use crate::expression::parentheses::{
|
use crate::expression::parentheses::{
|
||||||
is_expression_parenthesized, optional_parentheses, NeedsParentheses, OptionalParentheses,
|
is_expression_parenthesized, optional_parentheses, NeedsParentheses, OptionalParentheses,
|
||||||
Parentheses, Parenthesize,
|
Parentheses, Parenthesize,
|
||||||
|
@ -18,10 +17,7 @@ use crate::expression::{
|
||||||
can_omit_optional_parentheses, has_own_parentheses, has_parentheses,
|
can_omit_optional_parentheses, has_own_parentheses, has_parentheses,
|
||||||
maybe_parenthesize_expression,
|
maybe_parenthesize_expression,
|
||||||
};
|
};
|
||||||
use crate::other::f_string::{FStringLayout, FormatFString};
|
use crate::other::f_string::FStringLayout;
|
||||||
use crate::preview::{
|
|
||||||
is_f_string_formatting_enabled, is_join_implicit_concatenated_string_enabled,
|
|
||||||
};
|
|
||||||
use crate::statement::trailing_semicolon;
|
use crate::statement::trailing_semicolon;
|
||||||
use crate::string::implicit::{
|
use crate::string::implicit::{
|
||||||
FormatImplicitConcatenatedStringExpanded, FormatImplicitConcatenatedStringFlat,
|
FormatImplicitConcatenatedStringExpanded, FormatImplicitConcatenatedStringFlat,
|
||||||
|
@ -456,7 +452,7 @@ impl Format<PyFormatContext<'_>> for FormatStatementsLastExpression<'_> {
|
||||||
let f_string_flat = format_with(|f| {
|
let f_string_flat = format_with(|f| {
|
||||||
let mut buffer = RemoveSoftLinesBuffer::new(&mut *f);
|
let mut buffer = RemoveSoftLinesBuffer::new(&mut *f);
|
||||||
|
|
||||||
write!(buffer, [format_f_string])
|
write!(buffer, [format_f_string.format()])
|
||||||
})
|
})
|
||||||
.memoized();
|
.memoized();
|
||||||
|
|
||||||
|
@ -518,7 +514,7 @@ impl Format<PyFormatContext<'_>> for FormatStatementsLastExpression<'_> {
|
||||||
// }moreeeeeeeeeeeeeeeee"
|
// }moreeeeeeeeeeeeeeeee"
|
||||||
// ```
|
// ```
|
||||||
let format_f_string =
|
let format_f_string =
|
||||||
format_with(|f| write!(f, [format_f_string, inline_comments]));
|
format_with(|f| write!(f, [format_f_string.format(), inline_comments]));
|
||||||
|
|
||||||
best_fitting![single_line, joined_parenthesized, format_f_string]
|
best_fitting![single_line, joined_parenthesized, format_f_string]
|
||||||
.with_mode(BestFittingMode::AllLines)
|
.with_mode(BestFittingMode::AllLines)
|
||||||
|
@ -668,7 +664,7 @@ impl Format<PyFormatContext<'_>> for FormatStatementsLastExpression<'_> {
|
||||||
// Similar to above, remove any soft line breaks emitted by the f-string
|
// Similar to above, remove any soft line breaks emitted by the f-string
|
||||||
// formatting.
|
// formatting.
|
||||||
let mut buffer = RemoveSoftLinesBuffer::new(&mut *f);
|
let mut buffer = RemoveSoftLinesBuffer::new(&mut *f);
|
||||||
write!(buffer, [format_f_string])
|
write!(buffer, [format_f_string.format()])
|
||||||
} else {
|
} else {
|
||||||
value.format().with_options(Parentheses::Never).fmt(f)
|
value.format().with_options(Parentheses::Never).fmt(f)
|
||||||
}
|
}
|
||||||
|
@ -701,20 +697,22 @@ impl Format<PyFormatContext<'_>> for FormatStatementsLastExpression<'_> {
|
||||||
// )
|
// )
|
||||||
// ```
|
// ```
|
||||||
let flat_target_parenthesize_value = format_with(|f| {
|
let flat_target_parenthesize_value = format_with(|f| {
|
||||||
write!(f, [last_target, space(), operator, space(), token("("),])?;
|
write!(
|
||||||
|
f,
|
||||||
if is_join_implicit_concatenated_string_enabled(f.context()) {
|
[
|
||||||
group(&soft_block_indent(&format_args![
|
last_target,
|
||||||
format_value,
|
space(),
|
||||||
inline_comments
|
operator,
|
||||||
]))
|
space(),
|
||||||
.should_expand(true)
|
token("("),
|
||||||
.fmt(f)?;
|
group(&soft_block_indent(&format_args![
|
||||||
} else {
|
format_value,
|
||||||
block_indent(&format_args![format_value, inline_comments]).fmt(f)?;
|
inline_comments
|
||||||
}
|
]))
|
||||||
|
.should_expand(true),
|
||||||
token(")").fmt(f)
|
token(")")
|
||||||
|
]
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fall back to parenthesizing (or splitting) the last target part if we can't make the value
|
// Fall back to parenthesizing (or splitting) the last target part if we can't make the value
|
||||||
|
@ -726,15 +724,16 @@ impl Format<PyFormatContext<'_>> for FormatStatementsLastExpression<'_> {
|
||||||
// ] = c
|
// ] = c
|
||||||
// ```
|
// ```
|
||||||
let split_target_flat_value = format_with(|f| {
|
let split_target_flat_value = format_with(|f| {
|
||||||
if is_join_implicit_concatenated_string_enabled(f.context()) {
|
|
||||||
group(&last_target).should_expand(true).fmt(f)?;
|
|
||||||
} else {
|
|
||||||
last_target.fmt(f)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
[space(), operator, space(), format_value, inline_comments]
|
[
|
||||||
|
group(&last_target).should_expand(true),
|
||||||
|
space(),
|
||||||
|
operator,
|
||||||
|
space(),
|
||||||
|
format_value,
|
||||||
|
inline_comments
|
||||||
|
]
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -935,7 +934,8 @@ impl Format<PyFormatContext<'_>> for FormatStatementsLastExpression<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let format_f_string =
|
let format_f_string =
|
||||||
format_with(|f| write!(f, [format_f_string, inline_comments])).memoized();
|
format_with(|f| write!(f, [format_f_string.format(), inline_comments]))
|
||||||
|
.memoized();
|
||||||
|
|
||||||
// Considering the following initial source:
|
// Considering the following initial source:
|
||||||
//
|
//
|
||||||
|
@ -1102,11 +1102,7 @@ impl Format<PyFormatContext<'_>> for FormatStatementsLastExpression<'_> {
|
||||||
fn format_f_string_assignment<'a>(
|
fn format_f_string_assignment<'a>(
|
||||||
string: StringLike<'a>,
|
string: StringLike<'a>,
|
||||||
context: &PyFormatContext,
|
context: &PyFormatContext,
|
||||||
) -> Option<FormatFString<'a>> {
|
) -> Option<&'a FString> {
|
||||||
if !is_f_string_formatting_enabled(context) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let StringLike::FString(expr) = string else {
|
let StringLike::FString(expr) = string else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
@ -1128,10 +1124,7 @@ fn format_f_string_assignment<'a>(
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(FormatFString::new(
|
Some(f_string)
|
||||||
f_string,
|
|
||||||
f_string_quoting(expr, context.source()),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
|
|
@ -18,10 +18,6 @@ use {
|
||||||
ruff_text_size::{Ranged, TextLen, TextRange, TextSize},
|
ruff_text_size::{Ranged, TextLen, TextRange, TextSize},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::preview::{
|
|
||||||
is_docstring_code_block_in_docstring_indent_enabled,
|
|
||||||
is_join_implicit_concatenated_string_enabled,
|
|
||||||
};
|
|
||||||
use crate::string::StringQuotes;
|
use crate::string::StringQuotes;
|
||||||
use crate::{prelude::*, DocstringCodeLineWidth, FormatModuleError};
|
use crate::{prelude::*, DocstringCodeLineWidth, FormatModuleError};
|
||||||
|
|
||||||
|
@ -171,7 +167,7 @@ pub(crate) fn format(normalized: &NormalizedString, f: &mut PyFormatter) -> Form
|
||||||
if docstring[first.len()..].trim().is_empty() {
|
if docstring[first.len()..].trim().is_empty() {
|
||||||
// For `"""\n"""` or other whitespace between the quotes, black keeps a single whitespace,
|
// For `"""\n"""` or other whitespace between the quotes, black keeps a single whitespace,
|
||||||
// but `""""""` doesn't get one inserted.
|
// but `""""""` doesn't get one inserted.
|
||||||
if needs_chaperone_space(normalized.flags(), trim_end, f.context())
|
if needs_chaperone_space(normalized.flags(), trim_end)
|
||||||
|| (trim_end.is_empty() && !docstring.is_empty())
|
|| (trim_end.is_empty() && !docstring.is_empty())
|
||||||
{
|
{
|
||||||
space().fmt(f)?;
|
space().fmt(f)?;
|
||||||
|
@ -211,7 +207,7 @@ pub(crate) fn format(normalized: &NormalizedString, f: &mut PyFormatter) -> Form
|
||||||
let trim_end = docstring
|
let trim_end = docstring
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.trim_end_matches(|c: char| c.is_whitespace() && c != '\n');
|
.trim_end_matches(|c: char| c.is_whitespace() && c != '\n');
|
||||||
if needs_chaperone_space(normalized.flags(), trim_end, f.context()) {
|
if needs_chaperone_space(normalized.flags(), trim_end) {
|
||||||
space().fmt(f)?;
|
space().fmt(f)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,17 +504,15 @@ impl<'src> DocstringLinePrinter<'_, '_, '_, 'src> {
|
||||||
.to_ascii_spaces(indent_width)
|
.to_ascii_spaces(indent_width)
|
||||||
.saturating_add(kind.extra_indent_ascii_spaces());
|
.saturating_add(kind.extra_indent_ascii_spaces());
|
||||||
|
|
||||||
if is_docstring_code_block_in_docstring_indent_enabled(self.f.context()) {
|
// Add the in-docstring indentation
|
||||||
// Add the in-docstring indentation
|
current_indent = current_indent.saturating_add(
|
||||||
current_indent = current_indent.saturating_add(
|
u16::try_from(
|
||||||
u16::try_from(
|
kind.indent()
|
||||||
kind.indent()
|
.columns()
|
||||||
.columns()
|
.saturating_sub(self.stripped_indentation.columns()),
|
||||||
.saturating_sub(self.stripped_indentation.columns()),
|
)
|
||||||
)
|
.unwrap_or(u16::MAX),
|
||||||
.unwrap_or(u16::MAX),
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let width = std::cmp::max(1, global_line_width.saturating_sub(current_indent));
|
let width = std::cmp::max(1, global_line_width.saturating_sub(current_indent));
|
||||||
LineWidth::try_from(width).expect("width should be capped at a minimum of 1")
|
LineWidth::try_from(width).expect("width should be capped at a minimum of 1")
|
||||||
|
@ -1607,17 +1601,11 @@ fn docstring_format_source(
|
||||||
/// If the last line of the docstring is `content" """` or `content\ """`, we need a chaperone space
|
/// If the last line of the docstring is `content" """` or `content\ """`, we need a chaperone space
|
||||||
/// that avoids `content""""` and `content\"""`. This does only applies to un-escaped backslashes,
|
/// that avoids `content""""` and `content\"""`. This does only applies to un-escaped backslashes,
|
||||||
/// so `content\\ """` doesn't need a space while `content\\\ """` does.
|
/// so `content\\ """` doesn't need a space while `content\\\ """` does.
|
||||||
pub(super) fn needs_chaperone_space(
|
pub(super) fn needs_chaperone_space(flags: AnyStringFlags, trim_end: &str) -> bool {
|
||||||
flags: AnyStringFlags,
|
|
||||||
trim_end: &str,
|
|
||||||
context: &PyFormatContext,
|
|
||||||
) -> bool {
|
|
||||||
if trim_end.chars().rev().take_while(|c| *c == '\\').count() % 2 == 1 {
|
if trim_end.chars().rev().take_while(|c| *c == '\\').count() % 2 == 1 {
|
||||||
true
|
true
|
||||||
} else if is_join_implicit_concatenated_string_enabled(context) {
|
|
||||||
flags.is_triple_quoted() && trim_end.ends_with(flags.quote_style().as_char())
|
|
||||||
} else {
|
} else {
|
||||||
trim_end.ends_with(flags.quote_style().as_char())
|
flags.is_triple_quoted() && trim_end.ends_with(flags.quote_style().as_char())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,9 @@ use std::borrow::Cow;
|
||||||
|
|
||||||
use crate::comments::{leading_comments, trailing_comments};
|
use crate::comments::{leading_comments, trailing_comments};
|
||||||
use crate::expression::parentheses::in_parentheses_only_soft_line_break_or_space;
|
use crate::expression::parentheses::in_parentheses_only_soft_line_break_or_space;
|
||||||
use crate::other::f_string::{FStringContext, FStringLayout, FormatFString};
|
use crate::other::f_string::{FStringContext, FStringLayout};
|
||||||
use crate::other::f_string_element::FormatFStringExpressionElement;
|
use crate::other::f_string_element::FormatFStringExpressionElement;
|
||||||
use crate::other::string_literal::StringLiteralKind;
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::preview::{
|
|
||||||
is_f_string_formatting_enabled, is_join_implicit_concatenated_string_enabled,
|
|
||||||
};
|
|
||||||
use crate::string::docstring::needs_chaperone_space;
|
use crate::string::docstring::needs_chaperone_space;
|
||||||
use crate::string::normalize::{
|
use crate::string::normalize::{
|
||||||
is_fstring_with_quoted_debug_expression, is_fstring_with_quoted_format_spec_and_debug,
|
is_fstring_with_quoted_debug_expression, is_fstring_with_quoted_format_spec_and_debug,
|
||||||
|
@ -82,14 +78,9 @@ impl<'a> FormatImplicitConcatenatedStringExpanded<'a> {
|
||||||
impl Format<PyFormatContext<'_>> for FormatImplicitConcatenatedStringExpanded<'_> {
|
impl Format<PyFormatContext<'_>> for FormatImplicitConcatenatedStringExpanded<'_> {
|
||||||
fn fmt(&self, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> {
|
fn fmt(&self, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> {
|
||||||
let comments = f.context().comments().clone();
|
let comments = f.context().comments().clone();
|
||||||
let quoting = self.string.quoting(f.context().source());
|
|
||||||
|
|
||||||
let join_implicit_concatenated_string_enabled =
|
|
||||||
is_join_implicit_concatenated_string_enabled(f.context());
|
|
||||||
|
|
||||||
// Keep implicit concatenated strings expanded unless they're already written on a single line.
|
// Keep implicit concatenated strings expanded unless they're already written on a single line.
|
||||||
if matches!(self.layout, ImplicitConcatenatedLayout::Multipart)
|
if matches!(self.layout, ImplicitConcatenatedLayout::Multipart)
|
||||||
&& join_implicit_concatenated_string_enabled
|
|
||||||
&& self.string.parts().tuple_windows().any(|(a, b)| {
|
&& self.string.parts().tuple_windows().any(|(a, b)| {
|
||||||
f.context()
|
f.context()
|
||||||
.source()
|
.source()
|
||||||
|
@ -103,23 +94,13 @@ impl Format<PyFormatContext<'_>> for FormatImplicitConcatenatedStringExpanded<'_
|
||||||
|
|
||||||
for part in self.string.parts() {
|
for part in self.string.parts() {
|
||||||
let format_part = format_with(|f: &mut PyFormatter| match part {
|
let format_part = format_with(|f: &mut PyFormatter| match part {
|
||||||
StringLikePart::String(part) => {
|
StringLikePart::String(part) => part.format().fmt(f),
|
||||||
let kind = if self.string.is_fstring() {
|
|
||||||
#[allow(deprecated)]
|
|
||||||
StringLiteralKind::InImplicitlyConcatenatedFString(quoting)
|
|
||||||
} else {
|
|
||||||
StringLiteralKind::String
|
|
||||||
};
|
|
||||||
|
|
||||||
part.format().with_options(kind).fmt(f)
|
|
||||||
}
|
|
||||||
StringLikePart::Bytes(bytes_literal) => bytes_literal.format().fmt(f),
|
StringLikePart::Bytes(bytes_literal) => bytes_literal.format().fmt(f),
|
||||||
StringLikePart::FString(part) => FormatFString::new(part, quoting).fmt(f),
|
StringLikePart::FString(part) => part.format().fmt(f),
|
||||||
});
|
});
|
||||||
|
|
||||||
let part_comments = comments.leading_dangling_trailing(&part);
|
let part_comments = comments.leading_dangling_trailing(&part);
|
||||||
joiner.entry(&format_args![
|
joiner.entry(&format_args![
|
||||||
(!join_implicit_concatenated_string_enabled).then_some(line_suffix_boundary()),
|
|
||||||
leading_comments(part_comments.leading),
|
leading_comments(part_comments.leading),
|
||||||
format_part,
|
format_part,
|
||||||
trailing_comments(part_comments.trailing)
|
trailing_comments(part_comments.trailing)
|
||||||
|
@ -149,10 +130,6 @@ impl<'a> FormatImplicitConcatenatedStringFlat<'a> {
|
||||||
/// Creates a new formatter. Returns `None` if the string can't be merged into a single string.
|
/// Creates a new formatter. Returns `None` if the string can't be merged into a single string.
|
||||||
pub(crate) fn new(string: StringLike<'a>, context: &PyFormatContext) -> Option<Self> {
|
pub(crate) fn new(string: StringLike<'a>, context: &PyFormatContext) -> Option<Self> {
|
||||||
fn merge_flags(string: StringLike, context: &PyFormatContext) -> Option<AnyStringFlags> {
|
fn merge_flags(string: StringLike, context: &PyFormatContext) -> Option<AnyStringFlags> {
|
||||||
if !is_join_implicit_concatenated_string_enabled(context) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Multiline strings can never fit on a single line.
|
// Multiline strings can never fit on a single line.
|
||||||
if string.is_multiline(context) {
|
if string.is_multiline(context) {
|
||||||
return None;
|
return None;
|
||||||
|
@ -323,44 +300,29 @@ impl Format<PyFormatContext<'_>> for FormatImplicitConcatenatedStringFlat<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
StringLikePart::FString(f_string) => {
|
StringLikePart::FString(f_string) => {
|
||||||
if is_f_string_formatting_enabled(f.context()) {
|
for element in &f_string.elements {
|
||||||
for element in &f_string.elements {
|
match element {
|
||||||
match element {
|
FStringElement::Literal(literal) => {
|
||||||
FStringElement::Literal(literal) => {
|
FormatLiteralContent {
|
||||||
FormatLiteralContent {
|
range: literal.range(),
|
||||||
range: literal.range(),
|
flags: self.flags,
|
||||||
flags: self.flags,
|
is_fstring: true,
|
||||||
is_fstring: true,
|
trim_end: false,
|
||||||
trim_end: false,
|
trim_start: false,
|
||||||
trim_start: false,
|
|
||||||
}
|
|
||||||
.fmt(f)?;
|
|
||||||
}
|
}
|
||||||
// Formatting the expression here and in the expanded version is safe **only**
|
.fmt(f)?;
|
||||||
// because we assert that the f-string never contains any comments.
|
}
|
||||||
FStringElement::Expression(expression) => {
|
// Formatting the expression here and in the expanded version is safe **only**
|
||||||
let context = FStringContext::new(
|
// because we assert that the f-string never contains any comments.
|
||||||
self.flags,
|
FStringElement::Expression(expression) => {
|
||||||
FStringLayout::from_f_string(
|
let context = FStringContext::new(
|
||||||
f_string,
|
self.flags,
|
||||||
f.context().source(),
|
FStringLayout::from_f_string(f_string, f.context().source()),
|
||||||
),
|
);
|
||||||
);
|
|
||||||
|
|
||||||
FormatFStringExpressionElement::new(expression, context)
|
FormatFStringExpressionElement::new(expression, context).fmt(f)?;
|
||||||
.fmt(f)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
FormatLiteralContent {
|
|
||||||
range: part.content_range(),
|
|
||||||
flags: self.flags,
|
|
||||||
is_fstring: true,
|
|
||||||
trim_end: false,
|
|
||||||
trim_start: false,
|
|
||||||
}
|
|
||||||
.fmt(f)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -386,9 +348,6 @@ impl Format<PyFormatContext<'_>> for FormatLiteralContent {
|
||||||
0,
|
0,
|
||||||
self.flags,
|
self.flags,
|
||||||
self.flags.is_f_string() && !self.is_fstring,
|
self.flags.is_f_string() && !self.is_fstring,
|
||||||
// TODO: Remove the argument from `normalize_string` when promoting the `is_f_string_formatting_enabled` preview style.
|
|
||||||
self.flags.is_f_string() && !is_f_string_formatting_enabled(f.context()),
|
|
||||||
is_f_string_formatting_enabled(f.context()),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Trim the start and end of the string if it's the first or last part of a docstring.
|
// Trim the start and end of the string if it's the first or last part of a docstring.
|
||||||
|
@ -413,7 +372,7 @@ impl Format<PyFormatContext<'_>> for FormatLiteralContent {
|
||||||
Cow::Owned(normalized) => text(normalized).fmt(f)?,
|
Cow::Owned(normalized) => text(normalized).fmt(f)?,
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.trim_end && needs_chaperone_space(self.flags, &normalized, f.context()) {
|
if self.trim_end && needs_chaperone_space(self.flags, &normalized) {
|
||||||
space().fmt(f)?;
|
space().fmt(f)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,22 +10,13 @@ use ruff_python_ast::{
|
||||||
use ruff_source_file::LineRanges;
|
use ruff_source_file::LineRanges;
|
||||||
use ruff_text_size::Ranged;
|
use ruff_text_size::Ranged;
|
||||||
|
|
||||||
use crate::expression::expr_f_string::f_string_quoting;
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::preview::is_f_string_formatting_enabled;
|
|
||||||
use crate::QuoteStyle;
|
use crate::QuoteStyle;
|
||||||
|
|
||||||
pub(crate) mod docstring;
|
pub(crate) mod docstring;
|
||||||
pub(crate) mod implicit;
|
pub(crate) mod implicit;
|
||||||
mod normalize;
|
mod normalize;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default)]
|
|
||||||
pub(crate) enum Quoting {
|
|
||||||
#[default]
|
|
||||||
CanChange,
|
|
||||||
Preserve,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Format<PyFormatContext<'_>> for AnyStringPrefix {
|
impl Format<PyFormatContext<'_>> for AnyStringPrefix {
|
||||||
fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> {
|
fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> {
|
||||||
// Remove the unicode prefix `u` if any because it is meaningless in Python 3+.
|
// Remove the unicode prefix `u` if any because it is meaningless in Python 3+.
|
||||||
|
@ -90,19 +81,10 @@ impl From<Quote> for QuoteStyle {
|
||||||
|
|
||||||
// Extension trait that adds formatter specific helper methods to `StringLike`.
|
// Extension trait that adds formatter specific helper methods to `StringLike`.
|
||||||
pub(crate) trait StringLikeExtensions {
|
pub(crate) trait StringLikeExtensions {
|
||||||
fn quoting(&self, source: &str) -> Quoting;
|
|
||||||
|
|
||||||
fn is_multiline(&self, context: &PyFormatContext) -> bool;
|
fn is_multiline(&self, context: &PyFormatContext) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StringLikeExtensions for ast::StringLike<'_> {
|
impl StringLikeExtensions for ast::StringLike<'_> {
|
||||||
fn quoting(&self, source: &str) -> Quoting {
|
|
||||||
match self {
|
|
||||||
Self::String(_) | Self::Bytes(_) => Quoting::CanChange,
|
|
||||||
Self::FString(f_string) => f_string_quoting(f_string, source),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_multiline(&self, context: &PyFormatContext) -> bool {
|
fn is_multiline(&self, context: &PyFormatContext) -> bool {
|
||||||
self.parts().any(|part| match part {
|
self.parts().any(|part| match part {
|
||||||
StringLikePart::String(_) | StringLikePart::Bytes(_) => {
|
StringLikePart::String(_) | StringLikePart::Bytes(_) => {
|
||||||
|
@ -149,15 +131,11 @@ impl StringLikeExtensions for ast::StringLike<'_> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_f_string_formatting_enabled(context) {
|
contains_line_break_or_comments(
|
||||||
contains_line_break_or_comments(
|
&f_string.elements,
|
||||||
&f_string.elements,
|
context,
|
||||||
context,
|
f_string.flags.is_triple_quoted(),
|
||||||
f_string.flags.is_triple_quoted(),
|
)
|
||||||
)
|
|
||||||
} else {
|
|
||||||
context.source().contains_line_break(f_string.range())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,10 @@ use ruff_text_size::{Ranged, TextRange, TextSlice};
|
||||||
|
|
||||||
use crate::context::FStringState;
|
use crate::context::FStringState;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::preview::is_f_string_formatting_enabled;
|
use crate::string::StringQuotes;
|
||||||
use crate::string::{Quoting, StringQuotes};
|
|
||||||
use crate::QuoteStyle;
|
use crate::QuoteStyle;
|
||||||
|
|
||||||
pub(crate) struct StringNormalizer<'a, 'src> {
|
pub(crate) struct StringNormalizer<'a, 'src> {
|
||||||
quoting: Quoting,
|
|
||||||
preferred_quote_style: Option<QuoteStyle>,
|
preferred_quote_style: Option<QuoteStyle>,
|
||||||
context: &'a PyFormatContext<'src>,
|
context: &'a PyFormatContext<'src>,
|
||||||
}
|
}
|
||||||
|
@ -25,7 +23,6 @@ pub(crate) struct StringNormalizer<'a, 'src> {
|
||||||
impl<'a, 'src> StringNormalizer<'a, 'src> {
|
impl<'a, 'src> StringNormalizer<'a, 'src> {
|
||||||
pub(crate) fn from_context(context: &'a PyFormatContext<'src>) -> Self {
|
pub(crate) fn from_context(context: &'a PyFormatContext<'src>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
quoting: Quoting::default(),
|
|
||||||
preferred_quote_style: None,
|
preferred_quote_style: None,
|
||||||
context,
|
context,
|
||||||
}
|
}
|
||||||
|
@ -36,11 +33,6 @@ impl<'a, 'src> StringNormalizer<'a, 'src> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn with_quoting(mut self, quoting: Quoting) -> Self {
|
|
||||||
self.quoting = quoting;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Determines the preferred quote style for `string`.
|
/// Determines the preferred quote style for `string`.
|
||||||
/// The formatter should use the preferred quote style unless
|
/// The formatter should use the preferred quote style unless
|
||||||
/// it can't because the string contains the preferred quotes OR
|
/// it can't because the string contains the preferred quotes OR
|
||||||
|
@ -49,112 +41,106 @@ impl<'a, 'src> StringNormalizer<'a, 'src> {
|
||||||
/// Note: If you add more cases here where we return `QuoteStyle::Preserve`,
|
/// Note: If you add more cases here where we return `QuoteStyle::Preserve`,
|
||||||
/// make sure to also add them to [`FormatImplicitConcatenatedStringFlat::new`].
|
/// make sure to also add them to [`FormatImplicitConcatenatedStringFlat::new`].
|
||||||
pub(super) fn preferred_quote_style(&self, string: StringLikePart) -> QuoteStyle {
|
pub(super) fn preferred_quote_style(&self, string: StringLikePart) -> QuoteStyle {
|
||||||
match self.quoting {
|
let preferred_quote_style = self
|
||||||
Quoting::Preserve => QuoteStyle::Preserve,
|
.preferred_quote_style
|
||||||
Quoting::CanChange => {
|
.unwrap_or(self.context.options().quote_style());
|
||||||
let preferred_quote_style = self
|
|
||||||
.preferred_quote_style
|
|
||||||
.unwrap_or(self.context.options().quote_style());
|
|
||||||
|
|
||||||
if preferred_quote_style.is_preserve() {
|
if preferred_quote_style.is_preserve() {
|
||||||
|
return QuoteStyle::Preserve;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let StringLikePart::FString(fstring) = string {
|
||||||
|
// There are two cases where it's necessary to preserve the quotes if the
|
||||||
|
// target version is pre 3.12 and the part is an f-string.
|
||||||
|
if !self.context.options().target_version().supports_pep_701() {
|
||||||
|
// An f-string expression contains a debug text with a quote character
|
||||||
|
// because the formatter will emit the debug expression **exactly** the
|
||||||
|
// same as in the source text.
|
||||||
|
if is_fstring_with_quoted_debug_expression(fstring, self.context) {
|
||||||
return QuoteStyle::Preserve;
|
return QuoteStyle::Preserve;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let StringLikePart::FString(fstring) = string {
|
// An f-string expression that contains a triple quoted string literal
|
||||||
// There are two cases where it's necessary to preserve the quotes if the
|
// expression that contains a quote.
|
||||||
// target version is pre 3.12 and the part is an f-string.
|
if is_fstring_with_triple_quoted_literal_expression_containing_quotes(
|
||||||
if !self.context.options().target_version().supports_pep_701() {
|
fstring,
|
||||||
// An f-string expression contains a debug text with a quote character
|
self.context,
|
||||||
// because the formatter will emit the debug expression **exactly** the
|
) {
|
||||||
// same as in the source text.
|
return QuoteStyle::Preserve;
|
||||||
if is_fstring_with_quoted_debug_expression(fstring, self.context) {
|
|
||||||
return QuoteStyle::Preserve;
|
|
||||||
}
|
|
||||||
|
|
||||||
// An f-string expression that contains a triple quoted string literal
|
|
||||||
// expression that contains a quote.
|
|
||||||
if is_fstring_with_triple_quoted_literal_expression_containing_quotes(
|
|
||||||
fstring,
|
|
||||||
self.context,
|
|
||||||
) {
|
|
||||||
return QuoteStyle::Preserve;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// An f-string expression element contains a debug text and the corresponding
|
|
||||||
// format specifier has a literal element with a quote character.
|
|
||||||
if is_fstring_with_quoted_format_spec_and_debug(fstring, self.context) {
|
|
||||||
return QuoteStyle::Preserve;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// For f-strings prefer alternating the quotes unless The outer string is triple quoted and the inner isn't.
|
|
||||||
if let FStringState::InsideExpressionElement(parent_context) =
|
|
||||||
self.context.f_string_state()
|
|
||||||
{
|
|
||||||
let parent_flags = parent_context.f_string().flags();
|
|
||||||
|
|
||||||
if !parent_flags.is_triple_quoted() || string.flags().is_triple_quoted() {
|
|
||||||
return QuoteStyle::from(parent_flags.quote_style().opposite());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Per PEP 8, always prefer double quotes for triple-quoted strings.
|
|
||||||
if string.flags().is_triple_quoted() {
|
|
||||||
// ... unless we're formatting a code snippet inside a docstring,
|
|
||||||
// then we specifically want to invert our quote style to avoid
|
|
||||||
// writing out invalid Python.
|
|
||||||
//
|
|
||||||
// It's worth pointing out that we can actually wind up being
|
|
||||||
// somewhat out of sync with PEP8 in this case. Consider this
|
|
||||||
// example:
|
|
||||||
//
|
|
||||||
// def foo():
|
|
||||||
// '''
|
|
||||||
// Something.
|
|
||||||
//
|
|
||||||
// >>> """tricksy"""
|
|
||||||
// '''
|
|
||||||
// pass
|
|
||||||
//
|
|
||||||
// Ideally, this would be reformatted as:
|
|
||||||
//
|
|
||||||
// def foo():
|
|
||||||
// """
|
|
||||||
// Something.
|
|
||||||
//
|
|
||||||
// >>> '''tricksy'''
|
|
||||||
// """
|
|
||||||
// pass
|
|
||||||
//
|
|
||||||
// But the logic here results in the original quoting being
|
|
||||||
// preserved. This is because the quoting style of the outer
|
|
||||||
// docstring is determined, in part, by looking at its contents. In
|
|
||||||
// this case, it notices that it contains a `"""` and thus infers
|
|
||||||
// that using `'''` would overall read better because it avoids
|
|
||||||
// the need to escape the interior `"""`. Except... in this case,
|
|
||||||
// the `"""` is actually part of a code snippet that could get
|
|
||||||
// reformatted to using a different quoting style itself.
|
|
||||||
//
|
|
||||||
// Fixing this would, I believe, require some fairly seismic
|
|
||||||
// changes to how formatting strings works. Namely, we would need
|
|
||||||
// to look for code snippets before normalizing the docstring, and
|
|
||||||
// then figure out the quoting style more holistically by looking
|
|
||||||
// at the various kinds of quotes used in the code snippets and
|
|
||||||
// what reformatting them might look like.
|
|
||||||
//
|
|
||||||
// Overall this is a bit of a corner case and just inverting the
|
|
||||||
// style from what the parent ultimately decided upon works, even
|
|
||||||
// if it doesn't have perfect alignment with PEP8.
|
|
||||||
if let Some(quote) = self.context.docstring() {
|
|
||||||
QuoteStyle::from(quote.opposite())
|
|
||||||
} else {
|
|
||||||
QuoteStyle::Double
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
preferred_quote_style
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// An f-string expression element contains a debug text and the corresponding
|
||||||
|
// format specifier has a literal element with a quote character.
|
||||||
|
if is_fstring_with_quoted_format_spec_and_debug(fstring, self.context) {
|
||||||
|
return QuoteStyle::Preserve;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For f-strings prefer alternating the quotes unless The outer string is triple quoted and the inner isn't.
|
||||||
|
if let FStringState::InsideExpressionElement(parent_context) = self.context.f_string_state()
|
||||||
|
{
|
||||||
|
let parent_flags = parent_context.f_string().flags();
|
||||||
|
|
||||||
|
if !parent_flags.is_triple_quoted() || string.flags().is_triple_quoted() {
|
||||||
|
return QuoteStyle::from(parent_flags.quote_style().opposite());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Per PEP 8, always prefer double quotes for triple-quoted strings.
|
||||||
|
if string.flags().is_triple_quoted() {
|
||||||
|
// ... unless we're formatting a code snippet inside a docstring,
|
||||||
|
// then we specifically want to invert our quote style to avoid
|
||||||
|
// writing out invalid Python.
|
||||||
|
//
|
||||||
|
// It's worth pointing out that we can actually wind up being
|
||||||
|
// somewhat out of sync with PEP8 in this case. Consider this
|
||||||
|
// example:
|
||||||
|
//
|
||||||
|
// def foo():
|
||||||
|
// '''
|
||||||
|
// Something.
|
||||||
|
//
|
||||||
|
// >>> """tricksy"""
|
||||||
|
// '''
|
||||||
|
// pass
|
||||||
|
//
|
||||||
|
// Ideally, this would be reformatted as:
|
||||||
|
//
|
||||||
|
// def foo():
|
||||||
|
// """
|
||||||
|
// Something.
|
||||||
|
//
|
||||||
|
// >>> '''tricksy'''
|
||||||
|
// """
|
||||||
|
// pass
|
||||||
|
//
|
||||||
|
// But the logic here results in the original quoting being
|
||||||
|
// preserved. This is because the quoting style of the outer
|
||||||
|
// docstring is determined, in part, by looking at its contents. In
|
||||||
|
// this case, it notices that it contains a `"""` and thus infers
|
||||||
|
// that using `'''` would overall read better because it avoids
|
||||||
|
// the need to escape the interior `"""`. Except... in this case,
|
||||||
|
// the `"""` is actually part of a code snippet that could get
|
||||||
|
// reformatted to using a different quoting style itself.
|
||||||
|
//
|
||||||
|
// Fixing this would, I believe, require some fairly seismic
|
||||||
|
// changes to how formatting strings works. Namely, we would need
|
||||||
|
// to look for code snippets before normalizing the docstring, and
|
||||||
|
// then figure out the quoting style more holistically by looking
|
||||||
|
// at the various kinds of quotes used in the code snippets and
|
||||||
|
// what reformatting them might look like.
|
||||||
|
//
|
||||||
|
// Overall this is a bit of a corner case and just inverting the
|
||||||
|
// style from what the parent ultimately decided upon works, even
|
||||||
|
// if it doesn't have perfect alignment with PEP8.
|
||||||
|
if let Some(quote) = self.context.docstring() {
|
||||||
|
QuoteStyle::from(quote.opposite())
|
||||||
|
} else {
|
||||||
|
QuoteStyle::Double
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
preferred_quote_style
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +149,7 @@ impl<'a, 'src> StringNormalizer<'a, 'src> {
|
||||||
let raw_content = &self.context.source()[string.content_range()];
|
let raw_content = &self.context.source()[string.content_range()];
|
||||||
let first_quote_or_normalized_char_offset = raw_content
|
let first_quote_or_normalized_char_offset = raw_content
|
||||||
.bytes()
|
.bytes()
|
||||||
.position(|b| matches!(b, b'\\' | b'"' | b'\'' | b'\r' | b'{'));
|
.position(|b| matches!(b, b'\\' | b'"' | b'\'' | b'\r'));
|
||||||
let string_flags = string.flags();
|
let string_flags = string.flags();
|
||||||
let preferred_style = self.preferred_quote_style(string);
|
let preferred_style = self.preferred_quote_style(string);
|
||||||
|
|
||||||
|
@ -214,11 +200,7 @@ impl<'a, 'src> StringNormalizer<'a, 'src> {
|
||||||
raw_content,
|
raw_content,
|
||||||
first_quote_or_escape_offset,
|
first_quote_or_escape_offset,
|
||||||
quote_selection.flags,
|
quote_selection.flags,
|
||||||
// TODO: Remove the `b'{'` in `choose_quotes` when promoting the
|
|
||||||
// `format_fstring` preview style
|
|
||||||
false,
|
false,
|
||||||
false,
|
|
||||||
is_f_string_formatting_enabled(self.context),
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Cow::Borrowed(raw_content)
|
Cow::Borrowed(raw_content)
|
||||||
|
@ -269,20 +251,14 @@ impl QuoteMetadata {
|
||||||
Self::from_str(text, part.flags(), preferred_quote)
|
Self::from_str(text, part.flags(), preferred_quote)
|
||||||
}
|
}
|
||||||
StringLikePart::FString(fstring) => {
|
StringLikePart::FString(fstring) => {
|
||||||
if is_f_string_formatting_enabled(context) {
|
let metadata = QuoteMetadata::from_str("", part.flags(), preferred_quote);
|
||||||
let metadata = QuoteMetadata::from_str("", part.flags(), preferred_quote);
|
|
||||||
|
|
||||||
metadata.merge_fstring_elements(
|
metadata.merge_fstring_elements(
|
||||||
&fstring.elements,
|
&fstring.elements,
|
||||||
fstring.flags,
|
fstring.flags,
|
||||||
context,
|
context,
|
||||||
preferred_quote,
|
preferred_quote,
|
||||||
)
|
)
|
||||||
} else {
|
|
||||||
let text = &context.source()[part.content_range()];
|
|
||||||
|
|
||||||
Self::from_str(text, part.flags(), preferred_quote)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -635,8 +611,6 @@ pub(crate) fn normalize_string(
|
||||||
start_offset: usize,
|
start_offset: usize,
|
||||||
new_flags: AnyStringFlags,
|
new_flags: AnyStringFlags,
|
||||||
escape_braces: bool,
|
escape_braces: bool,
|
||||||
flip_nested_fstring_quotes: bool,
|
|
||||||
format_f_string: bool,
|
|
||||||
) -> Cow<str> {
|
) -> Cow<str> {
|
||||||
// The normalized string if `input` is not yet normalized.
|
// The normalized string if `input` is not yet normalized.
|
||||||
// `output` must remain empty if `input` is already normalized.
|
// `output` must remain empty if `input` is already normalized.
|
||||||
|
@ -653,9 +627,6 @@ pub(crate) fn normalize_string(
|
||||||
|
|
||||||
let is_raw = new_flags.is_raw_string();
|
let is_raw = new_flags.is_raw_string();
|
||||||
|
|
||||||
let is_fstring = !format_f_string && new_flags.is_f_string();
|
|
||||||
let mut formatted_value_nesting = 0u32;
|
|
||||||
|
|
||||||
while let Some((index, c)) = chars.next() {
|
while let Some((index, c)) = chars.next() {
|
||||||
if matches!(c, '{' | '}') {
|
if matches!(c, '{' | '}') {
|
||||||
if escape_braces {
|
if escape_braces {
|
||||||
|
@ -664,17 +635,6 @@ pub(crate) fn normalize_string(
|
||||||
output.push(c);
|
output.push(c);
|
||||||
last_index = index + c.len_utf8();
|
last_index = index + c.len_utf8();
|
||||||
continue;
|
continue;
|
||||||
} else if is_fstring {
|
|
||||||
if chars.peek().copied().is_some_and(|(_, next)| next == c) {
|
|
||||||
// Skip over the second character of the double braces
|
|
||||||
chars.next();
|
|
||||||
} else if c == '{' {
|
|
||||||
formatted_value_nesting += 1;
|
|
||||||
} else {
|
|
||||||
// Safe to assume that `c == '}'` here because of the matched pattern above
|
|
||||||
formatted_value_nesting = formatted_value_nesting.saturating_sub(1);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -723,7 +683,7 @@ pub(crate) fn normalize_string(
|
||||||
|
|
||||||
if !new_flags.is_triple_quoted() {
|
if !new_flags.is_triple_quoted() {
|
||||||
#[allow(clippy::if_same_then_else)]
|
#[allow(clippy::if_same_then_else)]
|
||||||
if next == opposite_quote && formatted_value_nesting == 0 {
|
if next == opposite_quote {
|
||||||
// Remove the escape by ending before the backslash and starting again with the quote
|
// Remove the escape by ending before the backslash and starting again with the quote
|
||||||
chars.next();
|
chars.next();
|
||||||
output.push_str(&input[last_index..index]);
|
output.push_str(&input[last_index..index]);
|
||||||
|
@ -734,23 +694,12 @@ pub(crate) fn normalize_string(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if !new_flags.is_triple_quoted()
|
} else if !new_flags.is_triple_quoted() && c == preferred_quote {
|
||||||
&& c == preferred_quote
|
|
||||||
&& formatted_value_nesting == 0
|
|
||||||
{
|
|
||||||
// Escape the quote
|
// Escape the quote
|
||||||
output.push_str(&input[last_index..index]);
|
output.push_str(&input[last_index..index]);
|
||||||
output.push('\\');
|
output.push('\\');
|
||||||
output.push(c);
|
output.push(c);
|
||||||
last_index = index + preferred_quote.len_utf8();
|
last_index = index + preferred_quote.len_utf8();
|
||||||
} else if c == preferred_quote
|
|
||||||
&& flip_nested_fstring_quotes
|
|
||||||
&& formatted_value_nesting > 0
|
|
||||||
{
|
|
||||||
// Flip the quotes
|
|
||||||
output.push_str(&input[last_index..index]);
|
|
||||||
output.push(opposite_quote);
|
|
||||||
last_index = index + preferred_quote.len_utf8();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1099,7 +1048,6 @@ fn contains_opposite_quote(content: &str, flags: AnyStringFlags) -> bool {
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use ruff_python_ast::str_prefix::FStringPrefix;
|
|
||||||
use ruff_python_ast::{
|
use ruff_python_ast::{
|
||||||
str::Quote,
|
str::Quote,
|
||||||
str_prefix::{AnyStringPrefix, ByteStringPrefix},
|
str_prefix::{AnyStringPrefix, ByteStringPrefix},
|
||||||
|
@ -1133,34 +1081,8 @@ mod tests {
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
false,
|
false,
|
||||||
false,
|
|
||||||
true,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(r"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", &normalized);
|
assert_eq!(r"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", &normalized);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn normalize_nested_fstring() {
|
|
||||||
let input =
|
|
||||||
r#"With single quote: ' {my_dict['foo']} With double quote: " {my_dict["bar"]}"#;
|
|
||||||
|
|
||||||
let normalized = normalize_string(
|
|
||||||
input,
|
|
||||||
0,
|
|
||||||
AnyStringFlags::new(
|
|
||||||
AnyStringPrefix::Format(FStringPrefix::Regular),
|
|
||||||
Quote::Double,
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
"With single quote: ' {my_dict['foo']} With double quote: \\\" {my_dict['bar']}",
|
|
||||||
&normalized
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,41 +194,7 @@ class C:
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -110,19 +110,20 @@
|
@@ -161,9 +161,7 @@
|
||||||
value, is_going_to_be="too long to fit in a single line", srsly=True
|
|
||||||
), "Not what we expected"
|
|
||||||
|
|
||||||
- assert {
|
|
||||||
- key1: value1,
|
|
||||||
- key2: value2,
|
|
||||||
- key3: value3,
|
|
||||||
- key4: value4,
|
|
||||||
- key5: value5,
|
|
||||||
- key6: value6,
|
|
||||||
- key7: value7,
|
|
||||||
- key8: value8,
|
|
||||||
- key9: value9,
|
|
||||||
- } == expected, (
|
|
||||||
- "Not what we expected and the message is too long to fit in one line"
|
|
||||||
- )
|
|
||||||
+ assert (
|
|
||||||
+ {
|
|
||||||
+ key1: value1,
|
|
||||||
+ key2: value2,
|
|
||||||
+ key3: value3,
|
|
||||||
+ key4: value4,
|
|
||||||
+ key5: value5,
|
|
||||||
+ key6: value6,
|
|
||||||
+ key7: value7,
|
|
||||||
+ key8: value8,
|
|
||||||
+ key9: value9,
|
|
||||||
+ }
|
|
||||||
+ == expected
|
|
||||||
+ ), "Not what we expected and the message is too long to fit in one line"
|
|
||||||
|
|
||||||
assert expected(
|
|
||||||
value, is_going_to_be="too long to fit in a single line", srsly=True
|
|
||||||
@@ -161,9 +162,7 @@
|
|
||||||
8 STORE_ATTR 0 (x)
|
8 STORE_ATTR 0 (x)
|
||||||
10 LOAD_CONST 0 (None)
|
10 LOAD_CONST 0 (None)
|
||||||
12 RETURN_VALUE
|
12 RETURN_VALUE
|
||||||
|
@ -356,20 +322,19 @@ class C:
|
||||||
value, is_going_to_be="too long to fit in a single line", srsly=True
|
value, is_going_to_be="too long to fit in a single line", srsly=True
|
||||||
), "Not what we expected"
|
), "Not what we expected"
|
||||||
|
|
||||||
assert (
|
assert {
|
||||||
{
|
key1: value1,
|
||||||
key1: value1,
|
key2: value2,
|
||||||
key2: value2,
|
key3: value3,
|
||||||
key3: value3,
|
key4: value4,
|
||||||
key4: value4,
|
key5: value5,
|
||||||
key5: value5,
|
key6: value6,
|
||||||
key6: value6,
|
key7: value7,
|
||||||
key7: value7,
|
key8: value8,
|
||||||
key8: value8,
|
key9: value9,
|
||||||
key9: value9,
|
} == expected, (
|
||||||
}
|
"Not what we expected and the message is too long to fit in one line"
|
||||||
== expected
|
)
|
||||||
), "Not what we expected and the message is too long to fit in one line"
|
|
||||||
|
|
||||||
assert expected(
|
assert expected(
|
||||||
value, is_going_to_be="too long to fit in a single line", srsly=True
|
value, is_going_to_be="too long to fit in a single line", srsly=True
|
||||||
|
|
|
@ -194,41 +194,7 @@ class C:
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -110,19 +110,20 @@
|
@@ -161,9 +161,7 @@
|
||||||
value, is_going_to_be="too long to fit in a single line", srsly=True
|
|
||||||
), "Not what we expected"
|
|
||||||
|
|
||||||
- assert {
|
|
||||||
- key1: value1,
|
|
||||||
- key2: value2,
|
|
||||||
- key3: value3,
|
|
||||||
- key4: value4,
|
|
||||||
- key5: value5,
|
|
||||||
- key6: value6,
|
|
||||||
- key7: value7,
|
|
||||||
- key8: value8,
|
|
||||||
- key9: value9,
|
|
||||||
- } == expected, (
|
|
||||||
- "Not what we expected and the message is too long to fit in one line"
|
|
||||||
- )
|
|
||||||
+ assert (
|
|
||||||
+ {
|
|
||||||
+ key1: value1,
|
|
||||||
+ key2: value2,
|
|
||||||
+ key3: value3,
|
|
||||||
+ key4: value4,
|
|
||||||
+ key5: value5,
|
|
||||||
+ key6: value6,
|
|
||||||
+ key7: value7,
|
|
||||||
+ key8: value8,
|
|
||||||
+ key9: value9,
|
|
||||||
+ }
|
|
||||||
+ == expected
|
|
||||||
+ ), "Not what we expected and the message is too long to fit in one line"
|
|
||||||
|
|
||||||
assert expected(
|
|
||||||
value, is_going_to_be="too long to fit in a single line", srsly=True
|
|
||||||
@@ -161,9 +162,7 @@
|
|
||||||
8 STORE_ATTR 0 (x)
|
8 STORE_ATTR 0 (x)
|
||||||
10 LOAD_CONST 0 (None)
|
10 LOAD_CONST 0 (None)
|
||||||
12 RETURN_VALUE
|
12 RETURN_VALUE
|
||||||
|
@ -356,20 +322,19 @@ class C:
|
||||||
value, is_going_to_be="too long to fit in a single line", srsly=True
|
value, is_going_to_be="too long to fit in a single line", srsly=True
|
||||||
), "Not what we expected"
|
), "Not what we expected"
|
||||||
|
|
||||||
assert (
|
assert {
|
||||||
{
|
key1: value1,
|
||||||
key1: value1,
|
key2: value2,
|
||||||
key2: value2,
|
key3: value3,
|
||||||
key3: value3,
|
key4: value4,
|
||||||
key4: value4,
|
key5: value5,
|
||||||
key5: value5,
|
key6: value6,
|
||||||
key6: value6,
|
key7: value7,
|
||||||
key7: value7,
|
key8: value8,
|
||||||
key8: value8,
|
key9: value9,
|
||||||
key9: value9,
|
} == expected, (
|
||||||
}
|
"Not what we expected and the message is too long to fit in one line"
|
||||||
== expected
|
)
|
||||||
), "Not what we expected and the message is too long to fit in one line"
|
|
||||||
|
|
||||||
assert expected(
|
assert expected(
|
||||||
value, is_going_to_be="too long to fit in a single line", srsly=True
|
value, is_going_to_be="too long to fit in a single line", srsly=True
|
||||||
|
|
|
@ -276,6 +276,19 @@ last_call()
|
||||||
) # note: no trailing comma pre-3.6
|
) # note: no trailing comma pre-3.6
|
||||||
call(*gidgets[:2])
|
call(*gidgets[:2])
|
||||||
call(a, *gidgets[:2])
|
call(a, *gidgets[:2])
|
||||||
|
@@ -251,9 +251,9 @@
|
||||||
|
print(**{1: 3} if False else {x: x for x in range(3)})
|
||||||
|
print(*lambda x: x)
|
||||||
|
assert not Test, "Short message"
|
||||||
|
-assert this is ComplexTest and not requirements.fit_in_a_single_line(
|
||||||
|
- force=False
|
||||||
|
-), "Short message"
|
||||||
|
+assert this is ComplexTest and not requirements.fit_in_a_single_line(force=False), (
|
||||||
|
+ "Short message"
|
||||||
|
+)
|
||||||
|
assert parens is TooMany
|
||||||
|
for (x,) in (1,), (2,), (3,):
|
||||||
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
## Ruff Output
|
## Ruff Output
|
||||||
|
@ -534,9 +547,9 @@ print(*[] or [1])
|
||||||
print(**{1: 3} if False else {x: x for x in range(3)})
|
print(**{1: 3} if False else {x: x for x in range(3)})
|
||||||
print(*lambda x: x)
|
print(*lambda x: x)
|
||||||
assert not Test, "Short message"
|
assert not Test, "Short message"
|
||||||
assert this is ComplexTest and not requirements.fit_in_a_single_line(
|
assert this is ComplexTest and not requirements.fit_in_a_single_line(force=False), (
|
||||||
force=False
|
"Short message"
|
||||||
), "Short message"
|
)
|
||||||
assert parens is TooMany
|
assert parens is TooMany
|
||||||
for (x,) in (1,), (2,), (3,):
|
for (x,) in (1,), (2,), (3,):
|
||||||
...
|
...
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||||
|
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/f_docstring.py
|
||||||
|
---
|
||||||
|
## Input
|
||||||
|
|
||||||
|
```python
|
||||||
|
def foo(e):
|
||||||
|
f""" {'.'.join(e)}"""
|
||||||
|
|
||||||
|
def bar(e):
|
||||||
|
f"{'.'.join(e)}"
|
||||||
|
|
||||||
|
def baz(e):
|
||||||
|
F""" {'.'.join(e)}"""
|
||||||
|
```
|
||||||
|
|
||||||
|
## Black Differences
|
||||||
|
|
||||||
|
```diff
|
||||||
|
--- Black
|
||||||
|
+++ Ruff
|
||||||
|
@@ -1,5 +1,5 @@
|
||||||
|
def foo(e):
|
||||||
|
- f""" {'.'.join(e)}"""
|
||||||
|
+ f""" {".".join(e)}"""
|
||||||
|
|
||||||
|
|
||||||
|
def bar(e):
|
||||||
|
@@ -7,4 +7,4 @@
|
||||||
|
|
||||||
|
|
||||||
|
def baz(e):
|
||||||
|
- f""" {'.'.join(e)}"""
|
||||||
|
+ f""" {".".join(e)}"""
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ruff Output
|
||||||
|
|
||||||
|
```python
|
||||||
|
def foo(e):
|
||||||
|
f""" {".".join(e)}"""
|
||||||
|
|
||||||
|
|
||||||
|
def bar(e):
|
||||||
|
f"{'.'.join(e)}"
|
||||||
|
|
||||||
|
|
||||||
|
def baz(e):
|
||||||
|
f""" {".".join(e)}"""
|
||||||
|
```
|
||||||
|
|
||||||
|
## Black Output
|
||||||
|
|
||||||
|
```python
|
||||||
|
def foo(e):
|
||||||
|
f""" {'.'.join(e)}"""
|
||||||
|
|
||||||
|
|
||||||
|
def bar(e):
|
||||||
|
f"{'.'.join(e)}"
|
||||||
|
|
||||||
|
|
||||||
|
def baz(e):
|
||||||
|
f""" {'.'.join(e)}"""
|
||||||
|
```
|
|
@ -105,7 +105,7 @@ elif unformatted:
|
||||||
- "=foo.bar.:main",
|
- "=foo.bar.:main",
|
||||||
- # fmt: on
|
- # fmt: on
|
||||||
- ] # Includes an formatted indentation.
|
- ] # Includes an formatted indentation.
|
||||||
+ "foo-bar" "=foo.bar.:main",
|
+ "foo-bar=foo.bar.:main",
|
||||||
+ # fmt: on
|
+ # fmt: on
|
||||||
+ ] # Includes an formatted indentation.
|
+ ] # Includes an formatted indentation.
|
||||||
},
|
},
|
||||||
|
@ -129,7 +129,7 @@ setup(
|
||||||
entry_points={
|
entry_points={
|
||||||
# fmt: off
|
# fmt: off
|
||||||
"console_scripts": [
|
"console_scripts": [
|
||||||
"foo-bar" "=foo.bar.:main",
|
"foo-bar=foo.bar.:main",
|
||||||
# fmt: on
|
# fmt: on
|
||||||
] # Includes an formatted indentation.
|
] # Includes an formatted indentation.
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||||
|
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/fstring.py
|
||||||
|
---
|
||||||
|
## Input
|
||||||
|
|
||||||
|
```python
|
||||||
|
f"f-string without formatted values is just a string"
|
||||||
|
f"{{NOT a formatted value}}"
|
||||||
|
f"{{NOT 'a' \"formatted\" \"value\"}}"
|
||||||
|
f"some f-string with {a} {few():.2f} {formatted.values!r}"
|
||||||
|
f'some f-string with {a} {few(""):.2f} {formatted.values!r}'
|
||||||
|
f"{f'''{'nested'} inner'''} outer"
|
||||||
|
f"\"{f'{nested} inner'}\" outer"
|
||||||
|
f"space between opening braces: { {a for a in (1, 2, 3)}}"
|
||||||
|
f'Hello \'{tricky + "example"}\''
|
||||||
|
f"Tried directories {str(rootdirs)} \
|
||||||
|
but none started with prefix {parentdir_prefix}"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Black Differences
|
||||||
|
|
||||||
|
```diff
|
||||||
|
--- Black
|
||||||
|
+++ Ruff
|
||||||
|
@@ -2,10 +2,10 @@
|
||||||
|
f"{{NOT a formatted value}}"
|
||||||
|
f'{{NOT \'a\' "formatted" "value"}}'
|
||||||
|
f"some f-string with {a} {few():.2f} {formatted.values!r}"
|
||||||
|
-f'some f-string with {a} {few(""):.2f} {formatted.values!r}'
|
||||||
|
-f"{f'''{'nested'} inner'''} outer"
|
||||||
|
-f"\"{f'{nested} inner'}\" outer"
|
||||||
|
-f"space between opening braces: { {a for a in (1, 2, 3)}}"
|
||||||
|
-f'Hello \'{tricky + "example"}\''
|
||||||
|
+f"some f-string with {a} {few(''):.2f} {formatted.values!r}"
|
||||||
|
+f"{f'''{"nested"} inner'''} outer"
|
||||||
|
+f'"{f"{nested} inner"}" outer'
|
||||||
|
+f"space between opening braces: { {a for a in (1, 2, 3)} }"
|
||||||
|
+f"Hello '{tricky + 'example'}'"
|
||||||
|
f"Tried directories {str(rootdirs)} \
|
||||||
|
but none started with prefix {parentdir_prefix}"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ruff Output
|
||||||
|
|
||||||
|
```python
|
||||||
|
f"f-string without formatted values is just a string"
|
||||||
|
f"{{NOT a formatted value}}"
|
||||||
|
f'{{NOT \'a\' "formatted" "value"}}'
|
||||||
|
f"some f-string with {a} {few():.2f} {formatted.values!r}"
|
||||||
|
f"some f-string with {a} {few(''):.2f} {formatted.values!r}"
|
||||||
|
f"{f'''{"nested"} inner'''} outer"
|
||||||
|
f'"{f"{nested} inner"}" outer'
|
||||||
|
f"space between opening braces: { {a for a in (1, 2, 3)} }"
|
||||||
|
f"Hello '{tricky + 'example'}'"
|
||||||
|
f"Tried directories {str(rootdirs)} \
|
||||||
|
but none started with prefix {parentdir_prefix}"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Black Output
|
||||||
|
|
||||||
|
```python
|
||||||
|
f"f-string without formatted values is just a string"
|
||||||
|
f"{{NOT a formatted value}}"
|
||||||
|
f'{{NOT \'a\' "formatted" "value"}}'
|
||||||
|
f"some f-string with {a} {few():.2f} {formatted.values!r}"
|
||||||
|
f'some f-string with {a} {few(""):.2f} {formatted.values!r}'
|
||||||
|
f"{f'''{'nested'} inner'''} outer"
|
||||||
|
f"\"{f'{nested} inner'}\" outer"
|
||||||
|
f"space between opening braces: { {a for a in (1, 2, 3)}}"
|
||||||
|
f'Hello \'{tricky + "example"}\''
|
||||||
|
f"Tried directories {str(rootdirs)} \
|
||||||
|
but none started with prefix {parentdir_prefix}"
|
||||||
|
```
|
|
@ -132,6 +132,19 @@ variable: (
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
|
@@ -52,9 +52,9 @@
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
-def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (
|
||||||
|
- Set["xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]
|
||||||
|
-):
|
||||||
|
+def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set[
|
||||||
|
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
|
+]:
|
||||||
|
json = {
|
||||||
|
"k": {
|
||||||
|
"k2": {
|
||||||
@@ -130,9 +130,7 @@
|
@@ -130,9 +130,7 @@
|
||||||
|
|
||||||
def foo() -> (
|
def foo() -> (
|
||||||
|
@ -225,9 +238,9 @@ def f(
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (
|
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set[
|
||||||
Set["xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]
|
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
):
|
]:
|
||||||
json = {
|
json = {
|
||||||
"k": {
|
"k": {
|
||||||
"k2": {
|
"k2": {
|
||||||
|
|
|
@ -309,33 +309,52 @@ long_unmergable_string_with_pragma = (
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -167,13 +167,9 @@
|
@@ -167,14 +167,14 @@
|
||||||
|
|
||||||
triple_quote_string = """This is a really really really long triple quote string assignment and it should not be touched."""
|
triple_quote_string = """This is a really really really long triple quote string assignment and it should not be touched."""
|
||||||
|
|
||||||
-assert (
|
-assert (
|
||||||
- some_type_of_boolean_expression
|
- some_type_of_boolean_expression
|
||||||
-), "Followed by a really really really long string that is used to provide context to the AssertionError exception."
|
-), "Followed by a really really really long string that is used to provide context to the AssertionError exception."
|
||||||
+assert some_type_of_boolean_expression, "Followed by a really really really long string that is used to provide context to the AssertionError exception."
|
+assert some_type_of_boolean_expression, (
|
||||||
|
+ "Followed by a really really really long string that is used to provide context to the AssertionError exception."
|
||||||
|
+)
|
||||||
|
|
||||||
-assert (
|
-assert (
|
||||||
- some_type_of_boolean_expression
|
- some_type_of_boolean_expression
|
||||||
-), "Followed by a really really really long string that is used to provide context to the AssertionError exception, which uses dynamic string {}.".format(
|
-), "Followed by a really really really long string that is used to provide context to the AssertionError exception, which uses dynamic string {}.".format(
|
||||||
+assert some_type_of_boolean_expression, "Followed by a really really really long string that is used to provide context to the AssertionError exception, which uses dynamic string {}.".format(
|
- "formatting"
|
||||||
"formatting"
|
+assert some_type_of_boolean_expression, (
|
||||||
|
+ "Followed by a really really really long string that is used to provide context to the AssertionError exception, which uses dynamic string {}.".format(
|
||||||
|
+ "formatting"
|
||||||
|
+ )
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -256,9 +252,7 @@
|
assert some_type_of_boolean_expression, (
|
||||||
|
@@ -255,10 +255,8 @@
|
||||||
|
+ " that has been "
|
||||||
+ CONCATENATED
|
+ CONCATENATED
|
||||||
+ "using the '+' operator."
|
+ "using the '+' operator."
|
||||||
)
|
-)
|
||||||
-annotated_variable: Final = (
|
-annotated_variable: Final = (
|
||||||
- "This is a large string that has a type annotation attached to it. A type annotation should NOT stop a long string from being wrapped."
|
- "This is a large string that has a type annotation attached to it. A type annotation should NOT stop a long string from being wrapped."
|
||||||
-)
|
)
|
||||||
+annotated_variable: Final = "This is a large string that has a type annotation attached to it. A type annotation should NOT stop a long string from being wrapped."
|
+annotated_variable: Final = "This is a large string that has a type annotation attached to it. A type annotation should NOT stop a long string from being wrapped."
|
||||||
annotated_variable: Literal["fakse_literal"] = (
|
annotated_variable: Literal["fakse_literal"] = (
|
||||||
"This is a large string that has a type annotation attached to it. A type annotation should NOT stop a long string from being wrapped."
|
"This is a large string that has a type annotation attached to it. A type annotation should NOT stop a long string from being wrapped."
|
||||||
)
|
)
|
||||||
|
@@ -267,9 +265,9 @@
|
||||||
|
backslashes = "This is a really long string with \"embedded\" double quotes and 'single' quotes that also handles checking for an even number of backslashes \\\\"
|
||||||
|
backslashes = "This is a really 'long' string with \"embedded double quotes\" and 'single' quotes that also handles checking for an odd number of backslashes \\\", like this...\\\\\\"
|
||||||
|
|
||||||
|
-short_string = "Hi" " there."
|
||||||
|
+short_string = "Hi there."
|
||||||
|
|
||||||
|
-func_call(short_string=("Hi" " there."))
|
||||||
|
+func_call(short_string=("Hi there."))
|
||||||
|
|
||||||
|
raw_strings = r"Don't" " get" r" merged" " unless they are all raw."
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Ruff Output
|
## Ruff Output
|
||||||
|
@ -510,10 +529,14 @@ pragma_comment_string2 = "Lines which end with an inline pragma comment of the f
|
||||||
|
|
||||||
triple_quote_string = """This is a really really really long triple quote string assignment and it should not be touched."""
|
triple_quote_string = """This is a really really really long triple quote string assignment and it should not be touched."""
|
||||||
|
|
||||||
assert some_type_of_boolean_expression, "Followed by a really really really long string that is used to provide context to the AssertionError exception."
|
assert some_type_of_boolean_expression, (
|
||||||
|
"Followed by a really really really long string that is used to provide context to the AssertionError exception."
|
||||||
|
)
|
||||||
|
|
||||||
assert some_type_of_boolean_expression, "Followed by a really really really long string that is used to provide context to the AssertionError exception, which uses dynamic string {}.".format(
|
assert some_type_of_boolean_expression, (
|
||||||
"formatting"
|
"Followed by a really really really long string that is used to provide context to the AssertionError exception, which uses dynamic string {}.".format(
|
||||||
|
"formatting"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
assert some_type_of_boolean_expression, (
|
assert some_type_of_boolean_expression, (
|
||||||
|
@ -604,9 +627,9 @@ backslashes = "This is a really long string with \"embedded\" double quotes and
|
||||||
backslashes = "This is a really long string with \"embedded\" double quotes and 'single' quotes that also handles checking for an even number of backslashes \\\\"
|
backslashes = "This is a really long string with \"embedded\" double quotes and 'single' quotes that also handles checking for an even number of backslashes \\\\"
|
||||||
backslashes = "This is a really 'long' string with \"embedded double quotes\" and 'single' quotes that also handles checking for an odd number of backslashes \\\", like this...\\\\\\"
|
backslashes = "This is a really 'long' string with \"embedded double quotes\" and 'single' quotes that also handles checking for an odd number of backslashes \\\", like this...\\\\\\"
|
||||||
|
|
||||||
short_string = "Hi" " there."
|
short_string = "Hi there."
|
||||||
|
|
||||||
func_call(short_string=("Hi" " there."))
|
func_call(short_string=("Hi there."))
|
||||||
|
|
||||||
raw_strings = r"Don't" " get" r" merged" " unless they are all raw."
|
raw_strings = r"Don't" " get" r" merged" " unless they are all raw."
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,241 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||||
|
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/pep_572_remove_parens.py
|
||||||
|
---
|
||||||
|
## Input
|
||||||
|
|
||||||
|
```python
|
||||||
|
if (foo := 0):
|
||||||
|
pass
|
||||||
|
|
||||||
|
if (foo := 1):
|
||||||
|
pass
|
||||||
|
|
||||||
|
if (y := 5 + 5):
|
||||||
|
pass
|
||||||
|
|
||||||
|
y = (x := 0)
|
||||||
|
|
||||||
|
y += (x := 0)
|
||||||
|
|
||||||
|
(y := 5 + 5)
|
||||||
|
|
||||||
|
test: int = (test2 := 2)
|
||||||
|
|
||||||
|
a, b = (test := (1, 2))
|
||||||
|
|
||||||
|
# see also https://github.com/psf/black/issues/2139
|
||||||
|
assert (foo := 42 - 12)
|
||||||
|
|
||||||
|
foo(x=(y := f(x)))
|
||||||
|
|
||||||
|
|
||||||
|
def foo(answer=(p := 42)):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
def foo2(answer: (p := 42) = 5):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
lambda: (x := 1)
|
||||||
|
|
||||||
|
a[(x := 12)]
|
||||||
|
a[:(x := 13)]
|
||||||
|
|
||||||
|
# we don't touch expressions in f-strings but if we do one day, don't break 'em
|
||||||
|
f'{(x:=10)}'
|
||||||
|
|
||||||
|
|
||||||
|
def a():
|
||||||
|
return (x := 3)
|
||||||
|
await (b := 1)
|
||||||
|
yield (a := 2)
|
||||||
|
raise (c := 3)
|
||||||
|
|
||||||
|
def this_is_so_dumb() -> (please := no):
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def await_the_walrus():
|
||||||
|
with (x := y):
|
||||||
|
pass
|
||||||
|
|
||||||
|
with (x := y) as z, (a := b) as c:
|
||||||
|
pass
|
||||||
|
|
||||||
|
with (x := await y):
|
||||||
|
pass
|
||||||
|
|
||||||
|
with (x := await a, y := await b):
|
||||||
|
pass
|
||||||
|
|
||||||
|
with ((x := await a, y := await b)):
|
||||||
|
pass
|
||||||
|
|
||||||
|
with (x := await a), (y := await b):
|
||||||
|
pass
|
||||||
|
```
|
||||||
|
|
||||||
|
## Black Differences
|
||||||
|
|
||||||
|
```diff
|
||||||
|
--- Black
|
||||||
|
+++ Ruff
|
||||||
|
@@ -35,7 +35,7 @@
|
||||||
|
a[: (x := 13)]
|
||||||
|
|
||||||
|
# we don't touch expressions in f-strings but if we do one day, don't break 'em
|
||||||
|
-f"{(x:=10)}"
|
||||||
|
+f"{(x := 10)}"
|
||||||
|
|
||||||
|
|
||||||
|
def a():
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ruff Output
|
||||||
|
|
||||||
|
```python
|
||||||
|
if foo := 0:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if foo := 1:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if y := 5 + 5:
|
||||||
|
pass
|
||||||
|
|
||||||
|
y = (x := 0)
|
||||||
|
|
||||||
|
y += (x := 0)
|
||||||
|
|
||||||
|
(y := 5 + 5)
|
||||||
|
|
||||||
|
test: int = (test2 := 2)
|
||||||
|
|
||||||
|
a, b = (test := (1, 2))
|
||||||
|
|
||||||
|
# see also https://github.com/psf/black/issues/2139
|
||||||
|
assert (foo := 42 - 12)
|
||||||
|
|
||||||
|
foo(x=(y := f(x)))
|
||||||
|
|
||||||
|
|
||||||
|
def foo(answer=(p := 42)): ...
|
||||||
|
|
||||||
|
|
||||||
|
def foo2(answer: (p := 42) = 5): ...
|
||||||
|
|
||||||
|
|
||||||
|
lambda: (x := 1)
|
||||||
|
|
||||||
|
a[(x := 12)]
|
||||||
|
a[: (x := 13)]
|
||||||
|
|
||||||
|
# we don't touch expressions in f-strings but if we do one day, don't break 'em
|
||||||
|
f"{(x := 10)}"
|
||||||
|
|
||||||
|
|
||||||
|
def a():
|
||||||
|
return (x := 3)
|
||||||
|
await (b := 1)
|
||||||
|
yield (a := 2)
|
||||||
|
raise (c := 3)
|
||||||
|
|
||||||
|
|
||||||
|
def this_is_so_dumb() -> (please := no):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
async def await_the_walrus():
|
||||||
|
with (x := y):
|
||||||
|
pass
|
||||||
|
|
||||||
|
with (x := y) as z, (a := b) as c:
|
||||||
|
pass
|
||||||
|
|
||||||
|
with (x := await y):
|
||||||
|
pass
|
||||||
|
|
||||||
|
with (x := await a, y := await b):
|
||||||
|
pass
|
||||||
|
|
||||||
|
with (x := await a, y := await b):
|
||||||
|
pass
|
||||||
|
|
||||||
|
with (x := await a), (y := await b):
|
||||||
|
pass
|
||||||
|
```
|
||||||
|
|
||||||
|
## Black Output
|
||||||
|
|
||||||
|
```python
|
||||||
|
if foo := 0:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if foo := 1:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if y := 5 + 5:
|
||||||
|
pass
|
||||||
|
|
||||||
|
y = (x := 0)
|
||||||
|
|
||||||
|
y += (x := 0)
|
||||||
|
|
||||||
|
(y := 5 + 5)
|
||||||
|
|
||||||
|
test: int = (test2 := 2)
|
||||||
|
|
||||||
|
a, b = (test := (1, 2))
|
||||||
|
|
||||||
|
# see also https://github.com/psf/black/issues/2139
|
||||||
|
assert (foo := 42 - 12)
|
||||||
|
|
||||||
|
foo(x=(y := f(x)))
|
||||||
|
|
||||||
|
|
||||||
|
def foo(answer=(p := 42)): ...
|
||||||
|
|
||||||
|
|
||||||
|
def foo2(answer: (p := 42) = 5): ...
|
||||||
|
|
||||||
|
|
||||||
|
lambda: (x := 1)
|
||||||
|
|
||||||
|
a[(x := 12)]
|
||||||
|
a[: (x := 13)]
|
||||||
|
|
||||||
|
# we don't touch expressions in f-strings but if we do one day, don't break 'em
|
||||||
|
f"{(x:=10)}"
|
||||||
|
|
||||||
|
|
||||||
|
def a():
|
||||||
|
return (x := 3)
|
||||||
|
await (b := 1)
|
||||||
|
yield (a := 2)
|
||||||
|
raise (c := 3)
|
||||||
|
|
||||||
|
|
||||||
|
def this_is_so_dumb() -> (please := no):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
async def await_the_walrus():
|
||||||
|
with (x := y):
|
||||||
|
pass
|
||||||
|
|
||||||
|
with (x := y) as z, (a := b) as c:
|
||||||
|
pass
|
||||||
|
|
||||||
|
with (x := await y):
|
||||||
|
pass
|
||||||
|
|
||||||
|
with (x := await a, y := await b):
|
||||||
|
pass
|
||||||
|
|
||||||
|
with (x := await a, y := await b):
|
||||||
|
pass
|
||||||
|
|
||||||
|
with (x := await a), (y := await b):
|
||||||
|
pass
|
||||||
|
```
|
|
@ -149,15 +149,155 @@ rf"\{"a"}"
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -119,7 +119,7 @@
|
@@ -11,16 +11,14 @@
|
||||||
|
# edge case: FSTRING_MIDDLE containing only whitespace should not be stripped
|
||||||
|
x = f"{a} {b}"
|
||||||
|
|
||||||
|
-x = f"foo {
|
||||||
|
- 2 + 2
|
||||||
|
-} bar baz"
|
||||||
|
+x = f"foo {2 + 2} bar baz"
|
||||||
|
|
||||||
|
-x = f"foo {{ {"a {2 + 2} b"}bar {{ baz"
|
||||||
|
+x = f"foo {{ {'a {2 + 2} b'}bar {{ baz"
|
||||||
|
+x = f"foo {{ {f'a {2 + 2} b'}bar {{ baz"
|
||||||
|
x = f"foo {{ {f'a {2 + 2} b'}bar {{ baz"
|
||||||
|
-x = f"foo {{ {f"a {2 + 2} b"}bar {{ baz"
|
||||||
|
|
||||||
|
x = f"foo {{ {f'a {f"a {2 + 2} b"} b'}bar {{ baz"
|
||||||
|
-x = f"foo {{ {f"a {f"a {2 + 2} b"} b"}bar {{ baz"
|
||||||
|
+x = f"foo {{ {f'a {f"a {2 + 2} b"} b'}bar {{ baz"
|
||||||
|
|
||||||
|
x = """foo {{ {2 + 2}bar
|
||||||
|
baz"""
|
||||||
|
@@ -28,74 +26,62 @@
|
||||||
|
|
||||||
|
x = f"""foo {{ {2 + 2}bar {{ baz"""
|
||||||
|
|
||||||
|
-x = f"""foo {{ {
|
||||||
|
- 2 + 2
|
||||||
|
-}bar {{ baz"""
|
||||||
|
+x = f"""foo {{ {2 + 2}bar {{ baz"""
|
||||||
|
|
||||||
|
|
||||||
|
-x = f"""foo {{ {
|
||||||
|
- 2 + 2
|
||||||
|
-}bar
|
||||||
|
+x = f"""foo {{ {2 + 2}bar
|
||||||
|
baz"""
|
||||||
|
|
||||||
|
x = f"""foo {{ a
|
||||||
|
foo {2 + 2}bar {{ baz
|
||||||
|
|
||||||
|
x = f"foo {{ {
|
||||||
|
- 2 + 2 # comment
|
||||||
|
- }bar"
|
||||||
|
+ 2 + 2 # comment
|
||||||
|
+}bar"
|
||||||
|
|
||||||
|
{{ baz
|
||||||
|
|
||||||
|
}} buzz
|
||||||
|
|
||||||
|
- {print("abc" + "def"
|
||||||
|
-)}
|
||||||
|
+ {print("abc" + "def")}
|
||||||
|
abc"""
|
||||||
|
|
||||||
|
# edge case: end triple quotes at index zero
|
||||||
|
-f"""foo {2+2} bar
|
||||||
|
+f"""foo {2 + 2} bar
|
||||||
|
"""
|
||||||
|
|
||||||
|
-f' \' {f"'"} \' '
|
||||||
|
-f" \" {f'"'} \" "
|
||||||
|
+f" ' {f"'"} ' "
|
||||||
|
+f' " {f'"'} " '
|
||||||
|
|
||||||
|
-x = f"a{2+2:=^72}b"
|
||||||
|
-x = f"a{2+2:x}b"
|
||||||
|
+x = f"a{2 + 2:=^72}b"
|
||||||
|
+x = f"a{2 + 2:x}b"
|
||||||
|
|
||||||
|
rf"foo"
|
||||||
|
rf"{foo}"
|
||||||
|
|
||||||
|
f"{x:{y}d}"
|
||||||
|
|
||||||
|
-x = f"a{2+2:=^{x}}b"
|
||||||
|
-x = f"a{2+2:=^{foo(x+y**2):something else}}b"
|
||||||
|
-x = f"a{2+2:=^{foo(x+y**2):something else}one more}b"
|
||||||
|
-f"{(abc:=10)}"
|
||||||
|
+x = f"a{2 + 2:=^{x}}b"
|
||||||
|
+x = f"a{2 + 2:=^{foo(x + y**2):something else}}b"
|
||||||
|
+x = f"a{2 + 2:=^{foo(x + y**2):something else}one more}b"
|
||||||
|
+f"{(abc := 10)}"
|
||||||
|
|
||||||
|
-f"This is a really long string, but just make sure that you reflow fstrings {
|
||||||
|
- 2+2:d
|
||||||
|
-}"
|
||||||
|
-f"This is a really long string, but just make sure that you reflow fstrings correctly {2+2:d}"
|
||||||
|
+f"This is a really long string, but just make sure that you reflow fstrings {2 + 2:d}"
|
||||||
|
+f"This is a really long string, but just make sure that you reflow fstrings correctly {2 + 2:d}"
|
||||||
|
|
||||||
|
f"{2+2=}"
|
||||||
|
f"{2+2 = }"
|
||||||
|
f"{ 2 + 2 = }"
|
||||||
|
|
||||||
|
-f"""foo {
|
||||||
|
- datetime.datetime.now():%Y
|
||||||
|
+f"""foo {datetime.datetime.now():%Y
|
||||||
|
%m
|
||||||
|
%d
|
||||||
|
}"""
|
||||||
|
|
||||||
|
-f"{
|
||||||
|
-X
|
||||||
|
-!r
|
||||||
|
-}"
|
||||||
|
+f"{X!r}"
|
||||||
|
|
||||||
|
raise ValueError(
|
||||||
|
- "xxxxxxxxxxxIncorrect --line-ranges format, expect START-END, found"
|
||||||
|
- f" {lines_str!r}"
|
||||||
|
+ f"xxxxxxxxxxxIncorrect --line-ranges format, expect START-END, found {lines_str!r}"
|
||||||
)
|
)
|
||||||
|
|
||||||
f"{1:{f'{2}'}}"
|
f"`escape` only permitted in {{'html', 'latex', 'latex-math'}}, \
|
||||||
-f"{1:{f'{2}'}}"
|
@@ -105,8 +91,10 @@
|
||||||
+f'{1:{f'{2}'}}'
|
rf"\{{\}}"
|
||||||
f"{1:{2}d}"
|
|
||||||
|
f"""
|
||||||
|
- WITH {f'''
|
||||||
|
- {1}_cte AS ()'''}
|
||||||
|
+ WITH {
|
||||||
|
+ f'''
|
||||||
|
+ {1}_cte AS ()'''
|
||||||
|
+}
|
||||||
|
"""
|
||||||
|
|
||||||
|
value: str = f"""foo
|
||||||
|
@@ -124,13 +112,15 @@
|
||||||
|
|
||||||
f'{{\\"kind\\":\\"ConfigMap\\",\\"metadata\\":{{\\"annotations\\":{{}},\\"name\\":\\"cluster-info\\",\\"namespace\\":\\"amazon-cloudwatch\\"}}}}'
|
f'{{\\"kind\\":\\"ConfigMap\\",\\"metadata\\":{{\\"annotations\\":{{}},\\"name\\":\\"cluster-info\\",\\"namespace\\":\\"amazon-cloudwatch\\"}}}}'
|
||||||
|
|
||||||
|
-f"""{'''
|
||||||
|
-'''}"""
|
||||||
|
+f"""{
|
||||||
|
+ '''
|
||||||
|
+'''
|
||||||
|
+}"""
|
||||||
|
|
||||||
|
-f"{'\''}"
|
||||||
|
-f"{f'\''}"
|
||||||
|
+f"{"'"}"
|
||||||
|
+f"{f"'"}"
|
||||||
|
|
||||||
|
f"{1}\{{"
|
||||||
|
f"{2} foo \{{[\}}"
|
||||||
|
f"\{3}"
|
||||||
|
-rf"\{"a"}"
|
||||||
|
+rf"\{'a'}"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Ruff Output
|
## Ruff Output
|
||||||
|
@ -176,16 +316,14 @@ x = f"""foo {{ {2 + 2}bar {{ baz"""
|
||||||
# edge case: FSTRING_MIDDLE containing only whitespace should not be stripped
|
# edge case: FSTRING_MIDDLE containing only whitespace should not be stripped
|
||||||
x = f"{a} {b}"
|
x = f"{a} {b}"
|
||||||
|
|
||||||
x = f"foo {
|
x = f"foo {2 + 2} bar baz"
|
||||||
2 + 2
|
|
||||||
} bar baz"
|
|
||||||
|
|
||||||
x = f"foo {{ {"a {2 + 2} b"}bar {{ baz"
|
x = f"foo {{ {'a {2 + 2} b'}bar {{ baz"
|
||||||
|
x = f"foo {{ {f'a {2 + 2} b'}bar {{ baz"
|
||||||
x = f"foo {{ {f'a {2 + 2} b'}bar {{ baz"
|
x = f"foo {{ {f'a {2 + 2} b'}bar {{ baz"
|
||||||
x = f"foo {{ {f"a {2 + 2} b"}bar {{ baz"
|
|
||||||
|
|
||||||
x = f"foo {{ {f'a {f"a {2 + 2} b"} b'}bar {{ baz"
|
x = f"foo {{ {f'a {f"a {2 + 2} b"} b'}bar {{ baz"
|
||||||
x = f"foo {{ {f"a {f"a {2 + 2} b"} b"}bar {{ baz"
|
x = f"foo {{ {f'a {f"a {2 + 2} b"} b'}bar {{ baz"
|
||||||
|
|
||||||
x = """foo {{ {2 + 2}bar
|
x = """foo {{ {2 + 2}bar
|
||||||
baz"""
|
baz"""
|
||||||
|
@ -193,74 +331,62 @@ baz"""
|
||||||
|
|
||||||
x = f"""foo {{ {2 + 2}bar {{ baz"""
|
x = f"""foo {{ {2 + 2}bar {{ baz"""
|
||||||
|
|
||||||
x = f"""foo {{ {
|
x = f"""foo {{ {2 + 2}bar {{ baz"""
|
||||||
2 + 2
|
|
||||||
}bar {{ baz"""
|
|
||||||
|
|
||||||
|
|
||||||
x = f"""foo {{ {
|
x = f"""foo {{ {2 + 2}bar
|
||||||
2 + 2
|
|
||||||
}bar
|
|
||||||
baz"""
|
baz"""
|
||||||
|
|
||||||
x = f"""foo {{ a
|
x = f"""foo {{ a
|
||||||
foo {2 + 2}bar {{ baz
|
foo {2 + 2}bar {{ baz
|
||||||
|
|
||||||
x = f"foo {{ {
|
x = f"foo {{ {
|
||||||
2 + 2 # comment
|
2 + 2 # comment
|
||||||
}bar"
|
}bar"
|
||||||
|
|
||||||
{{ baz
|
{{ baz
|
||||||
|
|
||||||
}} buzz
|
}} buzz
|
||||||
|
|
||||||
{print("abc" + "def"
|
{print("abc" + "def")}
|
||||||
)}
|
|
||||||
abc"""
|
abc"""
|
||||||
|
|
||||||
# edge case: end triple quotes at index zero
|
# edge case: end triple quotes at index zero
|
||||||
f"""foo {2+2} bar
|
f"""foo {2 + 2} bar
|
||||||
"""
|
"""
|
||||||
|
|
||||||
f' \' {f"'"} \' '
|
f" ' {f"'"} ' "
|
||||||
f" \" {f'"'} \" "
|
f' " {f'"'} " '
|
||||||
|
|
||||||
x = f"a{2+2:=^72}b"
|
x = f"a{2 + 2:=^72}b"
|
||||||
x = f"a{2+2:x}b"
|
x = f"a{2 + 2:x}b"
|
||||||
|
|
||||||
rf"foo"
|
rf"foo"
|
||||||
rf"{foo}"
|
rf"{foo}"
|
||||||
|
|
||||||
f"{x:{y}d}"
|
f"{x:{y}d}"
|
||||||
|
|
||||||
x = f"a{2+2:=^{x}}b"
|
x = f"a{2 + 2:=^{x}}b"
|
||||||
x = f"a{2+2:=^{foo(x+y**2):something else}}b"
|
x = f"a{2 + 2:=^{foo(x + y**2):something else}}b"
|
||||||
x = f"a{2+2:=^{foo(x+y**2):something else}one more}b"
|
x = f"a{2 + 2:=^{foo(x + y**2):something else}one more}b"
|
||||||
f"{(abc:=10)}"
|
f"{(abc := 10)}"
|
||||||
|
|
||||||
f"This is a really long string, but just make sure that you reflow fstrings {
|
f"This is a really long string, but just make sure that you reflow fstrings {2 + 2:d}"
|
||||||
2+2:d
|
f"This is a really long string, but just make sure that you reflow fstrings correctly {2 + 2:d}"
|
||||||
}"
|
|
||||||
f"This is a really long string, but just make sure that you reflow fstrings correctly {2+2:d}"
|
|
||||||
|
|
||||||
f"{2+2=}"
|
f"{2+2=}"
|
||||||
f"{2+2 = }"
|
f"{2+2 = }"
|
||||||
f"{ 2 + 2 = }"
|
f"{ 2 + 2 = }"
|
||||||
|
|
||||||
f"""foo {
|
f"""foo {datetime.datetime.now():%Y
|
||||||
datetime.datetime.now():%Y
|
|
||||||
%m
|
%m
|
||||||
%d
|
%d
|
||||||
}"""
|
}"""
|
||||||
|
|
||||||
f"{
|
f"{X!r}"
|
||||||
X
|
|
||||||
!r
|
|
||||||
}"
|
|
||||||
|
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"xxxxxxxxxxxIncorrect --line-ranges format, expect START-END, found"
|
f"xxxxxxxxxxxIncorrect --line-ranges format, expect START-END, found {lines_str!r}"
|
||||||
f" {lines_str!r}"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
f"`escape` only permitted in {{'html', 'latex', 'latex-math'}}, \
|
f"`escape` only permitted in {{'html', 'latex', 'latex-math'}}, \
|
||||||
|
@ -270,8 +396,10 @@ x = f"\N{GREEK CAPITAL LETTER DELTA} \N{SNOWMAN} {x}"
|
||||||
rf"\{{\}}"
|
rf"\{{\}}"
|
||||||
|
|
||||||
f"""
|
f"""
|
||||||
WITH {f'''
|
WITH {
|
||||||
{1}_cte AS ()'''}
|
f'''
|
||||||
|
{1}_cte AS ()'''
|
||||||
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
value: str = f"""foo
|
value: str = f"""foo
|
||||||
|
@ -284,21 +412,23 @@ log(
|
||||||
)
|
)
|
||||||
|
|
||||||
f"{1:{f'{2}'}}"
|
f"{1:{f'{2}'}}"
|
||||||
f'{1:{f'{2}'}}'
|
f"{1:{f'{2}'}}"
|
||||||
f"{1:{2}d}"
|
f"{1:{2}d}"
|
||||||
|
|
||||||
f'{{\\"kind\\":\\"ConfigMap\\",\\"metadata\\":{{\\"annotations\\":{{}},\\"name\\":\\"cluster-info\\",\\"namespace\\":\\"amazon-cloudwatch\\"}}}}'
|
f'{{\\"kind\\":\\"ConfigMap\\",\\"metadata\\":{{\\"annotations\\":{{}},\\"name\\":\\"cluster-info\\",\\"namespace\\":\\"amazon-cloudwatch\\"}}}}'
|
||||||
|
|
||||||
f"""{'''
|
f"""{
|
||||||
'''}"""
|
'''
|
||||||
|
'''
|
||||||
|
}"""
|
||||||
|
|
||||||
f"{'\''}"
|
f"{"'"}"
|
||||||
f"{f'\''}"
|
f"{f"'"}"
|
||||||
|
|
||||||
f"{1}\{{"
|
f"{1}\{{"
|
||||||
f"{2} foo \{{[\}}"
|
f"{2} foo \{{[\}}"
|
||||||
f"\{3}"
|
f"\{3}"
|
||||||
rf"\{"a"}"
|
rf"\{'a'}"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Black Output
|
## Black Output
|
||||||
|
|
|
@ -127,39 +127,7 @@ def foo(a,b) -> tuple[int, int, int,]:
|
||||||
return 2 * a
|
return 2 * a
|
||||||
|
|
||||||
|
|
||||||
@@ -99,25 +107,31 @@
|
@@ -117,7 +125,9 @@
|
||||||
return 2
|
|
||||||
|
|
||||||
|
|
||||||
-def foo() -> tuple[
|
|
||||||
- loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
|
|
||||||
- loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
|
|
||||||
- loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
|
|
||||||
-]:
|
|
||||||
+def foo() -> (
|
|
||||||
+ tuple[
|
|
||||||
+ loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
|
|
||||||
+ loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
|
|
||||||
+ loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
|
|
||||||
+ ]
|
|
||||||
+):
|
|
||||||
return 2
|
|
||||||
|
|
||||||
|
|
||||||
# Magic trailing comma example
|
|
||||||
-def foo() -> tuple[
|
|
||||||
- int,
|
|
||||||
- int,
|
|
||||||
- int,
|
|
||||||
-]:
|
|
||||||
+def foo() -> (
|
|
||||||
+ tuple[
|
|
||||||
+ int,
|
|
||||||
+ int,
|
|
||||||
+ int,
|
|
||||||
+ ]
|
|
||||||
+):
|
|
||||||
return 2
|
|
||||||
|
|
||||||
|
|
||||||
# Magic trailing comma example, with params
|
# Magic trailing comma example, with params
|
||||||
|
@ -284,24 +252,20 @@ def foo() -> tuple[int, int, int]:
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
|
|
||||||
def foo() -> (
|
def foo() -> tuple[
|
||||||
tuple[
|
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
|
||||||
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
|
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
|
||||||
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
|
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
|
||||||
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
|
]:
|
||||||
]
|
|
||||||
):
|
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
|
|
||||||
# Magic trailing comma example
|
# Magic trailing comma example
|
||||||
def foo() -> (
|
def foo() -> tuple[
|
||||||
tuple[
|
int,
|
||||||
int,
|
int,
|
||||||
int,
|
int,
|
||||||
int,
|
]:
|
||||||
]
|
|
||||||
):
|
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -64,11 +64,9 @@ assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx(
|
||||||
-assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx(
|
-assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx(
|
||||||
- xxxxxxxxx
|
- xxxxxxxxx
|
||||||
-).xxxxxxxxxxxxxxxxxx(), (
|
-).xxxxxxxxxxxxxxxxxx(), (
|
||||||
- "xxx {xxxxxxxxx} xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
+assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx(xxxxxxxxx).xxxxxxxxxxxxxxxxxx(), (
|
||||||
-)
|
"xxx {xxxxxxxxx} xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
+assert (
|
)
|
||||||
+ xxxxxxxxx.xxxxxxxxx.xxxxxxxxx(xxxxxxxxx).xxxxxxxxxxxxxxxxxx()
|
|
||||||
+), "xxx {xxxxxxxxx} xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Ruff Output
|
## Ruff Output
|
||||||
|
@ -117,9 +115,9 @@ assert (
|
||||||
)
|
)
|
||||||
|
|
||||||
# Regression test for https://github.com/psf/black/issues/3414.
|
# Regression test for https://github.com/psf/black/issues/3414.
|
||||||
assert (
|
assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx(xxxxxxxxx).xxxxxxxxxxxxxxxxxx(), (
|
||||||
xxxxxxxxx.xxxxxxxxx.xxxxxxxxx(xxxxxxxxx).xxxxxxxxxxxxxxxxxx()
|
"xxx {xxxxxxxxx} xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
), "xxx {xxxxxxxxx} xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Black Output
|
## Black Output
|
||||||
|
|
|
@ -71,7 +71,15 @@ f"\"{a}\"{'hello' * b}\"{c}\""
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -25,7 +25,12 @@
|
@@ -18,14 +18,19 @@
|
||||||
|
quote"""
|
||||||
|
f"just a normal {f} string"
|
||||||
|
f"""This is a triple-quoted {f}-string"""
|
||||||
|
-f'MOAR {" ".join([])}'
|
||||||
|
f"MOAR {' '.join([])}"
|
||||||
|
+f"MOAR {' '.join([])}"
|
||||||
|
r"raw string ftw"
|
||||||
|
r"Date d\'expiration:(.*)"
|
||||||
r'Tricky "quote'
|
r'Tricky "quote'
|
||||||
r"Not-so-tricky \"quote"
|
r"Not-so-tricky \"quote"
|
||||||
rf"{yay}"
|
rf"{yay}"
|
||||||
|
@ -85,6 +93,25 @@ f"\"{a}\"{'hello' * b}\"{c}\""
|
||||||
re.compile(r'[\\"]')
|
re.compile(r'[\\"]')
|
||||||
"x = ''; y = \"\""
|
"x = ''; y = \"\""
|
||||||
"x = '''; y = \"\""
|
"x = '''; y = \"\""
|
||||||
|
@@ -40,14 +45,14 @@
|
||||||
|
'\\""'
|
||||||
|
"\\''"
|
||||||
|
"Lots of \\\\\\\\'quotes'"
|
||||||
|
-f'{y * " "} \'{z}\''
|
||||||
|
+f"{y * ' '} '{z}'"
|
||||||
|
f"{{y * \" \"}} '{z}'"
|
||||||
|
-f'\'{z}\' {y * " "}'
|
||||||
|
+f"'{z}' {y * ' '}"
|
||||||
|
f"{y * x} '{z}'"
|
||||||
|
"'{z}' {y * \" \"}"
|
||||||
|
"{y * x} '{z}'"
|
||||||
|
|
||||||
|
# We must bail out if changing the quotes would introduce backslashes in f-string
|
||||||
|
# expressions. xref: https://github.com/psf/black/issues/2348
|
||||||
|
-f"\"{b}\"{' ' * (long-len(b)+1)}: \"{sts}\",\n"
|
||||||
|
-f"\"{a}\"{'hello' * b}\"{c}\""
|
||||||
|
+f'"{b}"{" " * (long - len(b) + 1)}: "{sts}",\n'
|
||||||
|
+f'"{a}"{"hello" * b}"{c}"'
|
||||||
```
|
```
|
||||||
|
|
||||||
## Ruff Output
|
## Ruff Output
|
||||||
|
@ -110,7 +137,7 @@ f"\"{a}\"{'hello' * b}\"{c}\""
|
||||||
quote"""
|
quote"""
|
||||||
f"just a normal {f} string"
|
f"just a normal {f} string"
|
||||||
f"""This is a triple-quoted {f}-string"""
|
f"""This is a triple-quoted {f}-string"""
|
||||||
f'MOAR {" ".join([])}'
|
f"MOAR {' '.join([])}"
|
||||||
f"MOAR {' '.join([])}"
|
f"MOAR {' '.join([])}"
|
||||||
r"raw string ftw"
|
r"raw string ftw"
|
||||||
r"Date d\'expiration:(.*)"
|
r"Date d\'expiration:(.*)"
|
||||||
|
@ -137,17 +164,17 @@ re.compile(r'[\\"]')
|
||||||
'\\""'
|
'\\""'
|
||||||
"\\''"
|
"\\''"
|
||||||
"Lots of \\\\\\\\'quotes'"
|
"Lots of \\\\\\\\'quotes'"
|
||||||
f'{y * " "} \'{z}\''
|
f"{y * ' '} '{z}'"
|
||||||
f"{{y * \" \"}} '{z}'"
|
f"{{y * \" \"}} '{z}'"
|
||||||
f'\'{z}\' {y * " "}'
|
f"'{z}' {y * ' '}"
|
||||||
f"{y * x} '{z}'"
|
f"{y * x} '{z}'"
|
||||||
"'{z}' {y * \" \"}"
|
"'{z}' {y * \" \"}"
|
||||||
"{y * x} '{z}'"
|
"{y * x} '{z}'"
|
||||||
|
|
||||||
# We must bail out if changing the quotes would introduce backslashes in f-string
|
# We must bail out if changing the quotes would introduce backslashes in f-string
|
||||||
# expressions. xref: https://github.com/psf/black/issues/2348
|
# expressions. xref: https://github.com/psf/black/issues/2348
|
||||||
f"\"{b}\"{' ' * (long-len(b)+1)}: \"{sts}\",\n"
|
f'"{b}"{" " * (long - len(b) + 1)}: "{sts}",\n'
|
||||||
f"\"{a}\"{'hello' * b}\"{c}\""
|
f'"{a}"{"hello" * b}"{c}"'
|
||||||
```
|
```
|
||||||
|
|
||||||
## Black Output
|
## Black Output
|
||||||
|
|
|
@ -616,7 +616,9 @@ def length_doctest():
|
||||||
Integer length of the list of numbers.
|
Integer length of the list of numbers.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
>>> length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
>>> length(
|
||||||
|
... [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||||
|
... )
|
||||||
20
|
20
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -631,7 +633,9 @@ def length_doctest_underindent():
|
||||||
Integer length of the list of numbers.
|
Integer length of the list of numbers.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
>>> length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
>>> length(
|
||||||
|
... [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||||
|
... )
|
||||||
20
|
20
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -649,7 +653,9 @@ def length_markdown():
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```
|
```
|
||||||
length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21])
|
length(
|
||||||
|
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
|
||||||
|
)
|
||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -659,7 +665,9 @@ def length_rst():
|
||||||
"""
|
"""
|
||||||
Do cool stuff::
|
Do cool stuff::
|
||||||
|
|
||||||
length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21])
|
length(
|
||||||
|
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
|
||||||
|
)
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -670,7 +678,9 @@ def length_rst_in_section():
|
||||||
Examples:
|
Examples:
|
||||||
Do cool stuff::
|
Do cool stuff::
|
||||||
|
|
||||||
length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
length(
|
||||||
|
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||||
|
)
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
```
|
```
|
||||||
|
@ -695,11 +705,13 @@ def length_rst_in_section():
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@@ -300,7 +302,28 @@
|
@@ -300,9 +302,28 @@
|
||||||
Integer length of the list of numbers.
|
Integer length of the list of numbers.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
- >>> length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
- >>> length(
|
||||||
|
- ... [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||||
|
- ... )
|
||||||
+ >>> length([
|
+ >>> length([
|
||||||
+ ... 1,
|
+ ... 1,
|
||||||
+ ... 2,
|
+ ... 2,
|
||||||
|
@ -725,11 +737,13 @@ def length_rst_in_section():
|
||||||
20
|
20
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -315,7 +338,28 @@
|
@@ -317,9 +338,28 @@
|
||||||
Integer length of the list of numbers.
|
Integer length of the list of numbers.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
- >>> length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
- >>> length(
|
||||||
|
- ... [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||||
|
- ... )
|
||||||
+ >>> length([
|
+ >>> length([
|
||||||
+ ... 1,
|
+ ... 1,
|
||||||
+ ... 2,
|
+ ... 2,
|
||||||
|
@ -755,11 +769,13 @@ def length_rst_in_section():
|
||||||
20
|
20
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -333,7 +377,29 @@
|
@@ -337,9 +377,29 @@
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```
|
```
|
||||||
- length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21])
|
- length(
|
||||||
|
- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
|
||||||
|
- )
|
||||||
+ length([
|
+ length([
|
||||||
+ 1,
|
+ 1,
|
||||||
+ 2,
|
+ 2,
|
||||||
|
@ -786,11 +802,13 @@ def length_rst_in_section():
|
||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -343,7 +409,29 @@
|
@@ -349,9 +409,29 @@
|
||||||
"""
|
"""
|
||||||
Do cool stuff::
|
Do cool stuff::
|
||||||
|
|
||||||
- length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21])
|
- length(
|
||||||
|
- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
|
||||||
|
- )
|
||||||
+ length([
|
+ length([
|
||||||
+ 1,
|
+ 1,
|
||||||
+ 2,
|
+ 2,
|
||||||
|
@ -817,11 +835,13 @@ def length_rst_in_section():
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -354,6 +442,27 @@
|
@@ -362,8 +442,27 @@
|
||||||
Examples:
|
Examples:
|
||||||
Do cool stuff::
|
Do cool stuff::
|
||||||
|
|
||||||
- length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
- length(
|
||||||
|
- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||||
|
- )
|
||||||
+ length([
|
+ length([
|
||||||
+ 1,
|
+ 1,
|
||||||
+ 2,
|
+ 2,
|
||||||
|
@ -1157,7 +1177,9 @@ def length_doctest():
|
||||||
Integer length of the list of numbers.
|
Integer length of the list of numbers.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
>>> length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
>>> length(
|
||||||
|
... [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||||
|
... )
|
||||||
20
|
20
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -1172,7 +1194,9 @@ def length_doctest_underindent():
|
||||||
Integer length of the list of numbers.
|
Integer length of the list of numbers.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
>>> length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
>>> length(
|
||||||
|
... [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||||
|
... )
|
||||||
20
|
20
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -1190,7 +1214,9 @@ def length_markdown():
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```
|
```
|
||||||
length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21])
|
length(
|
||||||
|
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
|
||||||
|
)
|
||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -1200,7 +1226,9 @@ def length_rst():
|
||||||
"""
|
"""
|
||||||
Do cool stuff::
|
Do cool stuff::
|
||||||
|
|
||||||
length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21])
|
length(
|
||||||
|
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
|
||||||
|
)
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -1211,7 +1239,9 @@ def length_rst_in_section():
|
||||||
Examples:
|
Examples:
|
||||||
Do cool stuff::
|
Do cool stuff::
|
||||||
|
|
||||||
length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
length(
|
||||||
|
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||||
|
)
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
```
|
```
|
||||||
|
@ -1221,11 +1251,13 @@ def length_rst_in_section():
|
||||||
```diff
|
```diff
|
||||||
--- Stable
|
--- Stable
|
||||||
+++ Preview
|
+++ Preview
|
||||||
@@ -290,7 +290,28 @@
|
@@ -290,9 +290,28 @@
|
||||||
Integer length of the list of numbers.
|
Integer length of the list of numbers.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
- >>> length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
- >>> length(
|
||||||
|
- ... [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||||
|
- ... )
|
||||||
+ >>> length([
|
+ >>> length([
|
||||||
+ ... 1,
|
+ ... 1,
|
||||||
+ ... 2,
|
+ ... 2,
|
||||||
|
@ -1251,11 +1283,13 @@ def length_rst_in_section():
|
||||||
20
|
20
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -305,7 +326,28 @@
|
@@ -307,9 +326,28 @@
|
||||||
Integer length of the list of numbers.
|
Integer length of the list of numbers.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
- >>> length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
- >>> length(
|
||||||
|
- ... [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||||
|
- ... )
|
||||||
+ >>> length([
|
+ >>> length([
|
||||||
+ ... 1,
|
+ ... 1,
|
||||||
+ ... 2,
|
+ ... 2,
|
||||||
|
@ -1281,11 +1315,13 @@ def length_rst_in_section():
|
||||||
20
|
20
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -323,7 +365,29 @@
|
@@ -327,9 +365,29 @@
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```
|
```
|
||||||
- length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21])
|
- length(
|
||||||
|
- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
|
||||||
|
- )
|
||||||
+ length([
|
+ length([
|
||||||
+ 1,
|
+ 1,
|
||||||
+ 2,
|
+ 2,
|
||||||
|
@ -1312,11 +1348,13 @@ def length_rst_in_section():
|
||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -333,7 +397,29 @@
|
@@ -339,9 +397,29 @@
|
||||||
"""
|
"""
|
||||||
Do cool stuff::
|
Do cool stuff::
|
||||||
|
|
||||||
- length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21])
|
- length(
|
||||||
|
- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
|
||||||
|
- )
|
||||||
+ length([
|
+ length([
|
||||||
+ 1,
|
+ 1,
|
||||||
+ 2,
|
+ 2,
|
||||||
|
@ -1343,11 +1381,13 @@ def length_rst_in_section():
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -344,6 +430,27 @@
|
@@ -352,8 +430,27 @@
|
||||||
Examples:
|
Examples:
|
||||||
Do cool stuff::
|
Do cool stuff::
|
||||||
|
|
||||||
- length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
- length(
|
||||||
|
- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||||
|
- )
|
||||||
+ length([
|
+ length([
|
||||||
+ 1,
|
+ 1,
|
||||||
+ 2,
|
+ 2,
|
||||||
|
@ -1693,7 +1733,9 @@ def length_doctest():
|
||||||
Integer length of the list of numbers.
|
Integer length of the list of numbers.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
>>> length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
>>> length(
|
||||||
|
... [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||||
|
... )
|
||||||
20
|
20
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -1708,7 +1750,9 @@ def length_doctest_underindent():
|
||||||
Integer length of the list of numbers.
|
Integer length of the list of numbers.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
>>> length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
>>> length(
|
||||||
|
... [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||||
|
... )
|
||||||
20
|
20
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -1726,7 +1770,9 @@ def length_markdown():
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```
|
```
|
||||||
length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21])
|
length(
|
||||||
|
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
|
||||||
|
)
|
||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -1736,7 +1782,9 @@ def length_rst():
|
||||||
"""
|
"""
|
||||||
Do cool stuff::
|
Do cool stuff::
|
||||||
|
|
||||||
length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21])
|
length(
|
||||||
|
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
|
||||||
|
)
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -1747,7 +1795,9 @@ def length_rst_in_section():
|
||||||
Examples:
|
Examples:
|
||||||
Do cool stuff::
|
Do cool stuff::
|
||||||
|
|
||||||
length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
length(
|
||||||
|
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||||
|
)
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
```
|
```
|
||||||
|
@ -1772,11 +1822,13 @@ def length_rst_in_section():
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@@ -300,7 +302,28 @@
|
@@ -300,9 +302,28 @@
|
||||||
Integer length of the list of numbers.
|
Integer length of the list of numbers.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
- >>> length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
- >>> length(
|
||||||
|
- ... [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||||
|
- ... )
|
||||||
+ >>> length([
|
+ >>> length([
|
||||||
+ ... 1,
|
+ ... 1,
|
||||||
+ ... 2,
|
+ ... 2,
|
||||||
|
@ -1802,11 +1854,13 @@ def length_rst_in_section():
|
||||||
20
|
20
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -315,7 +338,28 @@
|
@@ -317,9 +338,28 @@
|
||||||
Integer length of the list of numbers.
|
Integer length of the list of numbers.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
- >>> length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
- >>> length(
|
||||||
|
- ... [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||||
|
- ... )
|
||||||
+ >>> length([
|
+ >>> length([
|
||||||
+ ... 1,
|
+ ... 1,
|
||||||
+ ... 2,
|
+ ... 2,
|
||||||
|
@ -1832,11 +1886,13 @@ def length_rst_in_section():
|
||||||
20
|
20
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -333,7 +377,29 @@
|
@@ -337,9 +377,29 @@
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```
|
```
|
||||||
- length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21])
|
- length(
|
||||||
|
- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
|
||||||
|
- )
|
||||||
+ length([
|
+ length([
|
||||||
+ 1,
|
+ 1,
|
||||||
+ 2,
|
+ 2,
|
||||||
|
@ -1863,11 +1919,13 @@ def length_rst_in_section():
|
||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -343,7 +409,29 @@
|
@@ -349,9 +409,29 @@
|
||||||
"""
|
"""
|
||||||
Do cool stuff::
|
Do cool stuff::
|
||||||
|
|
||||||
- length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21])
|
- length(
|
||||||
|
- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
|
||||||
|
- )
|
||||||
+ length([
|
+ length([
|
||||||
+ 1,
|
+ 1,
|
||||||
+ 2,
|
+ 2,
|
||||||
|
@ -1894,11 +1952,13 @@ def length_rst_in_section():
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -354,6 +442,27 @@
|
@@ -362,8 +442,27 @@
|
||||||
Examples:
|
Examples:
|
||||||
Do cool stuff::
|
Do cool stuff::
|
||||||
|
|
||||||
- length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
- length(
|
||||||
|
- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||||
|
- )
|
||||||
+ length([
|
+ length([
|
||||||
+ 1,
|
+ 1,
|
||||||
+ 2,
|
+ 2,
|
||||||
|
@ -2822,7 +2882,30 @@ def length_rst_in_section():
|
||||||
Examples:
|
Examples:
|
||||||
Do cool stuff::
|
Do cool stuff::
|
||||||
|
|
||||||
length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
length(
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
19,
|
||||||
|
20,
|
||||||
|
]
|
||||||
|
)
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
```
|
```
|
||||||
|
@ -3063,11 +3146,34 @@ def length_rst_in_section():
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -878,6 +872,27 @@
|
@@ -878,29 +872,27 @@
|
||||||
Examples:
|
Examples:
|
||||||
Do cool stuff::
|
Do cool stuff::
|
||||||
|
|
||||||
- length([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
- length(
|
||||||
|
- [
|
||||||
|
- 1,
|
||||||
|
- 2,
|
||||||
|
- 3,
|
||||||
|
- 4,
|
||||||
|
- 5,
|
||||||
|
- 6,
|
||||||
|
- 7,
|
||||||
|
- 8,
|
||||||
|
- 9,
|
||||||
|
- 10,
|
||||||
|
- 11,
|
||||||
|
- 12,
|
||||||
|
- 13,
|
||||||
|
- 14,
|
||||||
|
- 15,
|
||||||
|
- 16,
|
||||||
|
- 17,
|
||||||
|
- 18,
|
||||||
|
- 19,
|
||||||
|
- 20,
|
||||||
|
- ]
|
||||||
|
- )
|
||||||
+ length([
|
+ length([
|
||||||
+ 1,
|
+ 1,
|
||||||
+ 2,
|
+ 2,
|
||||||
|
|
|
@ -911,52 +911,20 @@ if True:
|
||||||
)
|
)
|
||||||
|
|
||||||
# This f-string should be flattened
|
# This f-string should be flattened
|
||||||
xxxxxxxxxxxxxxxx = f"aaaaaaaaaaaaaaaaaaaaa {
|
xxxxxxxxxxxxxxxx = f"aaaaaaaaaaaaaaaaaaaaa {expression} bbbbbbbbbbbbbbbbbbbbbbbb" + (
|
||||||
expression } bbbbbbbbbbbbbbbbbbbbbbbb" + (yyyyyyyyyyyyyy + zzzzzzzzzzz)
|
yyyyyyyyyyyyyy + zzzzzzzzzzz
|
||||||
|
)
|
||||||
|
|
||||||
# This is not a multiline f-string, but the expression is too long so it should be
|
# This is not a multiline f-string, but the expression is too long so it should be
|
||||||
# wrapped in parentheses.
|
# wrapped in parentheses.
|
||||||
f"hellooooooooooooooooooooooo \
|
(
|
||||||
worlddddddddddddddddddddddddddddddddd" + (
|
f"hellooooooooooooooooooooooo \
|
||||||
aaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbb
|
worlddddddddddddddddddddddddddddddddd"
|
||||||
|
+ (aaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbb)
|
||||||
)
|
)
|
||||||
aaaaaaaaaaa = f"hellooooooooooooooooooooooo \
|
aaaaaaaaaaa = (
|
||||||
worlddddddddddddddddddddddddddddddddd" + (
|
f"hellooooooooooooooooooooooo \
|
||||||
aaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbb
|
worlddddddddddddddddddddddddddddddddd"
|
||||||
|
+ (aaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbb)
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Preview changes
|
|
||||||
```diff
|
|
||||||
--- Stable
|
|
||||||
+++ Preview
|
|
||||||
@@ -468,16 +468,19 @@
|
|
||||||
)
|
|
||||||
|
|
||||||
# This f-string should be flattened
|
|
||||||
-xxxxxxxxxxxxxxxx = f"aaaaaaaaaaaaaaaaaaaaa {
|
|
||||||
- expression } bbbbbbbbbbbbbbbbbbbbbbbb" + (yyyyyyyyyyyyyy + zzzzzzzzzzz)
|
|
||||||
+xxxxxxxxxxxxxxxx = f"aaaaaaaaaaaaaaaaaaaaa {expression} bbbbbbbbbbbbbbbbbbbbbbbb" + (
|
|
||||||
+ yyyyyyyyyyyyyy + zzzzzzzzzzz
|
|
||||||
+)
|
|
||||||
|
|
||||||
# This is not a multiline f-string, but the expression is too long so it should be
|
|
||||||
# wrapped in parentheses.
|
|
||||||
-f"hellooooooooooooooooooooooo \
|
|
||||||
- worlddddddddddddddddddddddddddddddddd" + (
|
|
||||||
- aaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbb
|
|
||||||
+(
|
|
||||||
+ f"hellooooooooooooooooooooooo \
|
|
||||||
+ worlddddddddddddddddddddddddddddddddd"
|
|
||||||
+ + (aaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbb)
|
|
||||||
)
|
|
||||||
-aaaaaaaaaaa = f"hellooooooooooooooooooooooo \
|
|
||||||
- worlddddddddddddddddddddddddddddddddd" + (
|
|
||||||
- aaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbb
|
|
||||||
+aaaaaaaaaaa = (
|
|
||||||
+ f"hellooooooooooooooooooooooo \
|
|
||||||
+ worlddddddddddddddddddddddddddddddddd"
|
|
||||||
+ + (aaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbb)
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
|
@ -399,27 +399,9 @@ c = (
|
||||||
"dddddddddddddddddddddddddd" % aaaaaaaaaaaa + x
|
"dddddddddddddddddddddddddd" % aaaaaaaaaaaa + x
|
||||||
)
|
)
|
||||||
|
|
||||||
"a" "b" "c" + "d" "e" + "f" "g" + "h" "i" "j"
|
"abc" + "de" + "fg" + "hij"
|
||||||
|
|
||||||
|
|
||||||
class EC2REPATH:
|
class EC2REPATH:
|
||||||
f.write("Pathway name" + "\t" "Database Identifier" + "\t" "Source database" + "\n")
|
f.write("Pathway name" + "\tDatabase Identifier" + "\tSource database" + "\n")
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Preview changes
|
|
||||||
```diff
|
|
||||||
--- Stable
|
|
||||||
+++ Preview
|
|
||||||
@@ -197,8 +197,8 @@
|
|
||||||
"dddddddddddddddddddddddddd" % aaaaaaaaaaaa + x
|
|
||||||
)
|
|
||||||
|
|
||||||
-"a" "b" "c" + "d" "e" + "f" "g" + "h" "i" "j"
|
|
||||||
+"abc" + "de" + "fg" + "hij"
|
|
||||||
|
|
||||||
|
|
||||||
class EC2REPATH:
|
|
||||||
- f.write("Pathway name" + "\t" "Database Identifier" + "\t" "Source database" + "\n")
|
|
||||||
+ f.write("Pathway name" + "\tDatabase Identifier" + "\tSource database" + "\n")
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -211,9 +211,9 @@ String \"\"\"
|
||||||
|
|
||||||
# String continuation
|
# String continuation
|
||||||
|
|
||||||
b"Let's" b"start" b"with" b"a" b"simple" b"example"
|
b"Let'sstartwithasimpleexample"
|
||||||
|
|
||||||
b"Let's" b"start" b"with" b"a" b"simple" b"example" b"now repeat after me:" b"I am confident" b"I am confident" b"I am confident" b"I am confident" b"I am confident"
|
b"Let'sstartwithasimpleexamplenow repeat after me:I am confidentI am confidentI am confidentI am confidentI am confident"
|
||||||
|
|
||||||
(
|
(
|
||||||
b"Let's"
|
b"Let's"
|
||||||
|
@ -280,39 +280,12 @@ test_particular = [
|
||||||
]
|
]
|
||||||
|
|
||||||
# Parenthesized string continuation with messed up indentation
|
# Parenthesized string continuation with messed up indentation
|
||||||
{"key": ([], b"a" b"b" b"c")}
|
{"key": ([], b"abc")}
|
||||||
|
|
||||||
b"Unicode Escape sequence don't apply to bytes: \N{0x} \u{ABCD} \U{ABCDEFGH}"
|
b"Unicode Escape sequence don't apply to bytes: \N{0x} \u{ABCD} \U{ABCDEFGH}"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
#### Preview changes
|
|
||||||
```diff
|
|
||||||
--- Stable
|
|
||||||
+++ Preview
|
|
||||||
@@ -63,9 +63,9 @@
|
|
||||||
|
|
||||||
# String continuation
|
|
||||||
|
|
||||||
-b"Let's" b"start" b"with" b"a" b"simple" b"example"
|
|
||||||
+b"Let'sstartwithasimpleexample"
|
|
||||||
|
|
||||||
-b"Let's" b"start" b"with" b"a" b"simple" b"example" b"now repeat after me:" b"I am confident" b"I am confident" b"I am confident" b"I am confident" b"I am confident"
|
|
||||||
+b"Let'sstartwithasimpleexamplenow repeat after me:I am confidentI am confidentI am confidentI am confidentI am confident"
|
|
||||||
|
|
||||||
(
|
|
||||||
b"Let's"
|
|
||||||
@@ -132,6 +132,6 @@
|
|
||||||
]
|
|
||||||
|
|
||||||
# Parenthesized string continuation with messed up indentation
|
|
||||||
-{"key": ([], b"a" b"b" b"c")}
|
|
||||||
+{"key": ([], b"abc")}
|
|
||||||
|
|
||||||
b"Unicode Escape sequence don't apply to bytes: \N{0x} \u{ABCD} \U{ABCDEFGH}"
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Output 2
|
### Output 2
|
||||||
```
|
```
|
||||||
indent-style = space
|
indent-style = space
|
||||||
|
@ -394,9 +367,9 @@ String \"\"\"
|
||||||
|
|
||||||
# String continuation
|
# String continuation
|
||||||
|
|
||||||
b"Let's" b'start' b'with' b'a' b'simple' b'example'
|
b"Let'sstartwithasimpleexample"
|
||||||
|
|
||||||
b"Let's" b'start' b'with' b'a' b'simple' b'example' b'now repeat after me:' b'I am confident' b'I am confident' b'I am confident' b'I am confident' b'I am confident'
|
b"Let'sstartwithasimpleexamplenow repeat after me:I am confidentI am confidentI am confidentI am confidentI am confident"
|
||||||
|
|
||||||
(
|
(
|
||||||
b"Let's"
|
b"Let's"
|
||||||
|
@ -463,34 +436,7 @@ test_particular = [
|
||||||
]
|
]
|
||||||
|
|
||||||
# Parenthesized string continuation with messed up indentation
|
# Parenthesized string continuation with messed up indentation
|
||||||
{'key': ([], b'a' b'b' b'c')}
|
{'key': ([], b'abc')}
|
||||||
|
|
||||||
b"Unicode Escape sequence don't apply to bytes: \N{0x} \u{ABCD} \U{ABCDEFGH}"
|
b"Unicode Escape sequence don't apply to bytes: \N{0x} \u{ABCD} \U{ABCDEFGH}"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
#### Preview changes
|
|
||||||
```diff
|
|
||||||
--- Stable
|
|
||||||
+++ Preview
|
|
||||||
@@ -63,9 +63,9 @@
|
|
||||||
|
|
||||||
# String continuation
|
|
||||||
|
|
||||||
-b"Let's" b'start' b'with' b'a' b'simple' b'example'
|
|
||||||
+b"Let'sstartwithasimpleexample"
|
|
||||||
|
|
||||||
-b"Let's" b'start' b'with' b'a' b'simple' b'example' b'now repeat after me:' b'I am confident' b'I am confident' b'I am confident' b'I am confident' b'I am confident'
|
|
||||||
+b"Let'sstartwithasimpleexamplenow repeat after me:I am confidentI am confidentI am confidentI am confidentI am confident"
|
|
||||||
|
|
||||||
(
|
|
||||||
b"Let's"
|
|
||||||
@@ -132,6 +132,6 @@
|
|
||||||
]
|
|
||||||
|
|
||||||
# Parenthesized string continuation with messed up indentation
|
|
||||||
-{'key': ([], b'a' b'b' b'c')}
|
|
||||||
+{'key': ([], b'abc')}
|
|
||||||
|
|
||||||
b"Unicode Escape sequence don't apply to bytes: \N{0x} \u{ABCD} \U{ABCDEFGH}"
|
|
||||||
```
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -355,22 +355,7 @@ f"aaaaaaaaaaaaaaaa \
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Outputs
|
## Output
|
||||||
### Output 1
|
|
||||||
```
|
|
||||||
indent-style = space
|
|
||||||
line-width = 88
|
|
||||||
indent-width = 4
|
|
||||||
quote-style = Double
|
|
||||||
line-ending = LineFeed
|
|
||||||
magic-trailing-comma = Respect
|
|
||||||
docstring-code = Disabled
|
|
||||||
docstring-code-line-width = "dynamic"
|
|
||||||
preview = Enabled
|
|
||||||
target_version = Py39
|
|
||||||
source_type = Python
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
"aaaaaaaaabbbbbbbbbbbbbbbbbbbb" # Join
|
"aaaaaaaaabbbbbbbbbbbbbbbbbbbb" # Join
|
||||||
|
|
||||||
|
@ -616,12 +601,9 @@ assert (
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# Use can_omit_optional_parentheses layout to avoid an instability where the formatter
|
# Use can_omit_optional_parentheses layout to avoid an instability where the formatter
|
||||||
# picks the can_omit_optional_parentheses layout when the strings are joined.
|
# picks the can_omit_optional_parentheses layout when the strings are joined.
|
||||||
if f"implicitconcatenatedstring" + f"implicitconcadddddddddddedring" * len([
|
if f"implicitconcatenatedstring" + f"implicitconcadddddddddddedring" * len(
|
||||||
aaaaaa,
|
[aaaaaa, bbbbbbbbbbbbbbbb, cccccccccccccccccc, ddddddddddddddddddddddddddd]
|
||||||
bbbbbbbbbbbbbbbb,
|
):
|
||||||
cccccccccccccccccc,
|
|
||||||
ddddddddddddddddddddddddddd,
|
|
||||||
]):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Keep parenthesizing multiline - implicit concatenated strings
|
# Keep parenthesizing multiline - implicit concatenated strings
|
||||||
|
@ -792,3 +774,26 @@ f"aaaaaaaaaaaaaaaa \
|
||||||
ddddddddddddddddddd" # comment 4
|
ddddddddddddddddddd" # comment 4
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Preview changes
|
||||||
|
```diff
|
||||||
|
--- Stable
|
||||||
|
+++ Preview
|
||||||
|
@@ -242,9 +242,12 @@
|
||||||
|
##############################################################################
|
||||||
|
# Use can_omit_optional_parentheses layout to avoid an instability where the formatter
|
||||||
|
# picks the can_omit_optional_parentheses layout when the strings are joined.
|
||||||
|
-if f"implicitconcatenatedstring" + f"implicitconcadddddddddddedring" * len(
|
||||||
|
- [aaaaaa, bbbbbbbbbbbbbbbb, cccccccccccccccccc, ddddddddddddddddddddddddddd]
|
||||||
|
-):
|
||||||
|
+if f"implicitconcatenatedstring" + f"implicitconcadddddddddddedring" * len([
|
||||||
|
+ aaaaaa,
|
||||||
|
+ bbbbbbbbbbbbbbbb,
|
||||||
|
+ cccccccccccccccccc,
|
||||||
|
+ ddddddddddddddddddddddddddd,
|
||||||
|
+]):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Keep parenthesizing multiline - implicit concatenated strings
|
||||||
|
```
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
---
|
---
|
||||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/join_implicit_concatenated_string_assignment.py
|
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/join_implicit_concatenated_string_assignment.py
|
||||||
snapshot_kind: text
|
|
||||||
---
|
---
|
||||||
## Input
|
## Input
|
||||||
```python
|
```python
|
||||||
|
@ -300,22 +299,7 @@ aaaaa[aaaaaaaaaaa] = (
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Outputs
|
## Output
|
||||||
### Output 1
|
|
||||||
```
|
|
||||||
indent-style = space
|
|
||||||
line-width = 88
|
|
||||||
indent-width = 4
|
|
||||||
quote-style = Double
|
|
||||||
line-ending = LineFeed
|
|
||||||
magic-trailing-comma = Respect
|
|
||||||
docstring-code = Disabled
|
|
||||||
docstring-code-line-width = "dynamic"
|
|
||||||
preview = Enabled
|
|
||||||
target_version = Py39
|
|
||||||
source_type = Python
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
## Implicit concatenated strings with a trailing comment but a non splittable target.
|
## Implicit concatenated strings with a trailing comment but a non splittable target.
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
---
|
---
|
||||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/join_implicit_concatenated_string_preserve.py
|
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/join_implicit_concatenated_string_preserve.py
|
||||||
snapshot_kind: text
|
|
||||||
---
|
---
|
||||||
## Input
|
## Input
|
||||||
```python
|
```python
|
||||||
|
@ -31,7 +30,7 @@ line-ending = LineFeed
|
||||||
magic-trailing-comma = Respect
|
magic-trailing-comma = Respect
|
||||||
docstring-code = Disabled
|
docstring-code = Disabled
|
||||||
docstring-code-line-width = "dynamic"
|
docstring-code-line-width = "dynamic"
|
||||||
preview = Enabled
|
preview = Disabled
|
||||||
target_version = Py39
|
target_version = Py39
|
||||||
source_type = Python
|
source_type = Python
|
||||||
```
|
```
|
||||||
|
@ -63,7 +62,7 @@ line-ending = LineFeed
|
||||||
magic-trailing-comma = Respect
|
magic-trailing-comma = Respect
|
||||||
docstring-code = Disabled
|
docstring-code = Disabled
|
||||||
docstring-code-line-width = "dynamic"
|
docstring-code-line-width = "dynamic"
|
||||||
preview = Enabled
|
preview = Disabled
|
||||||
target_version = Py312
|
target_version = Py312
|
||||||
source_type = Python
|
source_type = Python
|
||||||
```
|
```
|
||||||
|
|
|
@ -323,24 +323,20 @@ aaaaaaaaaaaaaaaaaaaaa = [
|
||||||
# Leading expression comments:
|
# Leading expression comments:
|
||||||
y = [
|
y = [
|
||||||
a
|
a
|
||||||
for
|
for (
|
||||||
(
|
|
||||||
# comment
|
# comment
|
||||||
a
|
a
|
||||||
) in
|
) in (
|
||||||
(
|
|
||||||
# comment
|
# comment
|
||||||
x
|
x
|
||||||
)
|
)
|
||||||
if
|
if (
|
||||||
(
|
|
||||||
# asdasd
|
# asdasd
|
||||||
"askldaklsdnmklasmdlkasmdlkasmdlkasmdasd"
|
"askldaklsdnmklasmdlkasmdlkasmdlkasmdasd"
|
||||||
!= "as,mdnaskldmlkasdmlaksdmlkasdlkasdm"
|
!= "as,mdnaskldmlkasdmlaksdmlkasdlkasdm"
|
||||||
and "zxcm,.nzxclm,zxnckmnzxckmnzxczxc" != "zxcasdasdlmnasdlknaslkdnmlaskdm"
|
and "zxcm,.nzxclm,zxnckmnzxckmnzxczxc" != "zxcasdasdlmnasdlknaslkdnmlaskdm"
|
||||||
)
|
)
|
||||||
if
|
if (
|
||||||
(
|
|
||||||
# comment
|
# comment
|
||||||
x
|
x
|
||||||
)
|
)
|
||||||
|
@ -383,39 +379,3 @@ y = [
|
||||||
x
|
x
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Preview changes
|
|
||||||
```diff
|
|
||||||
--- Stable
|
|
||||||
+++ Preview
|
|
||||||
@@ -142,24 +142,20 @@
|
|
||||||
# Leading expression comments:
|
|
||||||
y = [
|
|
||||||
a
|
|
||||||
- for
|
|
||||||
- (
|
|
||||||
+ for (
|
|
||||||
# comment
|
|
||||||
a
|
|
||||||
- ) in
|
|
||||||
- (
|
|
||||||
+ ) in (
|
|
||||||
# comment
|
|
||||||
x
|
|
||||||
)
|
|
||||||
- if
|
|
||||||
- (
|
|
||||||
+ if (
|
|
||||||
# asdasd
|
|
||||||
"askldaklsdnmklasmdlkasmdlkasmdlkasmdasd"
|
|
||||||
!= "as,mdnaskldmlkasdmlaksdmlkasdlkasdm"
|
|
||||||
and "zxcm,.nzxclm,zxnckmnzxckmnzxczxc" != "zxcasdasdlmnasdlknaslkdnmlaskdm"
|
|
||||||
)
|
|
||||||
- if
|
|
||||||
- (
|
|
||||||
+ if (
|
|
||||||
# comment
|
|
||||||
x
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
|
@ -310,9 +310,9 @@ String \"\"\"
|
||||||
|
|
||||||
# String continuation
|
# String continuation
|
||||||
|
|
||||||
"Let's" "start" "with" "a" "simple" "example"
|
"Let'sstartwithasimpleexample"
|
||||||
|
|
||||||
"Let's" "start" "with" "a" "simple" "example" "now repeat after me:" "I am confident" "I am confident" "I am confident" "I am confident" "I am confident"
|
"Let'sstartwithasimpleexamplenow repeat after me:I am confidentI am confidentI am confidentI am confidentI am confident"
|
||||||
|
|
||||||
(
|
(
|
||||||
"Let's"
|
"Let's"
|
||||||
|
@ -379,7 +379,7 @@ test_particular = [
|
||||||
]
|
]
|
||||||
|
|
||||||
# Parenthesized string continuation with messed up indentation
|
# Parenthesized string continuation with messed up indentation
|
||||||
{"key": ([], "a" "b" "c")}
|
{"key": ([], "abc")}
|
||||||
|
|
||||||
|
|
||||||
# Regression test for https://github.com/astral-sh/ruff/issues/5893
|
# Regression test for https://github.com/astral-sh/ruff/issues/5893
|
||||||
|
@ -412,19 +412,31 @@ a = """\\\x1f"""
|
||||||
# In preview, don't collapse implicit concatenated strings that can't be joined into a single string
|
# In preview, don't collapse implicit concatenated strings that can't be joined into a single string
|
||||||
# and that are multiline in the source.
|
# and that are multiline in the source.
|
||||||
|
|
||||||
(r"aaaaaaaaa" r"bbbbbbbbbbbbbbbbbbbb")
|
(
|
||||||
|
r"aaaaaaaaa"
|
||||||
(r"aaaaaaaaa" r"bbbbbbbbbbbbbbbbbbbb" "cccccccccccccccccccccc")
|
r"bbbbbbbbbbbbbbbbbbbb"
|
||||||
|
)
|
||||||
("""aaaaaaaaa""" """bbbbbbbbbbbbbbbbbbbb""")
|
|
||||||
|
|
||||||
(
|
(
|
||||||
f"""aaaa{
|
r"aaaaaaaaa"
|
||||||
10}aaaaa"""
|
r"bbbbbbbbbbbbbbbbbbbb"
|
||||||
|
"cccccccccccccccccccccc"
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
"""aaaaaaaaa"""
|
||||||
|
"""bbbbbbbbbbbbbbbbbbbb"""
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
f"""aaaa{10}aaaaa"""
|
||||||
rf"""bbbbbbbbbbbbbbbbbbbb"""
|
rf"""bbbbbbbbbbbbbbbbbbbb"""
|
||||||
)
|
)
|
||||||
|
|
||||||
if (r"aaaaaaaaa" r"bbbbbbbbbbbbbbbbbbbb") + ["aaaaaaaaaa", "bbbbbbbbbbbbbbbb"]:
|
if (
|
||||||
|
r"aaaaaaaaa"
|
||||||
|
r"bbbbbbbbbbbbbbbbbbbb"
|
||||||
|
) + ["aaaaaaaaaa", "bbbbbbbbbbbbbbbb"]:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@ -433,24 +445,19 @@ if (r"aaaaaaaaa" r"bbbbbbbbbbbbbbbbbbbb") + ["aaaaaaaaaa", "bbbbbbbbbbbbbbbb"]:
|
||||||
|
|
||||||
r"aaaaaaaaa" r"bbbbbbbbbbbbbbbbbbbb"
|
r"aaaaaaaaa" r"bbbbbbbbbbbbbbbbbbbb"
|
||||||
|
|
||||||
(
|
(f"aaaa{10}aaaaa" rf"bbbbbbbbbbbbbbbbbbbb")
|
||||||
f"aaaa{
|
|
||||||
10}aaaaa"
|
|
||||||
rf"bbbbbbbbbbbbbbbbbbbb"
|
|
||||||
)
|
|
||||||
|
|
||||||
(r"""aaaaaaaaa""" r"""bbbbbbbbbbbbbbbbbbbb""")
|
(r"""aaaaaaaaa""" r"""bbbbbbbbbbbbbbbbbbbb""")
|
||||||
|
|
||||||
(
|
(f"""aaaa{10}aaaaa""" rf"""bbbbbbbbbbbbbbbbbbbb""")
|
||||||
f"""aaaa{
|
|
||||||
10}aaaaa"""
|
|
||||||
rf"""bbbbbbbbbbbbbbbbbbbb"""
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# In docstring positions
|
# In docstring positions
|
||||||
def docstring():
|
def docstring():
|
||||||
r"aaaaaaaaa" "bbbbbbbbbbbbbbbbbbbb"
|
(
|
||||||
|
r"aaaaaaaaa"
|
||||||
|
"bbbbbbbbbbbbbbbbbbbb"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def docstring_flat():
|
def docstring_flat():
|
||||||
|
@ -465,103 +472,6 @@ def docstring_flat_overlong():
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
#### Preview changes
|
|
||||||
```diff
|
|
||||||
--- Stable
|
|
||||||
+++ Preview
|
|
||||||
@@ -70,9 +70,9 @@
|
|
||||||
|
|
||||||
# String continuation
|
|
||||||
|
|
||||||
-"Let's" "start" "with" "a" "simple" "example"
|
|
||||||
+"Let'sstartwithasimpleexample"
|
|
||||||
|
|
||||||
-"Let's" "start" "with" "a" "simple" "example" "now repeat after me:" "I am confident" "I am confident" "I am confident" "I am confident" "I am confident"
|
|
||||||
+"Let'sstartwithasimpleexamplenow repeat after me:I am confidentI am confidentI am confidentI am confidentI am confident"
|
|
||||||
|
|
||||||
(
|
|
||||||
"Let's"
|
|
||||||
@@ -139,7 +139,7 @@
|
|
||||||
]
|
|
||||||
|
|
||||||
# Parenthesized string continuation with messed up indentation
|
|
||||||
-{"key": ([], "a" "b" "c")}
|
|
||||||
+{"key": ([], "abc")}
|
|
||||||
|
|
||||||
|
|
||||||
# Regression test for https://github.com/astral-sh/ruff/issues/5893
|
|
||||||
@@ -172,19 +172,31 @@
|
|
||||||
# In preview, don't collapse implicit concatenated strings that can't be joined into a single string
|
|
||||||
# and that are multiline in the source.
|
|
||||||
|
|
||||||
-(r"aaaaaaaaa" r"bbbbbbbbbbbbbbbbbbbb")
|
|
||||||
+(
|
|
||||||
+ r"aaaaaaaaa"
|
|
||||||
+ r"bbbbbbbbbbbbbbbbbbbb"
|
|
||||||
+)
|
|
||||||
|
|
||||||
-(r"aaaaaaaaa" r"bbbbbbbbbbbbbbbbbbbb" "cccccccccccccccccccccc")
|
|
||||||
+(
|
|
||||||
+ r"aaaaaaaaa"
|
|
||||||
+ r"bbbbbbbbbbbbbbbbbbbb"
|
|
||||||
+ "cccccccccccccccccccccc"
|
|
||||||
+)
|
|
||||||
|
|
||||||
-("""aaaaaaaaa""" """bbbbbbbbbbbbbbbbbbbb""")
|
|
||||||
+(
|
|
||||||
+ """aaaaaaaaa"""
|
|
||||||
+ """bbbbbbbbbbbbbbbbbbbb"""
|
|
||||||
+)
|
|
||||||
|
|
||||||
(
|
|
||||||
- f"""aaaa{
|
|
||||||
- 10}aaaaa"""
|
|
||||||
+ f"""aaaa{10}aaaaa"""
|
|
||||||
rf"""bbbbbbbbbbbbbbbbbbbb"""
|
|
||||||
)
|
|
||||||
|
|
||||||
-if (r"aaaaaaaaa" r"bbbbbbbbbbbbbbbbbbbb") + ["aaaaaaaaaa", "bbbbbbbbbbbbbbbb"]:
|
|
||||||
+if (
|
|
||||||
+ r"aaaaaaaaa"
|
|
||||||
+ r"bbbbbbbbbbbbbbbbbbbb"
|
|
||||||
+) + ["aaaaaaaaaa", "bbbbbbbbbbbbbbbb"]:
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
@@ -193,24 +205,19 @@
|
|
||||||
|
|
||||||
r"aaaaaaaaa" r"bbbbbbbbbbbbbbbbbbbb"
|
|
||||||
|
|
||||||
-(
|
|
||||||
- f"aaaa{
|
|
||||||
- 10}aaaaa"
|
|
||||||
- rf"bbbbbbbbbbbbbbbbbbbb"
|
|
||||||
-)
|
|
||||||
+(f"aaaa{10}aaaaa" rf"bbbbbbbbbbbbbbbbbbbb")
|
|
||||||
|
|
||||||
(r"""aaaaaaaaa""" r"""bbbbbbbbbbbbbbbbbbbb""")
|
|
||||||
|
|
||||||
-(
|
|
||||||
- f"""aaaa{
|
|
||||||
- 10}aaaaa"""
|
|
||||||
- rf"""bbbbbbbbbbbbbbbbbbbb"""
|
|
||||||
-)
|
|
||||||
+(f"""aaaa{10}aaaaa""" rf"""bbbbbbbbbbbbbbbbbbbb""")
|
|
||||||
|
|
||||||
|
|
||||||
# In docstring positions
|
|
||||||
def docstring():
|
|
||||||
- r"aaaaaaaaa" "bbbbbbbbbbbbbbbbbbbb"
|
|
||||||
+ (
|
|
||||||
+ r"aaaaaaaaa"
|
|
||||||
+ "bbbbbbbbbbbbbbbbbbbb"
|
|
||||||
+ )
|
|
||||||
|
|
||||||
|
|
||||||
def docstring_flat():
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Output 2
|
### Output 2
|
||||||
```
|
```
|
||||||
indent-style = space
|
indent-style = space
|
||||||
|
@ -650,9 +560,9 @@ String \"\"\"
|
||||||
|
|
||||||
# String continuation
|
# String continuation
|
||||||
|
|
||||||
"Let's" 'start' 'with' 'a' 'simple' 'example'
|
"Let'sstartwithasimpleexample"
|
||||||
|
|
||||||
"Let's" 'start' 'with' 'a' 'simple' 'example' 'now repeat after me:' 'I am confident' 'I am confident' 'I am confident' 'I am confident' 'I am confident'
|
"Let'sstartwithasimpleexamplenow repeat after me:I am confidentI am confidentI am confidentI am confidentI am confident"
|
||||||
|
|
||||||
(
|
(
|
||||||
"Let's"
|
"Let's"
|
||||||
|
@ -719,7 +629,7 @@ test_particular = [
|
||||||
]
|
]
|
||||||
|
|
||||||
# Parenthesized string continuation with messed up indentation
|
# Parenthesized string continuation with messed up indentation
|
||||||
{'key': ([], 'a' 'b' 'c')}
|
{'key': ([], 'abc')}
|
||||||
|
|
||||||
|
|
||||||
# Regression test for https://github.com/astral-sh/ruff/issues/5893
|
# Regression test for https://github.com/astral-sh/ruff/issues/5893
|
||||||
|
@ -752,19 +662,31 @@ a = """\\\x1f"""
|
||||||
# In preview, don't collapse implicit concatenated strings that can't be joined into a single string
|
# In preview, don't collapse implicit concatenated strings that can't be joined into a single string
|
||||||
# and that are multiline in the source.
|
# and that are multiline in the source.
|
||||||
|
|
||||||
(r'aaaaaaaaa' r'bbbbbbbbbbbbbbbbbbbb')
|
(
|
||||||
|
r'aaaaaaaaa'
|
||||||
(r'aaaaaaaaa' r'bbbbbbbbbbbbbbbbbbbb' 'cccccccccccccccccccccc')
|
r'bbbbbbbbbbbbbbbbbbbb'
|
||||||
|
)
|
||||||
("""aaaaaaaaa""" """bbbbbbbbbbbbbbbbbbbb""")
|
|
||||||
|
|
||||||
(
|
(
|
||||||
f"""aaaa{
|
r'aaaaaaaaa'
|
||||||
10}aaaaa"""
|
r'bbbbbbbbbbbbbbbbbbbb'
|
||||||
|
'cccccccccccccccccccccc'
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
"""aaaaaaaaa"""
|
||||||
|
"""bbbbbbbbbbbbbbbbbbbb"""
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
f"""aaaa{10}aaaaa"""
|
||||||
rf"""bbbbbbbbbbbbbbbbbbbb"""
|
rf"""bbbbbbbbbbbbbbbbbbbb"""
|
||||||
)
|
)
|
||||||
|
|
||||||
if (r'aaaaaaaaa' r'bbbbbbbbbbbbbbbbbbbb') + ['aaaaaaaaaa', 'bbbbbbbbbbbbbbbb']:
|
if (
|
||||||
|
r'aaaaaaaaa'
|
||||||
|
r'bbbbbbbbbbbbbbbbbbbb'
|
||||||
|
) + ['aaaaaaaaaa', 'bbbbbbbbbbbbbbbb']:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@ -773,24 +695,19 @@ if (r'aaaaaaaaa' r'bbbbbbbbbbbbbbbbbbbb') + ['aaaaaaaaaa', 'bbbbbbbbbbbbbbbb']:
|
||||||
|
|
||||||
r'aaaaaaaaa' r'bbbbbbbbbbbbbbbbbbbb'
|
r'aaaaaaaaa' r'bbbbbbbbbbbbbbbbbbbb'
|
||||||
|
|
||||||
(
|
(f'aaaa{10}aaaaa' rf'bbbbbbbbbbbbbbbbbbbb')
|
||||||
f'aaaa{
|
|
||||||
10}aaaaa'
|
|
||||||
rf'bbbbbbbbbbbbbbbbbbbb'
|
|
||||||
)
|
|
||||||
|
|
||||||
(r"""aaaaaaaaa""" r"""bbbbbbbbbbbbbbbbbbbb""")
|
(r"""aaaaaaaaa""" r"""bbbbbbbbbbbbbbbbbbbb""")
|
||||||
|
|
||||||
(
|
(f"""aaaa{10}aaaaa""" rf"""bbbbbbbbbbbbbbbbbbbb""")
|
||||||
f"""aaaa{
|
|
||||||
10}aaaaa"""
|
|
||||||
rf"""bbbbbbbbbbbbbbbbbbbb"""
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# In docstring positions
|
# In docstring positions
|
||||||
def docstring():
|
def docstring():
|
||||||
r'aaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbb'
|
(
|
||||||
|
r'aaaaaaaaa'
|
||||||
|
'bbbbbbbbbbbbbbbbbbbb'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def docstring_flat():
|
def docstring_flat():
|
||||||
|
@ -803,100 +720,3 @@ def docstring_flat_overlong():
|
||||||
r'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'
|
r'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
#### Preview changes
|
|
||||||
```diff
|
|
||||||
--- Stable
|
|
||||||
+++ Preview
|
|
||||||
@@ -70,9 +70,9 @@
|
|
||||||
|
|
||||||
# String continuation
|
|
||||||
|
|
||||||
-"Let's" 'start' 'with' 'a' 'simple' 'example'
|
|
||||||
+"Let'sstartwithasimpleexample"
|
|
||||||
|
|
||||||
-"Let's" 'start' 'with' 'a' 'simple' 'example' 'now repeat after me:' 'I am confident' 'I am confident' 'I am confident' 'I am confident' 'I am confident'
|
|
||||||
+"Let'sstartwithasimpleexamplenow repeat after me:I am confidentI am confidentI am confidentI am confidentI am confident"
|
|
||||||
|
|
||||||
(
|
|
||||||
"Let's"
|
|
||||||
@@ -139,7 +139,7 @@
|
|
||||||
]
|
|
||||||
|
|
||||||
# Parenthesized string continuation with messed up indentation
|
|
||||||
-{'key': ([], 'a' 'b' 'c')}
|
|
||||||
+{'key': ([], 'abc')}
|
|
||||||
|
|
||||||
|
|
||||||
# Regression test for https://github.com/astral-sh/ruff/issues/5893
|
|
||||||
@@ -172,19 +172,31 @@
|
|
||||||
# In preview, don't collapse implicit concatenated strings that can't be joined into a single string
|
|
||||||
# and that are multiline in the source.
|
|
||||||
|
|
||||||
-(r'aaaaaaaaa' r'bbbbbbbbbbbbbbbbbbbb')
|
|
||||||
+(
|
|
||||||
+ r'aaaaaaaaa'
|
|
||||||
+ r'bbbbbbbbbbbbbbbbbbbb'
|
|
||||||
+)
|
|
||||||
|
|
||||||
-(r'aaaaaaaaa' r'bbbbbbbbbbbbbbbbbbbb' 'cccccccccccccccccccccc')
|
|
||||||
+(
|
|
||||||
+ r'aaaaaaaaa'
|
|
||||||
+ r'bbbbbbbbbbbbbbbbbbbb'
|
|
||||||
+ 'cccccccccccccccccccccc'
|
|
||||||
+)
|
|
||||||
|
|
||||||
-("""aaaaaaaaa""" """bbbbbbbbbbbbbbbbbbbb""")
|
|
||||||
+(
|
|
||||||
+ """aaaaaaaaa"""
|
|
||||||
+ """bbbbbbbbbbbbbbbbbbbb"""
|
|
||||||
+)
|
|
||||||
|
|
||||||
(
|
|
||||||
- f"""aaaa{
|
|
||||||
- 10}aaaaa"""
|
|
||||||
+ f"""aaaa{10}aaaaa"""
|
|
||||||
rf"""bbbbbbbbbbbbbbbbbbbb"""
|
|
||||||
)
|
|
||||||
|
|
||||||
-if (r'aaaaaaaaa' r'bbbbbbbbbbbbbbbbbbbb') + ['aaaaaaaaaa', 'bbbbbbbbbbbbbbbb']:
|
|
||||||
+if (
|
|
||||||
+ r'aaaaaaaaa'
|
|
||||||
+ r'bbbbbbbbbbbbbbbbbbbb'
|
|
||||||
+) + ['aaaaaaaaaa', 'bbbbbbbbbbbbbbbb']:
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
@@ -193,24 +205,19 @@
|
|
||||||
|
|
||||||
r'aaaaaaaaa' r'bbbbbbbbbbbbbbbbbbbb'
|
|
||||||
|
|
||||||
-(
|
|
||||||
- f'aaaa{
|
|
||||||
- 10}aaaaa'
|
|
||||||
- rf'bbbbbbbbbbbbbbbbbbbb'
|
|
||||||
-)
|
|
||||||
+(f'aaaa{10}aaaaa' rf'bbbbbbbbbbbbbbbbbbbb')
|
|
||||||
|
|
||||||
(r"""aaaaaaaaa""" r"""bbbbbbbbbbbbbbbbbbbb""")
|
|
||||||
|
|
||||||
-(
|
|
||||||
- f"""aaaa{
|
|
||||||
- 10}aaaaa"""
|
|
||||||
- rf"""bbbbbbbbbbbbbbbbbbbb"""
|
|
||||||
-)
|
|
||||||
+(f"""aaaa{10}aaaaa""" rf"""bbbbbbbbbbbbbbbbbbbb""")
|
|
||||||
|
|
||||||
|
|
||||||
# In docstring positions
|
|
||||||
def docstring():
|
|
||||||
- r'aaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbb'
|
|
||||||
+ (
|
|
||||||
+ r'aaaaaaaaa'
|
|
||||||
+ 'bbbbbbbbbbbbbbbbbbbb'
|
|
||||||
+ )
|
|
||||||
|
|
||||||
|
|
||||||
def docstring_flat():
|
|
||||||
```
|
|
||||||
|
|
|
@ -210,7 +210,7 @@ yield (
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
yield "Cache key will cause errors if used with memcached: %r " "(longer than %s)" % (
|
yield "Cache key will cause errors if used with memcached: %r (longer than %s)" % (
|
||||||
key,
|
key,
|
||||||
MEMCACHE_MAX_KEY_LENGTH,
|
MEMCACHE_MAX_KEY_LENGTH,
|
||||||
)
|
)
|
||||||
|
@ -228,8 +228,7 @@ yield (
|
||||||
"Django to create, modify, and delete the table"
|
"Django to create, modify, and delete the table"
|
||||||
)
|
)
|
||||||
yield (
|
yield (
|
||||||
"# Feel free to rename the models, but don't rename db_table values or "
|
"# Feel free to rename the models, but don't rename db_table values or field names."
|
||||||
"field names."
|
|
||||||
)
|
)
|
||||||
|
|
||||||
yield (
|
yield (
|
||||||
|
@ -241,8 +240,7 @@ yield (
|
||||||
"Django to create, modify, and delete the table"
|
"Django to create, modify, and delete the table"
|
||||||
)
|
)
|
||||||
yield (
|
yield (
|
||||||
"# Feel free to rename the models, but don't rename db_table values or "
|
"# Feel free to rename the models, but don't rename db_table values or field names."
|
||||||
"field names."
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Regression test for: https://github.com/astral-sh/ruff/issues/7420
|
# Regression test for: https://github.com/astral-sh/ruff/issues/7420
|
||||||
|
@ -278,39 +276,3 @@ result = yield (
|
||||||
|
|
||||||
print((yield x))
|
print((yield x))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Preview changes
|
|
||||||
```diff
|
|
||||||
--- Stable
|
|
||||||
+++ Preview
|
|
||||||
@@ -78,7 +78,7 @@
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
-yield "Cache key will cause errors if used with memcached: %r " "(longer than %s)" % (
|
|
||||||
+yield "Cache key will cause errors if used with memcached: %r (longer than %s)" % (
|
|
||||||
key,
|
|
||||||
MEMCACHE_MAX_KEY_LENGTH,
|
|
||||||
)
|
|
||||||
@@ -96,8 +96,7 @@
|
|
||||||
"Django to create, modify, and delete the table"
|
|
||||||
)
|
|
||||||
yield (
|
|
||||||
- "# Feel free to rename the models, but don't rename db_table values or "
|
|
||||||
- "field names."
|
|
||||||
+ "# Feel free to rename the models, but don't rename db_table values or field names."
|
|
||||||
)
|
|
||||||
|
|
||||||
yield (
|
|
||||||
@@ -109,8 +108,7 @@
|
|
||||||
"Django to create, modify, and delete the table"
|
|
||||||
)
|
|
||||||
yield (
|
|
||||||
- "# Feel free to rename the models, but don't rename db_table values or "
|
|
||||||
- "field names."
|
|
||||||
+ "# Feel free to rename the models, but don't rename db_table values or field names."
|
|
||||||
)
|
|
||||||
|
|
||||||
# Regression test for: https://github.com/astral-sh/ruff/issues/7420
|
|
||||||
```
|
|
||||||
|
|
|
@ -304,31 +304,43 @@ match x:
|
||||||
# Patterns that use BestFit should be parenthesized if they exceed the configured line width
|
# Patterns that use BestFit should be parenthesized if they exceed the configured line width
|
||||||
# but fit within parentheses.
|
# but fit within parentheses.
|
||||||
match x:
|
match x:
|
||||||
case "averyLongStringThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsPar":
|
case (
|
||||||
|
"averyLongStringThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsPar"
|
||||||
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
match x:
|
match x:
|
||||||
case b"averyLongStringThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsPa":
|
case (
|
||||||
|
b"averyLongStringThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsPa"
|
||||||
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
match x:
|
match x:
|
||||||
case f"averyLongStringThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsPa":
|
case (
|
||||||
|
f"averyLongStringThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsPa"
|
||||||
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
match x:
|
match x:
|
||||||
case 5444444444444444444444444444444444444444444444444444444444444444444444444444444j:
|
case (
|
||||||
|
5444444444444444444444444444444444444444444444444444444444444444444444444444444j
|
||||||
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
match x:
|
match x:
|
||||||
case 5444444444444444444444444444444444444444444444444444444444444444444444444444444:
|
case (
|
||||||
|
5444444444444444444444444444444444444444444444444444444444444444444444444444444
|
||||||
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
match x:
|
match x:
|
||||||
case 5.44444444444444444444444444444444444444444444444444444444444444444444444444444:
|
case (
|
||||||
|
5.44444444444444444444444444444444444444444444444444444444444444444444444444444
|
||||||
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -385,108 +397,89 @@ match x:
|
||||||
|
|
||||||
|
|
||||||
match x:
|
match x:
|
||||||
case "an implicit concatenated" "string literal" "in a match case" "that goes over multiple lines":
|
case (
|
||||||
|
"an implicit concatenated"
|
||||||
|
"string literal"
|
||||||
|
"in a match case"
|
||||||
|
"that goes over multiple lines"
|
||||||
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
## Patterns ending with a sequence, mapping, class, or parenthesized pattern should break the parenthesized-like pattern first
|
## Patterns ending with a sequence, mapping, class, or parenthesized pattern should break the parenthesized-like pattern first
|
||||||
match x:
|
match x:
|
||||||
case (
|
case A | [
|
||||||
A
|
aaaaaa,
|
||||||
| [
|
bbbbbbbbbbbbbbbb,
|
||||||
aaaaaa,
|
cccccccccccccccccc,
|
||||||
bbbbbbbbbbbbbbbb,
|
ddddddddddddddddddddddddddd,
|
||||||
cccccccccccccccccc,
|
]:
|
||||||
ddddddddddddddddddddddddddd,
|
|
||||||
]
|
|
||||||
):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
match x:
|
match x:
|
||||||
case (
|
case A | (
|
||||||
A
|
aaaaaa,
|
||||||
| (
|
bbbbbbbbbbbbbbbb,
|
||||||
aaaaaa,
|
cccccccccccccccccc,
|
||||||
bbbbbbbbbbbbbbbb,
|
ddddddddddddddddddddddddddd,
|
||||||
cccccccccccccccccc,
|
|
||||||
ddddddddddddddddddddddddddd,
|
|
||||||
)
|
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
match x:
|
match x:
|
||||||
case (
|
case A | {
|
||||||
A
|
"a": aaaaaa,
|
||||||
| {
|
"b": bbbbbbbbbbbbbbbb,
|
||||||
"a": aaaaaa,
|
"c": cccccccccccccccccc,
|
||||||
"b": bbbbbbbbbbbbbbbb,
|
"d": ddddddddddddddddddddddddddd,
|
||||||
"c": cccccccccccccccccc,
|
}:
|
||||||
"d": ddddddddddddddddddddddddddd,
|
pass
|
||||||
}
|
|
||||||
|
|
||||||
|
match x:
|
||||||
|
case A | Class(
|
||||||
|
aaaaaa,
|
||||||
|
bbbbbbbbbbbbbbbb,
|
||||||
|
cccccccccccccccccc,
|
||||||
|
ddddddddddddddddddddddddddd,
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
match x:
|
match x:
|
||||||
case (
|
case A | (
|
||||||
A
|
aaaaaaaaaaaaaaaaaaa.bbbbbbbbbbbbbbbbbbbbbbb.cccccccccccccccccccccccccccc.ddddddddddddddddddddddd
|
||||||
| Class(
|
|
||||||
aaaaaa,
|
|
||||||
bbbbbbbbbbbbbbbb,
|
|
||||||
cccccccccccccccccc,
|
|
||||||
ddddddddddddddddddddddddddd,
|
|
||||||
)
|
|
||||||
):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
match x:
|
|
||||||
case (
|
|
||||||
A
|
|
||||||
| (
|
|
||||||
aaaaaaaaaaaaaaaaaaa.bbbbbbbbbbbbbbbbbbbbbbb.cccccccccccccccccccccccccccc.ddddddddddddddddddddddd
|
|
||||||
)
|
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
## Patterns starting with a sequence, mapping, class, or parenthesized pattern should break the parenthesized-like pattern first
|
## Patterns starting with a sequence, mapping, class, or parenthesized pattern should break the parenthesized-like pattern first
|
||||||
match x:
|
match x:
|
||||||
case (
|
case [
|
||||||
[
|
aaaaaa,
|
||||||
aaaaaa,
|
bbbbbbbbbbbbbbbb,
|
||||||
bbbbbbbbbbbbbbbb,
|
cccccccccccccccccc,
|
||||||
cccccccccccccccccc,
|
ddddddddddddddddddddddddddd,
|
||||||
ddddddddddddddddddddddddddd,
|
] | A:
|
||||||
]
|
|
||||||
| A
|
|
||||||
):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
match x:
|
match x:
|
||||||
case (
|
case (
|
||||||
(
|
aaaaaa,
|
||||||
aaaaaa,
|
bbbbbbbbbbbbbbbb,
|
||||||
bbbbbbbbbbbbbbbb,
|
cccccccccccccccccc,
|
||||||
cccccccccccccccccc,
|
ddddddddddddddddddddddddddd,
|
||||||
ddddddddddddddddddddddddddd,
|
) | A:
|
||||||
)
|
|
||||||
| A
|
|
||||||
):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
match x:
|
match x:
|
||||||
case (
|
case {
|
||||||
{
|
"a": aaaaaa,
|
||||||
"a": aaaaaa,
|
"b": bbbbbbbbbbbbbbbb,
|
||||||
"b": bbbbbbbbbbbbbbbb,
|
"c": cccccccccccccccccc,
|
||||||
"c": cccccccccccccccccc,
|
"d": ddddddddddddddddddddddddddd,
|
||||||
"d": ddddddddddddddddddddddddddd,
|
} | A:
|
||||||
}
|
|
||||||
| A
|
|
||||||
):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -503,8 +496,7 @@ match x:
|
||||||
## Not for non-parenthesized sequence patterns
|
## Not for non-parenthesized sequence patterns
|
||||||
match x:
|
match x:
|
||||||
case (
|
case (
|
||||||
(1)
|
(1) | aaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
||||||
| aaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
|
||||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
||||||
ccccccccccccccccccccccccccccccccc,
|
ccccccccccccccccccccccccccccccccc,
|
||||||
):
|
):
|
||||||
|
@ -523,448 +515,81 @@ match x:
|
||||||
|
|
||||||
## Always use parentheses for implicitly concatenated strings
|
## Always use parentheses for implicitly concatenated strings
|
||||||
match x:
|
match x:
|
||||||
case (
|
case "implicitconcatenatedstring" | [
|
||||||
"implicit" "concatenated" "string"
|
aaaaaa,
|
||||||
| [aaaaaa, bbbbbbbbbbbbbbbb, cccccccccccccccccc, ddddddddddddddddddddddddddd]
|
bbbbbbbbbbbbbbbb,
|
||||||
):
|
cccccccccccccccccc,
|
||||||
|
ddddddddddddddddddddddddddd,
|
||||||
|
]:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
match x:
|
match x:
|
||||||
case (
|
case b"implicitconcatenatedstring" | [
|
||||||
b"implicit" b"concatenated" b"string"
|
aaaaaa,
|
||||||
| [aaaaaa, bbbbbbbbbbbbbbbb, cccccccccccccccccc, ddddddddddddddddddddddddddd]
|
bbbbbbbbbbbbbbbb,
|
||||||
):
|
cccccccccccccccccc,
|
||||||
|
ddddddddddddddddddddddddddd,
|
||||||
|
]:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
match x:
|
match x:
|
||||||
case (
|
case f"implicitconcatenatedstring" | [
|
||||||
f"implicit" "concatenated" "string"
|
aaaaaa,
|
||||||
| [aaaaaa, bbbbbbbbbbbbbbbb, cccccccccccccccccc, ddddddddddddddddddddddddddd]
|
bbbbbbbbbbbbbbbb,
|
||||||
):
|
cccccccccccccccccc,
|
||||||
|
ddddddddddddddddddddddddddd,
|
||||||
|
]:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
## Complex number expressions and unary expressions
|
## Complex number expressions and unary expressions
|
||||||
|
|
||||||
match x:
|
match x:
|
||||||
case (
|
case 4 - 3j | [
|
||||||
4 - 3j
|
aaaaaaaaaaaaaaaaaaaaaaaa,
|
||||||
| [
|
bbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
||||||
aaaaaaaaaaaaaaaaaaaaaaaa,
|
cccccccccccccccccccccccccccccccccccccccc,
|
||||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
]:
|
||||||
cccccccccccccccccccccccccccccccccccccccc,
|
|
||||||
]
|
|
||||||
):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
match x:
|
match x:
|
||||||
case (
|
case 4 + 3j | [
|
||||||
4 + 3j
|
aaaaaaaaaaaaaaaaaaaaaaaa,
|
||||||
| [
|
bbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
||||||
aaaaaaaaaaaaaaaaaaaaaaaa,
|
cccccccccccccccccccccccccccccccccccccccc,
|
||||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
]:
|
||||||
cccccccccccccccccccccccccccccccccccccccc,
|
|
||||||
]
|
|
||||||
):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
match x:
|
match x:
|
||||||
case (
|
case -1 | [
|
||||||
-1
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
||||||
| [
|
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
||||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
ccccccccccccccccccccccccccccccccc,
|
||||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
]:
|
||||||
ccccccccccccccccccccccccccccccccc,
|
|
||||||
]
|
|
||||||
):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
### Parenthesized patterns
|
### Parenthesized patterns
|
||||||
match x:
|
match x:
|
||||||
case (
|
case (1) | [
|
||||||
(1)
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
||||||
| [
|
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
||||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
ccccccccccccccccccccccccccccccccc,
|
||||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
]:
|
||||||
ccccccccccccccccccccccccccccccccc,
|
|
||||||
]
|
|
||||||
):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
match x:
|
match x:
|
||||||
case (
|
case ( # comment
|
||||||
( # comment
|
1
|
||||||
1
|
) | [
|
||||||
)
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
||||||
| [
|
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
||||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
ccccccccccccccccccccccccccccccccc,
|
||||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
]:
|
||||||
ccccccccccccccccccccccccccccccccc,
|
|
||||||
]
|
|
||||||
):
|
|
||||||
pass
|
pass
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Preview changes
|
|
||||||
```diff
|
|
||||||
--- Stable
|
|
||||||
+++ Preview
|
|
||||||
@@ -1,31 +1,43 @@
|
|
||||||
# Patterns that use BestFit should be parenthesized if they exceed the configured line width
|
|
||||||
# but fit within parentheses.
|
|
||||||
match x:
|
|
||||||
- case "averyLongStringThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsPar":
|
|
||||||
+ case (
|
|
||||||
+ "averyLongStringThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsPar"
|
|
||||||
+ ):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
match x:
|
|
||||||
- case b"averyLongStringThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsPa":
|
|
||||||
+ case (
|
|
||||||
+ b"averyLongStringThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsPa"
|
|
||||||
+ ):
|
|
||||||
pass
|
|
||||||
|
|
||||||
match x:
|
|
||||||
- case f"averyLongStringThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsPa":
|
|
||||||
+ case (
|
|
||||||
+ f"averyLongStringThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsPa"
|
|
||||||
+ ):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
match x:
|
|
||||||
- case 5444444444444444444444444444444444444444444444444444444444444444444444444444444j:
|
|
||||||
+ case (
|
|
||||||
+ 5444444444444444444444444444444444444444444444444444444444444444444444444444444j
|
|
||||||
+ ):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
match x:
|
|
||||||
- case 5444444444444444444444444444444444444444444444444444444444444444444444444444444:
|
|
||||||
+ case (
|
|
||||||
+ 5444444444444444444444444444444444444444444444444444444444444444444444444444444
|
|
||||||
+ ):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
match x:
|
|
||||||
- case 5.44444444444444444444444444444444444444444444444444444444444444444444444444444:
|
|
||||||
+ case (
|
|
||||||
+ 5.44444444444444444444444444444444444444444444444444444444444444444444444444444
|
|
||||||
+ ):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@@ -82,108 +94,89 @@
|
|
||||||
|
|
||||||
|
|
||||||
match x:
|
|
||||||
- case "an implicit concatenated" "string literal" "in a match case" "that goes over multiple lines":
|
|
||||||
+ case (
|
|
||||||
+ "an implicit concatenated"
|
|
||||||
+ "string literal"
|
|
||||||
+ "in a match case"
|
|
||||||
+ "that goes over multiple lines"
|
|
||||||
+ ):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
## Patterns ending with a sequence, mapping, class, or parenthesized pattern should break the parenthesized-like pattern first
|
|
||||||
match x:
|
|
||||||
- case (
|
|
||||||
- A
|
|
||||||
- | [
|
|
||||||
- aaaaaa,
|
|
||||||
- bbbbbbbbbbbbbbbb,
|
|
||||||
- cccccccccccccccccc,
|
|
||||||
- ddddddddddddddddddddddddddd,
|
|
||||||
- ]
|
|
||||||
- ):
|
|
||||||
+ case A | [
|
|
||||||
+ aaaaaa,
|
|
||||||
+ bbbbbbbbbbbbbbbb,
|
|
||||||
+ cccccccccccccccccc,
|
|
||||||
+ ddddddddddddddddddddddddddd,
|
|
||||||
+ ]:
|
|
||||||
pass
|
|
||||||
|
|
||||||
match x:
|
|
||||||
- case (
|
|
||||||
- A
|
|
||||||
- | (
|
|
||||||
- aaaaaa,
|
|
||||||
- bbbbbbbbbbbbbbbb,
|
|
||||||
- cccccccccccccccccc,
|
|
||||||
- ddddddddddddddddddddddddddd,
|
|
||||||
- )
|
|
||||||
+ case A | (
|
|
||||||
+ aaaaaa,
|
|
||||||
+ bbbbbbbbbbbbbbbb,
|
|
||||||
+ cccccccccccccccccc,
|
|
||||||
+ ddddddddddddddddddddddddddd,
|
|
||||||
):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
match x:
|
|
||||||
- case (
|
|
||||||
- A
|
|
||||||
- | {
|
|
||||||
- "a": aaaaaa,
|
|
||||||
- "b": bbbbbbbbbbbbbbbb,
|
|
||||||
- "c": cccccccccccccccccc,
|
|
||||||
- "d": ddddddddddddddddddddddddddd,
|
|
||||||
- }
|
|
||||||
- ):
|
|
||||||
+ case A | {
|
|
||||||
+ "a": aaaaaa,
|
|
||||||
+ "b": bbbbbbbbbbbbbbbb,
|
|
||||||
+ "c": cccccccccccccccccc,
|
|
||||||
+ "d": ddddddddddddddddddddddddddd,
|
|
||||||
+ }:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
match x:
|
|
||||||
- case (
|
|
||||||
- A
|
|
||||||
- | Class(
|
|
||||||
- aaaaaa,
|
|
||||||
- bbbbbbbbbbbbbbbb,
|
|
||||||
- cccccccccccccccccc,
|
|
||||||
- ddddddddddddddddddddddddddd,
|
|
||||||
- )
|
|
||||||
+ case A | Class(
|
|
||||||
+ aaaaaa,
|
|
||||||
+ bbbbbbbbbbbbbbbb,
|
|
||||||
+ cccccccccccccccccc,
|
|
||||||
+ ddddddddddddddddddddddddddd,
|
|
||||||
):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
match x:
|
|
||||||
- case (
|
|
||||||
- A
|
|
||||||
- | (
|
|
||||||
- aaaaaaaaaaaaaaaaaaa.bbbbbbbbbbbbbbbbbbbbbbb.cccccccccccccccccccccccccccc.ddddddddddddddddddddddd
|
|
||||||
- )
|
|
||||||
+ case A | (
|
|
||||||
+ aaaaaaaaaaaaaaaaaaa.bbbbbbbbbbbbbbbbbbbbbbb.cccccccccccccccccccccccccccc.ddddddddddddddddddddddd
|
|
||||||
):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
## Patterns starting with a sequence, mapping, class, or parenthesized pattern should break the parenthesized-like pattern first
|
|
||||||
match x:
|
|
||||||
- case (
|
|
||||||
- [
|
|
||||||
- aaaaaa,
|
|
||||||
- bbbbbbbbbbbbbbbb,
|
|
||||||
- cccccccccccccccccc,
|
|
||||||
- ddddddddddddddddddddddddddd,
|
|
||||||
- ]
|
|
||||||
- | A
|
|
||||||
- ):
|
|
||||||
+ case [
|
|
||||||
+ aaaaaa,
|
|
||||||
+ bbbbbbbbbbbbbbbb,
|
|
||||||
+ cccccccccccccccccc,
|
|
||||||
+ ddddddddddddddddddddddddddd,
|
|
||||||
+ ] | A:
|
|
||||||
pass
|
|
||||||
|
|
||||||
match x:
|
|
||||||
case (
|
|
||||||
- (
|
|
||||||
- aaaaaa,
|
|
||||||
- bbbbbbbbbbbbbbbb,
|
|
||||||
- cccccccccccccccccc,
|
|
||||||
- ddddddddddddddddddddddddddd,
|
|
||||||
- )
|
|
||||||
- | A
|
|
||||||
- ):
|
|
||||||
+ aaaaaa,
|
|
||||||
+ bbbbbbbbbbbbbbbb,
|
|
||||||
+ cccccccccccccccccc,
|
|
||||||
+ ddddddddddddddddddddddddddd,
|
|
||||||
+ ) | A:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
match x:
|
|
||||||
- case (
|
|
||||||
- {
|
|
||||||
- "a": aaaaaa,
|
|
||||||
- "b": bbbbbbbbbbbbbbbb,
|
|
||||||
- "c": cccccccccccccccccc,
|
|
||||||
- "d": ddddddddddddddddddddddddddd,
|
|
||||||
- }
|
|
||||||
- | A
|
|
||||||
- ):
|
|
||||||
+ case {
|
|
||||||
+ "a": aaaaaa,
|
|
||||||
+ "b": bbbbbbbbbbbbbbbb,
|
|
||||||
+ "c": cccccccccccccccccc,
|
|
||||||
+ "d": ddddddddddddddddddddddddddd,
|
|
||||||
+ } | A:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@@ -200,8 +193,7 @@
|
|
||||||
## Not for non-parenthesized sequence patterns
|
|
||||||
match x:
|
|
||||||
case (
|
|
||||||
- (1)
|
|
||||||
- | aaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
|
||||||
+ (1) | aaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
|
||||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
|
||||||
ccccccccccccccccccccccccccccccccc,
|
|
||||||
):
|
|
||||||
@@ -220,89 +212,80 @@
|
|
||||||
|
|
||||||
## Always use parentheses for implicitly concatenated strings
|
|
||||||
match x:
|
|
||||||
- case (
|
|
||||||
- "implicit" "concatenated" "string"
|
|
||||||
- | [aaaaaa, bbbbbbbbbbbbbbbb, cccccccccccccccccc, ddddddddddddddddddddddddddd]
|
|
||||||
- ):
|
|
||||||
+ case "implicitconcatenatedstring" | [
|
|
||||||
+ aaaaaa,
|
|
||||||
+ bbbbbbbbbbbbbbbb,
|
|
||||||
+ cccccccccccccccccc,
|
|
||||||
+ ddddddddddddddddddddddddddd,
|
|
||||||
+ ]:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
match x:
|
|
||||||
- case (
|
|
||||||
- b"implicit" b"concatenated" b"string"
|
|
||||||
- | [aaaaaa, bbbbbbbbbbbbbbbb, cccccccccccccccccc, ddddddddddddddddddddddddddd]
|
|
||||||
- ):
|
|
||||||
+ case b"implicitconcatenatedstring" | [
|
|
||||||
+ aaaaaa,
|
|
||||||
+ bbbbbbbbbbbbbbbb,
|
|
||||||
+ cccccccccccccccccc,
|
|
||||||
+ ddddddddddddddddddddddddddd,
|
|
||||||
+ ]:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
match x:
|
|
||||||
- case (
|
|
||||||
- f"implicit" "concatenated" "string"
|
|
||||||
- | [aaaaaa, bbbbbbbbbbbbbbbb, cccccccccccccccccc, ddddddddddddddddddddddddddd]
|
|
||||||
- ):
|
|
||||||
+ case f"implicitconcatenatedstring" | [
|
|
||||||
+ aaaaaa,
|
|
||||||
+ bbbbbbbbbbbbbbbb,
|
|
||||||
+ cccccccccccccccccc,
|
|
||||||
+ ddddddddddddddddddddddddddd,
|
|
||||||
+ ]:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
## Complex number expressions and unary expressions
|
|
||||||
|
|
||||||
match x:
|
|
||||||
- case (
|
|
||||||
- 4 - 3j
|
|
||||||
- | [
|
|
||||||
- aaaaaaaaaaaaaaaaaaaaaaaa,
|
|
||||||
- bbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
|
||||||
- cccccccccccccccccccccccccccccccccccccccc,
|
|
||||||
- ]
|
|
||||||
- ):
|
|
||||||
+ case 4 - 3j | [
|
|
||||||
+ aaaaaaaaaaaaaaaaaaaaaaaa,
|
|
||||||
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
|
||||||
+ cccccccccccccccccccccccccccccccccccccccc,
|
|
||||||
+ ]:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
match x:
|
|
||||||
- case (
|
|
||||||
- 4 + 3j
|
|
||||||
- | [
|
|
||||||
- aaaaaaaaaaaaaaaaaaaaaaaa,
|
|
||||||
- bbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
|
||||||
- cccccccccccccccccccccccccccccccccccccccc,
|
|
||||||
- ]
|
|
||||||
- ):
|
|
||||||
+ case 4 + 3j | [
|
|
||||||
+ aaaaaaaaaaaaaaaaaaaaaaaa,
|
|
||||||
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
|
||||||
+ cccccccccccccccccccccccccccccccccccccccc,
|
|
||||||
+ ]:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
match x:
|
|
||||||
- case (
|
|
||||||
- -1
|
|
||||||
- | [
|
|
||||||
- aaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
|
||||||
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
|
||||||
- ccccccccccccccccccccccccccccccccc,
|
|
||||||
- ]
|
|
||||||
- ):
|
|
||||||
+ case -1 | [
|
|
||||||
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
|
||||||
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
|
||||||
+ ccccccccccccccccccccccccccccccccc,
|
|
||||||
+ ]:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
### Parenthesized patterns
|
|
||||||
match x:
|
|
||||||
- case (
|
|
||||||
- (1)
|
|
||||||
- | [
|
|
||||||
- aaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
|
||||||
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
|
||||||
- ccccccccccccccccccccccccccccccccc,
|
|
||||||
- ]
|
|
||||||
- ):
|
|
||||||
+ case (1) | [
|
|
||||||
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
|
||||||
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
|
||||||
+ ccccccccccccccccccccccccccccccccc,
|
|
||||||
+ ]:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
match x:
|
|
||||||
- case (
|
|
||||||
- ( # comment
|
|
||||||
- 1
|
|
||||||
- )
|
|
||||||
- | [
|
|
||||||
- aaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
|
||||||
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
|
||||||
- ccccccccccccccccccccccccccccccccc,
|
|
||||||
- ]
|
|
||||||
- ):
|
|
||||||
+ case ( # comment
|
|
||||||
+ 1
|
|
||||||
+ ) | [
|
|
||||||
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
|
||||||
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
|
||||||
+ ccccccccccccccccccccccccccccccccc,
|
|
||||||
+ ]:
|
|
||||||
pass
|
|
||||||
```
|
|
||||||
|
|
|
@ -109,10 +109,10 @@ rb"""rb double triple"""
|
||||||
rb"""br single triple"""
|
rb"""br single triple"""
|
||||||
rb"""br double triple"""
|
rb"""br double triple"""
|
||||||
|
|
||||||
'single1' 'single2'
|
'single1single2'
|
||||||
'single1' 'double2'
|
'single1double2'
|
||||||
'double1' 'single2'
|
'double1single2'
|
||||||
'double1' 'double2'
|
'double1double2'
|
||||||
|
|
||||||
|
|
||||||
def docstring_single_triple():
|
def docstring_single_triple():
|
||||||
|
@ -132,28 +132,6 @@ def docstring_single():
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
#### Preview changes
|
|
||||||
```diff
|
|
||||||
--- Stable
|
|
||||||
+++ Preview
|
|
||||||
@@ -33,10 +33,10 @@
|
|
||||||
rb"""br single triple"""
|
|
||||||
rb"""br double triple"""
|
|
||||||
|
|
||||||
-'single1' 'single2'
|
|
||||||
-'single1' 'double2'
|
|
||||||
-'double1' 'single2'
|
|
||||||
-'double1' 'double2'
|
|
||||||
+'single1single2'
|
|
||||||
+'single1double2'
|
|
||||||
+'double1single2'
|
|
||||||
+'double1double2'
|
|
||||||
|
|
||||||
|
|
||||||
def docstring_single_triple():
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Output 2
|
### Output 2
|
||||||
```
|
```
|
||||||
indent-style = space
|
indent-style = space
|
||||||
|
@ -205,10 +183,10 @@ rb"""rb double triple"""
|
||||||
rb"""br single triple"""
|
rb"""br single triple"""
|
||||||
rb"""br double triple"""
|
rb"""br double triple"""
|
||||||
|
|
||||||
"single1" "single2"
|
"single1single2"
|
||||||
"single1" "double2"
|
"single1double2"
|
||||||
"double1" "single2"
|
"double1single2"
|
||||||
"double1" "double2"
|
"double1double2"
|
||||||
|
|
||||||
|
|
||||||
def docstring_single_triple():
|
def docstring_single_triple():
|
||||||
|
@ -228,28 +206,6 @@ def docstring_single():
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
#### Preview changes
|
|
||||||
```diff
|
|
||||||
--- Stable
|
|
||||||
+++ Preview
|
|
||||||
@@ -33,10 +33,10 @@
|
|
||||||
rb"""br single triple"""
|
|
||||||
rb"""br double triple"""
|
|
||||||
|
|
||||||
-"single1" "single2"
|
|
||||||
-"single1" "double2"
|
|
||||||
-"double1" "single2"
|
|
||||||
-"double1" "double2"
|
|
||||||
+"single1single2"
|
|
||||||
+"single1double2"
|
|
||||||
+"double1single2"
|
|
||||||
+"double1double2"
|
|
||||||
|
|
||||||
|
|
||||||
def docstring_single_triple():
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Output 3
|
### Output 3
|
||||||
```
|
```
|
||||||
indent-style = space
|
indent-style = space
|
||||||
|
@ -301,10 +257,10 @@ rb"""rb double triple"""
|
||||||
rb'''br single triple'''
|
rb'''br single triple'''
|
||||||
rb"""br double triple"""
|
rb"""br double triple"""
|
||||||
|
|
||||||
'single1' 'single2'
|
'single1single2'
|
||||||
'single1' "double2"
|
'single1double2'
|
||||||
"double1" 'single2'
|
"double1single2"
|
||||||
"double1" "double2"
|
"double1double2"
|
||||||
|
|
||||||
|
|
||||||
def docstring_single_triple():
|
def docstring_single_triple():
|
||||||
|
@ -322,25 +278,3 @@ def docstring_double():
|
||||||
def docstring_single():
|
def docstring_single():
|
||||||
'single'
|
'single'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
#### Preview changes
|
|
||||||
```diff
|
|
||||||
--- Stable
|
|
||||||
+++ Preview
|
|
||||||
@@ -33,10 +33,10 @@
|
|
||||||
rb'''br single triple'''
|
|
||||||
rb"""br double triple"""
|
|
||||||
|
|
||||||
-'single1' 'single2'
|
|
||||||
-'single1' "double2"
|
|
||||||
-"double1" 'single2'
|
|
||||||
-"double1" "double2"
|
|
||||||
+'single1single2'
|
|
||||||
+'single1double2'
|
|
||||||
+"double1single2"
|
|
||||||
+"double1double2"
|
|
||||||
|
|
||||||
|
|
||||||
def docstring_single_triple():
|
|
||||||
```
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
---
|
---
|
||||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/range_formatting/stub.pyi
|
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/range_formatting/stub.pyi
|
||||||
snapshot_kind: text
|
|
||||||
---
|
---
|
||||||
## Input
|
## Input
|
||||||
```python
|
```python
|
||||||
|
@ -34,7 +33,7 @@ line-ending = LineFeed
|
||||||
magic-trailing-comma = Respect
|
magic-trailing-comma = Respect
|
||||||
docstring-code = Disabled
|
docstring-code = Disabled
|
||||||
docstring-code-line-width = "dynamic"
|
docstring-code-line-width = "dynamic"
|
||||||
preview = Enabled
|
preview = Disabled
|
||||||
target_version = Py39
|
target_version = Py39
|
||||||
source_type = Stub
|
source_type = Stub
|
||||||
```
|
```
|
||||||
|
|
|
@ -212,50 +212,47 @@ assert (
|
||||||
|
|
||||||
|
|
||||||
def test():
|
def test():
|
||||||
assert (
|
assert {
|
||||||
{
|
key1: value1,
|
||||||
key1: value1,
|
key2: value2,
|
||||||
key2: value2,
|
key3: value3,
|
||||||
key3: value3,
|
key4: value4,
|
||||||
key4: value4,
|
key5: value5,
|
||||||
key5: value5,
|
key6: value6,
|
||||||
key6: value6,
|
key7: value7,
|
||||||
key7: value7,
|
key8: value8,
|
||||||
key8: value8,
|
key9: value9,
|
||||||
key9: value9,
|
} == expected, (
|
||||||
}
|
"Not what we expected and the message is too long to fit ineeeeee one line"
|
||||||
== expected
|
)
|
||||||
), "Not what we expected and the message is too long to fit ineeeeee one line"
|
|
||||||
|
|
||||||
assert (
|
assert {
|
||||||
{
|
key1: value1,
|
||||||
key1: value1,
|
key2: value2,
|
||||||
key2: value2,
|
key3: value3,
|
||||||
key3: value3,
|
key4: value4,
|
||||||
key4: value4,
|
key5: value5,
|
||||||
key5: value5,
|
key6: value6,
|
||||||
key6: value6,
|
key7: value7,
|
||||||
key7: value7,
|
key8: value8,
|
||||||
key8: value8,
|
key9: value9,
|
||||||
key9: value9,
|
} == expected, (
|
||||||
}
|
"Not what we expected and the message is too long to fit in one lineeeee"
|
||||||
== expected
|
)
|
||||||
), "Not what we expected and the message is too long to fit in one lineeeee"
|
|
||||||
|
|
||||||
assert (
|
assert {
|
||||||
{
|
key1: value1,
|
||||||
key1: value1,
|
key2: value2,
|
||||||
key2: value2,
|
key3: value3,
|
||||||
key3: value3,
|
key4: value4,
|
||||||
key4: value4,
|
key5: value5,
|
||||||
key5: value5,
|
key6: value6,
|
||||||
key6: value6,
|
key7: value7,
|
||||||
key7: value7,
|
key8: value8,
|
||||||
key8: value8,
|
key9: value9,
|
||||||
key9: value9,
|
} == expected, (
|
||||||
}
|
"Not what we expected and the message is too long to fit in one lineeeeeeeeeeeee"
|
||||||
== expected
|
)
|
||||||
), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeee"
|
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
{
|
{
|
||||||
|
@ -285,7 +282,9 @@ def test():
|
||||||
key9: value9,
|
key9: value9,
|
||||||
}
|
}
|
||||||
== expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
|
== expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
|
||||||
), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeeeee"
|
), (
|
||||||
|
"Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeeeee"
|
||||||
|
)
|
||||||
|
|
||||||
assert expected == {
|
assert expected == {
|
||||||
key1: value1,
|
key1: value1,
|
||||||
|
@ -299,20 +298,19 @@ def test():
|
||||||
key9: value9,
|
key9: value9,
|
||||||
}, "Not what we expected and the message is too long to fit ineeeeee one line"
|
}, "Not what we expected and the message is too long to fit ineeeeee one line"
|
||||||
|
|
||||||
assert (
|
assert expected == {
|
||||||
expected
|
key1: value1,
|
||||||
== {
|
key2: value2,
|
||||||
key1: value1,
|
key3: value3,
|
||||||
key2: value2,
|
key4: value4,
|
||||||
key3: value3,
|
key5: value5,
|
||||||
key4: value4,
|
key6: value6,
|
||||||
key5: value5,
|
key7: value7,
|
||||||
key6: value6,
|
key8: value8,
|
||||||
key7: value7,
|
key9: value9,
|
||||||
key8: value8,
|
}, (
|
||||||
key9: value9,
|
"Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeeeeeeee"
|
||||||
}
|
)
|
||||||
), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeeeeeeee"
|
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
|
expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
|
||||||
|
@ -342,7 +340,9 @@ def test():
|
||||||
key8: value8,
|
key8: value8,
|
||||||
key9: value9,
|
key9: value9,
|
||||||
}
|
}
|
||||||
), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeee"
|
), (
|
||||||
|
"Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeee"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Test for https://github.com/astral-sh/ruff/issues/7246
|
# Test for https://github.com/astral-sh/ruff/issues/7246
|
||||||
|
@ -361,156 +361,3 @@ assert package.files == [
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Preview changes
|
|
||||||
```diff
|
|
||||||
--- Stable
|
|
||||||
+++ Preview
|
|
||||||
@@ -30,50 +30,47 @@
|
|
||||||
|
|
||||||
|
|
||||||
def test():
|
|
||||||
- assert (
|
|
||||||
- {
|
|
||||||
- key1: value1,
|
|
||||||
- key2: value2,
|
|
||||||
- key3: value3,
|
|
||||||
- key4: value4,
|
|
||||||
- key5: value5,
|
|
||||||
- key6: value6,
|
|
||||||
- key7: value7,
|
|
||||||
- key8: value8,
|
|
||||||
- key9: value9,
|
|
||||||
- }
|
|
||||||
- == expected
|
|
||||||
- ), "Not what we expected and the message is too long to fit ineeeeee one line"
|
|
||||||
+ assert {
|
|
||||||
+ key1: value1,
|
|
||||||
+ key2: value2,
|
|
||||||
+ key3: value3,
|
|
||||||
+ key4: value4,
|
|
||||||
+ key5: value5,
|
|
||||||
+ key6: value6,
|
|
||||||
+ key7: value7,
|
|
||||||
+ key8: value8,
|
|
||||||
+ key9: value9,
|
|
||||||
+ } == expected, (
|
|
||||||
+ "Not what we expected and the message is too long to fit ineeeeee one line"
|
|
||||||
+ )
|
|
||||||
|
|
||||||
- assert (
|
|
||||||
- {
|
|
||||||
- key1: value1,
|
|
||||||
- key2: value2,
|
|
||||||
- key3: value3,
|
|
||||||
- key4: value4,
|
|
||||||
- key5: value5,
|
|
||||||
- key6: value6,
|
|
||||||
- key7: value7,
|
|
||||||
- key8: value8,
|
|
||||||
- key9: value9,
|
|
||||||
- }
|
|
||||||
- == expected
|
|
||||||
- ), "Not what we expected and the message is too long to fit in one lineeeee"
|
|
||||||
+ assert {
|
|
||||||
+ key1: value1,
|
|
||||||
+ key2: value2,
|
|
||||||
+ key3: value3,
|
|
||||||
+ key4: value4,
|
|
||||||
+ key5: value5,
|
|
||||||
+ key6: value6,
|
|
||||||
+ key7: value7,
|
|
||||||
+ key8: value8,
|
|
||||||
+ key9: value9,
|
|
||||||
+ } == expected, (
|
|
||||||
+ "Not what we expected and the message is too long to fit in one lineeeee"
|
|
||||||
+ )
|
|
||||||
|
|
||||||
- assert (
|
|
||||||
- {
|
|
||||||
- key1: value1,
|
|
||||||
- key2: value2,
|
|
||||||
- key3: value3,
|
|
||||||
- key4: value4,
|
|
||||||
- key5: value5,
|
|
||||||
- key6: value6,
|
|
||||||
- key7: value7,
|
|
||||||
- key8: value8,
|
|
||||||
- key9: value9,
|
|
||||||
- }
|
|
||||||
- == expected
|
|
||||||
- ), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeee"
|
|
||||||
+ assert {
|
|
||||||
+ key1: value1,
|
|
||||||
+ key2: value2,
|
|
||||||
+ key3: value3,
|
|
||||||
+ key4: value4,
|
|
||||||
+ key5: value5,
|
|
||||||
+ key6: value6,
|
|
||||||
+ key7: value7,
|
|
||||||
+ key8: value8,
|
|
||||||
+ key9: value9,
|
|
||||||
+ } == expected, (
|
|
||||||
+ "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeee"
|
|
||||||
+ )
|
|
||||||
|
|
||||||
assert (
|
|
||||||
{
|
|
||||||
@@ -103,7 +100,9 @@
|
|
||||||
key9: value9,
|
|
||||||
}
|
|
||||||
== expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
|
|
||||||
- ), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeeeee"
|
|
||||||
+ ), (
|
|
||||||
+ "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeeeee"
|
|
||||||
+ )
|
|
||||||
|
|
||||||
assert expected == {
|
|
||||||
key1: value1,
|
|
||||||
@@ -117,20 +116,19 @@
|
|
||||||
key9: value9,
|
|
||||||
}, "Not what we expected and the message is too long to fit ineeeeee one line"
|
|
||||||
|
|
||||||
- assert (
|
|
||||||
- expected
|
|
||||||
- == {
|
|
||||||
- key1: value1,
|
|
||||||
- key2: value2,
|
|
||||||
- key3: value3,
|
|
||||||
- key4: value4,
|
|
||||||
- key5: value5,
|
|
||||||
- key6: value6,
|
|
||||||
- key7: value7,
|
|
||||||
- key8: value8,
|
|
||||||
- key9: value9,
|
|
||||||
- }
|
|
||||||
- ), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeeeeeeee"
|
|
||||||
+ assert expected == {
|
|
||||||
+ key1: value1,
|
|
||||||
+ key2: value2,
|
|
||||||
+ key3: value3,
|
|
||||||
+ key4: value4,
|
|
||||||
+ key5: value5,
|
|
||||||
+ key6: value6,
|
|
||||||
+ key7: value7,
|
|
||||||
+ key8: value8,
|
|
||||||
+ key9: value9,
|
|
||||||
+ }, (
|
|
||||||
+ "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeeeeeeee"
|
|
||||||
+ )
|
|
||||||
|
|
||||||
assert (
|
|
||||||
expectedeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
|
|
||||||
@@ -160,7 +158,9 @@
|
|
||||||
key8: value8,
|
|
||||||
key9: value9,
|
|
||||||
}
|
|
||||||
- ), "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeee"
|
|
||||||
+ ), (
|
|
||||||
+ "Not what we expected and the message is too long to fit in one lineeeeeeeeeeeeeee"
|
|
||||||
+ )
|
|
||||||
|
|
||||||
|
|
||||||
# Test for https://github.com/astral-sh/ruff/issues/7246
|
|
||||||
```
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
---
|
---
|
||||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/assignment_split_value_first.py
|
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/assignment_split_value_first.py
|
||||||
snapshot_kind: text
|
|
||||||
---
|
---
|
||||||
## Input
|
## Input
|
||||||
```python
|
```python
|
||||||
|
@ -242,22 +241,7 @@ type A[VeryLongTypeNameThatShouldBreakFirstToTheRightBeforeSplitngtinthatExceeds
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Outputs
|
## Output
|
||||||
### Output 1
|
|
||||||
```
|
|
||||||
indent-style = space
|
|
||||||
line-width = 88
|
|
||||||
indent-width = 4
|
|
||||||
quote-style = Double
|
|
||||||
line-ending = LineFeed
|
|
||||||
magic-trailing-comma = Respect
|
|
||||||
docstring-code = Disabled
|
|
||||||
docstring-code-line-width = "dynamic"
|
|
||||||
preview = Enabled
|
|
||||||
target_version = Py39
|
|
||||||
source_type = Python
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
#######
|
#######
|
||||||
# Unsplittable target and value
|
# Unsplittable target and value
|
||||||
|
|
|
@ -695,7 +695,7 @@ match newlines:
|
||||||
case "case comment with newlines" if foo == 2: # second
|
case "case comment with newlines" if foo == 2: # second
|
||||||
pass
|
pass
|
||||||
|
|
||||||
case "one", "newline" if (foo := 1): # third
|
case "one", "newline" if foo := 1: # third
|
||||||
pass
|
pass
|
||||||
|
|
||||||
case "two newlines":
|
case "two newlines":
|
||||||
|
@ -708,7 +708,9 @@ match newlines:
|
||||||
|
|
||||||
|
|
||||||
match long_lines:
|
match long_lines:
|
||||||
case "this is a long line for if condition" if aaaaaaaaahhhhhhhh == 1 and bbbbbbaaaaaaaaaaa == 2: # comment
|
case "this is a long line for if condition" if (
|
||||||
|
aaaaaaaaahhhhhhhh == 1 and bbbbbbaaaaaaaaaaa == 2
|
||||||
|
): # comment
|
||||||
pass
|
pass
|
||||||
|
|
||||||
case "this is a long line for if condition with parentheses" if (
|
case "this is a long line for if condition with parentheses" if (
|
||||||
|
@ -719,7 +721,7 @@ match long_lines:
|
||||||
case "named expressions aren't special" if foo := 1:
|
case "named expressions aren't special" if foo := 1:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
case "named expressions aren't that special" if (foo := 1):
|
case "named expressions aren't that special" if foo := 1:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
case "but with already broken long lines" if (
|
case "but with already broken long lines" if (
|
||||||
|
@ -727,9 +729,9 @@ match long_lines:
|
||||||
): # another comment
|
): # another comment
|
||||||
pass
|
pass
|
||||||
|
|
||||||
case {
|
case {"long_long_long_key": str(long_long_long_key)} if (
|
||||||
"long_long_long_key": str(long_long_long_key)
|
value := "long long long long long long long long long long long value"
|
||||||
} if value := "long long long long long long long long long long long value":
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -824,7 +826,9 @@ match pattern_singleton:
|
||||||
# trailing own 2
|
# trailing own 2
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
case True: # trailing
|
case (
|
||||||
|
True # trailing
|
||||||
|
):
|
||||||
pass
|
pass
|
||||||
case False:
|
case False:
|
||||||
pass
|
pass
|
||||||
|
@ -875,7 +879,9 @@ match foo:
|
||||||
1
|
1
|
||||||
):
|
):
|
||||||
y = 1
|
y = 1
|
||||||
case 1: # comment
|
case (
|
||||||
|
1 # comment
|
||||||
|
):
|
||||||
y = 1
|
y = 1
|
||||||
case (
|
case (
|
||||||
1
|
1
|
||||||
|
@ -1133,11 +1139,8 @@ match pattern_match_or:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
case (
|
case (
|
||||||
(
|
a # trailing
|
||||||
a # trailing
|
) | (b):
|
||||||
)
|
|
||||||
| (b)
|
|
||||||
):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
case a | b | c:
|
case a | b | c:
|
||||||
|
@ -1151,8 +1154,7 @@ match pattern_match_or:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
case ( # end of line
|
case ( # end of line
|
||||||
a
|
a | b
|
||||||
| b
|
|
||||||
# own line
|
# own line
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
@ -1284,98 +1286,3 @@ match guard_comments:
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Preview changes
|
|
||||||
```diff
|
|
||||||
--- Stable
|
|
||||||
+++ Preview
|
|
||||||
@@ -69,7 +69,7 @@
|
|
||||||
case "case comment with newlines" if foo == 2: # second
|
|
||||||
pass
|
|
||||||
|
|
||||||
- case "one", "newline" if (foo := 1): # third
|
|
||||||
+ case "one", "newline" if foo := 1: # third
|
|
||||||
pass
|
|
||||||
|
|
||||||
case "two newlines":
|
|
||||||
@@ -82,7 +82,9 @@
|
|
||||||
|
|
||||||
|
|
||||||
match long_lines:
|
|
||||||
- case "this is a long line for if condition" if aaaaaaaaahhhhhhhh == 1 and bbbbbbaaaaaaaaaaa == 2: # comment
|
|
||||||
+ case "this is a long line for if condition" if (
|
|
||||||
+ aaaaaaaaahhhhhhhh == 1 and bbbbbbaaaaaaaaaaa == 2
|
|
||||||
+ ): # comment
|
|
||||||
pass
|
|
||||||
|
|
||||||
case "this is a long line for if condition with parentheses" if (
|
|
||||||
@@ -93,7 +95,7 @@
|
|
||||||
case "named expressions aren't special" if foo := 1:
|
|
||||||
pass
|
|
||||||
|
|
||||||
- case "named expressions aren't that special" if (foo := 1):
|
|
||||||
+ case "named expressions aren't that special" if foo := 1:
|
|
||||||
pass
|
|
||||||
|
|
||||||
case "but with already broken long lines" if (
|
|
||||||
@@ -101,9 +103,9 @@
|
|
||||||
): # another comment
|
|
||||||
pass
|
|
||||||
|
|
||||||
- case {
|
|
||||||
- "long_long_long_key": str(long_long_long_key)
|
|
||||||
- } if value := "long long long long long long long long long long long value":
|
|
||||||
+ case {"long_long_long_key": str(long_long_long_key)} if (
|
|
||||||
+ value := "long long long long long long long long long long long value"
|
|
||||||
+ ):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@@ -198,7 +200,9 @@
|
|
||||||
# trailing own 2
|
|
||||||
):
|
|
||||||
pass
|
|
||||||
- case True: # trailing
|
|
||||||
+ case (
|
|
||||||
+ True # trailing
|
|
||||||
+ ):
|
|
||||||
pass
|
|
||||||
case False:
|
|
||||||
pass
|
|
||||||
@@ -249,7 +253,9 @@
|
|
||||||
1
|
|
||||||
):
|
|
||||||
y = 1
|
|
||||||
- case 1: # comment
|
|
||||||
+ case (
|
|
||||||
+ 1 # comment
|
|
||||||
+ ):
|
|
||||||
y = 1
|
|
||||||
case (
|
|
||||||
1
|
|
||||||
@@ -507,11 +513,8 @@
|
|
||||||
pass
|
|
||||||
|
|
||||||
case (
|
|
||||||
- (
|
|
||||||
- a # trailing
|
|
||||||
- )
|
|
||||||
- | (b)
|
|
||||||
- ):
|
|
||||||
+ a # trailing
|
|
||||||
+ ) | (b):
|
|
||||||
pass
|
|
||||||
|
|
||||||
case a | b | c:
|
|
||||||
@@ -525,8 +528,7 @@
|
|
||||||
pass
|
|
||||||
|
|
||||||
case ( # end of line
|
|
||||||
- a
|
|
||||||
- | b
|
|
||||||
+ a | b
|
|
||||||
# own line
|
|
||||||
):
|
|
||||||
pass
|
|
||||||
```
|
|
||||||
|
|
|
@ -336,32 +336,24 @@ def f[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa](
|
||||||
|
|
||||||
# Breaking return type annotations. Black adds parentheses if the parameters are
|
# Breaking return type annotations. Black adds parentheses if the parameters are
|
||||||
# empty; otherwise, it leverages the expressions own parentheses if possible.
|
# empty; otherwise, it leverages the expressions own parentheses if possible.
|
||||||
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (
|
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set[
|
||||||
Set[
|
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
]: ...
|
||||||
]
|
|
||||||
): ...
|
|
||||||
|
|
||||||
|
|
||||||
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (
|
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set[
|
||||||
Set[
|
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
]: ...
|
||||||
]
|
|
||||||
): ...
|
|
||||||
|
|
||||||
|
|
||||||
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (
|
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set[
|
||||||
Set[
|
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
]: ...
|
||||||
]
|
|
||||||
): ...
|
|
||||||
|
|
||||||
|
|
||||||
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (
|
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set[
|
||||||
Set[
|
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
]: ...
|
||||||
]
|
|
||||||
): ...
|
|
||||||
|
|
||||||
|
|
||||||
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(
|
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(
|
||||||
|
@ -462,11 +454,8 @@ def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(
|
||||||
): ...
|
): ...
|
||||||
|
|
||||||
|
|
||||||
def double() -> (
|
def double() -> first_item and foo.bar.baz().bop(
|
||||||
first_item
|
1,
|
||||||
and foo.bar.baz().bop(
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
):
|
):
|
||||||
return 2 * a
|
return 2 * a
|
||||||
|
|
||||||
|
@ -520,69 +509,3 @@ def process_board_action(
|
||||||
) -> Optional[Tuple[str, str]]:
|
) -> Optional[Tuple[str, str]]:
|
||||||
pass
|
pass
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Preview changes
|
|
||||||
```diff
|
|
||||||
--- Stable
|
|
||||||
+++ Preview
|
|
||||||
@@ -131,32 +131,24 @@
|
|
||||||
|
|
||||||
# Breaking return type annotations. Black adds parentheses if the parameters are
|
|
||||||
# empty; otherwise, it leverages the expressions own parentheses if possible.
|
|
||||||
-def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (
|
|
||||||
- Set[
|
|
||||||
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
||||||
- ]
|
|
||||||
-): ...
|
|
||||||
+def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set[
|
|
||||||
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
||||||
+]: ...
|
|
||||||
|
|
||||||
|
|
||||||
-def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (
|
|
||||||
- Set[
|
|
||||||
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
||||||
- ]
|
|
||||||
-): ...
|
|
||||||
+def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set[
|
|
||||||
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
||||||
+]: ...
|
|
||||||
|
|
||||||
|
|
||||||
-def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (
|
|
||||||
- Set[
|
|
||||||
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
||||||
- ]
|
|
||||||
-): ...
|
|
||||||
+def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set[
|
|
||||||
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
||||||
+]: ...
|
|
||||||
|
|
||||||
|
|
||||||
-def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (
|
|
||||||
- Set[
|
|
||||||
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
||||||
- ]
|
|
||||||
-): ...
|
|
||||||
+def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set[
|
|
||||||
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
||||||
+]: ...
|
|
||||||
|
|
||||||
|
|
||||||
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(
|
|
||||||
@@ -257,11 +249,8 @@
|
|
||||||
): ...
|
|
||||||
|
|
||||||
|
|
||||||
-def double() -> (
|
|
||||||
- first_item
|
|
||||||
- and foo.bar.baz().bop(
|
|
||||||
- 1,
|
|
||||||
- )
|
|
||||||
+def double() -> first_item and foo.bar.baz().bop(
|
|
||||||
+ 1,
|
|
||||||
):
|
|
||||||
return 2 * a
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
|
@ -245,11 +245,9 @@ def test_return_union_with_elements_exceeding_length() -> (
|
||||||
#########################################################################################
|
#########################################################################################
|
||||||
|
|
||||||
|
|
||||||
def test_return_multiline_string_type_annotation() -> (
|
def test_return_multiline_string_type_annotation() -> """str
|
||||||
"""str
|
|
||||||
| list[str]
|
| list[str]
|
||||||
"""
|
""":
|
||||||
):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -267,12 +265,12 @@ def test_return_multiline_string_binary_expression_return_type_annotation() -> (
|
||||||
#########################################################################################
|
#########################################################################################
|
||||||
|
|
||||||
|
|
||||||
def test_implicit_concatenated_string_return_type() -> "str" "bbbbbbbbbbbbbbbb":
|
def test_implicit_concatenated_string_return_type() -> "strbbbbbbbbbbbbbbbb":
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def test_overlong_implicit_concatenated_string_return_type() -> (
|
def test_overlong_implicit_concatenated_string_return_type() -> (
|
||||||
"liiiiiiiiiiiisssssst[str]" "bbbbbbbbbbbbbbbb"
|
"liiiiiiiiiiiisssssst[str]bbbbbbbbbbbbbbbb"
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -295,9 +293,9 @@ def no_parameters_subscript_return_type() -> list[str]:
|
||||||
# 1. Black tries to keep the list flat by parenthesizing the list as shown below even when the `list` identifier
|
# 1. Black tries to keep the list flat by parenthesizing the list as shown below even when the `list` identifier
|
||||||
# fits on the header line. IMO, this adds unnecessary parentheses that can be avoided
|
# fits on the header line. IMO, this adds unnecessary parentheses that can be avoided
|
||||||
# and supporting it requires extra complexity (best_fitting! layout)
|
# and supporting it requires extra complexity (best_fitting! layout)
|
||||||
def no_parameters_overlong_subscript_return_type_with_single_element() -> (
|
def no_parameters_overlong_subscript_return_type_with_single_element() -> list[
|
||||||
list[xxxxxxxxxxxxxxxxxxxxx]
|
xxxxxxxxxxxxxxxxxxxxx
|
||||||
):
|
]:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -306,23 +304,18 @@ def no_parameters_overlong_subscript_return_type_with_single_element() -> (
|
||||||
# `list[`. It is also inconsistent with how subscripts are normally formatted where it first tries to fit the entire subscript,
|
# `list[`. It is also inconsistent with how subscripts are normally formatted where it first tries to fit the entire subscript,
|
||||||
# then splits after `list[` but keeps all elements on a single line, and finally, splits after each element.
|
# then splits after `list[` but keeps all elements on a single line, and finally, splits after each element.
|
||||||
# IMO: Splitting after the `list[` and trying to keep the elements together when possible seems more consistent.
|
# IMO: Splitting after the `list[` and trying to keep the elements together when possible seems more consistent.
|
||||||
def no_parameters_subscript_return_type_multiple_elements() -> (
|
def no_parameters_subscript_return_type_multiple_elements() -> list[
|
||||||
list[
|
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
|
]:
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
|
|
||||||
]
|
|
||||||
):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
# Black removes the parentheses even the elements exceed the configured line width.
|
# Black removes the parentheses even the elements exceed the configured line width.
|
||||||
# So does Ruff.
|
# So does Ruff.
|
||||||
def no_parameters_subscript_return_type_multiple_overlong_elements() -> (
|
def no_parameters_subscript_return_type_multiple_overlong_elements() -> list[
|
||||||
list[
|
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
|
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
|
]:
|
||||||
]
|
|
||||||
):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -341,11 +334,9 @@ def no_parameters_subscriptreturn_type_with_overlong_value_() -> (
|
||||||
# `no_parameters_subscript_return_type_multiple_overlong_elements` shows. However, it doesn't
|
# `no_parameters_subscript_return_type_multiple_overlong_elements` shows. However, it doesn't
|
||||||
# when the subscript contains a single element. Black then keeps the parentheses.
|
# when the subscript contains a single element. Black then keeps the parentheses.
|
||||||
# Ruff removes the parentheses in this case for consistency.
|
# Ruff removes the parentheses in this case for consistency.
|
||||||
def no_parameters_overlong_subscript_return_type_with_overlong_single_element() -> (
|
def no_parameters_overlong_subscript_return_type_with_overlong_single_element() -> list[
|
||||||
list[
|
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
]:
|
||||||
]
|
|
||||||
):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -354,13 +345,10 @@ def no_parameters_overlong_subscript_return_type_with_overlong_single_element()
|
||||||
#########################################################################################
|
#########################################################################################
|
||||||
|
|
||||||
|
|
||||||
def test_binary_expression_return_type_annotation() -> (
|
def test_binary_expression_return_type_annotation() -> aaaaaaaaaaaaaaaaaaaaaaaaaa > [
|
||||||
aaaaaaaaaaaaaaaaaaaaaaaaaa
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
||||||
> [
|
bbbbbbbbbbbbbbbbbbbbbbbbb,
|
||||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
]:
|
||||||
bbbbbbbbbbbbbbbbbbbbbbbbb,
|
|
||||||
]
|
|
||||||
):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -370,139 +358,9 @@ def test_binary_expression_return_type_annotation() -> (
|
||||||
|
|
||||||
|
|
||||||
# Don't paranthesize lists
|
# Don't paranthesize lists
|
||||||
def f() -> (
|
def f() -> [
|
||||||
[
|
a,
|
||||||
a,
|
b,
|
||||||
b,
|
]:
|
||||||
]
|
|
||||||
):
|
|
||||||
pass
|
pass
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Preview changes
|
|
||||||
```diff
|
|
||||||
--- Stable
|
|
||||||
+++ Preview
|
|
||||||
@@ -58,11 +58,9 @@
|
|
||||||
#########################################################################################
|
|
||||||
|
|
||||||
|
|
||||||
-def test_return_multiline_string_type_annotation() -> (
|
|
||||||
- """str
|
|
||||||
+def test_return_multiline_string_type_annotation() -> """str
|
|
||||||
| list[str]
|
|
||||||
-"""
|
|
||||||
-):
|
|
||||||
+""":
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@@ -80,12 +78,12 @@
|
|
||||||
#########################################################################################
|
|
||||||
|
|
||||||
|
|
||||||
-def test_implicit_concatenated_string_return_type() -> "str" "bbbbbbbbbbbbbbbb":
|
|
||||||
+def test_implicit_concatenated_string_return_type() -> "strbbbbbbbbbbbbbbbb":
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def test_overlong_implicit_concatenated_string_return_type() -> (
|
|
||||||
- "liiiiiiiiiiiisssssst[str]" "bbbbbbbbbbbbbbbb"
|
|
||||||
+ "liiiiiiiiiiiisssssst[str]bbbbbbbbbbbbbbbb"
|
|
||||||
):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@@ -108,9 +106,9 @@
|
|
||||||
# 1. Black tries to keep the list flat by parenthesizing the list as shown below even when the `list` identifier
|
|
||||||
# fits on the header line. IMO, this adds unnecessary parentheses that can be avoided
|
|
||||||
# and supporting it requires extra complexity (best_fitting! layout)
|
|
||||||
-def no_parameters_overlong_subscript_return_type_with_single_element() -> (
|
|
||||||
- list[xxxxxxxxxxxxxxxxxxxxx]
|
|
||||||
-):
|
|
||||||
+def no_parameters_overlong_subscript_return_type_with_single_element() -> list[
|
|
||||||
+ xxxxxxxxxxxxxxxxxxxxx
|
|
||||||
+]:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@@ -119,23 +117,18 @@
|
|
||||||
# `list[`. It is also inconsistent with how subscripts are normally formatted where it first tries to fit the entire subscript,
|
|
||||||
# then splits after `list[` but keeps all elements on a single line, and finally, splits after each element.
|
|
||||||
# IMO: Splitting after the `list[` and trying to keep the elements together when possible seems more consistent.
|
|
||||||
-def no_parameters_subscript_return_type_multiple_elements() -> (
|
|
||||||
- list[
|
|
||||||
- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
|
|
||||||
- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
|
|
||||||
- ]
|
|
||||||
-):
|
|
||||||
+def no_parameters_subscript_return_type_multiple_elements() -> list[
|
|
||||||
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
+]:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
# Black removes the parentheses even the elements exceed the configured line width.
|
|
||||||
# So does Ruff.
|
|
||||||
-def no_parameters_subscript_return_type_multiple_overlong_elements() -> (
|
|
||||||
- list[
|
|
||||||
- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
|
|
||||||
- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
|
|
||||||
- ]
|
|
||||||
-):
|
|
||||||
+def no_parameters_subscript_return_type_multiple_overlong_elements() -> list[
|
|
||||||
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
|
|
||||||
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
|
|
||||||
+]:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@@ -154,11 +147,9 @@
|
|
||||||
# `no_parameters_subscript_return_type_multiple_overlong_elements` shows. However, it doesn't
|
|
||||||
# when the subscript contains a single element. Black then keeps the parentheses.
|
|
||||||
# Ruff removes the parentheses in this case for consistency.
|
|
||||||
-def no_parameters_overlong_subscript_return_type_with_overlong_single_element() -> (
|
|
||||||
- list[
|
|
||||||
- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
- ]
|
|
||||||
-):
|
|
||||||
+def no_parameters_overlong_subscript_return_type_with_overlong_single_element() -> list[
|
|
||||||
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
+]:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@@ -167,13 +158,10 @@
|
|
||||||
#########################################################################################
|
|
||||||
|
|
||||||
|
|
||||||
-def test_binary_expression_return_type_annotation() -> (
|
|
||||||
- aaaaaaaaaaaaaaaaaaaaaaaaaa
|
|
||||||
- > [
|
|
||||||
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
|
||||||
- bbbbbbbbbbbbbbbbbbbbbbbbb,
|
|
||||||
- ]
|
|
||||||
-):
|
|
||||||
+def test_binary_expression_return_type_annotation() -> aaaaaaaaaaaaaaaaaaaaaaaaaa > [
|
|
||||||
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
|
|
||||||
+ bbbbbbbbbbbbbbbbbbbbbbbbb,
|
|
||||||
+]:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@@ -183,10 +171,8 @@
|
|
||||||
|
|
||||||
|
|
||||||
# Don't paranthesize lists
|
|
||||||
-def f() -> (
|
|
||||||
- [
|
|
||||||
- a,
|
|
||||||
- b,
|
|
||||||
- ]
|
|
||||||
-):
|
|
||||||
+def f() -> [
|
|
||||||
+ a,
|
|
||||||
+ b,
|
|
||||||
+]:
|
|
||||||
pass
|
|
||||||
```
|
|
||||||
|
|
|
@ -288,13 +288,13 @@ def test_return_multiline_string_binary_expression_return_type_annotation(
|
||||||
#########################################################################################
|
#########################################################################################
|
||||||
|
|
||||||
|
|
||||||
def test_implicit_concatenated_string_return_type(a) -> "str" "bbbbbbbbbbbbbbbb":
|
def test_implicit_concatenated_string_return_type(a) -> "strbbbbbbbbbbbbbbbb":
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def test_overlong_implicit_concatenated_string_return_type(
|
def test_overlong_implicit_concatenated_string_return_type(
|
||||||
a,
|
a,
|
||||||
) -> "liiiiiiiiiiiisssssst[str]" "bbbbbbbbbbbbbbbb":
|
) -> "liiiiiiiiiiiisssssst[str]bbbbbbbbbbbbbbbb":
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -413,26 +413,3 @@ def test_return_multiline_string_binary_expression_return_type_annotation(
|
||||||
]:
|
]:
|
||||||
pass
|
pass
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Preview changes
|
|
||||||
```diff
|
|
||||||
--- Stable
|
|
||||||
+++ Preview
|
|
||||||
@@ -82,13 +82,13 @@
|
|
||||||
#########################################################################################
|
|
||||||
|
|
||||||
|
|
||||||
-def test_implicit_concatenated_string_return_type(a) -> "str" "bbbbbbbbbbbbbbbb":
|
|
||||||
+def test_implicit_concatenated_string_return_type(a) -> "strbbbbbbbbbbbbbbbb":
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def test_overlong_implicit_concatenated_string_return_type(
|
|
||||||
a,
|
|
||||||
-) -> "liiiiiiiiiiiisssssst[str]" "bbbbbbbbbbbbbbbb":
|
|
||||||
+) -> "liiiiiiiiiiiisssssst[str]bbbbbbbbbbbbbbbb":
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
---
|
---
|
||||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/with.py
|
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/with.py
|
||||||
snapshot_kind: text
|
|
||||||
---
|
---
|
||||||
## Input
|
## Input
|
||||||
```python
|
```python
|
||||||
|
@ -444,7 +443,9 @@ with (
|
||||||
with a: # should remove brackets
|
with a: # should remove brackets
|
||||||
pass
|
pass
|
||||||
|
|
||||||
with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as c:
|
with (
|
||||||
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||||
|
) as c:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -609,7 +610,9 @@ with ( # outer comment
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Breaking of with items.
|
# Breaking of with items.
|
||||||
with test as ( # bar # foo
|
with (
|
||||||
|
test # bar
|
||||||
|
) as ( # foo
|
||||||
# test
|
# test
|
||||||
foo
|
foo
|
||||||
):
|
):
|
||||||
|
@ -621,7 +624,9 @@ with test as (
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
with test as ( # bar # foo # baz
|
with (
|
||||||
|
test # bar
|
||||||
|
) as ( # foo # baz
|
||||||
# test
|
# test
|
||||||
foo
|
foo
|
||||||
):
|
):
|
||||||
|
@ -674,7 +679,9 @@ with (
|
||||||
) as b:
|
) as b:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as b:
|
with (
|
||||||
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||||
|
) as b:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
with (
|
with (
|
||||||
|
@ -717,15 +724,19 @@ if True:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if True:
|
if True:
|
||||||
with anyio.CancelScope(
|
with (
|
||||||
shield=True
|
anyio.CancelScope(shield=True)
|
||||||
) if get_running_loop() else contextlib.nullcontext():
|
if get_running_loop()
|
||||||
|
else contextlib.nullcontext()
|
||||||
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if True:
|
if True:
|
||||||
with anyio.CancelScope(
|
with (
|
||||||
shield=True
|
anyio.CancelScope(shield=True)
|
||||||
) if get_running_loop() else contextlib.nullcontext() as c:
|
if get_running_loop()
|
||||||
|
else contextlib.nullcontext()
|
||||||
|
) as c:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
with Child(aaaaaaaaa, bbbbbbbbbbbbbbb, cccccc), Document(
|
with Child(aaaaaaaaa, bbbbbbbbbbbbbbb, cccccc), Document(
|
||||||
|
@ -739,16 +750,22 @@ with open(
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:
|
with (
|
||||||
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||||
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as b:
|
with (
|
||||||
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||||
|
) as b:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if True:
|
if True:
|
||||||
with anyio.CancelScope(
|
with (
|
||||||
shield=True
|
anyio.CancelScope(shield=True)
|
||||||
) if get_running_loop() else contextlib.nullcontext() as b:
|
if get_running_loop()
|
||||||
|
else contextlib.nullcontext()
|
||||||
|
) as b:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -800,103 +817,7 @@ with (
|
||||||
```diff
|
```diff
|
||||||
--- Stable
|
--- Stable
|
||||||
+++ Preview
|
+++ Preview
|
||||||
@@ -49,7 +49,9 @@
|
@@ -377,42 +377,36 @@
|
||||||
with a: # should remove brackets
|
|
||||||
pass
|
|
||||||
|
|
||||||
-with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as c:
|
|
||||||
+with (
|
|
||||||
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
|
||||||
+) as c:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@@ -214,7 +216,9 @@
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Breaking of with items.
|
|
||||||
-with test as ( # bar # foo
|
|
||||||
+with (
|
|
||||||
+ test # bar
|
|
||||||
+) as ( # foo
|
|
||||||
# test
|
|
||||||
foo
|
|
||||||
):
|
|
||||||
@@ -226,7 +230,9 @@
|
|
||||||
):
|
|
||||||
pass
|
|
||||||
|
|
||||||
-with test as ( # bar # foo # baz
|
|
||||||
+with (
|
|
||||||
+ test # bar
|
|
||||||
+) as ( # foo # baz
|
|
||||||
# test
|
|
||||||
foo
|
|
||||||
):
|
|
||||||
@@ -279,7 +285,9 @@
|
|
||||||
) as b:
|
|
||||||
pass
|
|
||||||
|
|
||||||
-with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as b:
|
|
||||||
+with (
|
|
||||||
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
|
||||||
+) as b:
|
|
||||||
pass
|
|
||||||
|
|
||||||
with (
|
|
||||||
@@ -322,15 +330,19 @@
|
|
||||||
pass
|
|
||||||
|
|
||||||
if True:
|
|
||||||
- with anyio.CancelScope(
|
|
||||||
- shield=True
|
|
||||||
- ) if get_running_loop() else contextlib.nullcontext():
|
|
||||||
+ with (
|
|
||||||
+ anyio.CancelScope(shield=True)
|
|
||||||
+ if get_running_loop()
|
|
||||||
+ else contextlib.nullcontext()
|
|
||||||
+ ):
|
|
||||||
pass
|
|
||||||
|
|
||||||
if True:
|
|
||||||
- with anyio.CancelScope(
|
|
||||||
- shield=True
|
|
||||||
- ) if get_running_loop() else contextlib.nullcontext() as c:
|
|
||||||
+ with (
|
|
||||||
+ anyio.CancelScope(shield=True)
|
|
||||||
+ if get_running_loop()
|
|
||||||
+ else contextlib.nullcontext()
|
|
||||||
+ ) as c:
|
|
||||||
pass
|
|
||||||
|
|
||||||
with Child(aaaaaaaaa, bbbbbbbbbbbbbbb, cccccc), Document(
|
|
||||||
@@ -344,57 +356,57 @@
|
|
||||||
):
|
|
||||||
pass
|
|
||||||
|
|
||||||
-with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:
|
|
||||||
+with (
|
|
||||||
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
|
||||||
+):
|
|
||||||
pass
|
|
||||||
|
|
||||||
-with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as b:
|
|
||||||
+with (
|
|
||||||
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
|
||||||
+) as b:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if True:
|
|
||||||
- with anyio.CancelScope(
|
|
||||||
- shield=True
|
|
||||||
- ) if get_running_loop() else contextlib.nullcontext() as b:
|
|
||||||
+ with (
|
|
||||||
+ anyio.CancelScope(shield=True)
|
|
||||||
+ if get_running_loop()
|
|
||||||
+ else contextlib.nullcontext()
|
|
||||||
+ ) as b:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
# Regression test for https://github.com/astral-sh/ruff/issues/14001
|
# Regression test for https://github.com/astral-sh/ruff/issues/14001
|
||||||
with (
|
with (
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue