Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
{
"target_version": "3.11"
},
{
"target_version": "3.12"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
if f"aaaaaaaaaaa {[ttttteeeeeeeeest,]} more {
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
}":
pass
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ use std::borrow::Cow;
use ruff_formatter::{Buffer, FormatOptions as _, RemoveSoftLinesBuffer, format_args, write};
use ruff_python_ast::{
AnyStringFlags, ConversionFlag, Expr, InterpolatedElement, InterpolatedStringElement,
InterpolatedStringLiteralElement,
InterpolatedStringLiteralElement, StringFlags,
};
use ruff_text_size::{Ranged, TextSlice};
use ruff_source_file::LineRanges;
use ruff_text_size::{Ranged, TextRange, TextSlice};

use crate::comments::dangling_open_parenthesis_comments;
use crate::context::{
Expand All @@ -16,7 +17,7 @@ use crate::prelude::*;
use crate::string::normalize_string;
use crate::verbatim::verbatim_text;

use super::interpolated_string::InterpolatedStringContext;
use super::interpolated_string::{InterpolatedStringContext, InterpolatedStringLayout};

/// Formats an f-string element which is either a literal or a formatted expression.
///
Expand Down Expand Up @@ -155,8 +156,23 @@ impl Format<PyFormatContext<'_>> for FormatInterpolatedElement<'_> {
} else {
let comments = f.context().comments().clone();
let dangling_item_comments = comments.dangling(self.element);

let multiline = self.context.is_multiline();
let flags = self.context.flags();

// Before Python 3.12, non-triple-quoted f-strings cannot introduce new multiline
// replacement fields. Preserve existing multiline fields from unsupported syntax
// inputs, but keep originally flat fields flat.
let multiline = self.context.is_multiline()
&& (f.options().target_version().supports_pep_701()
|| flags.is_triple_quoted()
|| f.context()
.source()
.contains_line_break(interpolated_element_expression_range(self.element)));

let context = if multiline {
self.context
} else {
InterpolatedStringContext::new(flags, InterpolatedStringLayout::Flat)
};

// If an expression starts with a `{`, we need to add a space before the
// curly brace to avoid turning it into a literal curly with `{{`.
Expand Down Expand Up @@ -184,10 +200,10 @@ impl Format<PyFormatContext<'_>> for FormatInterpolatedElement<'_> {
let state = match f.context().interpolated_string_state() {
InterpolatedStringState::InsideInterpolatedElement(_)
| InterpolatedStringState::NestedInterpolatedElement(_) => {
InterpolatedStringState::NestedInterpolatedElement(self.context)
InterpolatedStringState::NestedInterpolatedElement(context)
}
InterpolatedStringState::Outside => {
InterpolatedStringState::InsideInterpolatedElement(self.context)
InterpolatedStringState::InsideInterpolatedElement(context)
}
};
let f = &mut WithInterpolatedStringState::new(state, f);
Expand Down Expand Up @@ -216,7 +232,7 @@ impl Format<PyFormatContext<'_>> for FormatInterpolatedElement<'_> {
token(":").fmt(f)?;

for element in &format_spec.elements {
FormatInterpolatedStringElement::new(element, self.context).fmt(f)?;
FormatInterpolatedStringElement::new(element, context).fmt(f)?;
}
}

Expand Down Expand Up @@ -268,6 +284,14 @@ impl Format<PyFormatContext<'_>> for FormatInterpolatedElement<'_> {
}
}

fn interpolated_element_expression_range(element: &InterpolatedElement) -> TextRange {
element
.format_spec
.as_deref()
.map(|format_spec| TextRange::new(element.start(), format_spec.start()))
.unwrap_or_else(|| element.range())
}

fn needs_bracket_spacing(expr: &Expr, context: &PyFormatContext) -> bool {
// Ruff parenthesizes single element tuples, that's why we shouldn't insert
// a space around the curly braces for those.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1337,27 +1337,15 @@ if f"aaaaaaaaaaa {ttttteeeeeeeeest} more { # comment
}":
pass

if f"aaaaaaaaaaa {
[
ttttteeeeeeeeest,
]
} more {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}":
if f"aaaaaaaaaaa {[ttttteeeeeeeeest]} more {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}":
pass

if f"aaaaaaaaaaa {
[
ttttteeeeeeeeest,
]
} more {
if f"aaaaaaaaaaa {[ttttteeeeeeeeest]} more {
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
}":
pass

if f"aaaaaaaaaaa {
[
ttttteeeeeeeeest,
]
} more {
if f"aaaaaaaaaaa {[ttttteeeeeeeeest]} more {
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
}":
pass
Expand Down Expand Up @@ -2169,27 +2157,15 @@ if f"aaaaaaaaaaa {ttttteeeeeeeeest} more { # comment
}":
pass

if f"aaaaaaaaaaa {
[
ttttteeeeeeeeest,
]
} more {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}":
if f"aaaaaaaaaaa {[ttttteeeeeeeeest]} more {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}":
pass

if f"aaaaaaaaaaa {
[
ttttteeeeeeeeest,
]
} more {
if f"aaaaaaaaaaa {[ttttteeeeeeeeest]} more {
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
}":
pass

if f"aaaaaaaaaaa {
[
ttttteeeeeeeeest,
]
} more {
if f"aaaaaaaaaaa {[ttttteeeeeeeeest]} more {
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
}":
pass
Expand Down Expand Up @@ -2435,27 +2411,3 @@ error[invalid-syntax]: Cannot reuse outer quote character in f-strings on Python
179 | f"foo {'"bar"'}"
|
warning: Only accept new syntax errors if they are also present in the input. The formatter should not introduce syntax errors.

error[invalid-syntax]: Cannot use line breaks in non-triple-quoted f-string replacement fields on Python 3.10 (syntax was added in Python 3.12)
--> fstring.py:572:8
|
570 | ttttteeeeeeeeest,
571 | ]
572 | } more {
| ^
573 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
574 | }":
|
warning: Only accept new syntax errors if they are also present in the input. The formatter should not introduce syntax errors.

error[invalid-syntax]: Cannot use line breaks in non-triple-quoted f-string replacement fields on Python 3.10 (syntax was added in Python 3.12)
--> fstring.py:581:8
|
579 | ttttteeeeeeeeest,
580 | ]
581 | } more {
| ^
582 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
583 | }":
|
warning: Only accept new syntax errors if they are also present in the input. The formatter should not introduce syntax errors.
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
source: crates/ruff_python_formatter/tests/fixtures.rs
---
## Input
```python
if f"aaaaaaaaaaa {[ttttteeeeeeeeest,]} more {
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
}":
pass
```

## Outputs
### 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 = Disabled
target_version = 3.11
source_type = Python
nested-string-quote-style = alternating
```

```python
if f"aaaaaaaaaaa {[ttttteeeeeeeeest]} more {
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
}":
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually invalid on Python 3.11, but the input is already invalid in this case, so I think it's within the bounds of the formatter contract?

pass
```


### Output 2
```
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 = Disabled
target_version = 3.12
source_type = Python
nested-string-quote-style = alternating
```

```python
if f"aaaaaaaaaaa {
[
ttttteeeeeeeeest,
]
} more {
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
}":
pass
```
Loading