This commit is contained in:
Takayuki Maeda 2025-12-16 16:40:21 -05:00 committed by GitHub
commit 2508432788
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 113 additions and 9 deletions

View File

@ -64,3 +64,8 @@ import logging
x = 1 x = 1
logging.error(f"{x} -> %s", x) logging.error(f"{x} -> %s", x)
# https://github.com/astral-sh/ruff/issues/20151
logging.warning(fr"\'{x}")
logging.warning(f"{x}" "!")
logging.warning((f"{x}"))

View File

@ -1,6 +1,6 @@
use ruff_python_ast::InterpolatedStringElement; use ruff_python_ast::parenthesize::parenthesized_range;
use ruff_python_ast::{self as ast, Arguments, Expr, Keyword, Operator, StringFlags}; use ruff_python_ast::{self as ast, Arguments, Expr, Keyword, Operator, StringFlags};
use ruff_python_ast::{FStringPart, InterpolatedStringElement};
use ruff_python_semantic::analyze::logging; use ruff_python_semantic::analyze::logging;
use ruff_python_stdlib::logging::LoggingLevel; use ruff_python_stdlib::logging::LoggingLevel;
use ruff_text_size::{Ranged, TextRange}; use ruff_text_size::{Ranged, TextRange};
@ -38,28 +38,31 @@ fn logging_f_string(
let mut format_string = String::new(); let mut format_string = String::new();
let mut args: Vec<&str> = Vec::new(); let mut args: Vec<&str> = Vec::new();
let f_string_flags = f_string.value.f_strings().next().map(|f| f.flags);
let is_raw = f_string_flags.is_some_and(|flags| flags.prefix().is_raw());
// Try to reuse the first part's quote style when building the replacement. // Try to reuse the first part's quote style when building the replacement.
// Default to double quotes if we can't determine it. // Default to double quotes if we can't determine it.
let quote_str = f_string let quote_str = f_string
.value .value
.iter() .iter()
.map(|part| match part { .map(|part| match part {
ast::FStringPart::Literal(literal) => literal.flags.quote_str(), FStringPart::Literal(literal) => literal.flags.quote_str(),
ast::FStringPart::FString(f) => f.flags.quote_str(), FStringPart::FString(f) => f.flags.quote_str(),
}) })
.next() .next()
.unwrap_or("\""); .unwrap_or("\"");
for part in &f_string.value { for part in &f_string.value {
match part { match part {
ast::FStringPart::Literal(literal) => { FStringPart::Literal(literal) => {
let literal_text = literal.as_str(); let literal_text = literal.as_str();
if literal_text.contains('%') { if literal_text.contains('%') {
return; return;
} }
format_string.push_str(literal_text); format_string.push_str(literal_text);
} }
ast::FStringPart::FString(f) => { FStringPart::FString(f) => {
for element in &f.elements { for element in &f.elements {
match element { match element {
InterpolatedStringElement::Literal(lit) => { InterpolatedStringElement::Literal(lit) => {
@ -99,13 +102,23 @@ fn logging_f_string(
} }
let replacement = format!( let replacement = format!(
"{q}{format_string}{q}, {args}", "{prefix}{q}{format_string}{q}, {args}",
prefix = if is_raw { "r" } else { "" },
q = quote_str, q = quote_str,
format_string = format_string,
args = args.join(", ") args = args.join(", ")
); );
let fix = Fix::safe_edit(Edit::range_replacement(replacement, msg.range())); // Replace the full message argument, including redundant grouping parentheses
// around the f-string expression (e.g., `logging.warning((f"{Ellipsis}"))`).
let replace_range = parenthesized_range(
msg.into(),
(arguments).into(),
checker.comment_ranges(),
checker.source(),
)
.unwrap_or_else(|| msg.range());
let fix = Fix::safe_edit(Edit::range_replacement(replacement, replace_range));
diagnostic.set_fix(fix); diagnostic.set_fix(fix);
} }

View File

@ -217,5 +217,39 @@ G004 Logging statement uses f-string
65 | x = 1 65 | x = 1
66 | logging.error(f"{x} -> %s", x) 66 | logging.error(f"{x} -> %s", x)
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
67 |
68 | # https://github.com/astral-sh/ruff/issues/20151
|
help: Convert to lazy `%` formatting
G004 Logging statement uses f-string
--> G004.py:69:17
|
68 | # https://github.com/astral-sh/ruff/issues/20151
69 | logging.warning(fr"\'{x}")
| ^^^^^^^^^
70 | logging.warning(f"{x}" "!")
71 | logging.warning((f"{x}"))
|
help: Convert to lazy `%` formatting
G004 Logging statement uses f-string
--> G004.py:70:17
|
68 | # https://github.com/astral-sh/ruff/issues/20151
69 | logging.warning(fr"\'{x}")
70 | logging.warning(f"{x}" "!")
| ^^^^^^^^^^
71 | logging.warning((f"{x}"))
|
help: Convert to lazy `%` formatting
G004 Logging statement uses f-string
--> G004.py:71:18
|
69 | logging.warning(fr"\'{x}")
70 | logging.warning(f"{x}" "!")
71 | logging.warning((f"{x}"))
| ^^^^^^
| |
help: Convert to lazy `%` formatting help: Convert to lazy `%` formatting

View File

@ -273,5 +273,57 @@ G004 Logging statement uses f-string
65 | x = 1 65 | x = 1
66 | logging.error(f"{x} -> %s", x) 66 | logging.error(f"{x} -> %s", x)
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
67 |
68 | # https://github.com/astral-sh/ruff/issues/20151
| |
help: Convert to lazy `%` formatting help: Convert to lazy `%` formatting
G004 [*] Logging statement uses f-string
--> G004.py:69:17
|
68 | # https://github.com/astral-sh/ruff/issues/20151
69 | logging.warning(fr"\'{x}")
| ^^^^^^^^^
70 | logging.warning(f"{x}" "!")
71 | logging.warning((f"{x}"))
|
help: Convert to lazy `%` formatting
66 | logging.error(f"{x} -> %s", x)
67 |
68 | # https://github.com/astral-sh/ruff/issues/20151
- logging.warning(fr"\'{x}")
69 + logging.warning(r"\'%s", x)
70 | logging.warning(f"{x}" "!")
71 | logging.warning((f"{x}"))
G004 [*] Logging statement uses f-string
--> G004.py:70:17
|
68 | # https://github.com/astral-sh/ruff/issues/20151
69 | logging.warning(fr"\'{x}")
70 | logging.warning(f"{x}" "!")
| ^^^^^^^^^^
71 | logging.warning((f"{x}"))
|
help: Convert to lazy `%` formatting
67 |
68 | # https://github.com/astral-sh/ruff/issues/20151
69 | logging.warning(fr"\'{x}")
- logging.warning(f"{x}" "!")
70 + logging.warning("%s!", x)
71 | logging.warning((f"{x}"))
G004 [*] Logging statement uses f-string
--> G004.py:71:18
|
69 | logging.warning(fr"\'{x}")
70 | logging.warning(f"{x}" "!")
71 | logging.warning((f"{x}"))
| ^^^^^^
|
help: Convert to lazy `%` formatting
68 | # https://github.com/astral-sh/ruff/issues/20151
69 | logging.warning(fr"\'{x}")
70 | logging.warning(f"{x}" "!")
- logging.warning((f"{x}"))
71 + logging.warning("%s", x)