mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-27 20:42:10 +00:00
# Summary Closes #14455, migrated from https://github.com/astral-sh/docs/pull/106.
This commit is contained in:
parent
87043a2415
commit
b9da4305e6
3 changed files with 22 additions and 13 deletions
|
@ -11,12 +11,14 @@ use crate::checkers::ast::Checker;
|
||||||
use crate::registry::Rule;
|
use crate::registry::Rule;
|
||||||
|
|
||||||
/// ## What it does
|
/// ## 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?
|
/// ## Why is this bad?
|
||||||
/// Abstract base classes are used to define interfaces. If an abstract base
|
/// 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
|
/// class has no abstract methods or properties, you may have forgotten
|
||||||
/// method to the class or omitted an `@abstractmethod` decorator.
|
/// 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
|
/// If the class is _not_ meant to be used as an interface, consider removing
|
||||||
/// the `ABC` base class from the class definition.
|
/// the `ABC` base class from the class definition.
|
||||||
|
@ -24,9 +26,12 @@ use crate::registry::Rule;
|
||||||
/// ## Example
|
/// ## Example
|
||||||
/// ```python
|
/// ```python
|
||||||
/// from abc import ABC
|
/// from abc import ABC
|
||||||
|
/// from typing import ClassVar
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// class Foo(ABC):
|
/// class Foo(ABC):
|
||||||
|
/// class_var: ClassVar[str] = "assigned"
|
||||||
|
///
|
||||||
/// def method(self):
|
/// def method(self):
|
||||||
/// bar()
|
/// bar()
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -34,9 +39,12 @@ use crate::registry::Rule;
|
||||||
/// Use instead:
|
/// Use instead:
|
||||||
/// ```python
|
/// ```python
|
||||||
/// from abc import ABC, abstractmethod
|
/// from abc import ABC, abstractmethod
|
||||||
|
/// from typing import ClassVar
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// class Foo(ABC):
|
/// class Foo(ABC):
|
||||||
|
/// class_var: ClassVar[str] # unassigned
|
||||||
|
///
|
||||||
/// @abstractmethod
|
/// @abstractmethod
|
||||||
/// def method(self):
|
/// def method(self):
|
||||||
/// bar()
|
/// bar()
|
||||||
|
@ -44,6 +52,7 @@ use crate::registry::Rule;
|
||||||
///
|
///
|
||||||
/// ## References
|
/// ## References
|
||||||
/// - [Python documentation: `abc`](https://docs.python.org/3/library/abc.html)
|
/// - [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]
|
#[violation]
|
||||||
pub struct AbstractBaseClassWithoutAbstractMethod {
|
pub struct AbstractBaseClassWithoutAbstractMethod {
|
||||||
name: String,
|
name: String,
|
||||||
|
@ -53,7 +62,7 @@ impl Violation for AbstractBaseClassWithoutAbstractMethod {
|
||||||
#[derive_message_formats]
|
#[derive_message_formats]
|
||||||
fn message(&self) -> String {
|
fn message(&self) -> String {
|
||||||
let AbstractBaseClassWithoutAbstractMethod { name } = self;
|
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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
|
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
|
||||||
snapshot_kind: text
|
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
|
18 | class Base_1(ABC): # error
|
||||||
| ^^^^^^ B024
|
| ^^^^^^ B024
|
||||||
|
@ -10,7 +10,7 @@ B024.py:18:7: B024 `Base_1` is an abstract base class, but it has no abstract me
|
||||||
20 | foo()
|
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
|
71 | class MetaBase_1(metaclass=ABCMeta): # error
|
||||||
| ^^^^^^^^^^ B024
|
| ^^^^^^^^^^ B024
|
||||||
|
@ -18,7 +18,7 @@ B024.py:71:7: B024 `MetaBase_1` is an abstract base class, but it has no abstrac
|
||||||
73 | foo()
|
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
|
82 | class abc_Base_1(abc.ABC): # error
|
||||||
| ^^^^^^^^^^ B024
|
| ^^^^^^^^^^ B024
|
||||||
|
@ -26,7 +26,7 @@ B024.py:82:7: B024 `abc_Base_1` is an abstract base class, but it has no abstrac
|
||||||
84 | foo()
|
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
|
87 | class abc_Base_2(metaclass=abc.ABCMeta): # error
|
||||||
| ^^^^^^^^^^ B024
|
| ^^^^^^^^^^ B024
|
||||||
|
@ -34,7 +34,7 @@ B024.py:87:7: B024 `abc_Base_2` is an abstract base class, but it has no abstrac
|
||||||
89 | foo()
|
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
|
92 | class notabc_Base_1(notabc.ABC): # error
|
||||||
| ^^^^^^^^^^^^^ B024
|
| ^^^^^^^^^^^^^ B024
|
||||||
|
@ -42,21 +42,21 @@ 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
|
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)
|
132 | class abc_set_class_variable_2(ABC): # error (not an abstract attribute)
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ B024
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ B024
|
||||||
133 | foo = 2
|
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)
|
136 | class abc_set_class_variable_3(ABC): # error (not an abstract attribute)
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ B024
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ B024
|
||||||
137 | foo: int = 2
|
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
|
140 | # this doesn't actually declare a class variable, it's just an expression
|
||||||
141 | class abc_set_class_variable_4(ABC): # error
|
141 | class abc_set_class_variable_4(ABC): # error
|
||||||
|
|
|
@ -110,7 +110,7 @@ def generate_rule_metadata(rule_doc: Path) -> None:
|
||||||
For example:
|
For example:
|
||||||
```yaml
|
```yaml
|
||||||
---
|
---
|
||||||
description: Checks for abstract classes without abstract methods.
|
description: Checks for abstract classes without abstract methods or properties.
|
||||||
tags:
|
tags:
|
||||||
- B024
|
- B024
|
||||||
---
|
---
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue