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(**{})
foo(**{**data, "foo": "buzz"}) foo(**{**data, "foo": "buzz"})
foo(**buzz) foo(**buzz)
foo(**{"bar-foo": True}) foo(**{"bar-foo": True})
@ -20,3 +19,5 @@ foo(**{buzz: True})
foo(**{"": True}) foo(**{"": True})
foo(**{f"buzz__{bar}": True}) foo(**{f"buzz__{bar}": True})
abc(**{"for": 3}) 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); flake8_bugbear::rules::no_explicit_stacklevel(checker, call);
} }
if checker.enabled(Rule::UnnecessaryDictKwargs) { 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) { if checker.enabled(Rule::UnnecessaryRangeStart) {
flake8_pie::rules::unnecessary_range_start(checker, call); flake8_pie::rules::unnecessary_range_start(checker, call);

View file

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

View file

@ -106,6 +106,8 @@ PIE804.py:11:1: PIE804 [*] Unnecessary `dict` kwargs
10 | 10 |
11 | foo(**{}) 11 | foo(**{})
| ^^^^^^^^^ PIE804 | ^^^^^^^^^ PIE804
12 |
13 | foo(**{**data, "foo": "buzz"})
| |
= help: Remove unnecessary kwargs = help: Remove unnecessary kwargs
@ -116,7 +118,23 @@ PIE804.py:11:1: PIE804 [*] Unnecessary `dict` kwargs
11 |-foo(**{}) 11 |-foo(**{})
11 |+foo() 11 |+foo()
12 12 | 12 12 |
13 13 | 13 13 | foo(**{**data, "foo": "buzz"})
14 14 | 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()