This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: dataclass __post_init__ recursion
Type: behavior Stage:
Components: Documentation, Library (Lib) Versions: Python 3.11
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: eric.smith Nosy List: bar.harel, docs@python, eric.smith
Priority: normal Keywords:

Created on 2022-03-06 11:34 by bar.harel, last changed 2022-04-11 14:59 by admin.

Messages (5)
msg414613 - (view) Author: Bar Harel (bar.harel) * Date: 2022-03-06 11:34
Not sure if a continuance of https://bugs.python.org/issue44365 or not, but the suggestion to call super().__init__() in __post__init__ will cause infinite recursion if the superclass also contains __post__init__:

>>> @d
... class A:
...  test: int
...  def __post_init__(self):
...    pass

>>> @d
... class B(A):
...  test2: int
...  def __post_init__(self):
...    super().__init__(test=1)

>>> B(test2=1, test=3) <-- infinite recursion.

This is caused by line 564 (https://github.com/python/cpython/blob/4716f70c8543d12d18c64677af650d479b99edac/Lib/dataclasses.py#L564) checking for post init on current class, and calling it on self (child class).

Not sure if the bug is in the documentation/suggestion, or if it's a bug in the implementation, in which case we need to call the current class's __post_init__.
msg414619 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2022-03-06 17:10
I think this is a bug in the code. I'll have a PR ready shortly.

But since it's a non-trivial change, I'm going to target it for 3.11 only.
msg414626 - (view) Author: Bar Harel (bar.harel) * Date: 2022-03-06 21:44
@Eric, I can easily fix it if you wish :-)

Just wondered if it's intended or not, as it looked like a bug but the documentation was somewhat endorsing it and I got confused.

Either case, a simple fix.
msg414627 - (view) Author: Bar Harel (bar.harel) * Date: 2022-03-06 21:51
Actually I'm not sure if the fix is so simple. What happens if B does not inherit from dataclass, but still inherits from A? Do we want to use the new __post_init__? I would assume we do, meaning we don't necessarily want to attach the __post_init__ to the dataclass, but to subclasses.

If so, the suggestion to call __init__() from __post_init__() might be the problematic part, and is what conceptually breaks the inheritance linearization.
msg414628 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2022-03-06 22:26
Yeah, I've come to the conclusion that it's not so simple, either. I'm also thinking that advising to call the base __init__ is a mistake.
History
Date User Action Args
2022-04-11 14:59:57adminsetgithub: 91094
2022-03-06 22:26:25eric.smithsetmessages: + msg414628
2022-03-06 21:51:20bar.harelsetmessages: + msg414627
2022-03-06 21:44:59bar.harelsetmessages: + msg414626
2022-03-06 17:10:39eric.smithsetassignee: docs@python -> eric.smith
messages: + msg414619
versions: - Python 3.9, Python 3.10
2022-03-06 11:57:13AlexWaygoodsetnosy: + eric.smith
2022-03-06 11:34:34bar.harelcreate