Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: avoid multiple calls of __post_init__ when dataclasses are inherited #4493

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/4487-PrettyWood.md
@@ -0,0 +1 @@
fix: avoid multiple calls of `__post_init__` when dataclasses are inherited
5 changes: 4 additions & 1 deletion pydantic/dataclasses.py
Expand Up @@ -285,7 +285,10 @@ def handle_extra_init(self: 'Dataclass', *args: Any, **kwargs: Any) -> None:
init(self, *args, **kwargs)

if hasattr(dc_cls, '__post_init__'):
post_init = dc_cls.__post_init__
try:
post_init = dc_cls.__post_init__.__wrapped__ # type: ignore[attr-defined]
except AttributeError:
post_init = dc_cls.__post_init__

@wraps(post_init)
def new_post_init(self: 'Dataclass', *args: Any, **kwargs: Any) -> None:
Expand Down
25 changes: 25 additions & 0 deletions tests/test_dataclasses.py
Expand Up @@ -1472,3 +1472,28 @@ def __post_init__(self):
self.a *= 3

assert C().a == 6 # 1 * 3 + 3


def test_inheritance_post_init_2():
post_init_calls = 0
post_init_post_parse_calls = 0

@pydantic.dataclasses.dataclass
class BaseClass:
def __post_init__(self):
nonlocal post_init_calls
post_init_calls += 1

@pydantic.dataclasses.dataclass
class AbstractClass(BaseClass):
pass

@pydantic.dataclasses.dataclass
class ConcreteClass(AbstractClass):
def __post_init_post_parse__(self):
nonlocal post_init_post_parse_calls
post_init_post_parse_calls += 1

ConcreteClass()
assert post_init_calls == 1
assert post_init_post_parse_calls == 1