mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-01 06:11:21 +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_0.py"))]
|
||||||
#[test_case(Rule::FString, Path::new("UP032_1.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_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_0.py"))]
|
||||||
#[test_case(Rule::FormatLiterals, Path::new("UP030_1.py"))]
|
#[test_case(Rule::FormatLiterals, Path::new("UP030_1.py"))]
|
||||||
#[test_case(Rule::LRUCacheWithMaxsizeNone, Path::new("UP033_0.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 {
|
let Some(mut summary) = FormatSummaryValues::try_from_call(call, checker.locator()) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut patches: Vec<(TextRange, String)> = vec![];
|
let mut patches: Vec<(TextRange, String)> = vec![];
|
||||||
let mut lex = lexer::lex_starts_at(
|
let mut lex = lexer::lex_starts_at(
|
||||||
checker.locator().slice(call.func.range()),
|
checker.locator().slice(call.func.range()),
|
||||||
|
@ -405,6 +406,25 @@ pub(crate) fn f_strings(
|
||||||
return;
|
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());
|
let mut diagnostic = Diagnostic::new(FString, call.range());
|
||||||
|
|
||||||
// Avoid fix if there are comments within the call:
|
// 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