-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix f-string formatting in assignment statement #14454
base: dhruv/f-string-assignment-1
Are you sure you want to change the base?
Changes from all commits
a56a721
2e73688
4212114
55574a9
8ec8a1c
03896f0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,7 +28,7 @@ impl NeedsParentheses for ExprBinOp { | |
} else if let Ok(string) = StringLike::try_from(&*self.left) { | ||
// Multiline strings are guaranteed to never fit, avoid adding unnecessary parentheses | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add an example covering this path with an expression that starts as a mulitline f-string but then gets formatted as a flat f-string? |
||
if !string.is_implicit_concatenated() | ||
&& string.is_multiline(context.source()) | ||
&& string.is_multiline(context) | ||
&& has_parentheses(&self.right, context).is_some() | ||
&& !context.comments().has_dangling(self) | ||
&& !context.comments().has(string) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,8 +6,10 @@ use crate::expression::parentheses::{ | |
}; | ||
use crate::other::f_string::FormatFString; | ||
use crate::prelude::*; | ||
use crate::string::implicit::FormatImplicitConcatenatedStringFlat; | ||
use crate::string::{implicit::FormatImplicitConcatenatedString, Quoting, StringLikeExtensions}; | ||
use crate::string::implicit::{ | ||
FormatImplicitConcatenatedString, FormatImplicitConcatenatedStringFlat, | ||
}; | ||
use crate::string::{Quoting, StringLikeExtensions}; | ||
|
||
#[derive(Default)] | ||
pub struct FormatExprFString; | ||
|
@@ -45,26 +47,7 @@ impl NeedsParentheses for ExprFString { | |
) -> OptionalParentheses { | ||
if self.value.is_implicit_concatenated() { | ||
OptionalParentheses::Multiline | ||
} | ||
// TODO(dhruvmanila): Ideally what we want here is a new variant which | ||
// is something like: | ||
// - If the expression fits by just adding the parentheses, then add them and | ||
// avoid breaking the f-string expression. So, | ||
// ``` | ||
// xxxxxxxxx = ( | ||
// f"aaaaaaaaaaaa { xxxxxxx + yyyyyyyy } bbbbbbbbbbbbb" | ||
// ) | ||
// ``` | ||
// - But, if the expression is too long to fit even with parentheses, then | ||
// don't add the parentheses and instead break the expression at `soft_line_break`. | ||
// ``` | ||
// xxxxxxxxx = f"aaaaaaaaaaaa { | ||
// xxxxxxxxx + yyyyyyyyyy | ||
// } bbbbbbbbbbbbb" | ||
// ``` | ||
// This isn't decided yet, refer to the relevant discussion: | ||
// https://github.com/astral-sh/ruff/discussions/9785 | ||
else if StringLike::FString(self).is_multiline(context.source()) { | ||
} else if StringLike::FString(self).is_multiline(context) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think using if f"aaaaaaaaaaa { ttttteeeeeeeeest} more {
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
}": pass being formatted as if f"aaaaaaaaaaa {ttttteeeeeeeeest} more {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}":
pass Which seems worse than before. I think we should keep using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the reason it was formatted like that previously is because the if (
f"aaaaaaaaaaa {ttttteeeeeeeeest} more {
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
}"
):
pass There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can also decide to return Using Never has the advantage that it avoids unnecessary parentheses and is closer to what we had today (and no one complained?). Adding parentheses is similar to having There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, that's a good idea, I can do that. |
||
OptionalParentheses::Never | ||
} else { | ||
OptionalParentheses::BestFit | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -223,7 +223,7 @@ fn is_huggable_string_argument( | |
arguments: &Arguments, | ||
context: &PyFormatContext, | ||
) -> bool { | ||
if string.is_implicit_concatenated() || !string.is_multiline(context.source()) { | ||
if string.is_implicit_concatenated() || !string.is_multiline(context) { | ||
return false; | ||
} | ||
Comment on lines
+226
to
228
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Your change is an improvement to what we had before. For example, this was correctly formatted code before call(f"{
testeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
}") But I don't think it's correct to use the "hug" layout if an inner expression is multiline call(f"{
aaaaaa
+ '''test
more'''
}") There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure I follow here. Are you saying that both the code snippet should result in the formatting where the f-string is on the same line as the call expression ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not directly related to your PR, but I noticed it when reviewing it because you changed I'm leaning towards that we should only "hug" if the f-string itself contains any multiline string literal, but not if any inner-expression is multiline. Similar to prettier: call(
`${
aaaaaaaaaaaaaaaaaaaaaaaaaaaa +
`test more
aaa` +
morrrrrrrrrrrrrrrrrrrrrr
}`,
); So what I'm saying is that we should probably not hug for the both cases above. |
||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add some examples with inner comments or debug expressions (and format specs)? See
ruff/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/join_implicit_concatenated_string_assignment.py
Lines 236 to 293 in 73ee72b