mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-26 11:59:10 +00:00
Avoid no-self-use
for attrs
-style validators (#13166)
## Summary Closes https://github.com/astral-sh/ruff/issues/12568.
This commit is contained in:
parent
34dafb67a2
commit
a73bebcf15
4 changed files with 51 additions and 2 deletions
|
@ -83,3 +83,23 @@ class B(A):
|
||||||
def baz(self):
|
def baz(self):
|
||||||
if super().foo():
|
if super().foo():
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
# See: https://github.com/astral-sh/ruff/issues/12568
|
||||||
|
from attrs import define, field
|
||||||
|
|
||||||
|
|
||||||
|
@define
|
||||||
|
class Foo:
|
||||||
|
x: int = field()
|
||||||
|
y: int
|
||||||
|
|
||||||
|
@x.validator
|
||||||
|
def validate_x(self, attribute, value):
|
||||||
|
if value <= 0:
|
||||||
|
raise ValueError("x must be a positive integer")
|
||||||
|
|
||||||
|
@y.validator
|
||||||
|
def validate_y(self, attribute, value):
|
||||||
|
if value <= 0:
|
||||||
|
raise ValueError("y must be a positive integer")
|
||||||
|
|
|
@ -87,6 +87,7 @@ pub(crate) fn no_self_use(
|
||||||
|| visibility::is_override(decorator_list, semantic)
|
|| visibility::is_override(decorator_list, semantic)
|
||||||
|| visibility::is_overload(decorator_list, semantic)
|
|| visibility::is_overload(decorator_list, semantic)
|
||||||
|| visibility::is_property(decorator_list, extra_property_decorators, semantic)
|
|| visibility::is_property(decorator_list, extra_property_decorators, semantic)
|
||||||
|
|| visibility::is_validator(decorator_list, semantic)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,4 +27,11 @@ no_self_use.py:13:9: PLR6301 Method `greeting_2` could be a function, class meth
|
||||||
14 | print("Hi!")
|
14 | print("Hi!")
|
||||||
|
|
|
|
||||||
|
|
||||||
|
no_self_use.py:103:9: PLR6301 Method `validate_y` could be a function, class method, or static method
|
||||||
|
|
|
||||||
|
102 | @y.validator
|
||||||
|
103 | def validate_y(self, attribute, value):
|
||||||
|
| ^^^^^^^^^^ PLR6301
|
||||||
|
104 | if value <= 0:
|
||||||
|
105 | raise ValueError("y must be a positive integer")
|
||||||
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use ruff_python_ast::{self as ast, Decorator};
|
use ruff_python_ast::{self as ast, Decorator, Expr};
|
||||||
|
|
||||||
use ruff_python_ast::helpers::map_callable;
|
use ruff_python_ast::helpers::map_callable;
|
||||||
use ruff_python_ast::name::{QualifiedName, UnqualifiedName};
|
use ruff_python_ast::name::{QualifiedName, UnqualifiedName};
|
||||||
|
@ -90,6 +90,27 @@ where
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if a function definition is an `attrs`-like validator based on its decorators.
|
||||||
|
pub fn is_validator(decorator_list: &[Decorator], semantic: &SemanticModel) -> bool {
|
||||||
|
decorator_list.iter().any(|decorator| {
|
||||||
|
let Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = &decorator.expression else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if attr.as_str() != "validator" {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Expr::Name(value) = value.as_ref() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
semantic
|
||||||
|
.resolve_name(value)
|
||||||
|
.is_some_and(|id| semantic.binding(id).kind.is_assignment())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if a class is an `final`.
|
/// Returns `true` if a class is an `final`.
|
||||||
pub fn is_final(decorator_list: &[Decorator], semantic: &SemanticModel) -> bool {
|
pub fn is_final(decorator_list: &[Decorator], semantic: &SemanticModel) -> bool {
|
||||||
decorator_list
|
decorator_list
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue