Repository navigation
dataclass, slots, __post_init__ and super #111500
Description
Activity
- addedtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
on Oct 30, 2023 - addedstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
on Oct 30, 2023 I think that I found why this happens :)
First of all, I was not able to reproduce it without
@dataclass, so I assumed it is related to the internal machinery.This is my debug patch:
» git patch diff --git Lib/dataclasses.py Lib/dataclasses.py index 2fba32b5ffb..a7ce3c03e9b 100644 --- Lib/dataclasses.py +++ Lib/dataclasses.py @@ -1232,7 +1232,7 @@ def _add_slots(cls, is_frozen, weakref_slot): # And finally create the class. qualname = getattr(cls, '__qualname__', None) - cls = type(cls)(cls.__name__, cls.__bases__, cls_dict) + cls = type(cls)(cls.__name__ + '__slots', cls.__bases__, cls_dict) if qualname is not None: cls.__qualname__ = qualname diff --git Objects/typeobject.c Objects/typeobject.c index 25085693070..79db15579e5 100644 --- Objects/typeobject.c +++ Objects/typeobject.c @@ -10400,9 +10400,11 @@ supercheck(PyTypeObject *type, PyObject *obj) Py_XDECREF(class_attr); } - PyErr_SetString(PyExc_TypeError, + PyErr_Format(PyExc_TypeError, "super(type, obj): " - "obj must be an instance or subtype of type"); + "obj must be an instance or subtype of type %s %s", + Py_TYPE(obj)->tp_name, + type->tp_name); return NULL; }
Turns out, I was right. Given the code in the original bug report, it produces:
Traceback (most recent call last): File "/Users/sobolev/Desktop/cpython2/ex.py", line 32, in <module> Thing2(1, 2) File "/Users/sobolev/Desktop/cpython2/ex.py", line 19, in __init__ self.__post_init__() File "/Users/sobolev/Desktop/cpython2/ex.py", line 24, in __post_init__ super().__post_init__() ^^^^^^^^^^^^^^^^^^^^^ TypeError: super(type, obj): obj must be an instance or subtype of type Thing__slots ThingLooks like we add slots and regenerate class in the very end. I think we can try doing it at the beggining. Maybe it will help.
I am working on this idea! :)
Reacted by Asif Saif Uddin {"Auvi":"অভি"}Here are some experiments that I had:
from dataclasses import dataclass # from attr import dataclass @dataclass(slots=True) class Base: def m(self): return "DONE!" class Thing(Base): def m(self): print(super().m()) Thing2 = dataclass(slots=True)(Thing) Thing2().m()
It fails with the same error. However, if you
pip install attrsand uncomment# from attr import dataclassit will work and printDONE!So, it can be fixed (given that our
_add_slotsfunctions are similar): https://github.com/python-attrs/attrs/blob/52c1cd97d723cde6d75259a22d218f9305ecf8ee/src/attr/_make.py#L809-L914Nice work @sobolevn
Reacted by HashDuplicate of #90562
- marked this as a duplicate of RFE: @dataclasses.dataclass(slots=True) doesn't support methods using zero-arg super() #90562
on Mar 12, 2024
Bug report
Bug description:
Using
super()in__post_init__on a dataclass with slots fails.This code:
Produces this exception:
The fix is to use Python 2 style
super(Class, self).__post_init__().CPython versions tested on:
3.11
Operating systems tested on:
Windows
Linked PRs
super()without args calls fordataclasseswith slots #111538