Compare commits

...

3 Commits

Author SHA1 Message Date
Charlie Marsh
a710e35ebc Bump version to 0.0.170 2022-12-08 11:36:24 -05:00
Charlie Marsh
49df43bb78 Use single newlines in .pyi import sorting (#1142) 2022-12-08 11:34:41 -05:00
Charlie Marsh
e338d9acbe Remove 'consider' language from check messages (#1135) 2022-12-07 20:10:36 -05:00
27 changed files with 231 additions and 88 deletions

View File

@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.169
rev: v0.0.170
hooks:
- id: ruff

8
Cargo.lock generated
View File

@@ -724,7 +724,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "flake8-to-ruff"
version = "0.0.169-dev.0"
version = "0.0.170-dev.0"
dependencies = [
"anyhow",
"clap 4.0.29",
@@ -1821,7 +1821,7 @@ dependencies = [
[[package]]
name = "ruff"
version = "0.0.169"
version = "0.0.170"
dependencies = [
"annotate-snippets 0.9.1",
"anyhow",
@@ -1874,7 +1874,7 @@ dependencies = [
[[package]]
name = "ruff_dev"
version = "0.0.169"
version = "0.0.170"
dependencies = [
"anyhow",
"clap 4.0.29",
@@ -1892,7 +1892,7 @@ dependencies = [
[[package]]
name = "ruff_macros"
version = "0.0.169"
version = "0.0.170"
dependencies = [
"proc-macro2",
"quote",

View File

@@ -6,7 +6,7 @@ members = [
[package]
name = "ruff"
version = "0.0.169"
version = "0.0.170"
edition = "2021"
rust-version = "1.65.0"
@@ -41,7 +41,7 @@ quick-junit = { version = "0.3.2" }
rayon = { version = "1.5.3" }
regex = { version = "1.6.0" }
ropey = { version = "1.5.0", features = ["cr_lines", "simd"], default-features = false }
ruff_macros = { version = "0.0.169", path = "ruff_macros" }
ruff_macros = { version = "0.0.170", path = "ruff_macros" }
rustc-hash = { version = "1.1.0" }
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "28f9f65ccc625f00835d84bbb5fba274dce5aa89" }
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "28f9f65ccc625f00835d84bbb5fba274dce5aa89" }

View File

@@ -147,7 +147,7 @@ Ruff also works with [pre-commit](https://pre-commit.com):
```yaml
repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.169
rev: v0.0.170
hooks:
- id: ruff
```
@@ -808,9 +808,9 @@ For more, see [Pylint](https://pypi.org/project/pylint/2.15.7/) on PyPI.
| PLC3002 | UnnecessaryDirectLambdaCall | Lambda expression called directly. Execute the expression inline instead. | |
| PLE1142 | AwaitOutsideAsync | `await` should be used within an async function | |
| PLR0206 | PropertyWithParameters | Cannot have defined parameters for properties | |
| PLR0402 | ConsiderUsingFromImport | Consider using `from ... import ...` | |
| PLR1701 | ConsiderMergingIsinstance | Consider merging these isinstance calls: `isinstance(..., (...))` | |
| PLR1722 | ConsiderUsingSysExit | Consider using `sys.exit()` | 🛠 |
| PLR0402 | ConsiderUsingFromImport | Use `from ... import ...` in lieu of alias | |
| PLR1701 | ConsiderMergingIsinstance | Merge these isinstance calls: `isinstance(..., (...))` | |
| PLR1722 | UseSysExit | Use `sys.exit()` instead of `exit` | 🛠 |
| PLW0120 | UselessElseOnLoop | Else clause on loop without a break statement, remove the else and de-indent all the code inside it | |
### Ruff-specific rules (RUF)

View File

@@ -771,7 +771,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "flake8_to_ruff"
version = "0.0.169"
version = "0.0.170"
dependencies = [
"anyhow",
"clap",
@@ -1975,7 +1975,7 @@ dependencies = [
[[package]]
name = "ruff"
version = "0.0.169"
version = "0.0.170"
dependencies = [
"anyhow",
"bincode",

View File

@@ -1,6 +1,6 @@
[package]
name = "flake8-to-ruff"
version = "0.0.169-dev.0"
version = "0.0.170-dev.0"
edition = "2021"
[lib]

View File

@@ -0,0 +1,41 @@
import a
import b
x = 1
import os
import sys
def f():
pass
if True:
x = 1
import collections
import typing
class X: pass
y = 1
import os
import sys
"""Docstring"""
if True:
import os
def f():
pass
if True:
import os
def f():
pass
if True:
x = 1
import collections
import typing
class X: pass
if True:
x = 1
import collections
import typing
def f(): pass

View File

@@ -1,6 +1,6 @@
[package]
name = "ruff_dev"
version = "0.0.169"
version = "0.0.170"
edition = "2021"
[dependencies]

View File

@@ -1,6 +1,6 @@
[package]
name = "ruff_macros"
version = "0.0.169"
version = "0.0.170"
edition = "2021"
[lib]

View File

@@ -673,7 +673,7 @@ where
pylint::plugins::useless_import_alias(self, alias);
}
if self.settings.enabled.contains(&CheckCode::PLR0402) {
pylint::plugins::consider_using_from_import(self, alias);
pylint::plugins::use_from_import(self, alias);
}
if let Some(asname) = &alias.node.asname {
@@ -1773,7 +1773,7 @@ where
pylint::plugins::unnecessary_direct_lambda_call(self, expr, func);
}
if self.settings.enabled.contains(&CheckCode::PLR1722) {
pylint::plugins::consider_using_sys_exit(self, func);
pylint::plugins::use_sys_exit(self, func);
}
}
ExprKind::Dict { keys, .. } => {
@@ -2129,7 +2129,7 @@ where
}
ExprKind::BoolOp { op, values } => {
if self.settings.enabled.contains(&CheckCode::PLR1701) {
pylint::plugins::consider_merging_isinstance(self, expr, op, values);
pylint::plugins::merge_isinstance(self, expr, op, values);
}
}
_ => {}

View File

@@ -1,5 +1,7 @@
//! Lint rules based on import analysis.
use std::path::Path;
use rustpython_parser::ast::Suite;
use crate::ast::visitor::Visitor;
@@ -33,8 +35,9 @@ pub fn check_imports(
directives: &IsortDirectives,
settings: &Settings,
autofix: bool,
path: &Path,
) -> Vec<Check> {
let mut tracker = ImportTracker::new(directives);
let mut tracker = ImportTracker::new(directives, path);
for stmt in python_ast {
tracker.visit_stmt(stmt);
}

View File

@@ -638,7 +638,7 @@ pub enum CheckKind {
ConsiderUsingFromImport(String, String),
AwaitOutsideAsync,
UselessElseOnLoop,
ConsiderUsingSysExit,
UseSysExit(String),
// flake8-builtins
BuiltinVariableShadowing(String),
BuiltinArgumentShadowing(String),
@@ -950,7 +950,7 @@ impl CheckCode {
CheckCode::PLR1701 => {
CheckKind::ConsiderMergingIsinstance("...".to_string(), vec!["...".to_string()])
}
CheckCode::PLR1722 => CheckKind::ConsiderUsingSysExit,
CheckCode::PLR1722 => CheckKind::UseSysExit("exit".to_string()),
CheckCode::PLW0120 => CheckKind::UselessElseOnLoop,
// flake8-builtins
CheckCode::A001 => CheckKind::BuiltinVariableShadowing("...".to_string()),
@@ -1523,7 +1523,7 @@ impl CheckKind {
CheckKind::ConsiderMergingIsinstance(..) => &CheckCode::PLR1701,
CheckKind::PropertyWithParameters => &CheckCode::PLR0206,
CheckKind::ConsiderUsingFromImport(..) => &CheckCode::PLR0402,
CheckKind::ConsiderUsingSysExit => &CheckCode::PLR1722,
CheckKind::UseSysExit(_) => &CheckCode::PLR1722,
CheckKind::UselessElseOnLoop => &CheckCode::PLW0120,
// flake8-builtins
CheckKind::BuiltinVariableShadowing(_) => &CheckCode::A001,
@@ -1921,7 +1921,7 @@ impl CheckKind {
}
CheckKind::ConsiderMergingIsinstance(obj, types) => {
let types = types.join(", ");
format!("Consider merging these isinstance calls: `isinstance({obj}, ({types}))`")
format!("Merge these isinstance calls: `isinstance({obj}, ({types}))`")
}
CheckKind::MisplacedComparisonConstant(comprison) => {
format!("Comparison should be {comprison}")
@@ -1933,7 +1933,7 @@ impl CheckKind {
"Cannot have defined parameters for properties".to_string()
}
CheckKind::ConsiderUsingFromImport(module, name) => {
format!("Consider using `from {module} import {name}`")
format!("Use `from {module} import {name}` in lieu of alias")
}
CheckKind::AwaitOutsideAsync => {
"`await` should be used within an async function".to_string()
@@ -1941,7 +1941,7 @@ impl CheckKind {
CheckKind::UselessElseOnLoop => "Else clause on loop without a break statement, \
remove the else and de-indent all the code inside it"
.to_string(),
CheckKind::ConsiderUsingSysExit => "Consider using `sys.exit()`".to_string(),
CheckKind::UseSysExit(name) => format!("Use `sys.exit()` instead of `{name}`"),
// flake8-builtins
CheckKind::BuiltinVariableShadowing(name) => {
format!("Variable `{name}` is shadowing a python builtin")
@@ -2599,7 +2599,6 @@ impl CheckKind {
| CheckKind::BlankLineBeforeSection(..)
| CheckKind::CapitalizeSectionName(..)
| CheckKind::CommentedOutCode
| CheckKind::ConsiderUsingSysExit
| CheckKind::ConvertNamedTupleFunctionalToClass(..)
| CheckKind::ConvertTypedDictFunctionalToClass(..)
| CheckKind::DashedUnderlineAfterSection(..)
@@ -2665,6 +2664,7 @@ impl CheckKind {
| CheckKind::UnusedNOQA(..)
| CheckKind::UsePEP585Annotation(..)
| CheckKind::UsePEP604Annotation
| CheckKind::UseSysExit(..)
| CheckKind::UselessImportAlias
| CheckKind::UselessMetaclassType
| CheckKind::UselessObjectInheritance(..)

View File

@@ -559,6 +559,7 @@ mod tests {
#[test_case(Path::new("force_wrap_aliases.py"))]
#[test_case(Path::new("import_from_after_import.py"))]
#[test_case(Path::new("insert_empty_lines.py"))]
#[test_case(Path::new("insert_empty_lines.pyi"))]
#[test_case(Path::new("leading_prefix.py"))]
#[test_case(Path::new("no_reorder_within_section.py"))]
#[test_case(Path::new("no_wrap_star.py"))]

View File

@@ -0,0 +1,65 @@
---
source: src/isort/mod.rs
expression: checks
---
- kind: UnsortedImports
location:
row: 1
column: 0
end_location:
row: 3
column: 0
fix:
content: "import a\nimport b\n\n"
location:
row: 1
column: 0
end_location:
row: 3
column: 0
- kind: UnsortedImports
location:
row: 4
column: 0
end_location:
row: 6
column: 0
fix:
content: "import os\nimport sys\n\n"
location:
row: 4
column: 0
end_location:
row: 6
column: 0
- kind: UnsortedImports
location:
row: 14
column: 0
end_location:
row: 16
column: 0
fix:
content: "import os\nimport sys\n\n"
location:
row: 14
column: 0
end_location:
row: 16
column: 0
- kind: UnsortedImports
location:
row: 33
column: 0
end_location:
row: 35
column: 0
fix:
content: " import collections\n import typing\n\n"
location:
row: 33
column: 0
end_location:
row: 35
column: 0

View File

@@ -1,3 +1,5 @@
use std::path::Path;
use rustpython_ast::{
Alias, Arg, Arguments, Boolop, Cmpop, Comprehension, Constant, Excepthandler,
ExcepthandlerKind, Expr, ExprContext, Keyword, MatchCase, Operator, Pattern, Stmt, StmtKind,
@@ -20,16 +22,18 @@ pub struct Block<'a> {
}
pub struct ImportTracker<'a> {
blocks: Vec<Block<'a>>,
directives: &'a IsortDirectives,
pyi: bool,
blocks: Vec<Block<'a>>,
split_index: usize,
nested: bool,
}
impl<'a> ImportTracker<'a> {
pub fn new(directives: &'a IsortDirectives) -> Self {
pub fn new(directives: &'a IsortDirectives, path: &'a Path) -> Self {
Self {
directives,
pyi: path.extension().map_or(false, |ext| ext == "pyi"),
blocks: vec![Block::default()],
split_index: 0,
nested: false,
@@ -41,6 +45,34 @@ impl<'a> ImportTracker<'a> {
self.blocks[index].imports.push(stmt);
}
fn trailer_for(&self, stmt: &'a Stmt) -> Option<Trailer> {
if self.pyi {
// Black treats interface files differently, limiting to one newline
// (`Trailing::Sibling`), and avoiding inserting any newlines in nested function
// blocks.
if self.nested
&& matches!(
stmt.node,
StmtKind::FunctionDef { .. } | StmtKind::AsyncFunctionDef { .. }
)
{
None
} else {
Some(Trailer::Sibling)
}
} else if self.nested {
Some(Trailer::Sibling)
} else {
Some(match &stmt.node {
StmtKind::FunctionDef { .. } | StmtKind::AsyncFunctionDef { .. } => {
Trailer::FunctionDef
}
StmtKind::ClassDef { .. } => Trailer::ClassDef,
_ => Trailer::Sibling,
})
}
}
fn finalize(&mut self, trailer: Option<Trailer>) {
let index = self.blocks.len() - 1;
if !self.blocks[index].imports.is_empty() {
@@ -62,17 +94,7 @@ where
// Track manual splits.
while self.split_index < self.directives.splits.len() {
if stmt.location.row() >= self.directives.splits[self.split_index] {
self.finalize(Some(if self.nested {
Trailer::Sibling
} else {
match &stmt.node {
StmtKind::FunctionDef { .. } | StmtKind::AsyncFunctionDef { .. } => {
Trailer::FunctionDef
}
StmtKind::ClassDef { .. } => Trailer::ClassDef,
_ => Trailer::Sibling,
}
}));
self.finalize(self.trailer_for(stmt));
self.split_index += 1;
} else {
break;
@@ -87,17 +109,7 @@ where
{
self.track_import(stmt);
} else {
self.finalize(Some(if self.nested {
Trailer::Sibling
} else {
match &stmt.node {
StmtKind::FunctionDef { .. } | StmtKind::AsyncFunctionDef { .. } => {
Trailer::FunctionDef
}
StmtKind::ClassDef { .. } => Trailer::ClassDef,
_ => Trailer::Sibling,
}
}));
self.finalize(self.trailer_for(stmt));
}
// Track scope.

View File

@@ -92,6 +92,7 @@ pub(crate) fn check_path(
&directives.isort,
settings,
autofix,
path,
));
}
}

View File

@@ -8,12 +8,7 @@ use crate::checks::CheckKind;
use crate::Check;
/// PLR1701
pub fn consider_merging_isinstance(
checker: &mut Checker,
expr: &Expr,
op: &Boolop,
values: &[Expr],
) {
pub fn merge_isinstance(checker: &mut Checker, expr: &Expr, op: &Boolop, values: &[Expr]) {
if !matches!(op, Boolop::Or) || !checker.is_builtin("isinstance") {
return;
}

View File

@@ -1,19 +1,19 @@
pub use await_outside_async::await_outside_async;
pub use consider_merging_isinstance::consider_merging_isinstance;
pub use consider_using_from_import::consider_using_from_import;
pub use consider_using_sys_exit::consider_using_sys_exit;
pub use merge_isinstance::merge_isinstance;
pub use misplaced_comparison_constant::misplaced_comparison_constant;
pub use property_with_parameters::property_with_parameters;
pub use unnecessary_direct_lambda_call::unnecessary_direct_lambda_call;
pub use use_from_import::use_from_import;
pub use use_sys_exit::use_sys_exit;
pub use useless_else_on_loop::useless_else_on_loop;
pub use useless_import_alias::useless_import_alias;
mod await_outside_async;
mod consider_merging_isinstance;
mod consider_using_from_import;
mod consider_using_sys_exit;
mod merge_isinstance;
mod misplaced_comparison_constant;
mod property_with_parameters;
mod unnecessary_direct_lambda_call;
mod use_from_import;
mod use_sys_exit;
mod useless_else_on_loop;
mod useless_import_alias;

View File

@@ -6,7 +6,7 @@ use crate::checks::CheckKind;
use crate::Check;
/// PLR0402
pub fn consider_using_from_import(checker: &mut Checker, alias: &Alias) {
pub fn use_from_import(checker: &mut Checker, alias: &Alias) {
let Some(asname) = &alias.node.asname else {
return;
};

View File

@@ -60,7 +60,7 @@ fn get_member_import_name_alias(checker: &Checker, module: &str, member: &str) -
}
/// RUF004
pub fn consider_using_sys_exit(checker: &mut Checker, func: &Expr) {
pub fn use_sys_exit(checker: &mut Checker, func: &Expr) {
let ExprKind::Name { id, .. } = &func.node else {
return;
};
@@ -74,7 +74,10 @@ pub fn consider_using_sys_exit(checker: &mut Checker, func: &Expr) {
if !checker.is_builtin(name) {
continue;
}
let mut check = Check::new(CheckKind::ConsiderUsingSysExit, Range::from_located(func));
let mut check = Check::new(
CheckKind::UseSysExit(name.to_string()),
Range::from_located(func),
);
if checker.patch(check.kind.code()) {
if let Some(content) = get_member_import_name_alias(checker, "sys", "exit") {
check.amend(Fix::replacement(

View File

@@ -2,7 +2,8 @@
source: src/pylint/mod.rs
expression: checks
---
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: exit
location:
row: 1
column: 0
@@ -10,7 +11,8 @@ expression: checks
row: 1
column: 4
fix: ~
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: quit
location:
row: 2
column: 0
@@ -18,7 +20,8 @@ expression: checks
row: 2
column: 4
fix: ~
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: exit
location:
row: 6
column: 4
@@ -26,7 +29,8 @@ expression: checks
row: 6
column: 8
fix: ~
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: quit
location:
row: 7
column: 4

View File

@@ -2,7 +2,8 @@
source: src/pylint/mod.rs
expression: checks
---
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: exit
location:
row: 3
column: 0
@@ -17,7 +18,8 @@ expression: checks
end_location:
row: 3
column: 4
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: quit
location:
row: 4
column: 0
@@ -32,7 +34,8 @@ expression: checks
end_location:
row: 4
column: 4
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: exit
location:
row: 8
column: 4
@@ -47,7 +50,8 @@ expression: checks
end_location:
row: 8
column: 8
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: quit
location:
row: 9
column: 4

View File

@@ -2,7 +2,8 @@
source: src/pylint/mod.rs
expression: checks
---
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: exit
location:
row: 3
column: 0
@@ -17,7 +18,8 @@ expression: checks
end_location:
row: 3
column: 4
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: quit
location:
row: 4
column: 0
@@ -32,7 +34,8 @@ expression: checks
end_location:
row: 4
column: 4
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: exit
location:
row: 8
column: 4
@@ -47,7 +50,8 @@ expression: checks
end_location:
row: 8
column: 8
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: quit
location:
row: 9
column: 4

View File

@@ -2,7 +2,8 @@
source: src/pylint/mod.rs
expression: checks
---
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: quit
location:
row: 4
column: 0
@@ -17,7 +18,8 @@ expression: checks
end_location:
row: 4
column: 4
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: quit
location:
row: 9
column: 4

View File

@@ -2,7 +2,8 @@
source: src/pylint/mod.rs
expression: checks
---
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: exit
location:
row: 3
column: 0
@@ -17,7 +18,8 @@ expression: checks
end_location:
row: 3
column: 4
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: quit
location:
row: 4
column: 0
@@ -32,7 +34,8 @@ expression: checks
end_location:
row: 4
column: 4
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: exit
location:
row: 8
column: 4
@@ -47,7 +50,8 @@ expression: checks
end_location:
row: 8
column: 8
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: quit
location:
row: 9
column: 4

View File

@@ -2,7 +2,8 @@
source: src/pylint/mod.rs
expression: checks
---
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: quit
location:
row: 4
column: 0
@@ -17,7 +18,8 @@ expression: checks
end_location:
row: 4
column: 4
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: quit
location:
row: 9
column: 4

View File

@@ -2,7 +2,8 @@
source: src/pylint/mod.rs
expression: checks
---
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: exit
location:
row: 1
column: 0
@@ -10,7 +11,8 @@ expression: checks
row: 1
column: 4
fix: ~
- kind: ConsiderUsingSysExit
- kind:
UseSysExit: quit
location:
row: 2
column: 0