Respect trailing comma in unnecessary-dict-kwargs (#9015)

Closes https://github.com/astral-sh/ruff/issues/9014.
This commit is contained in:
Charlie Marsh 2023-12-05 16:30:29 -05:00 committed by GitHub
parent 268d95e911
commit 958702ded0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 38 additions and 10 deletions

View file

@ -10,7 +10,6 @@ Foo.objects.create(**{**bar}) # PIE804
foo(**{})
foo(**{**data, "foo": "buzz"})
foo(**buzz)
foo(**{"bar-foo": True})
@ -20,3 +19,5 @@ foo(**{buzz: True})
foo(**{"": True})
foo(**{f"buzz__{bar}": True})
abc(**{"for": 3})
foo(**{},)

View file

@ -543,7 +543,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
flake8_bugbear::rules::no_explicit_stacklevel(checker, call);
}
if checker.enabled(Rule::UnnecessaryDictKwargs) {
flake8_pie::rules::unnecessary_dict_kwargs(checker, expr, keywords);
flake8_pie::rules::unnecessary_dict_kwargs(checker, call);
}
if checker.enabled(Rule::UnnecessaryRangeStart) {
flake8_pie::rules::unnecessary_range_start(checker, call);

View file

@ -1,6 +1,6 @@
use itertools::Itertools;
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
use ruff_python_ast::{self as ast, Expr, Keyword};
use ruff_python_ast::{self as ast, Expr};
use ruff_macros::{derive_message_formats, violation};
use ruff_text_size::Ranged;
@ -8,6 +8,7 @@ use ruff_text_size::Ranged;
use ruff_python_stdlib::identifiers::is_identifier;
use crate::checkers::ast::Checker;
use crate::fix::edits::{remove_argument, Parentheses};
/// ## What it does
/// Checks for unnecessary `dict` kwargs.
@ -52,8 +53,8 @@ impl AlwaysFixableViolation for UnnecessaryDictKwargs {
}
/// PIE804
pub(crate) fn unnecessary_dict_kwargs(checker: &mut Checker, expr: &Expr, kwargs: &[Keyword]) {
for kw in kwargs {
pub(crate) fn unnecessary_dict_kwargs(checker: &mut Checker, call: &ast::ExprCall) {
for kw in &call.arguments.keywords {
// keyword is a spread operator (indicated by None)
if kw.arg.is_some() {
continue;
@ -65,7 +66,7 @@ pub(crate) fn unnecessary_dict_kwargs(checker: &mut Checker, expr: &Expr, kwargs
// Ex) `foo(**{**bar})`
if matches!(keys.as_slice(), [None]) {
let mut diagnostic = Diagnostic::new(UnnecessaryDictKwargs, expr.range());
let mut diagnostic = Diagnostic::new(UnnecessaryDictKwargs, call.range());
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
format!("**{}", checker.locator().slice(values[0].range())),
@ -86,10 +87,18 @@ pub(crate) fn unnecessary_dict_kwargs(checker: &mut Checker, expr: &Expr, kwargs
continue;
}
let mut diagnostic = Diagnostic::new(UnnecessaryDictKwargs, expr.range());
let mut diagnostic = Diagnostic::new(UnnecessaryDictKwargs, call.range());
if values.is_empty() {
diagnostic.set_fix(Fix::safe_edit(Edit::deletion(kw.start(), kw.end())));
diagnostic.try_set_fix(|| {
remove_argument(
kw,
&call.arguments,
Parentheses::Preserve,
checker.locator().contents(),
)
.map(Fix::safe_edit)
});
} else {
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
kwargs

View file

@ -106,6 +106,8 @@ PIE804.py:11:1: PIE804 [*] Unnecessary `dict` kwargs
10 |
11 | foo(**{})
| ^^^^^^^^^ PIE804
12 |
13 | foo(**{**data, "foo": "buzz"})
|
= help: Remove unnecessary kwargs
@ -116,7 +118,23 @@ PIE804.py:11:1: PIE804 [*] Unnecessary `dict` kwargs
11 |-foo(**{})
11 |+foo()
12 12 |
13 13 |
14 14 | foo(**{**data, "foo": "buzz"})
13 13 | foo(**{**data, "foo": "buzz"})
14 14 | foo(**buzz)
PIE804.py:23:1: PIE804 [*] Unnecessary `dict` kwargs
|
21 | abc(**{"for": 3})
22 |
23 | foo(**{},)
| ^^^^^^^^^^ PIE804
|
= help: Remove unnecessary kwargs
Safe fix
20 20 | foo(**{f"buzz__{bar}": True})
21 21 | abc(**{"for": 3})
22 22 |
23 |-foo(**{},)
23 |+foo()