mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 22:01:18 +00:00
Avoid converting f-strings within Django gettext
calls (#7898)
## Summary Django's `gettext` doesn't support f-strings, so we should avoid translating `.format` calls in those cases. Closes https://github.com/astral-sh/ruff/issues/7891.
This commit is contained in:
parent
2b95d3832b
commit
090c1a4a19
4 changed files with 34 additions and 0 deletions
9
crates/ruff_linter/resources/test/fixtures/pyupgrade/UP032_3.py
vendored
Normal file
9
crates/ruff_linter/resources/test/fixtures/pyupgrade/UP032_3.py
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
from django.utils.translation import gettext
|
||||
|
||||
long = 'long'
|
||||
split_to = 'split_to'
|
||||
gettext(
|
||||
'some super {} and complicated string so that the error code '
|
||||
'E501 Triggers when this is not {} multi-line'.format(
|
||||
long, split_to)
|
||||
)
|
|
@ -28,6 +28,7 @@ mod tests {
|
|||
#[test_case(Rule::FString, Path::new("UP032_0.py"))]
|
||||
#[test_case(Rule::FString, Path::new("UP032_1.py"))]
|
||||
#[test_case(Rule::FString, Path::new("UP032_2.py"))]
|
||||
#[test_case(Rule::FString, Path::new("UP032_3.py"))]
|
||||
#[test_case(Rule::FormatLiterals, Path::new("UP030_0.py"))]
|
||||
#[test_case(Rule::FormatLiterals, Path::new("UP030_1.py"))]
|
||||
#[test_case(Rule::LRUCacheWithMaxsizeNone, Path::new("UP033_0.py"))]
|
||||
|
|
|
@ -328,6 +328,7 @@ pub(crate) fn f_strings(
|
|||
let Some(mut summary) = FormatSummaryValues::try_from_call(call, checker.locator()) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let mut patches: Vec<(TextRange, String)> = vec![];
|
||||
let mut lex = lexer::lex_starts_at(
|
||||
checker.locator().slice(call.func.range()),
|
||||
|
@ -405,6 +406,25 @@ pub(crate) fn f_strings(
|
|||
return;
|
||||
}
|
||||
|
||||
// Finally, avoid refactors that would introduce a runtime error.
|
||||
// For example, Django's `gettext` supports `format`-style arguments, but not f-strings.
|
||||
// See: https://docs.djangoproject.com/en/4.2/topics/i18n/translation
|
||||
if checker.semantic().current_expressions().any(|expr| {
|
||||
expr.as_call_expr().is_some_and(|call| {
|
||||
checker
|
||||
.semantic()
|
||||
.resolve_call_path(call.func.as_ref())
|
||||
.map_or(false, |call_path| {
|
||||
matches!(
|
||||
call_path.as_slice(),
|
||||
["django", "utils", "translation", "gettext" | "gettext_lazy"]
|
||||
)
|
||||
})
|
||||
})
|
||||
}) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut diagnostic = Diagnostic::new(FString, call.range());
|
||||
|
||||
// Avoid fix if there are comments within the call:
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/pyupgrade/mod.rs
|
||||
---
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue