mirror of
https://github.com/python/cpython.git
synced 2025-12-03 08:04:34 +00:00
gh-135228: When @dataclass(slots=True) replaces a dataclass, make the original class collectible (take 2) (GH-137047)
Remove the `__dict__` and `__weakref__` descriptors from the original class when creating a dataclass from it. An interesting hack, but more localized in scope than gh-135230. This may be a breaking change if people intentionally keep the original class around when using `@dataclass(slots=True)`, and then use `__dict__` or `__weakref__` on the original class. Co-authored-by: Alyssa Coghlan <ncoghlan@gmail.com> Co-authored-by: Petr Viktorin <encukou@gmail.com> Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
parent
027cacb67c
commit
6859b95cff
5 changed files with 117 additions and 7 deletions
|
|
@ -1283,6 +1283,10 @@ def _add_slots(cls, is_frozen, weakref_slot, defined_fields):
|
|||
if '__slots__' in cls.__dict__:
|
||||
raise TypeError(f'{cls.__name__} already specifies __slots__')
|
||||
|
||||
# gh-102069: Remove existing __weakref__ descriptor.
|
||||
# gh-135228: Make sure the original class can be garbage collected.
|
||||
sys._clear_type_descriptors(cls)
|
||||
|
||||
# Create a new dict for our new class.
|
||||
cls_dict = dict(cls.__dict__)
|
||||
field_names = tuple(f.name for f in fields(cls))
|
||||
|
|
@ -1300,12 +1304,6 @@ def _add_slots(cls, is_frozen, weakref_slot, defined_fields):
|
|||
# available in _MARKER.
|
||||
cls_dict.pop(field_name, None)
|
||||
|
||||
# Remove __dict__ itself.
|
||||
cls_dict.pop('__dict__', None)
|
||||
|
||||
# Clear existing `__weakref__` descriptor, it belongs to a previous type:
|
||||
cls_dict.pop('__weakref__', None) # gh-102069
|
||||
|
||||
# And finally create the class.
|
||||
qualname = getattr(cls, '__qualname__', None)
|
||||
newcls = type(cls)(cls.__name__, cls.__bases__, cls_dict)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue