mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-17 22:07:42 +00:00
Disallow newlines in format specifiers of single quoted f- or t-strings (#18708)
This commit is contained in:
parent
23261a38a0
commit
1188ffccc4
17 changed files with 521 additions and 513 deletions
|
@ -74,8 +74,7 @@ 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
|
||||
}"
|
||||
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=}"
|
||||
|
|
|
@ -278,16 +278,7 @@ x = f"aaaaaaaaa { x = !r }"
|
|||
|
||||
# Combine conversion flags with format specifiers
|
||||
x = f"{x = !s
|
||||
:>0
|
||||
|
||||
}"
|
||||
# This is interesting. There can be a comment after the format specifier but only if it's
|
||||
# on it's own line. Refer to https://github.com/astral-sh/ruff/pull/7787 for more details.
|
||||
# We'll format is as trailing comments.
|
||||
x = f"{x !s
|
||||
:>0
|
||||
# comment 21
|
||||
}"
|
||||
:>0}"
|
||||
|
||||
x = f"{
|
||||
x!s:>{
|
||||
|
@ -295,6 +286,13 @@ x = f"{
|
|||
# comment 21-2
|
||||
}}"
|
||||
|
||||
f"{1
|
||||
# comment 21-3
|
||||
:}"
|
||||
|
||||
f"{1 # comment 21-4
|
||||
:} a"
|
||||
|
||||
|
||||
x = f"""
|
||||
{ # comment 22
|
||||
|
@ -311,14 +309,14 @@ x = f"""{"foo " + # comment 24
|
|||
"""
|
||||
|
||||
# Mix of various features.
|
||||
f"{ # comment 26
|
||||
f"""{ # comment 26
|
||||
foo # after foo
|
||||
:>{
|
||||
x # after x
|
||||
}
|
||||
# comment 27
|
||||
# comment 28
|
||||
} woah {x}"
|
||||
} woah {x}"""
|
||||
|
||||
|
||||
f"""{foo
|
||||
|
@ -332,8 +330,7 @@ f"""{foo
|
|||
f"{
|
||||
# comment 31
|
||||
foo
|
||||
:>
|
||||
}"
|
||||
:>}"
|
||||
|
||||
# Assignment statement
|
||||
|
||||
|
@ -487,13 +484,11 @@ aaaaa[aaaaaaaaaaa] = (
|
|||
|
||||
# This is not a multiline f-string even though it has a newline after the format specifier.
|
||||
aaaaaaaaaaaaaaaaaa = f"testeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
a:.3f
|
||||
}moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
a:.3f}moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
|
||||
aaaaaaaaaaaaaaaaaa = (
|
||||
f"testeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
a:.3f
|
||||
}moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
a:.3f}moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
# The newline is only considered when it's a tripled-quoted f-string.
|
||||
|
|
|
@ -274,16 +274,7 @@ x = t"aaaaaaaaa { x = !r }"
|
|||
|
||||
# Combine conversion flags with format specifiers
|
||||
x = t"{x = !s
|
||||
:>0
|
||||
|
||||
}"
|
||||
# This is interesting. There can be a comment after the format specifier but only if it's
|
||||
# on it's own line. Refer to https://github.com/astral-sh/ruff/pull/7787 for more details.
|
||||
# We'll format is as trailing comments.
|
||||
x = t"{x !s
|
||||
:>0
|
||||
# comment 21
|
||||
}"
|
||||
:>0}"
|
||||
|
||||
x = f"{
|
||||
x!s:>{
|
||||
|
@ -291,6 +282,13 @@ x = f"{
|
|||
# comment 21-2
|
||||
}}"
|
||||
|
||||
f"{1
|
||||
# comment 21-3
|
||||
:}"
|
||||
|
||||
f"{1 # comment 21-4
|
||||
:} a"
|
||||
|
||||
x = t"""
|
||||
{ # comment 22
|
||||
x = :.0{y # comment 23
|
||||
|
@ -306,14 +304,14 @@ x = t"""{"foo " + # comment 24
|
|||
"""
|
||||
|
||||
# Mix of various features.
|
||||
t"{ # comment 26
|
||||
t"""{ # comment 26
|
||||
foo # after foo
|
||||
:>{
|
||||
x # after x
|
||||
}
|
||||
# comment 27
|
||||
# comment 28
|
||||
} woah {x}"
|
||||
} woah {x}"""
|
||||
|
||||
# Assignment statement
|
||||
|
||||
|
@ -467,13 +465,11 @@ aaaaa[aaaaaaaaaaa] = (
|
|||
|
||||
# This is not a multiline t-string even though it has a newline after the format specifier.
|
||||
aaaaaaaaaaaaaaaaaa = t"testeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
a:.3f
|
||||
}moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
a:.3f}moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
|
||||
aaaaaaaaaaaaaaaaaa = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
a:.3f
|
||||
}moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
a:.3f}moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
# The newline is only considered when it's a tripled-quoted t-string.
|
||||
|
|
|
@ -323,27 +323,18 @@ fn handle_enclosed_comment<'a>(
|
|||
AnyNodeRef::TString(tstring) => CommentPlacement::dangling(tstring, comment),
|
||||
AnyNodeRef::InterpolatedElement(element) => {
|
||||
if let Some(preceding) = comment.preceding_node() {
|
||||
if comment.line_position().is_own_line() && element.format_spec.is_some() {
|
||||
return if comment.following_node().is_some() {
|
||||
// Own line comment before format specifier
|
||||
// ```py
|
||||
// aaaaaaaaaaa = f"""asaaaaaaaaaaaaaaaa {
|
||||
// aaaaaaaaaaaa + bbbbbbbbbbbb + ccccccccccccccc + dddddddd
|
||||
// # comment
|
||||
// :.3f} cccccccccc"""
|
||||
// ```
|
||||
CommentPlacement::trailing(preceding, comment)
|
||||
} else {
|
||||
// TODO: This can be removed once format specifiers with a newline are a syntax error.
|
||||
// This is to handle cases like:
|
||||
// ```py
|
||||
// x = f"{x !s
|
||||
// :>0
|
||||
// # comment 21
|
||||
// }"
|
||||
// ```
|
||||
CommentPlacement::trailing(element, comment)
|
||||
};
|
||||
// Own line comment before format specifier
|
||||
// ```py
|
||||
// aaaaaaaaaaa = f"""asaaaaaaaaaaaaaaaa {
|
||||
// aaaaaaaaaaaa + bbbbbbbbbbbb + ccccccccccccccc + dddddddd
|
||||
// # comment
|
||||
// :.3f} cccccccccc"""
|
||||
// ```
|
||||
if comment.line_position().is_own_line()
|
||||
&& element.format_spec.is_some()
|
||||
&& comment.following_node().is_some()
|
||||
{
|
||||
return CommentPlacement::trailing(preceding, comment);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use ruff_python_ast::{
|
|||
};
|
||||
use ruff_text_size::{Ranged, TextSlice};
|
||||
|
||||
use crate::comments::{dangling_open_parenthesis_comments, trailing_comments};
|
||||
use crate::comments::dangling_open_parenthesis_comments;
|
||||
use crate::context::{
|
||||
InterpolatedStringState, NodeLevel, WithInterpolatedStringState, WithNodeLevel,
|
||||
};
|
||||
|
@ -203,7 +203,7 @@ impl Format<PyFormatContext<'_>> for FormatInterpolatedElement<'_> {
|
|||
// # comment 27
|
||||
// :test}"
|
||||
// ```
|
||||
if comments.has_trailing_own_line(expression) {
|
||||
if comments.has_trailing(expression) {
|
||||
soft_line_break().fmt(f)?;
|
||||
}
|
||||
|
||||
|
@ -214,31 +214,6 @@ impl Format<PyFormatContext<'_>> for FormatInterpolatedElement<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
// These trailing comments can only occur if the format specifier is
|
||||
// present. For example,
|
||||
//
|
||||
// ```python
|
||||
// f"{
|
||||
// x:.3f
|
||||
// # comment
|
||||
// }"
|
||||
// ```
|
||||
|
||||
// This can also be triggered outside of a format spec, at
|
||||
// least until https://github.com/astral-sh/ruff/issues/18632 is a syntax error
|
||||
// TODO(https://github.com/astral-sh/ruff/issues/18632) Remove this
|
||||
// and double check if it is still necessary for the triple quoted case
|
||||
// once this is a syntax error.
|
||||
// ```py
|
||||
// f"{
|
||||
// foo
|
||||
// :{x}
|
||||
// # comment 28
|
||||
// } woah {x}"
|
||||
// ```
|
||||
// Any other trailing comments are attached to the expression itself.
|
||||
trailing_comments(comments.trailing(self.element)).fmt(f)?;
|
||||
|
||||
if conversion.is_none() && format_spec.is_none() {
|
||||
bracket_spacing.fmt(f)?;
|
||||
}
|
||||
|
@ -258,15 +233,7 @@ impl Format<PyFormatContext<'_>> for FormatInterpolatedElement<'_> {
|
|||
let mut f = WithNodeLevel::new(NodeLevel::ParenthesizedExpression, f);
|
||||
|
||||
if self.context.is_multiline() {
|
||||
// TODO: The `or comments.has_trailing...` can be removed once newlines in format specs are a syntax error.
|
||||
// This is to support the following case:
|
||||
// ```py
|
||||
// x = f"{x !s
|
||||
// :>0
|
||||
// # comment 21
|
||||
// }"
|
||||
// ```
|
||||
if format_spec.is_none() || comments.has_trailing_own_line(self.element) {
|
||||
if format_spec.is_none() {
|
||||
group(&format_args![
|
||||
open_parenthesis_comments,
|
||||
soft_block_indent(&item)
|
||||
|
@ -276,6 +243,7 @@ impl Format<PyFormatContext<'_>> for FormatInterpolatedElement<'_> {
|
|||
// For strings ending with a format spec, don't add a newline between the end of the format spec
|
||||
// and closing curly brace because that is invalid syntax for single quoted strings and
|
||||
// the newline is preserved as part of the format spec for triple quoted strings.
|
||||
|
||||
group(&format_args![
|
||||
open_parenthesis_comments,
|
||||
indent(&format_args![soft_line_break(), item])
|
||||
|
|
|
@ -324,7 +324,12 @@ fn format_file(source: &str, options: &PyFormatOptions, input_path: &Path) -> St
|
|||
|
||||
(Cow::Owned(without_markers), content)
|
||||
} else {
|
||||
let printed = format_module_source(source, options.clone()).expect("Formatting to succeed");
|
||||
let printed = format_module_source(source, options.clone()).unwrap_or_else(|err| {
|
||||
panic!(
|
||||
"Formatting `{input_path} was expected to succeed but it failed: {err}",
|
||||
input_path = input_path.display()
|
||||
)
|
||||
});
|
||||
let formatted_code = printed.into_code();
|
||||
|
||||
ensure_stability_when_formatting_twice(&formatted_code, options, input_path);
|
||||
|
|
|
@ -81,8 +81,7 @@ 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
|
||||
}"
|
||||
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=}"
|
||||
|
|
|
@ -284,16 +284,7 @@ x = f"aaaaaaaaa { x = !r }"
|
|||
|
||||
# Combine conversion flags with format specifiers
|
||||
x = f"{x = !s
|
||||
:>0
|
||||
|
||||
}"
|
||||
# This is interesting. There can be a comment after the format specifier but only if it's
|
||||
# on it's own line. Refer to https://github.com/astral-sh/ruff/pull/7787 for more details.
|
||||
# We'll format is as trailing comments.
|
||||
x = f"{x !s
|
||||
:>0
|
||||
# comment 21
|
||||
}"
|
||||
:>0}"
|
||||
|
||||
x = f"{
|
||||
x!s:>{
|
||||
|
@ -301,6 +292,13 @@ x = f"{
|
|||
# comment 21-2
|
||||
}}"
|
||||
|
||||
f"{1
|
||||
# comment 21-3
|
||||
:}"
|
||||
|
||||
f"{1 # comment 21-4
|
||||
:} a"
|
||||
|
||||
|
||||
x = f"""
|
||||
{ # comment 22
|
||||
|
@ -317,14 +315,14 @@ x = f"""{"foo " + # comment 24
|
|||
"""
|
||||
|
||||
# Mix of various features.
|
||||
f"{ # comment 26
|
||||
f"""{ # comment 26
|
||||
foo # after foo
|
||||
:>{
|
||||
x # after x
|
||||
}
|
||||
# comment 27
|
||||
# comment 28
|
||||
} woah {x}"
|
||||
} woah {x}"""
|
||||
|
||||
|
||||
f"""{foo
|
||||
|
@ -338,8 +336,7 @@ f"""{foo
|
|||
f"{
|
||||
# comment 31
|
||||
foo
|
||||
:>
|
||||
}"
|
||||
:>}"
|
||||
|
||||
# Assignment statement
|
||||
|
||||
|
@ -493,13 +490,11 @@ aaaaa[aaaaaaaaaaa] = (
|
|||
|
||||
# This is not a multiline f-string even though it has a newline after the format specifier.
|
||||
aaaaaaaaaaaaaaaaaa = f"testeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
a:.3f
|
||||
}moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
a:.3f}moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
|
||||
aaaaaaaaaaaaaaaaaa = (
|
||||
f"testeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
a:.3f
|
||||
}moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
a:.3f}moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
# The newline is only considered when it's a tripled-quoted f-string.
|
||||
|
@ -1071,13 +1066,6 @@ x = f"aaaaaaaaa { x = !r}"
|
|||
|
||||
# Combine conversion flags with format specifiers
|
||||
x = f"{x = !s:>0}"
|
||||
# This is interesting. There can be a comment after the format specifier but only if it's
|
||||
# on it's own line. Refer to https://github.com/astral-sh/ruff/pull/7787 for more details.
|
||||
# We'll format is as trailing comments.
|
||||
x = f"{
|
||||
x!s:>0
|
||||
# comment 21
|
||||
}"
|
||||
|
||||
x = f"{
|
||||
x!s:>{
|
||||
|
@ -1085,6 +1073,15 @@ x = f"{
|
|||
# comment 21-2
|
||||
}}"
|
||||
|
||||
f"{
|
||||
1
|
||||
# comment 21-3
|
||||
:}"
|
||||
|
||||
f"{
|
||||
1 # comment 21-4
|
||||
:} a"
|
||||
|
||||
|
||||
x = f"""
|
||||
{ # comment 22
|
||||
|
@ -1102,13 +1099,14 @@ x = f"""{
|
|||
"""
|
||||
|
||||
# Mix of various features.
|
||||
f"{ # comment 26
|
||||
foo:>{ # after foo
|
||||
f"""{ # comment 26
|
||||
foo # after foo
|
||||
:>{
|
||||
x # after x
|
||||
}
|
||||
# comment 27
|
||||
# comment 28
|
||||
} woah {x}"
|
||||
} woah {x}"""
|
||||
|
||||
|
||||
f"""{
|
||||
|
@ -1895,13 +1893,6 @@ x = f"aaaaaaaaa { x = !r}"
|
|||
|
||||
# Combine conversion flags with format specifiers
|
||||
x = f"{x = !s:>0}"
|
||||
# This is interesting. There can be a comment after the format specifier but only if it's
|
||||
# on it's own line. Refer to https://github.com/astral-sh/ruff/pull/7787 for more details.
|
||||
# We'll format is as trailing comments.
|
||||
x = f"{
|
||||
x!s:>0
|
||||
# comment 21
|
||||
}"
|
||||
|
||||
x = f"{
|
||||
x!s:>{
|
||||
|
@ -1909,6 +1900,15 @@ x = f"{
|
|||
# comment 21-2
|
||||
}}"
|
||||
|
||||
f"{
|
||||
1
|
||||
# comment 21-3
|
||||
:}"
|
||||
|
||||
f"{
|
||||
1 # comment 21-4
|
||||
:} a"
|
||||
|
||||
|
||||
x = f"""
|
||||
{ # comment 22
|
||||
|
@ -1926,13 +1926,14 @@ x = f"""{
|
|||
"""
|
||||
|
||||
# Mix of various features.
|
||||
f"{ # comment 26
|
||||
foo:>{ # after foo
|
||||
f"""{ # comment 26
|
||||
foo # after foo
|
||||
:>{
|
||||
x # after x
|
||||
}
|
||||
# comment 27
|
||||
# comment 28
|
||||
} woah {x}"
|
||||
} woah {x}"""
|
||||
|
||||
|
||||
f"""{
|
||||
|
|
|
@ -280,16 +280,7 @@ x = t"aaaaaaaaa { x = !r }"
|
|||
|
||||
# Combine conversion flags with format specifiers
|
||||
x = t"{x = !s
|
||||
:>0
|
||||
|
||||
}"
|
||||
# This is interesting. There can be a comment after the format specifier but only if it's
|
||||
# on it's own line. Refer to https://github.com/astral-sh/ruff/pull/7787 for more details.
|
||||
# We'll format is as trailing comments.
|
||||
x = t"{x !s
|
||||
:>0
|
||||
# comment 21
|
||||
}"
|
||||
:>0}"
|
||||
|
||||
x = f"{
|
||||
x!s:>{
|
||||
|
@ -297,6 +288,13 @@ x = f"{
|
|||
# comment 21-2
|
||||
}}"
|
||||
|
||||
f"{1
|
||||
# comment 21-3
|
||||
:}"
|
||||
|
||||
f"{1 # comment 21-4
|
||||
:} a"
|
||||
|
||||
x = t"""
|
||||
{ # comment 22
|
||||
x = :.0{y # comment 23
|
||||
|
@ -312,14 +310,14 @@ x = t"""{"foo " + # comment 24
|
|||
"""
|
||||
|
||||
# Mix of various features.
|
||||
t"{ # comment 26
|
||||
t"""{ # comment 26
|
||||
foo # after foo
|
||||
:>{
|
||||
x # after x
|
||||
}
|
||||
# comment 27
|
||||
# comment 28
|
||||
} woah {x}"
|
||||
} woah {x}"""
|
||||
|
||||
# Assignment statement
|
||||
|
||||
|
@ -473,13 +471,11 @@ aaaaa[aaaaaaaaaaa] = (
|
|||
|
||||
# This is not a multiline t-string even though it has a newline after the format specifier.
|
||||
aaaaaaaaaaaaaaaaaa = t"testeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
a:.3f
|
||||
}moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
a:.3f}moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
|
||||
aaaaaaaaaaaaaaaaaa = (
|
||||
t"testeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
a:.3f
|
||||
}moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
a:.3f}moreeeeeeeeeeeeeeeeeetest" # comment
|
||||
)
|
||||
|
||||
# The newline is only considered when it's a tripled-quoted t-string.
|
||||
|
@ -1045,13 +1041,6 @@ x = t"aaaaaaaaa { x = !r}"
|
|||
|
||||
# Combine conversion flags with format specifiers
|
||||
x = t"{x = !s:>0}"
|
||||
# This is interesting. There can be a comment after the format specifier but only if it's
|
||||
# on it's own line. Refer to https://github.com/astral-sh/ruff/pull/7787 for more details.
|
||||
# We'll format is as trailing comments.
|
||||
x = t"{
|
||||
x!s:>0
|
||||
# comment 21
|
||||
}"
|
||||
|
||||
x = f"{
|
||||
x!s:>{
|
||||
|
@ -1059,6 +1048,15 @@ x = f"{
|
|||
# comment 21-2
|
||||
}}"
|
||||
|
||||
f"{
|
||||
1
|
||||
# comment 21-3
|
||||
:}"
|
||||
|
||||
f"{
|
||||
1 # comment 21-4
|
||||
:} a"
|
||||
|
||||
x = t"""
|
||||
{ # comment 22
|
||||
x = :.0{y # comment 23
|
||||
|
@ -1075,13 +1073,14 @@ x = t"""{
|
|||
"""
|
||||
|
||||
# Mix of various features.
|
||||
t"{ # comment 26
|
||||
foo:>{ # after foo
|
||||
t"""{ # comment 26
|
||||
foo # after foo
|
||||
:>{
|
||||
x # after x
|
||||
}
|
||||
# comment 27
|
||||
# comment 28
|
||||
} woah {x}"
|
||||
} woah {x}"""
|
||||
|
||||
# Assignment statement
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue