mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-09 13:18:52 +00:00
Include static and class methods in in abstract decorator list (#4298)
This commit is contained in:
parent
f23851130a
commit
d365dab904
3 changed files with 108 additions and 79 deletions
|
@ -4,7 +4,12 @@ B027 - on lines 13, 16, 19, 23
|
||||||
"""
|
"""
|
||||||
import abc
|
import abc
|
||||||
from abc import ABC
|
from abc import ABC
|
||||||
from abc import abstractmethod, abstractproperty
|
from abc import (
|
||||||
|
abstractmethod,
|
||||||
|
abstractproperty,
|
||||||
|
abstractclassmethod,
|
||||||
|
abstractstaticmethod,
|
||||||
|
)
|
||||||
from abc import abstractmethod as notabstract
|
from abc import abstractmethod as notabstract
|
||||||
from abc import abstractproperty as notabstract_property
|
from abc import abstractproperty as notabstract_property
|
||||||
|
|
||||||
|
@ -55,6 +60,22 @@ class AbstractClass(ABC):
|
||||||
def abstract_6(self):
|
def abstract_6(self):
|
||||||
...
|
...
|
||||||
|
|
||||||
|
@abstractclassmethod
|
||||||
|
def abstract_7(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractclassmethod
|
||||||
|
def abstract_8(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
@abstractstaticmethod
|
||||||
|
def abstract_9(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractstaticmethod
|
||||||
|
def abstract_10(self):
|
||||||
|
...
|
||||||
|
|
||||||
def body_1(self):
|
def body_1(self):
|
||||||
print("foo")
|
print("foo")
|
||||||
...
|
...
|
||||||
|
|
|
@ -1,96 +1,96 @@
|
||||||
---
|
---
|
||||||
source: crates/ruff/src/rules/flake8_bugbear/mod.rs
|
source: crates/ruff/src/rules/flake8_bugbear/mod.rs
|
||||||
---
|
---
|
||||||
B027.py:13:5: B027 [*] `AbstractClass.empty_1` is an empty method in an abstract base class, but has no abstract decorator
|
B027.py:18:5: B027 [*] `AbstractClass.empty_1` is an empty method in an abstract base class, but has no abstract decorator
|
||||||
|
|
|
|
||||||
13 | class AbstractClass(ABC):
|
18 | class AbstractClass(ABC):
|
||||||
14 | def empty_1(self): # error
|
19 | def empty_1(self): # error
|
||||||
| _____^
|
| _____^
|
||||||
15 | | ...
|
20 | | ...
|
||||||
| |___________^ B027
|
| |___________^ B027
|
||||||
16 |
|
21 |
|
||||||
17 | def empty_2(self): # error
|
22 | def empty_2(self): # error
|
||||||
|
|
|
|
||||||
= help: Add the `@abstractmethod` decorator
|
= help: Add the `@abstractmethod` decorator
|
||||||
|
|
||||||
ℹ Suggested fix
|
ℹ Suggested fix
|
||||||
10 10 |
|
|
||||||
11 11 |
|
|
||||||
12 12 | class AbstractClass(ABC):
|
|
||||||
13 |+ @notabstract
|
|
||||||
13 14 | def empty_1(self): # error
|
|
||||||
14 15 | ...
|
|
||||||
15 16 |
|
|
||||||
|
|
||||||
B027.py:16:5: B027 [*] `AbstractClass.empty_2` is an empty method in an abstract base class, but has no abstract decorator
|
|
||||||
|
|
|
||||||
16 | ...
|
|
||||||
17 |
|
|
||||||
18 | def empty_2(self): # error
|
|
||||||
| _____^
|
|
||||||
19 | | pass
|
|
||||||
| |____________^ B027
|
|
||||||
20 |
|
|
||||||
21 | def empty_3(self): # error
|
|
||||||
|
|
|
||||||
= help: Add the `@abstractmethod` decorator
|
|
||||||
|
|
||||||
ℹ Suggested fix
|
|
||||||
13 13 | def empty_1(self): # error
|
|
||||||
14 14 | ...
|
|
||||||
15 15 |
|
15 15 |
|
||||||
16 |+ @notabstract
|
16 16 |
|
||||||
16 17 | def empty_2(self): # error
|
17 17 | class AbstractClass(ABC):
|
||||||
17 18 | pass
|
18 |+ @notabstract
|
||||||
18 19 |
|
18 19 | def empty_1(self): # error
|
||||||
|
19 20 | ...
|
||||||
|
20 21 |
|
||||||
|
|
||||||
B027.py:19:5: B027 [*] `AbstractClass.empty_3` is an empty method in an abstract base class, but has no abstract decorator
|
B027.py:21:5: B027 [*] `AbstractClass.empty_2` is an empty method in an abstract base class, but has no abstract decorator
|
||||||
|
|
|
|
||||||
19 | pass
|
21 | ...
|
||||||
20 |
|
22 |
|
||||||
21 | def empty_3(self): # error
|
23 | def empty_2(self): # error
|
||||||
| _____^
|
| _____^
|
||||||
22 | | """docstring"""
|
24 | | pass
|
||||||
23 | | ...
|
|
||||||
| |___________^ B027
|
|
||||||
24 |
|
|
||||||
25 | def empty_4(self): # error
|
|
||||||
|
|
|
||||||
= help: Add the `@abstractmethod` decorator
|
|
||||||
|
|
||||||
ℹ Suggested fix
|
|
||||||
16 16 | def empty_2(self): # error
|
|
||||||
17 17 | pass
|
|
||||||
18 18 |
|
|
||||||
19 |+ @notabstract
|
|
||||||
19 20 | def empty_3(self): # error
|
|
||||||
20 21 | """docstring"""
|
|
||||||
21 22 | ...
|
|
||||||
|
|
||||||
B027.py:23:5: B027 [*] `AbstractClass.empty_4` is an empty method in an abstract base class, but has no abstract decorator
|
|
||||||
|
|
|
||||||
23 | ...
|
|
||||||
24 |
|
|
||||||
25 | def empty_4(self): # error
|
|
||||||
| _____^
|
|
||||||
26 | | """multiple ellipsis/pass"""
|
|
||||||
27 | | ...
|
|
||||||
28 | | pass
|
|
||||||
29 | | ...
|
|
||||||
30 | | pass
|
|
||||||
| |____________^ B027
|
| |____________^ B027
|
||||||
31 |
|
25 |
|
||||||
32 | @notabstract
|
26 | def empty_3(self): # error
|
||||||
|
|
|
|
||||||
= help: Add the `@abstractmethod` decorator
|
= help: Add the `@abstractmethod` decorator
|
||||||
|
|
||||||
ℹ Suggested fix
|
ℹ Suggested fix
|
||||||
20 20 | """docstring"""
|
18 18 | def empty_1(self): # error
|
||||||
21 21 | ...
|
19 19 | ...
|
||||||
22 22 |
|
20 20 |
|
||||||
23 |+ @notabstract
|
21 |+ @notabstract
|
||||||
23 24 | def empty_4(self): # error
|
21 22 | def empty_2(self): # error
|
||||||
24 25 | """multiple ellipsis/pass"""
|
22 23 | pass
|
||||||
25 26 | ...
|
23 24 |
|
||||||
|
|
||||||
|
B027.py:24:5: B027 [*] `AbstractClass.empty_3` is an empty method in an abstract base class, but has no abstract decorator
|
||||||
|
|
|
||||||
|
24 | pass
|
||||||
|
25 |
|
||||||
|
26 | def empty_3(self): # error
|
||||||
|
| _____^
|
||||||
|
27 | | """docstring"""
|
||||||
|
28 | | ...
|
||||||
|
| |___________^ B027
|
||||||
|
29 |
|
||||||
|
30 | def empty_4(self): # error
|
||||||
|
|
|
||||||
|
= help: Add the `@abstractmethod` decorator
|
||||||
|
|
||||||
|
ℹ Suggested fix
|
||||||
|
21 21 | def empty_2(self): # error
|
||||||
|
22 22 | pass
|
||||||
|
23 23 |
|
||||||
|
24 |+ @notabstract
|
||||||
|
24 25 | def empty_3(self): # error
|
||||||
|
25 26 | """docstring"""
|
||||||
|
26 27 | ...
|
||||||
|
|
||||||
|
B027.py:28:5: B027 [*] `AbstractClass.empty_4` is an empty method in an abstract base class, but has no abstract decorator
|
||||||
|
|
|
||||||
|
28 | ...
|
||||||
|
29 |
|
||||||
|
30 | def empty_4(self): # error
|
||||||
|
| _____^
|
||||||
|
31 | | """multiple ellipsis/pass"""
|
||||||
|
32 | | ...
|
||||||
|
33 | | pass
|
||||||
|
34 | | ...
|
||||||
|
35 | | pass
|
||||||
|
| |____________^ B027
|
||||||
|
36 |
|
||||||
|
37 | @notabstract
|
||||||
|
|
|
||||||
|
= help: Add the `@abstractmethod` decorator
|
||||||
|
|
||||||
|
ℹ Suggested fix
|
||||||
|
25 25 | """docstring"""
|
||||||
|
26 26 | ...
|
||||||
|
27 27 |
|
||||||
|
28 |+ @notabstract
|
||||||
|
28 29 | def empty_4(self): # error
|
||||||
|
29 30 | """multiple ellipsis/pass"""
|
||||||
|
30 31 | ...
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -60,13 +60,21 @@ pub fn is_override(ctx: &Context, decorator_list: &[Expr]) -> bool {
|
||||||
.any(|expr| ctx.match_typing_expr(map_callable(expr), "override"))
|
.any(|expr| ctx.match_typing_expr(map_callable(expr), "override"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if a function definition is an `@abstractmethod`.
|
/// Returns `true` if a function definition is an abstract method based on its decorators.
|
||||||
pub fn is_abstract(ctx: &Context, decorator_list: &[Expr]) -> bool {
|
pub fn is_abstract(ctx: &Context, decorator_list: &[Expr]) -> bool {
|
||||||
decorator_list.iter().any(|expr| {
|
decorator_list.iter().any(|expr| {
|
||||||
ctx.resolve_call_path(map_callable(expr))
|
ctx.resolve_call_path(map_callable(expr))
|
||||||
.map_or(false, |call_path| {
|
.map_or(false, |call_path| {
|
||||||
call_path.as_slice() == ["abc", "abstractmethod"]
|
matches!(
|
||||||
|| call_path.as_slice() == ["abc", "abstractproperty"]
|
call_path.as_slice(),
|
||||||
|
[
|
||||||
|
"abc",
|
||||||
|
"abstractmethod"
|
||||||
|
| "abstractclassmethod"
|
||||||
|
| "abstractstaticmethod"
|
||||||
|
| "abstractproperty"
|
||||||
|
]
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue