Add flake8-pie PIE800: no-unnecessary-spread (#1881)

Checks for unnecessary spreads, like `{**foo, **{"bar": True}}`
rel: https://github.com/charliermarsh/ruff/issues/1879
rel: https://github.com/charliermarsh/ruff/issues/1543
This commit is contained in:
Steve Dignam 2023-01-22 21:43:34 -05:00 committed by GitHub
parent 4ca328f964
commit 0c624af036
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 97 additions and 2 deletions

View File

@ -1151,6 +1151,7 @@ For more, see [flake8-pie](https://pypi.org/project/flake8-pie/) on PyPI.
| PIE790 | no-unnecessary-pass | Unnecessary `pass` statement | 🛠 |
| PIE794 | dupe-class-field-definitions | Class field `{name}` is defined multiple times | 🛠 |
| PIE796 | prefer-unique-enums | Enum contains duplicate value: `{value}` | |
| PIE800 | no-unnecessary-spread | Unnecessary spread `**` | |
| PIE804 | no-unnecessary-dict-kwargs | Unnecessary `dict` kwargs | |
| PIE807 | prefer-list-builtin | Prefer `list` over useless lambda | 🛠 |

View File

@ -0,0 +1,17 @@
{"foo": 1, **{"bar": 1}} # PIE800
foo({**foo, **{"bar": True}}) # PIE800
{**foo, **{"bar": 10}} # PIE800
{**foo, **buzz, **{bar: 10}} # PIE800
{**foo, "bar": True } # OK
{"foo": 1, "buzz": {"bar": 1}} # OK
{**foo, "bar": True } # OK
Table.objects.filter(inst=inst, **{f"foo__{bar}__exists": True}) # OK
buzz = {**foo, "bar": { 1: 2 }} # OK

View File

@ -1553,6 +1553,7 @@
"PIE796",
"PIE8",
"PIE80",
"PIE800",
"PIE804",
"PIE807",
"PL",

View File

@ -2596,6 +2596,10 @@ where
{
pyflakes::rules::repeated_keys(self, keys, values);
}
if self.settings.rules.enabled(&Rule::NoUnnecessarySpread) {
flake8_pie::rules::no_unnecessary_spread(self, keys, values);
}
}
ExprKind::Yield { .. } => {
if self.settings.rules.enabled(&Rule::YieldOutsideFunction) {

View File

@ -413,6 +413,7 @@ ruff_macros::define_rule_mapping!(
PIE790 => violations::NoUnnecessaryPass,
PIE794 => violations::DupeClassFieldDefinitions,
PIE796 => violations::PreferUniqueEnums,
PIE800 => violations::NoUnnecessarySpread,
PIE804 => violations::NoUnnecessaryDictKwargs,
PIE807 => violations::PreferListBuiltin,
// flake8-commas

View File

@ -12,11 +12,12 @@ mod tests {
use crate::registry::Rule;
use crate::settings;
#[test_case(Rule::NoUnnecessaryPass, Path::new("PIE790.py"); "PIE790")]
#[test_case(Rule::DupeClassFieldDefinitions, Path::new("PIE794.py"); "PIE794")]
#[test_case(Rule::PreferUniqueEnums, Path::new("PIE796.py"); "PIE796")]
#[test_case(Rule::NoUnnecessaryDictKwargs, Path::new("PIE804.py"); "PIE804")]
#[test_case(Rule::NoUnnecessaryPass, Path::new("PIE790.py"); "PIE790")]
#[test_case(Rule::NoUnnecessarySpread, Path::new("PIE800.py"); "PIE800")]
#[test_case(Rule::PreferListBuiltin, Path::new("PIE807.py"); "PIE807")]
#[test_case(Rule::PreferUniqueEnums, Path::new("PIE796.py"); "PIE796")]
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
let snapshot = format!("{}_{}", rule_code.code(), path.to_string_lossy());
let diagnostics = test_path(

View File

@ -153,6 +153,21 @@ where
}
}
/// PIE800
pub fn no_unnecessary_spread(checker: &mut Checker, keys: &[Option<Expr>], values: &[Expr]) {
for item in keys.iter().zip(values.iter()) {
if let (None, value) = item {
// We only care about when the key is None which indicates a spread `**`
// inside a dict.
if let ExprKind::Dict { .. } = value.node {
let diagnostic =
Diagnostic::new(violations::NoUnnecessarySpread, Range::from_located(value));
checker.diagnostics.push(diagnostic);
}
}
}
}
/// Return `true` if a key is a valid keyword argument name.
fn is_valid_kwarg_name(key: &Expr) -> bool {
if let ExprKind::Constant {

View File

@ -0,0 +1,45 @@
---
source: src/rules/flake8_pie/mod.rs
expression: diagnostics
---
- kind:
NoUnnecessarySpread: ~
location:
row: 1
column: 13
end_location:
row: 1
column: 23
fix: ~
parent: ~
- kind:
NoUnnecessarySpread: ~
location:
row: 3
column: 14
end_location:
row: 3
column: 27
fix: ~
parent: ~
- kind:
NoUnnecessarySpread: ~
location:
row: 5
column: 10
end_location:
row: 5
column: 21
fix: ~
parent: ~
- kind:
NoUnnecessarySpread: ~
location:
row: 7
column: 18
end_location:
row: 7
column: 27
fix: ~
parent: ~

View File

@ -4984,6 +4984,16 @@ impl Violation for PreferUniqueEnums {
}
}
define_violation!(
pub struct NoUnnecessarySpread;
);
impl Violation for NoUnnecessarySpread {
#[derive_message_formats]
fn message(&self) -> String {
format!("Unnecessary spread `**`")
}
}
define_violation!(
pub struct NoUnnecessaryDictKwargs;
);