Skip to content

Commit

Permalink
fix: avoid multiple calls of __post_init__ when dataclasses are inh…
Browse files Browse the repository at this point in the history
…erited (#4493)
  • Loading branch information
PrettyWood committed Dec 29, 2022
1 parent c04923c commit a825106
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 1 deletion.
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 @@ -288,7 +288,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 @@ -1474,6 +1474,31 @@ def __post_init__(self):
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


def test_dataclass_setattr():
class Foo:
bar: str = 'cat'
Expand Down

0 comments on commit a825106

Please sign in to comment.