The behavior of the __post_init__ routine for pydantic dataclasses is inconsistent across pydantic versions.
Output of python -c "import pydantic.utils; print(pydantic.utils.version_info())":
pydantic version: 1.3
pydantic compiled: True
install path: /home/ubuntu/moo/lib/python3.6/site-packages/pydantic
python version: 3.6.7 (default, Oct 22 2018, 11:32:17) [GCC 8.2.0]
platform: Linux-4.15.0-1057-aws-x86_64-with-Ubuntu-18.04-bionic
optional deps. installed: []
Issue #739 is related but it talks specifically about descendant classes.
from pydantic.dataclasses import dataclass
@dataclass
class A:
a = 10
def __post_init__(self):
print("custom initializer called")
self.x = {}
a = A()
print(a.x)
The post init method is called but the extra attribute x is not added to the class instance.
custom initializer called
Traceback (most recent call last):
File "test.py", line 10, in <module>
print(a.x)
AttributeError: 'A' object has no attribute 'x'
Downgrading pydantic version to 0.26, it does work. So does using the dataclass object from dataclasses module for python 3.6.
custom initializer called
{}
Is this an intentional change in behavior? Apologies if I've missed something
The solution is to use __post_init_post_parse__ instead of __post_init__.
This was changed back in v0.28 see #567 and associated issues/PRs for dicussion
Thank you. Would it be useful to specifically point out in the documentation that pydantic dataclass initialize hooks are split into two - before and after validation, and extra attributes can only be added after? Happy to submit a PR.
It tripped me up a bit since it worked okay before in older pydantic versions and dataclasses package.
okay, I'd accept a PR. But I would guess very few people are still using pydantic pre v0.28, so I'm not sure how helpful that specific pointer would be?
right. I was thinking more about the difference between pydantic dataclass and python standard library dataclass in that the __post_init__ method doesn't work _exactly_ the same. I added a note here - #1188.