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
# 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()
# that we create internally.
self.assertEqual(CorrectSuper.args, ["default", "default"])
- def test_original_class_is_gced(self):
- # gh-135228: Make sure when we replace the class with slots=True, the original class
- # gets garbage collected.
- def make_simple():
- @dataclass(slots=True)
- class SlotsTest:
- pass
-
- return SlotsTest
-
- def make_with_annotations():
- @dataclass(slots=True)
- class SlotsTest:
- x: int
-
- return SlotsTest
-
- def make_with_annotations_and_method():
- @dataclass(slots=True)
- class SlotsTest:
- x: int
-
- def method(self) -> int:
- return self.x
-
- return SlotsTest
-
- for make in (make_simple, make_with_annotations, make_with_annotations_and_method):
- with self.subTest(make=make):
- C = make()
- support.gc_collect()
- candidates = [cls for cls in object.__subclasses__() if cls.__name__ == 'SlotsTest'
- and cls.__firstlineno__ == make.__code__.co_firstlineno + 1]
- self.assertEqual(candidates, [C])
-
class TestDescriptors(unittest.TestCase):
def test_set_name(self):
+++ /dev/null
-When :mod:`dataclasses` replaces a class with a slotted dataclass, the
-original class is now garbage collected again. Earlier changes in Python
-3.14 caused this class to remain in existence together with the replacement
-class synthesized by :mod:`dataclasses`.