]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Revert "gh-135228: When @dataclass(slots=True) replaces a dataclass, make the origina...
authorJelle Zijlstra <jelle.zijlstra@gmail.com>
Wed, 23 Jul 2025 15:13:19 +0000 (08:13 -0700)
committerGitHub <noreply@github.com>
Wed, 23 Jul 2025 15:13:19 +0000 (08:13 -0700)
This reverts commit 46cbdf967ada11b0286060488b61635fd6a2bb23.

Lib/dataclasses.py
Lib/test/test_dataclasses/__init__.py
Misc/NEWS.d/next/Library/2025-07-20-16-56-55.gh-issue-135228.n_XIao.rst [deleted file]

index 22b78bb2fbe6ed3784d701cf8a4480a065ac7d03..83ea623dce6281be6e0e738b0746554ce5ab3139 100644 (file)
@@ -1338,13 +1338,6 @@ 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
 
 
@@ -1739,11 +1732,3 @@ 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()
index 6bf5e5b3e5554be954ac4b34b5c78fda27531311..e98a8f284cec9fd0d2b8257f1f9b74318c06840a 100644 (file)
@@ -3804,41 +3804,6 @@ class TestSlots(unittest.TestCase):
         # 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):
diff --git a/Misc/NEWS.d/next/Library/2025-07-20-16-56-55.gh-issue-135228.n_XIao.rst b/Misc/NEWS.d/next/Library/2025-07-20-16-56-55.gh-issue-135228.n_XIao.rst
deleted file mode 100644 (file)
index ee8962c..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-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`.