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.

Author jfuruness
Recipients eric.smith, jfuruness, josh.r
Date 2021-10-20.21:01:44
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <CANDi=9HFU20f5vUDvr7e_CGMhT6S5_Pi7EtP7XFhf8mcU6kBNg@mail.gmail.com>
In-reply-to <1634678917.75.0.508428359028.issue45520@roundup.psfhosted.org>
Content
Thank you for the in-depth explanation. That all makes sense to me, I have
run into the __slots__ with defaults issues before, I'll be sure to try out
these fixes. I appreciate you taking the time.

Thanks,
Justin

On Tue, Oct 19, 2021 at 5:28 PM Josh Rosenberg <report@bugs.python.org>
wrote:

>
> Josh Rosenberg <shadowranger+python@gmail.com> added the comment:
>
> You're right that in non-dataclass scenarios, you'd just use __slots__.
>
> The slots=True thing was necessary for any case where any of the
> dataclass's attributes have default values (my_int: int = 0), or are
> defined with fields (my_list: list = field(default_factory=list)). The
> problem is that __slots__ is implemented by, after the class definition
> ends, creating descriptors on the class to access the data stored at known
> offsets in the underlying PyObject structure. Those descriptors themselves
> being class attributes means that when the type definition machinery tries
> to use __slots__ to create them, it finds conflicting class attributes (the
> defaults/fields) that already exist and explodes.
>
> Adding support for slots=True means it does two things:
>
> 1. It completely defines the class without slots, extracts the stuff it
> needs to make the dataclass separately, then deletes it from the class
> definition namespace and makes a *new* class with __slots__ defined (so no
> conflict occurs)
> 2. It checks if the dataclass is also frozen, and applies alternate
> __getstate__/__setstate__ methods that are compatible with a frozen,
> slotted dataclass
>
> #2 is what fixes this bug (while #1 makes it possible to use the full
> range of dataclass features without sacrificing the ability to use
> __slots__). If you need this to work in 3.9, you could borrow the 3.10
> implementations that make this work for frozen dataclasses to explicitly
> define __getstate__/__setstate__ for your frozen slotted dataclasses:
>
> def __getstate__(self):
>     return [getattr(self, f.name) for f in fields(self)]
>
>
> def __setstate__(self, state):
>     for field, value in zip(fields(self), state):
>         # use setattr because dataclass may be frozen
>         object.__setattr__(self, field.name, value)
>
> I'm not closing this since backporting just the fix for frozen slotted
> dataclasses (without backporting the full slots=True functionality that's a
> new feature) is possibly within scope for a bugfix release of 3.9 (it
> wouldn't change the behavior of working code, and fixes broken code that
> might reasonably be expected to work).
>
> ----------
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <https://bugs.python.org/issue45520>
> _______________________________________
>
History
Date User Action Args
2021-10-20 21:01:44jfurunesssetrecipients: + jfuruness, eric.smith, josh.r
2021-10-20 21:01:44jfurunesslinkissue45520 messages
2021-10-20 21:01:44jfurunesscreate