mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-02 22:54:42 +00:00
Avoid recommending no-argument super in slots=True
dataclasses (#12530)
## Summary Closes https://github.com/astral-sh/ruff/issues/12506.
This commit is contained in:
parent
6f4db8675b
commit
998bfe0847
3 changed files with 67 additions and 1 deletions
|
@ -63,3 +63,19 @@ class MyClass(BaseClass):
|
|||
InnerClass().method()
|
||||
|
||||
defined_outside = defined_outside
|
||||
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class DataClass:
|
||||
def normal(self):
|
||||
super(DataClass, self).f() # Error
|
||||
super().f() # OK
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
def normal(self):
|
||||
super(DataClass, self).f() # OK
|
||||
super().f() # OK (`TypeError` in practice)
|
||||
|
|
|
@ -102,7 +102,9 @@ pub(crate) fn super_call_with_parameters(checker: &mut Checker, call: &ast::Expr
|
|||
|
||||
// Find the enclosing class definition (if any).
|
||||
let Some(Stmt::ClassDef(ast::StmtClassDef {
|
||||
name: parent_name, ..
|
||||
name: parent_name,
|
||||
decorator_list,
|
||||
..
|
||||
})) = parents.find(|stmt| stmt.is_class_def_stmt())
|
||||
else {
|
||||
return;
|
||||
|
@ -126,6 +128,36 @@ pub(crate) fn super_call_with_parameters(checker: &mut Checker, call: &ast::Expr
|
|||
|
||||
drop(parents);
|
||||
|
||||
// If the class is an `@dataclass` with `slots=True`, calling `super()` without arguments raises
|
||||
// a `TypeError`.
|
||||
//
|
||||
// See: https://docs.python.org/3/library/dataclasses.html#dataclasses.dataclass
|
||||
if decorator_list.iter().any(|decorator| {
|
||||
let Expr::Call(ast::ExprCall {
|
||||
func, arguments, ..
|
||||
}) = &decorator.expression
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
|
||||
if checker
|
||||
.semantic()
|
||||
.resolve_qualified_name(func)
|
||||
.is_some_and(|name| name.segments() == ["dataclasses", "dataclass"])
|
||||
{
|
||||
arguments.find_keyword("slots").map_or(false, |keyword| {
|
||||
matches!(
|
||||
keyword.value,
|
||||
Expr::BooleanLiteral(ast::ExprBooleanLiteral { value: true, .. })
|
||||
)
|
||||
})
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut diagnostic = Diagnostic::new(SuperCallWithParameters, call.arguments.range());
|
||||
diagnostic.set_fix(Fix::unsafe_edit(Edit::deletion(
|
||||
call.arguments.start() + TextSize::new(1),
|
||||
|
|
|
@ -107,4 +107,22 @@ UP008.py:50:18: UP008 [*] Use `super()` instead of `super(__class__, self)`
|
|||
52 52 |
|
||||
53 53 | outer_argument()
|
||||
|
||||
UP008.py:74:14: UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||
|
|
||||
72 | class DataClass:
|
||||
73 | def normal(self):
|
||||
74 | super(DataClass, self).f() # Error
|
||||
| ^^^^^^^^^^^^^^^^^ UP008
|
||||
75 | super().f() # OK
|
||||
|
|
||||
= help: Remove `__super__` parameters
|
||||
|
||||
ℹ Unsafe fix
|
||||
71 71 | @dataclass
|
||||
72 72 | class DataClass:
|
||||
73 73 | def normal(self):
|
||||
74 |- super(DataClass, self).f() # Error
|
||||
74 |+ super().f() # Error
|
||||
75 75 | super().f() # OK
|
||||
76 76 |
|
||||
77 77 |
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue