[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"")
deque(t"" t"") deque(t"" t"")
deque(t"{""}") # OK 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_diagnostics::{Applicability, Edit};
use ruff_macros::{ViolationMetadata, derive_message_formats}; 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::parenthesize::parenthesized_range;
use ruff_python_ast::{self as ast, Expr}; use ruff_python_ast::{self as ast, Expr};
use ruff_text_size::Ranged; 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::StringLiteral(string) => string.value.is_empty(),
Expr::BytesLiteral(bytes) => bytes.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(), Expr::TString(tstring) => tstring.value.is_empty_iterable(),
_ => false, _ => false,
}; };

View file

@ -369,6 +369,7 @@ help: Replace with `deque()`
107 + deque() 107 + deque()
108 | deque(t"" t"") 108 | deque(t"" t"")
109 | deque(t"{""}") # OK 109 | deque(t"{""}") # OK
110 |
RUF037 [*] Unnecessary empty iterable within a deque call RUF037 [*] Unnecessary empty iterable within a deque call
--> RUF037.py:108:1 --> RUF037.py:108:1
@ -386,3 +387,19 @@ help: Replace with `deque()`
- deque(t"" t"") - deque(t"" t"")
108 + deque() 108 + deque()
109 | deque(t"{""}") # OK 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 /// Returns `true` if the expression definitely resolves to the empty string, when used as an f-string
/// expression. /// 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 { fn inner(expr: &Expr) -> bool {
match expr { match expr {
Expr::StringLiteral(ast::ExprStringLiteral { value, .. }) => value.is_empty(), Expr::StringLiteral(ast::ExprStringLiteral { value, .. }) => value.is_empty(),