mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 05:45:24 +00:00
Ignore non-abstract class attributes when enforcing B024 (#11210)
## Summary I think the check included here does make sense, but I don't see why we would allow it if a value is provided for the attribute -- since, in that case, isn't it _not_ abstract? Closes: https://github.com/astral-sh/ruff/issues/11208.
This commit is contained in:
parent
c6dcf3502b
commit
c5adbf17da
3 changed files with 27 additions and 9 deletions
|
@ -115,25 +115,25 @@ class non_keyword_abcmeta_2(abc.ABCMeta): # safe
|
||||||
|
|
||||||
|
|
||||||
# very invalid code, but that's up to mypy et al to check
|
# very invalid code, but that's up to mypy et al to check
|
||||||
class keyword_abc_1(metaclass=ABC): # safe
|
class keyword_abc_1(metaclass=ABC): # incorrect but outside scope of this check
|
||||||
def method(self):
|
def method(self):
|
||||||
foo()
|
foo()
|
||||||
|
|
||||||
|
|
||||||
class keyword_abc_2(metaclass=abc.ABC): # safe
|
class keyword_abc_2(metaclass=abc.ABC): # incorrect but outside scope of this check
|
||||||
def method(self):
|
def method(self):
|
||||||
foo()
|
foo()
|
||||||
|
|
||||||
|
|
||||||
class abc_set_class_variable_1(ABC): # safe
|
class abc_set_class_variable_1(ABC): # safe (abstract attribute)
|
||||||
foo: int
|
foo: int
|
||||||
|
|
||||||
|
|
||||||
class abc_set_class_variable_2(ABC): # safe
|
class abc_set_class_variable_2(ABC): # error (not an abstract attribute)
|
||||||
foo = 2
|
foo = 2
|
||||||
|
|
||||||
|
|
||||||
class abc_set_class_variable_3(ABC): # safe
|
class abc_set_class_variable_3(ABC): # error (not an abstract attribute)
|
||||||
foo: int = 2
|
foo: int = 2
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,7 @@ impl Violation for AbstractBaseClassWithoutAbstractMethod {
|
||||||
format!("`{name}` is an abstract base class, but it has no abstract methods")
|
format!("`{name}` is an abstract base class, but it has no abstract methods")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ## What it does
|
/// ## What it does
|
||||||
/// Checks for empty methods in abstract base classes without an abstract
|
/// Checks for empty methods in abstract base classes without an abstract
|
||||||
/// decorator.
|
/// decorator.
|
||||||
|
@ -156,8 +157,13 @@ pub(crate) fn abstract_base_class(
|
||||||
let mut has_abstract_method = false;
|
let mut has_abstract_method = false;
|
||||||
for stmt in body {
|
for stmt in body {
|
||||||
// https://github.com/PyCQA/flake8-bugbear/issues/293
|
// https://github.com/PyCQA/flake8-bugbear/issues/293
|
||||||
// Ignore abc's that declares a class attribute that must be set
|
// If an ABC declares an attribute by providing a type annotation
|
||||||
if let Stmt::AnnAssign(_) | Stmt::Assign(_) = stmt {
|
// but does not actually assign a value for that attribute,
|
||||||
|
// assume it is intended to be an "abstract attribute"
|
||||||
|
if matches!(
|
||||||
|
stmt,
|
||||||
|
Stmt::AnnAssign(ast::StmtAnnAssign { value: None, .. })
|
||||||
|
) {
|
||||||
has_abstract_method = true;
|
has_abstract_method = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,20 @@ B024.py:92:7: B024 `notabc_Base_1` is an abstract base class, but it has no abst
|
||||||
94 | foo()
|
94 | foo()
|
||||||
|
|
|
|
||||||
|
|
||||||
|
B024.py:132:7: B024 `abc_set_class_variable_2` is an abstract base class, but it has no abstract methods
|
||||||
|
|
|
||||||
|
132 | class abc_set_class_variable_2(ABC): # error (not an abstract attribute)
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ B024
|
||||||
|
133 | foo = 2
|
||||||
|
|
|
||||||
|
|
||||||
|
B024.py:136:7: B024 `abc_set_class_variable_3` is an abstract base class, but it has no abstract methods
|
||||||
|
|
|
||||||
|
136 | class abc_set_class_variable_3(ABC): # error (not an abstract attribute)
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ B024
|
||||||
|
137 | foo: int = 2
|
||||||
|
|
|
||||||
|
|
||||||
B024.py:141:7: B024 `abc_set_class_variable_4` is an abstract base class, but it has no abstract methods
|
B024.py:141:7: B024 `abc_set_class_variable_4` is an abstract base class, but it has no abstract methods
|
||||||
|
|
|
|
||||||
140 | # this doesn't actually declare a class variable, it's just an expression
|
140 | # this doesn't actually declare a class variable, it's just an expression
|
||||||
|
@ -48,5 +62,3 @@ B024.py:141:7: B024 `abc_set_class_variable_4` is an abstract base class, but it
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ B024
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ B024
|
||||||
142 | foo
|
142 | foo
|
||||||
|
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue