`__hash__` with custom `__eq__`
Hi, I know that hashing is a complicated topic and I've seen the sections in the docs / API reference + the resources linked therein. However, I'm still somewhat unclear about what is expected to happen in the situation described at the end.
Is this:
- expected?
- an attrs issue?
- a ruff issue?
And regardless of which it is, how to properly resolve it? The attrs docs say the following:
My understanding is that we are facing the highlighted case here, but I don't see the fallback to id-based hashing (regardless of whether I explicitly declare eq=True/False in the decorator) unless I add the __hash__ = object.__hash__ line.
Issue
from attrs import define
@define(frozen=True)
class C:
x: int
def __eq__(self, value):
return self.x in (0, value)
Gives the following ruff error:
PLW1641 Object does not implement `__hash__` method
--> dbg.py:5:7
|
4 | @define(frozen=True)
5 | class C:
| ^
6 | x: int
|
These are multiple questions – the main one for me is:
but I don't see the fallback to id-based hashing (regardless of whether I explicitly declare eq=True/False in the decorator
This code prints False, True, True as the docs write – what am I missing?
from __future__ import annotations
from attrs import define, field, frozen
@frozen
class C:
x: int
@define(eq=False)
class CD:
x: int
@frozen(eq=False)
class CF:
x: int
print(C.__hash__ is object.__hash__)
print(CD.__hash__ is object.__hash__)
print(CF.__hash__ is object.__hash__)
BTW, coincidentally I've been refactoring this code and I think it's now clearer. You may want to have a peek at #1454.
Sorry for the late reply, have been traveling.
So probably it is a ruff bug then (perhaps you can confirm), but take your example and add a custom __eq__ method to any of your classes (e.g. like the one I defined in my example) and you'll get the ruff false-positive (?) error I pasted above.