If a child dataclass of a parent dataclass who specified weakref_slot, also decides to set weakref_slot to True, Python will raise a TypeError as seen below:
TypeError: __weakref__ slot disallowed: either we already got one, or __itemsize__ != 0
Description
I am porting dataclasses' slots and weakref slots kwargs into a decorator I can use. While doing so, I decided to change the default of the weakref_slot because I would like all of my classes to be weakref:able. This is when I ran into the issue which can be reproduced by the code below:
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "C:\Users\%username%\Projects\testing\copyclasses.py", line 1207, in wrap
return _process_class(cls, init, repr, eq, order, unsafe_hash,
File "C:\Users\%username%\Projects\testing\copyclasses.py", line 1108, in _process_class
cls = _add_slots(cls, frozen, weakref_slot)
File "C:\Users\%username%\Projects\testing\copyclasses.py", line 1176, in _add_slots
cls = type(cls)(cls.__name__, cls.__bases__, cls_dict)
TypeError: __weakref__ slot disallowed: either we already got one, or __itemsize__ != 0
Environment
This was tested by creating a file named copyclasses.py with the current contents of Lib/dataclasses.py ran using a 3.10 CPython interpreter. Note that I've restored the naming of the module in the codeblock above assuming those who will be running it will have a built 3.11 CPython interpreter.
Footnotes: I will mention @ericvsmith as the code owner of the dataclasses file.
Traceback (most recent call last):
File "gh-93521.py", line 4, in <module>
class B(A):
TypeError: __weakref__ slot disallowed: either we already got one, or __itemsize__ != 0
It would be nice if dataclasses took care of this issue automatically though.
Example scenario: I have a library in which I expose a dataclass. A user subclasses my class in another dataclass, and wants to use weakrefs, so they use weakref_slots. Then I change my library to allow weakrefs on the base class, but now the user's child class is broken.
Locally I fixed this already, and I am planning on opening a PR with an added test. Should that PR point to main or the 3.11 branch (seeing as both branches should get the patch)?
Activity
ericvsmith commented on Jun 5, 2022
Here's an example of the same thing without dataclasses:
Traceback (most recent call last): File "gh-93521.py", line 4, in <module> class B(A): TypeError: __weakref__ slot disallowed: either we already got one, or __itemsize__ != 0ericvsmith commented on Jun 5, 2022
I'm not sure this is a bug, just the way things work.
JelleZijlstra commented on Jun 6, 2022
It would be nice if dataclasses took care of this issue automatically though.
Example scenario: I have a library in which I expose a dataclass. A user subclasses my class in another dataclass, and wants to use weakrefs, so they use weakref_slots. Then I change my library to allow weakrefs on the base class, but now the user's child class is broken.
Bluenix2 commented on Jun 6, 2022
Locally I fixed this already, and I am planning on opening a PR with an added test. Should that PR point to main or the 3.11 branch (seeing as both branches should get the patch)?
ericvsmith commented on Jun 6, 2022
main
pythonGH-93521: Filter out `__weakref__` slot if present in bases
GH-93521: For dataclasses, filter out `__weakref__` slot if present i…
pythonGH-93521: For dataclasses, filter out `__weakref__` slot if pre…
GH-93521: For dataclasses, filter out `__weakref__` slot if present i…
Revert 30935 defer bpo45162 to 312 (#94285)