Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,48 @@ use crate::checkers::ast::Checker;
use crate::registry::Rule;

/// ## What it does
/// Checks for abstract classes without abstract methods.
/// Checks for abstract classes without abstract methods or properties.
/// Annotated but unassigned class variables are regarded as abstract.
///
/// ## Why is this bad?
/// Abstract base classes are used to define interfaces. If an abstract base
/// class has no abstract methods, you may have forgotten to add an abstract
/// method to the class or omitted an `@abstractmethod` decorator.
/// class has no abstract methods or properties, you may have forgotten
/// to add an abstract method or property to the class,
/// or omitted an `@abstractmethod` decorator.
///
/// If the class is _not_ meant to be used as an interface, consider removing
/// the `ABC` base class from the class definition.
///
/// ## Example
/// ```python
/// from abc import ABC
/// from typing import ClassVar
///
///
/// class Foo(ABC):
/// class_var: ClassVar[str] = "assigned"
///
/// def method(self):
/// bar()
/// ```
///
/// Use instead:
/// ```python
/// from abc import ABC, abstractmethod
/// from typing import ClassVar
///
///
/// class Foo(ABC):
/// class_var: ClassVar[str] # unassigned
///
/// @abstractmethod
/// def method(self):
/// bar()
/// ```
///
/// ## References
/// - [Python documentation: `abc`](https://docs.python.org/3/library/abc.html)
/// - [Python documentation: `typing.ClassVar`](https://docs.python.org/3/library/typing.html#typing.ClassVar)
#[violation]
pub struct AbstractBaseClassWithoutAbstractMethod {
name: String,
Expand All @@ -53,7 +62,7 @@ impl Violation for AbstractBaseClassWithoutAbstractMethod {
#[derive_message_formats]
fn message(&self) -> String {
let AbstractBaseClassWithoutAbstractMethod { name } = self;
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 or properties")
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,61 @@
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
snapshot_kind: text
---
B024.py:18:7: B024 `Base_1` is an abstract base class, but it has no abstract methods
B024.py:18:7: B024 `Base_1` is an abstract base class, but it has no abstract methods or properties
|
18 | class Base_1(ABC): # error
| ^^^^^^ B024
19 | def method(self):
20 | foo()
|

B024.py:71:7: B024 `MetaBase_1` is an abstract base class, but it has no abstract methods
B024.py:71:7: B024 `MetaBase_1` is an abstract base class, but it has no abstract methods or properties
|
71 | class MetaBase_1(metaclass=ABCMeta): # error
| ^^^^^^^^^^ B024
72 | def method(self):
73 | foo()
|

B024.py:82:7: B024 `abc_Base_1` is an abstract base class, but it has no abstract methods
B024.py:82:7: B024 `abc_Base_1` is an abstract base class, but it has no abstract methods or properties
|
82 | class abc_Base_1(abc.ABC): # error
| ^^^^^^^^^^ B024
83 | def method(self):
84 | foo()
|

B024.py:87:7: B024 `abc_Base_2` is an abstract base class, but it has no abstract methods
B024.py:87:7: B024 `abc_Base_2` is an abstract base class, but it has no abstract methods or properties
|
87 | class abc_Base_2(metaclass=abc.ABCMeta): # error
| ^^^^^^^^^^ B024
88 | def method(self):
89 | foo()
|

B024.py:92:7: B024 `notabc_Base_1` is an abstract base class, but it has no abstract methods
B024.py:92:7: B024 `notabc_Base_1` is an abstract base class, but it has no abstract methods or properties
|
92 | class notabc_Base_1(notabc.ABC): # error
| ^^^^^^^^^^^^^ B024
93 | def method(self):
94 | foo()
|

B024.py:132:7: B024 `abc_set_class_variable_2` is an abstract base class, but it has no abstract methods
B024.py:132:7: B024 `abc_set_class_variable_2` is an abstract base class, but it has no abstract methods or properties
|
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
B024.py:136:7: B024 `abc_set_class_variable_3` is an abstract base class, but it has no abstract methods or properties
|
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 or properties
|
140 | # this doesn't actually declare a class variable, it's just an expression
141 | class abc_set_class_variable_4(ABC): # error
Expand Down
2 changes: 1 addition & 1 deletion scripts/generate_mkdocs.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def generate_rule_metadata(rule_doc: Path) -> None:
For example:
```yaml
---
description: Checks for abstract classes without abstract methods.
description: Checks for abstract classes without abstract methods or properties.
tags:
- B024
---
Expand Down
Loading