Skip to content

Commit

Permalink
doc(B024): #14455 add annotated but unassgined class variables (#14502)
Browse files Browse the repository at this point in the history
# Summary

Closes #14455, migrated from astral-sh/docs#106.
  • Loading branch information
cmp0xff authored Nov 21, 2024
1 parent 87043a2 commit b9da430
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 13 deletions.
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

0 comments on commit b9da430

Please sign in to comment.