fix __post_init__ cause infinite recursion in inheritance #606
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Change Summary
_pydantic_post_init
into_process_class
, so it can use the closure feature to capture parent scopepost_init_original
method.__post_init_original__
and__post_init_post_parse__
method.Related issue number
It will resolve #536
Checklist
HISTORY.rst
has been updated#<number>
@<whomever>
Why it can resolve the problem
Sorry for my pool English, it is not my native language.
Firstly, we should know
Above code will print
<__main__.B object at 0x7fdb1d7a1908>
, it is a instance of ClassB
that we pass toA.test
.In pydantic, if we use the
dataclass
decorator, it will replace user's__post_init__
to_pydantic_post_init
, and save original__post_init__
in__post_init_original__
pydantic/pydantic/dataclasses.py
Lines 74 to 86 in dd44fda
According to code of issue #536,
After decorated by
dataclass
,So when we create an instance of class
B
, likeB(a=1, b=2)
. Python stdlib's dataclass will call__post_init__
automatically. But it callspydantic.dataclasses._pydantic_post_init
actually(we replace it).In
_pydantic_post_init
, it will call original__post_init__
through__post_init_original__
pydantic/pydantic/dataclasses.py
Lines 28 to 35 in dd44fda
In above code, we call
super().__post_init__()
in__post_init_original__
, Python will findA.__post_init__
and pass instanceb
. CurrentlyA.__post_init__
is also apydantic.dataclasses._pydantic_post_init
. So it will get__post_init_original__
by instanceb
, we fall into a infinite recursion.