[ruff] Fix false negative for empty f-strings in deque calls (RUF037) (#20109)

## Summary

Fixes #20050
This commit is contained in:
Dan Parizher 2025-08-28 16:58:39 -04:00 committed by GitHub
parent b6522cb534
commit 26082e8ec1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 24 additions and 2 deletions

View file

@ -107,3 +107,6 @@ deque(f"{x}" "") # OK
deque(t"")
deque(t"" t"")
deque(t"{""}") # OK
# https://github.com/astral-sh/ruff/issues/20050
deque(f"{""}") # RUF037

View file

@ -1,5 +1,7 @@
use ruff_diagnostics::{Applicability, Edit};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::is_empty_f_string;
use ruff_python_ast::parenthesize::parenthesized_range;
use ruff_python_ast::{self as ast, Expr};
use ruff_text_size::Ranged;
@ -102,7 +104,7 @@ pub(crate) fn unnecessary_literal_within_deque_call(checker: &Checker, deque: &a
}
Expr::StringLiteral(string) => string.value.is_empty(),
Expr::BytesLiteral(bytes) => bytes.value.is_empty(),
Expr::FString(fstring) => fstring.value.is_empty_literal(),
Expr::FString(fstring) => is_empty_f_string(fstring),
Expr::TString(tstring) => tstring.value.is_empty_iterable(),
_ => false,
};

View file

@ -369,6 +369,7 @@ help: Replace with `deque()`
107 + deque()
108 | deque(t"" t"")
109 | deque(t"{""}") # OK
110 |
RUF037 [*] Unnecessary empty iterable within a deque call
--> RUF037.py:108:1
@ -386,3 +387,19 @@ help: Replace with `deque()`
- deque(t"" t"")
108 + deque()
109 | deque(t"{""}") # OK
110 |
111 | # https://github.com/astral-sh/ruff/issues/20050
RUF037 [*] Unnecessary empty iterable within a deque call
--> RUF037.py:112:1
|
111 | # https://github.com/astral-sh/ruff/issues/20050
112 | deque(f"{""}") # RUF037
| ^^^^^^^^^^^^^^
|
help: Replace with `deque()`
109 | deque(t"{""}") # OK
110 |
111 | # https://github.com/astral-sh/ruff/issues/20050
- deque(f"{""}") # RUF037
112 + deque() # RUF037

View file

@ -1406,7 +1406,7 @@ fn is_non_empty_f_string(expr: &ast::ExprFString) -> bool {
/// Returns `true` if the expression definitely resolves to the empty string, when used as an f-string
/// expression.
fn is_empty_f_string(expr: &ast::ExprFString) -> bool {
pub fn is_empty_f_string(expr: &ast::ExprFString) -> bool {
fn inner(expr: &Expr) -> bool {
match expr {
Expr::StringLiteral(ast::ExprStringLiteral { value, .. }) => value.is_empty(),