Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90bfc4ec4d | ||
|
|
b04a6a3f7c |
@@ -1,6 +1,6 @@
|
||||
repos:
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: v0.0.123
|
||||
rev: v0.0.124
|
||||
hooks:
|
||||
- id: ruff
|
||||
|
||||
|
||||
6
Cargo.lock
generated
6
Cargo.lock
generated
@@ -930,7 +930,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.123-dev.0"
|
||||
version = "0.0.124-dev.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.0.22",
|
||||
@@ -2238,7 +2238,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.123"
|
||||
version = "0.0.124"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"assert_cmd",
|
||||
@@ -2287,7 +2287,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_dev"
|
||||
version = "0.0.123"
|
||||
version = "0.0.124"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.0.22",
|
||||
|
||||
@@ -6,7 +6,7 @@ members = [
|
||||
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.0.123"
|
||||
version = "0.0.124"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
4
flake8_to_ruff/Cargo.lock
generated
4
flake8_to_ruff/Cargo.lock
generated
@@ -771,7 +771,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flake8_to_ruff"
|
||||
version = "0.0.123"
|
||||
version = "0.0.124"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@@ -1975,7 +1975,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.123"
|
||||
version = "0.0.124"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.123-dev.0"
|
||||
version = "0.0.124-dev.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
10
resources/test/fixtures/N805.py
vendored
10
resources/test/fixtures/N805.py
vendored
@@ -1,5 +1,7 @@
|
||||
from abc import ABCMeta
|
||||
|
||||
import pydantic
|
||||
|
||||
|
||||
class Class:
|
||||
def bad_method(this):
|
||||
@@ -21,6 +23,14 @@ class Class:
|
||||
def static_method(x):
|
||||
return x
|
||||
|
||||
@pydantic.validator
|
||||
def lower(cls, my_field: str) -> str:
|
||||
pass
|
||||
|
||||
@pydantic.validator("my_field")
|
||||
def lower(cls, my_field: str) -> str:
|
||||
pass
|
||||
|
||||
def __init__(self):
|
||||
...
|
||||
|
||||
|
||||
1
resources/test/fixtures/pyproject.toml
vendored
1
resources/test/fixtures/pyproject.toml
vendored
@@ -33,6 +33,7 @@ ignore-names = [
|
||||
]
|
||||
classmethod-decorators = [
|
||||
"classmethod",
|
||||
"pydantic.validator",
|
||||
]
|
||||
staticmethod-decorators = [
|
||||
"staticmethod",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_dev"
|
||||
version = "0.0.123"
|
||||
version = "0.0.124"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
||||
@@ -239,6 +239,15 @@ pub fn format_import_from(level: Option<&usize>, module: Option<&String>) -> Str
|
||||
module_name
|
||||
}
|
||||
|
||||
/// Split a target string (like `typing.List`) into (`typing`, `List`).
|
||||
pub fn to_module_and_member(target: &str) -> (&str, &str) {
|
||||
if let Some(index) = target.rfind('.') {
|
||||
(&target[..index], &target[index + 1..])
|
||||
} else {
|
||||
("", target)
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a location within a file (relative to `base`) to an absolute
|
||||
/// position.
|
||||
pub fn to_absolute(relative: &Location, base: &Location) -> Location {
|
||||
|
||||
@@ -309,6 +309,8 @@ where
|
||||
name,
|
||||
decorator_list,
|
||||
args,
|
||||
&self.from_imports,
|
||||
&self.import_aliases,
|
||||
&self.settings.pep8_naming,
|
||||
)
|
||||
{
|
||||
@@ -322,6 +324,8 @@ where
|
||||
name,
|
||||
decorator_list,
|
||||
args,
|
||||
&self.from_imports,
|
||||
&self.import_aliases,
|
||||
&self.settings.pep8_naming,
|
||||
) {
|
||||
self.add_check(check);
|
||||
|
||||
@@ -2,7 +2,7 @@ use fnv::{FnvHashMap, FnvHashSet};
|
||||
use rustpython_ast::{Arguments, Constant, Expr, ExprKind};
|
||||
|
||||
use crate::ast::helpers::{
|
||||
collect_call_paths, compose_call_path, dealias_call_path, match_call_path,
|
||||
collect_call_paths, compose_call_path, dealias_call_path, match_call_path, to_module_and_member,
|
||||
};
|
||||
use crate::ast::types::Range;
|
||||
use crate::ast::visitor;
|
||||
@@ -104,14 +104,7 @@ pub fn function_call_argument_default(checker: &mut Checker, arguments: &Argumen
|
||||
.flake8_bugbear
|
||||
.extend_immutable_calls
|
||||
.iter()
|
||||
.map(|s| {
|
||||
let s = s.as_str();
|
||||
if let Some(index) = s.rfind('.') {
|
||||
(&s[..index], &s[index + 1..])
|
||||
} else {
|
||||
("", s)
|
||||
}
|
||||
})
|
||||
.map(|target| to_module_and_member(target))
|
||||
.collect();
|
||||
let mut visitor = ArgumentDefaultVisitor {
|
||||
checks: vec![],
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use fnv::{FnvHashMap, FnvHashSet};
|
||||
use rustpython_ast::{Arguments, Expr, ExprKind, Stmt};
|
||||
|
||||
use crate::ast::types::{Range, Scope, ScopeKind};
|
||||
@@ -58,10 +59,19 @@ pub fn invalid_first_argument_name_for_class_method(
|
||||
name: &str,
|
||||
decorator_list: &[Expr],
|
||||
args: &Arguments,
|
||||
from_imports: &FnvHashMap<&str, FnvHashSet<&str>>,
|
||||
import_aliases: &FnvHashMap<&str, &str>,
|
||||
settings: &Settings,
|
||||
) -> Option<Check> {
|
||||
if matches!(
|
||||
helpers::function_type(scope, name, decorator_list, settings),
|
||||
helpers::function_type(
|
||||
scope,
|
||||
name,
|
||||
decorator_list,
|
||||
from_imports,
|
||||
import_aliases,
|
||||
settings,
|
||||
),
|
||||
FunctionType::ClassMethod
|
||||
) {
|
||||
if let Some(arg) = args.args.first() {
|
||||
@@ -82,10 +92,19 @@ pub fn invalid_first_argument_name_for_method(
|
||||
name: &str,
|
||||
decorator_list: &[Expr],
|
||||
args: &Arguments,
|
||||
from_imports: &FnvHashMap<&str, FnvHashSet<&str>>,
|
||||
import_aliases: &FnvHashMap<&str, &str>,
|
||||
settings: &Settings,
|
||||
) -> Option<Check> {
|
||||
if matches!(
|
||||
helpers::function_type(scope, name, decorator_list, settings),
|
||||
helpers::function_type(
|
||||
scope,
|
||||
name,
|
||||
decorator_list,
|
||||
from_imports,
|
||||
import_aliases,
|
||||
settings,
|
||||
),
|
||||
FunctionType::Method
|
||||
) {
|
||||
if let Some(arg) = args.args.first() {
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
use fnv::{FnvHashMap, FnvHashSet};
|
||||
use itertools::Itertools;
|
||||
use rustpython_ast::{Expr, ExprKind, Stmt, StmtKind};
|
||||
use rustpython_ast::{Expr, Stmt, StmtKind};
|
||||
|
||||
use crate::ast::helpers::{collect_call_paths, match_call_path, match_name_or_attr};
|
||||
use crate::ast::helpers::{
|
||||
collect_call_paths, dealias_call_path, match_call_path, to_module_and_member,
|
||||
};
|
||||
use crate::ast::types::{Scope, ScopeKind};
|
||||
use crate::pep8_naming::settings::Settings;
|
||||
use crate::python::string::{is_lower, is_upper};
|
||||
|
||||
const CLASS_METHODS: [&str; 3] = ["__new__", "__init_subclass__", "__class_getitem__"];
|
||||
const METACLASS_BASES: [&str; 2] = ["type", "ABCMeta"];
|
||||
const METACLASS_BASES: [(&str, &str); 2] = [("", "type"), ("abc", "ABCMeta")];
|
||||
|
||||
pub enum FunctionType {
|
||||
Function,
|
||||
@@ -22,35 +24,39 @@ pub fn function_type(
|
||||
scope: &Scope,
|
||||
name: &str,
|
||||
decorator_list: &[Expr],
|
||||
from_imports: &FnvHashMap<&str, FnvHashSet<&str>>,
|
||||
import_aliases: &FnvHashMap<&str, &str>,
|
||||
settings: &Settings,
|
||||
) -> FunctionType {
|
||||
if let ScopeKind::Class(scope) = &scope.kind {
|
||||
// Special-case class method, like `__new__`.
|
||||
if CLASS_METHODS.contains(&name)
|
||||
// The class itself extends a known metaclass, so all methods are class methods.
|
||||
|| scope.bases.iter().any(|expr| {
|
||||
METACLASS_BASES
|
||||
.iter()
|
||||
.any(|target| match_name_or_attr(expr, target))
|
||||
// The class itself extends a known metaclass, so all methods are class methods.
|
||||
let call_path = dealias_call_path(collect_call_paths(expr), import_aliases);
|
||||
METACLASS_BASES.iter().any(|(module, member)| {
|
||||
match_call_path(&call_path, module, member, from_imports)
|
||||
})
|
||||
})
|
||||
// The method is decorated with a class method decorator (like `@classmethod`).
|
||||
|| decorator_list.iter().any(|expr| {
|
||||
if let ExprKind::Name { id, .. } = &expr.node {
|
||||
settings.classmethod_decorators.contains(id)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}) {
|
||||
// The method is decorated with a class method decorator (like `@classmethod`).
|
||||
let call_path = dealias_call_path(collect_call_paths(expr), import_aliases);
|
||||
settings.classmethod_decorators.iter().any(|decorator| {
|
||||
let (module, member) = to_module_and_member(decorator);
|
||||
match_call_path(&call_path, module, member, from_imports)
|
||||
})
|
||||
})
|
||||
{
|
||||
FunctionType::ClassMethod
|
||||
} else if decorator_list.iter().any(|expr| {
|
||||
if let ExprKind::Name { id, .. } = &expr.node {
|
||||
settings.staticmethod_decorators.contains(id)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}) {
|
||||
// The method is decorated with a static method decorator (like
|
||||
// `@staticmethod`).
|
||||
let call_path = dealias_call_path(collect_call_paths(expr), import_aliases);
|
||||
settings.staticmethod_decorators.iter().any(|decorator| {
|
||||
let (module, member) = to_module_and_member(decorator);
|
||||
match_call_path(&call_path, module, member, from_imports)
|
||||
})
|
||||
}) {
|
||||
FunctionType::StaticMethod
|
||||
} else {
|
||||
// It's an instance method.
|
||||
|
||||
@@ -4,18 +4,34 @@ expression: checks
|
||||
---
|
||||
- kind: InvalidFirstArgumentNameForMethod
|
||||
location:
|
||||
row: 5
|
||||
row: 7
|
||||
column: 19
|
||||
end_location:
|
||||
row: 5
|
||||
row: 7
|
||||
column: 23
|
||||
fix: ~
|
||||
- kind: InvalidFirstArgumentNameForMethod
|
||||
location:
|
||||
row: 10
|
||||
row: 12
|
||||
column: 29
|
||||
end_location:
|
||||
row: 10
|
||||
row: 12
|
||||
column: 33
|
||||
fix: ~
|
||||
- kind: InvalidFirstArgumentNameForMethod
|
||||
location:
|
||||
row: 27
|
||||
column: 14
|
||||
end_location:
|
||||
row: 27
|
||||
column: 17
|
||||
fix: ~
|
||||
- kind: InvalidFirstArgumentNameForMethod
|
||||
location:
|
||||
row: 31
|
||||
column: 14
|
||||
end_location:
|
||||
row: 31
|
||||
column: 17
|
||||
fix: ~
|
||||
|
||||
|
||||
Reference in New Issue
Block a user