From 4c41099fb85ff58aec74d167935b3716557dad6d Mon Sep 17 00:00:00 2001 From: George Macon Date: Sat, 28 Jul 2018 06:24:53 -0400 Subject: [PATCH] Do not copy __weakref__ from original _cls_dict (#410) self._cls_dict["__weakref__"] holds a reference to self._cls, preventing self._cls from being released after the new, slots-enabled class is returned. Fixes #407 --- changelog.d/407.change.rst | 1 + src/attr/_make.py | 2 +- tests/test_make.py | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 changelog.d/407.change.rst diff --git a/changelog.d/407.change.rst b/changelog.d/407.change.rst new file mode 100644 index 00000000..8adc0602 --- /dev/null +++ b/changelog.d/407.change.rst @@ -0,0 +1 @@ +Fixed a reference leak where the original class would remain live after being replaced when ``slots=True`` is set. diff --git a/src/attr/_make.py b/src/attr/_make.py index 905f3092..a8d9c70c 100644 --- a/src/attr/_make.py +++ b/src/attr/_make.py @@ -493,7 +493,7 @@ class _ClassBuilder(object): cd = { k: v for k, v in iteritems(self._cls_dict) - if k not in tuple(self._attr_names) + ("__dict__",) + if k not in tuple(self._attr_names) + ("__dict__", "__weakref__") } # We only add the names of attributes that aren't inherited. diff --git a/tests/test_make.py b/tests/test_make.py index e407b9f4..20d13b6a 100644 --- a/tests/test_make.py +++ b/tests/test_make.py @@ -5,6 +5,7 @@ Tests for `attr._make`. from __future__ import absolute_import, division, print_function import copy +import gc import inspect import itertools import sys @@ -1250,6 +1251,25 @@ class TestClassBuilder(object): assert C() == copy.deepcopy(C()) + def test_no_references_to_original(self): + """ + When subclassing a slots class, there are no stray references to the + original class. + """ + + @attr.s(slots=True) + class C(object): + pass + + @attr.s(slots=True) + class C2(C): + pass + + # The original C2 is in a reference cycle, so force a collect: + gc.collect() + + assert [C2] == C.__subclasses__() + class TestMakeCmp: """