Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add flake8-pie plugin with prefer_list_builtin #1578

Merged
merged 5 commits into from
Jan 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ of [Conda](https://docs.conda.io/en/latest/):
1. [pandas-vet (PD)](#pandas-vet-pd)
1. [pygrep-hooks (PGH)](#pygrep-hooks-pgh)
1. [Pylint (PLC, PLE, PLR, PLW)](#pylint-plc-ple-plr-plw)
1. [flake8-pie (PIE)](#flake8-pie-pie)
1. [Ruff-specific rules (RUF)](#ruff-specific-rules-ruf)<!-- End auto-generated table of contents. -->
1. [Editor Integrations](#editor-integrations)
1. [FAQ](#faq)
Expand Down Expand Up @@ -1052,6 +1053,14 @@ For more, see [Pylint](https://pypi.org/project/pylint/2.15.7/) on PyPI.
| PLW0120 | UselessElseOnLoop | Else clause on loop without a break statement, remove the else and de-indent all the code inside it | |
| PLW0602 | GlobalVariableNotAssigned | Using global for `...` but no assignment is done | |

### flake8-pie (PIE)

For more, see [flake8-pie](https://pypi.org/project/flake8-pie/0.16.0/) on PyPI.

| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| PIE807 | PreferListBuiltin | | 🛠 |

### Ruff-specific rules (RUF)

| Code | Name | Message | Fix |
Expand Down Expand Up @@ -1331,6 +1340,7 @@ natively, including:
- [`flake8-errmsg`](https://pypi.org/project/flake8-errmsg/)
- [`flake8-implicit-str-concat`](https://pypi.org/project/flake8-implicit-str-concat/)
- [`flake8-import-conventions`](https://github.com/joaopalmeiro/flake8-import-conventions)
- [`flake8-pie`](https://pypi.org/project/flake8-pie/) (1/7)
- [`flake8-print`](https://pypi.org/project/flake8-print/)
- [`flake8-quotes`](https://pypi.org/project/flake8-quotes/)
- [`flake8-return`](https://pypi.org/project/flake8-return/)
Expand Down Expand Up @@ -1388,6 +1398,7 @@ Today, Ruff can be used to replace Flake8 when used with any of the following pl
- [`flake8-errmsg`](https://pypi.org/project/flake8-errmsg/)
- [`flake8-implicit-str-concat`](https://pypi.org/project/flake8-implicit-str-concat/)
- [`flake8-import-conventions`](https://github.com/joaopalmeiro/flake8-import-conventions)
- [`flake8-pie`](https://pypi.org/project/flake8-pie/) (1/7)
- [`flake8-print`](https://pypi.org/project/flake8-print/)
- [`flake8-quotes`](https://pypi.org/project/flake8-quotes/)
- [`flake8-return`](https://pypi.org/project/flake8-return/)
Expand Down
20 changes: 20 additions & 0 deletions resources/test/fixtures/flake8_pie/PIE807.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
@dataclass
class Foo:
foo: List[str] = field(default_factory=lambda: []) # PIE807


class FooTable(BaseTable):
bar = fields.ListField(default=lambda: []) # PIE807


class FooTable(BaseTable):
bar = fields.ListField(lambda: []) # PIE807


@dataclass
class Foo:
foo: List[str] = field(default_factory=list)


class FooTable(BaseTable):
bar = fields.ListField(list)
4 changes: 4 additions & 0 deletions ruff.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,10 @@
"PGH002",
"PGH003",
"PGH004",
"PIE",
"PIE8",
"PIE80",
"PIE807",
"PLC",
"PLC0",
"PLC04",
Expand Down
10 changes: 7 additions & 3 deletions src/checkers/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ use crate::{
docstrings, flake8_2020, flake8_annotations, flake8_bandit, flake8_blind_except,
flake8_boolean_trap, flake8_bugbear, flake8_builtins, flake8_comprehensions, flake8_datetimez,
flake8_debugger, flake8_errmsg, flake8_implicit_str_concat, flake8_import_conventions,
flake8_print, flake8_pytest_style, flake8_return, flake8_simplify, flake8_tidy_imports,
flake8_unused_arguments, mccabe, noqa, pandas_vet, pep8_naming, pycodestyle, pydocstyle,
pyflakes, pygrep_hooks, pylint, pyupgrade, ruff, visibility,
flake8_pie, flake8_print, flake8_pytest_style, flake8_return, flake8_simplify,
flake8_tidy_imports, flake8_unused_arguments, mccabe, noqa, pandas_vet, pep8_naming,
pycodestyle, pydocstyle, pyflakes, pygrep_hooks, pylint, pyupgrade, ruff, visibility,
};

const GLOBAL_SCOPE_INDEX: usize = 0;
Expand Down Expand Up @@ -2521,6 +2521,10 @@ where
}
}
ExprKind::Lambda { args, body, .. } => {
if self.settings.enabled.contains(&CheckCode::PIE807) {
flake8_pie::plugins::prefer_list_builtin(self, expr);
}

// Visit the arguments, but avoid the body, which will be deferred.
for arg in &args.posonlyargs {
if let Some(expr) = &arg.node.annotation {
Expand Down
27 changes: 27 additions & 0 deletions src/flake8_pie/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
pub mod plugins;

#[cfg(test)]
mod tests {
use std::convert::AsRef;
use std::path::Path;

use anyhow::Result;
use test_case::test_case;

use crate::linter::test_path;
use crate::registry::CheckCode;
use crate::settings;

#[test_case(CheckCode::PIE807, Path::new("PIE807.py"); "PIE807")]
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
let checks = test_path(
Path::new("./resources/test/fixtures/flake8_pie")
.join(path)
.as_path(),
&settings::Settings::for_rule(check_code),
)?;
insta::assert_yaml_snapshot!(snapshot, checks);
Ok(())
}
}
28 changes: 28 additions & 0 deletions src/flake8_pie/plugins.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use rustpython_ast::{Expr, ExprKind};

use crate::ast::types::Range;
use crate::autofix::Fix;
use crate::checkers::ast::Checker;
use crate::registry::{Check, CheckCode, CheckKind};

/// PIE807
pub fn prefer_list_builtin(checker: &mut Checker, expr: &Expr) {
let ExprKind::Lambda { args, body } = &expr.node else {
unreachable!("Expected ExprKind::Lambda");
};
if args.args.is_empty() {
if let ExprKind::List { elts, .. } = &body.node {
if elts.is_empty() {
let mut check = Check::new(CheckKind::PreferListBuiltin, Range::from_located(expr));
if checker.patch(&CheckCode::PIE807) {
check.amend(Fix::replacement(
"list".to_string(),
expr.location,
expr.end_location.unwrap(),
));
}
checker.add_check(check);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
source: src/flake8_pie/mod.rs
expression: checks
---
- kind: PreferListBuiltin
location:
row: 3
column: 43
end_location:
row: 3
column: 53
fix:
content: list
location:
row: 3
column: 43
end_location:
row: 3
column: 53
parent: ~
- kind: PreferListBuiltin
location:
row: 7
column: 35
end_location:
row: 7
column: 45
fix:
content: list
location:
row: 7
column: 35
end_location:
row: 7
column: 45
parent: ~
- kind: PreferListBuiltin
location:
row: 11
column: 27
end_location:
row: 11
column: 37
fix:
content: list
location:
row: 11
column: 27
end_location:
row: 11
column: 37
parent: ~

1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,4 @@ cfg_if! {
pub use lib_wasm::check;
}
}
pub mod flake8_pie;
25 changes: 23 additions & 2 deletions src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,8 @@ pub enum CheckCode {
PT024,
PT025,
PT026,
// flake8-pie
PIE807,
// Ruff
RUF001,
RUF002,
Expand Down Expand Up @@ -430,6 +432,7 @@ pub enum CheckCategory {
PandasVet,
PygrepHooks,
Pylint,
Flake8Pie,
Ruff,
}

Expand Down Expand Up @@ -481,6 +484,7 @@ impl CheckCategory {
CheckCategory::PygrepHooks => "pygrep-hooks",
CheckCategory::Pylint => "Pylint",
CheckCategory::Pyupgrade => "pyupgrade",
CheckCategory::Flake8Pie => "flake8-pie",
CheckCategory::Ruff => "Ruff-specific rules",
}
}
Expand Down Expand Up @@ -523,6 +527,7 @@ impl CheckCategory {
CheckCodePrefix::PLW,
],
CheckCategory::Pyupgrade => vec![CheckCodePrefix::UP],
CheckCategory::Flake8Pie => vec![CheckCodePrefix::PIE],
CheckCategory::Ruff => vec![CheckCodePrefix::RUF],
}
}
Expand Down Expand Up @@ -644,6 +649,10 @@ impl CheckCategory {
CheckCategory::Pyupgrade => {
Some(("https://pypi.org/project/pyupgrade/3.2.0/", &Platform::PyPI))
}
CheckCategory::Flake8Pie => Some((
"https://pypi.org/project/flake8-pie/0.16.0/",
&Platform::PyPI,
)),
CheckCategory::Ruff => None,
}
}
Expand Down Expand Up @@ -1105,6 +1114,8 @@ pub enum CheckKind {
UnnecessaryAsyncioMarkOnFixture,
ErroneousUseFixturesOnFixture,
UseFixturesWithoutParameters,
// flake8-pie
PreferListBuiltin,
// Ruff
AmbiguousUnicodeCharacterString(char, char),
AmbiguousUnicodeCharacterDocstring(char, char),
Expand Down Expand Up @@ -1556,6 +1567,8 @@ impl CheckCode {
CheckCode::PT024 => CheckKind::UnnecessaryAsyncioMarkOnFixture,
CheckCode::PT025 => CheckKind::ErroneousUseFixturesOnFixture,
CheckCode::PT026 => CheckKind::UseFixturesWithoutParameters,
// flake8-pie
CheckCode::PIE807 => CheckKind::PreferListBuiltin,
// Ruff
CheckCode::RUF001 => CheckKind::AmbiguousUnicodeCharacterString('𝐁', 'B'),
CheckCode::RUF002 => CheckKind::AmbiguousUnicodeCharacterDocstring('𝐁', 'B'),
Expand Down Expand Up @@ -1920,6 +1933,8 @@ impl CheckCode {
CheckCode::YTT301 => CheckCategory::Flake82020,
CheckCode::YTT302 => CheckCategory::Flake82020,
CheckCode::YTT303 => CheckCategory::Flake82020,
// flake8-pie
CheckCode::PIE807 => CheckCategory::Flake8Pie,
// Ruff
CheckCode::RUF001 => CheckCategory::Ruff,
CheckCode::RUF002 => CheckCategory::Ruff,
Expand Down Expand Up @@ -2285,6 +2300,8 @@ impl CheckKind {
CheckKind::UnnecessaryAsyncioMarkOnFixture => &CheckCode::PT024,
CheckKind::ErroneousUseFixturesOnFixture => &CheckCode::PT025,
CheckKind::UseFixturesWithoutParameters => &CheckCode::PT026,
// flake8-pie
CheckKind::PreferListBuiltin => &CheckCode::PIE807,
// Ruff
CheckKind::AmbiguousUnicodeCharacterString(..) => &CheckCode::RUF001,
CheckKind::AmbiguousUnicodeCharacterDocstring(..) => &CheckCode::RUF002,
Expand Down Expand Up @@ -3335,6 +3352,8 @@ impl CheckKind {
CheckKind::UseFixturesWithoutParameters => {
"Useless `pytest.mark.usefixtures` without parameters".to_string()
}
// flake8-pie
CheckKind::PreferListBuiltin => String::new(),
// Ruff
CheckKind::AmbiguousUnicodeCharacterString(confusable, representant) => {
format!(
Expand Down Expand Up @@ -3491,19 +3510,20 @@ impl CheckKind {
| CheckKind::OpenAlias
| CheckKind::PEP3120UnnecessaryCodingComment
| CheckKind::PPrintFound
| CheckKind::ParametrizeNamesWrongType(..)
| CheckKind::PercentFormatExtraNamedArguments(..)
| CheckKind::PreferListBuiltin
| CheckKind::PrintFound
| CheckKind::ParametrizeNamesWrongType(..)
| CheckKind::RaiseNotImplemented
| CheckKind::RedundantOpenModes(..)
| CheckKind::RedundantTupleInExceptionHandler(..)
| CheckKind::RemoveSixCompat
| CheckKind::ReplaceStdoutStderr
| CheckKind::ReplaceUniversalNewlines
| CheckKind::RewriteCElementTree
| CheckKind::RewriteListComprehension
| CheckKind::RewriteMockImport(..)
| CheckKind::RewriteUnicodeLiteral
| CheckKind::RewriteListComprehension
| CheckKind::SectionNameEndsInColon(..)
| CheckKind::SectionNotOverIndented(..)
| CheckKind::SectionUnderlineAfterName(..)
Expand Down Expand Up @@ -3671,6 +3691,7 @@ impl CheckKind {
CheckKind::PEP3120UnnecessaryCodingComment => {
Some("Remove unnecessary coding comment".to_string())
}
CheckKind::PreferListBuiltin => Some("Replace with `list`".to_string()),
CheckKind::PPrintFound => Some("Remove `pprint`".to_string()),
CheckKind::PercentFormatExtraNamedArguments(missing)
| CheckKind::StringDotFormatExtraNamedArguments(missing) => {
Expand Down
14 changes: 14 additions & 0 deletions src/registry_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,10 @@ pub enum CheckCodePrefix {
PGH002,
PGH003,
PGH004,
PIE,
PIE8,
PIE80,
PIE807,
PLC,
PLC0,
PLC04,
Expand Down Expand Up @@ -944,6 +948,7 @@ impl CheckCodePrefix {
CheckCode::PT024,
CheckCode::PT025,
CheckCode::PT026,
CheckCode::PIE807,
CheckCode::RUF001,
CheckCode::RUF002,
CheckCode::RUF003,
Expand Down Expand Up @@ -2174,6 +2179,10 @@ impl CheckCodePrefix {
CheckCodePrefix::PGH002 => vec![CheckCode::PGH002],
CheckCodePrefix::PGH003 => vec![CheckCode::PGH003],
CheckCodePrefix::PGH004 => vec![CheckCode::PGH004],
CheckCodePrefix::PIE => vec![CheckCode::PIE807],
CheckCodePrefix::PIE8 => vec![CheckCode::PIE807],
CheckCodePrefix::PIE80 => vec![CheckCode::PIE807],
CheckCodePrefix::PIE807 => vec![CheckCode::PIE807],
CheckCodePrefix::PLC => {
vec![CheckCode::PLC0414, CheckCode::PLC2201, CheckCode::PLC3002]
}
Expand Down Expand Up @@ -3390,6 +3399,10 @@ impl CheckCodePrefix {
CheckCodePrefix::PGH002 => SuffixLength::Three,
CheckCodePrefix::PGH003 => SuffixLength::Three,
CheckCodePrefix::PGH004 => SuffixLength::Three,
CheckCodePrefix::PIE => SuffixLength::Zero,
CheckCodePrefix::PIE8 => SuffixLength::One,
CheckCodePrefix::PIE80 => SuffixLength::Two,
CheckCodePrefix::PIE807 => SuffixLength::Three,
CheckCodePrefix::PLC => SuffixLength::Zero,
CheckCodePrefix::PLC0 => SuffixLength::One,
CheckCodePrefix::PLC04 => SuffixLength::Two,
Expand Down Expand Up @@ -3634,6 +3647,7 @@ pub const CATEGORIES: &[CheckCodePrefix] = &[
CheckCodePrefix::N,
CheckCodePrefix::PD,
CheckCodePrefix::PGH,
CheckCodePrefix::PIE,
CheckCodePrefix::PLC,
CheckCodePrefix::PLE,
CheckCodePrefix::PLR,
Expand Down