You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Generate a hash function when allow_mutation is False #1880
I need the model to be hashable when I set allow_mutation to False. I could write myself a __hash__ function, but I think it could be nice if pydantic generated it by default in the class BaseModel.
This would be the same behavior of the built-in dataclass which generate a hash function if the object is immutable (parameter frozen is True) and the __eq__ function exists.
@rhuille@samuelcolvin I believe that the introduction of explicitly setting __hash__ to None for non frozen BaseModels is a backwards incompatible breaking change for models which inherit from a common BaseModel implementation that defines __hash__ and __eq__.
Minimal reproduction:
importpydanticfrompydanticimportBaseModelprint(f"Version: {pydantic.version.VERSION}")
classHashableModel(BaseModel):
x: intclassConfig:
allow_mutation=Falsedef__hash__(self):
returnhash((type(self),) +tuple(self.__dict__.values()))
def__eq__(self, other):
returnself.__hash__() ==other.__hash__()
classChildModel(HashableModel):
y: int# This is fine test= {HashableModel(x=4): HashableModel(x=2)}
print(test)
# This will fail on 1.8 test= {ChildModel(x=4, y=2): ChildModel(x=2, y=2)}
print(test)
Version: 1.8
{HashableModel(x=4): HashableModel(x=2)}
Traceback (most recent call last):
File "repro.py", line 26, in <module>
test = {ChildModel(x=4, y=2): ChildModel(x=2, y=2)}
TypeError: unhashable type: 'ChildModel'
A temporary workaround that is both forwards and backwards compatible is to set frozen explicitly to True on the superclass:
classConfig:
allow_mutation=Falsefrozen=True
Looking at the patch I'm not sure if there is a simple way to fix this, but I imagine this might hit some folks who have previously defined a common ImmutableBaseModel and are using that instead of BaseModel various places.
Activity
Generate a hash function when `allow_mutation` is `False`
Generate a hash function when `allow_mutation` is `False`
Generate a hash function when `allow_mutation` is `False`
jolynch commentedon Mar 1, 2021
@rhuille @samuelcolvin I believe that the introduction of explicitly setting
__hash__to None for non frozen BaseModels is a backwards incompatible breaking change for models which inherit from a common BaseModel implementation that defines__hash__and__eq__.Minimal reproduction:
On
1.7.3:On
1.8:A temporary workaround that is both forwards and backwards compatible is to set
frozenexplicitly toTrueon the superclass:Looking at the patch I'm not sure if there is a simple way to fix this, but I imagine this might hit some folks who have previously defined a common
ImmutableBaseModeland are using that instead ofBaseModelvarious places.Workaround for pydantic/pydantic#1880
samuelcolvin commentedon Mar 1, 2021
Is this fixed by #2423?
jolynch commentedon Mar 1, 2021
Yes it is fixed by that patch, verified with:
$ python3 -m venv venv_test $ venv_test/bin/pip install wheel $ venv_test/bin/pip install git+https://github.com/samuelcolvin/pydantic.git@f9fe4aa086e7458f3c3339c408b3215f34e6ca18 $ venv_test/bin/python repro.py Version: 1.8 {HashableModel(x=4): HashableModel(x=2)} {ChildModel(x=4, y=2): ChildModel(x=2, y=2)}Thanks and apologies for not seeing the new patch!
ekampf commentedon Mar 2, 2021
@samuelcolvin any chance you can push a
1.8.1with that fix?Squashed 'pydantic-core/' changes from 1b8dbfa..b52670e84