mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
[3.14] gh-135228: When @dataclass(slots=True) replaces a dataclass, make the original class collectible (GH-136893) (#136960)
gh-135228: When @dataclass(slots=True) replaces a dataclass, make the original class collectible (GH-136893)
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.
(cherry picked from commit 46cbdf967a)
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Co-authored-by: Alyssa Coghlan <ncoghlan@gmail.com>
This commit is contained in:
parent
caef946a25
commit
6e1b31b87e
3 changed files with 54 additions and 0 deletions
|
|
@ -1338,6 +1338,13 @@ def _add_slots(cls, is_frozen, weakref_slot, defined_fields):
|
|||
or _update_func_cell_for__class__(member.fdel, cls, newcls)):
|
||||
break
|
||||
|
||||
# gh-135228: Make sure the original class can be garbage collected.
|
||||
# Bypass mapping proxy to allow __dict__ to be removed
|
||||
old_cls_dict = cls.__dict__ | _deproxier
|
||||
old_cls_dict.pop('__dict__', None)
|
||||
if "__weakref__" in cls.__dict__:
|
||||
del cls.__weakref__
|
||||
|
||||
return newcls
|
||||
|
||||
|
||||
|
|
@ -1732,3 +1739,11 @@ def _replace(self, /, **changes):
|
|||
# changes that aren't fields, this will correctly raise a
|
||||
# TypeError.
|
||||
return self.__class__(**changes)
|
||||
|
||||
|
||||
# Hack to the get the underlying dict out of a mappingproxy
|
||||
# Use it with: cls.__dict__ | _deproxier
|
||||
class _Deproxier:
|
||||
def __ror__(self, other):
|
||||
return other
|
||||
_deproxier = _Deproxier()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue