mirror of https://github.com/astral-sh/ruff
Don't trigger `eq-without-hash` when `__hash__` is explicitly set to `None` (#6739)
This commit is contained in:
parent
c0df99b965
commit
37f4920e1e
|
|
@ -1,10 +1,11 @@
|
|||
class Person:
|
||||
class Person: # [eq-without-hash]
|
||||
def __init__(self):
|
||||
self.name = "monty"
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, Person) and other.name == self.name
|
||||
|
||||
# OK
|
||||
class Language:
|
||||
def __init__(self):
|
||||
self.name = "python"
|
||||
|
|
@ -14,3 +15,9 @@ class Language:
|
|||
|
||||
def __hash__(self):
|
||||
return hash(self.name)
|
||||
|
||||
class MyClass:
|
||||
def __eq__(self, other):
|
||||
return True
|
||||
|
||||
__hash__ = None
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use ruff_python_ast::{self as ast, Ranged, Stmt};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::helpers::is_const_none;
|
||||
use ruff_python_ast::{self as ast, Expr, Ranged, Stmt};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
|
|
@ -65,13 +65,30 @@ fn has_eq_without_hash(body: &[Stmt]) -> bool {
|
|||
let mut has_hash = false;
|
||||
let mut has_eq = false;
|
||||
for statement in body {
|
||||
let Stmt::FunctionDef(ast::StmtFunctionDef { name, .. }) = statement else {
|
||||
match statement {
|
||||
Stmt::Assign(ast::StmtAssign { targets, value, .. }) => {
|
||||
let [Expr::Name(ast::ExprName { id, .. })] = targets.as_slice() else {
|
||||
continue;
|
||||
};
|
||||
match name.as_str() {
|
||||
|
||||
// Check if `__hash__` was explicitly set to `None`, as in:
|
||||
// ```python
|
||||
// class Class:
|
||||
// def __eq__(self, other):
|
||||
// return True
|
||||
//
|
||||
// __hash__ = None
|
||||
// ```
|
||||
if id == "__hash__" && is_const_none(value) {
|
||||
has_hash = true;
|
||||
}
|
||||
}
|
||||
Stmt::FunctionDef(ast::StmtFunctionDef { name, .. }) => match name.as_str() {
|
||||
"__hash__" => has_hash = true,
|
||||
"__eq__" => has_eq = true,
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
has_eq && !has_hash
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ source: crates/ruff/src/rules/pylint/mod.rs
|
|||
---
|
||||
eq_without_hash.py:1:7: PLW1641 Object does not implement `__hash__` method
|
||||
|
|
||||
1 | class Person:
|
||||
1 | class Person: # [eq-without-hash]
|
||||
| ^^^^^^ PLW1641
|
||||
2 | def __init__(self):
|
||||
3 | self.name = "monty"
|
||||
|
|
|
|||
Loading…
Reference in New Issue