Skip to content

Commit ea6a62d

Browse files
hynekJelleZijlstra
andcommitted
Fix slotted reference cycles on 3.14
Ref python/cpython#136893 & python/cpython#135228 Co-authored-by: Jelle Zijlstra <906600+JelleZijlstra@users.noreply.github.com>
1 parent 6879ffd commit ea6a62d

File tree

2 files changed

+20
-2
lines changed

2 files changed

+20
-2
lines changed

src/attr/_make.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
PY_3_10_PLUS,
2525
PY_3_11_PLUS,
2626
PY_3_13_PLUS,
27+
PY_3_14_PLUS,
2728
_AnnotationExtractor,
2829
_get_annotations,
2930
get_generic_base,
@@ -618,6 +619,17 @@ def evolve(*args, **changes):
618619
return cls(**changes)
619620

620621

622+
# Hack to the get the underlying dict out of a mappingproxy
623+
# Use it with: cls.__dict__ | _deproxier
624+
# See: https://github.com/python/cpython/pull/136893
625+
class _Deproxier:
626+
def __ror__(self, other):
627+
return other
628+
629+
630+
_deproxier = _Deproxier()
631+
632+
621633
class _ClassBuilder:
622634
"""
623635
Iteratively build *one* class.
@@ -845,6 +857,13 @@ def _create_slots_class(self):
845857
if k not in (*tuple(self._attr_names), "__dict__", "__weakref__")
846858
}
847859

860+
if PY_3_14_PLUS:
861+
# Clean up old dict to avoid leaks.
862+
old_cls_dict = self._cls.__dict__ | _deproxier
863+
old_cls_dict.pop("__dict__", None)
864+
if "__weakref__" in self._cls.__dict__:
865+
del self._cls.__weakref__
866+
848867
# If our class doesn't have its own implementation of __setattr__
849868
# (either from the user or by us), check the bases, if one of them has
850869
# an attrs-made __setattr__, that needs to be reset. We don't walk the

tests/test_make.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import attr
2424

2525
from attr import _config
26-
from attr._compat import PY_3_10_PLUS, PY_3_14_PLUS
26+
from attr._compat import PY_3_10_PLUS
2727
from attr._make import (
2828
Attribute,
2929
Factory,
@@ -1939,7 +1939,6 @@ class C2(C):
19391939

19401940
assert [C2] == C.__subclasses__()
19411941

1942-
@pytest.mark.xfail(PY_3_14_PLUS, reason="Currently broken on nightly.")
19431942
def test_no_references_to_original_when_using_cached_property(self):
19441943
"""
19451944
When subclassing a slotted class and using cached property, there are

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy