mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
bpo-46382 dataclass(slots=True) now takes inherited slots into account (GH-31980)
Do not include any members in __slots__ that are already in a base class's __slots__.
This commit is contained in:
parent
383a3bec74
commit
82e9b0bb0a
4 changed files with 77 additions and 9 deletions
|
@ -6,6 +6,7 @@ import inspect
|
|||
import keyword
|
||||
import builtins
|
||||
import functools
|
||||
import itertools
|
||||
import abc
|
||||
import _thread
|
||||
from types import FunctionType, GenericAlias
|
||||
|
@ -1122,6 +1123,20 @@ def _dataclass_setstate(self, state):
|
|||
object.__setattr__(self, field.name, value)
|
||||
|
||||
|
||||
def _get_slots(cls):
|
||||
match cls.__dict__.get('__slots__'):
|
||||
case None:
|
||||
return
|
||||
case str(slot):
|
||||
yield slot
|
||||
# Slots may be any iterable, but we cannot handle an iterator
|
||||
# because it will already be (partially) consumed.
|
||||
case iterable if not hasattr(iterable, '__next__'):
|
||||
yield from iterable
|
||||
case _:
|
||||
raise TypeError(f"Slots of '{cls.__name__}' cannot be determined")
|
||||
|
||||
|
||||
def _add_slots(cls, is_frozen):
|
||||
# Need to create a new class, since we can't set __slots__
|
||||
# after a class has been created.
|
||||
|
@ -1133,7 +1148,13 @@ def _add_slots(cls, is_frozen):
|
|||
# Create a new dict for our new class.
|
||||
cls_dict = dict(cls.__dict__)
|
||||
field_names = tuple(f.name for f in fields(cls))
|
||||
cls_dict['__slots__'] = field_names
|
||||
# Make sure slots don't overlap with those in base classes.
|
||||
inherited_slots = set(
|
||||
itertools.chain.from_iterable(map(_get_slots, cls.__mro__[1:-1]))
|
||||
)
|
||||
cls_dict["__slots__"] = tuple(
|
||||
itertools.filterfalse(inherited_slots.__contains__, field_names)
|
||||
)
|
||||
for field_name in field_names:
|
||||
# Remove our attributes, if present. They'll still be
|
||||
# available in _MARKER.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue