Index: Lib/abc.py =================================================================== --- Lib/abc.py (revision 79493) +++ Lib/abc.py (working copy) @@ -3,6 +3,7 @@ """Abstract Base Classes (ABCs) according to PEP 3119.""" +from _weakrefset import WeakSet # Instance of old-style class class _C: pass @@ -93,9 +94,9 @@ abstracts.add(name) cls.__abstractmethods__ = frozenset(abstracts) # Set up inheritance registry - cls._abc_registry = set() - cls._abc_cache = set() - cls._abc_negative_cache = set() + cls._abc_registry = WeakSet() + cls._abc_cache = WeakSet() + cls._abc_negative_cache = WeakSet() cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter return cls @@ -150,7 +151,7 @@ # Check negative cache; may have to invalidate if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter: # Invalidate the negative cache - cls._abc_negative_cache = set() + cls._abc_negative_cache = WeakSet() cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter elif subclass in cls._abc_negative_cache: return False Index: Lib/test/test_collections.py =================================================================== --- Lib/test/test_collections.py (revision 79493) +++ Lib/test/test_collections.py (working copy) @@ -1,5 +1,5 @@ -import unittest, doctest +import unittest, doctest, gc import inspect from test import test_support from collections import namedtuple, Counter, OrderedDict @@ -454,6 +454,36 @@ self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__', 'add', 'discard') + def test_cache_leak(self): + class sortedlist(collections.Sequence): + def __init__(self, v): + self.add(v) + + def add(self, value): + pass + + def __len__(self): + pass + + def __getitem__(self, index): + pass + + class sortedset(sortedlist): + def add(self, value): + sortedlist.add(self, value) + + def leak(): + class T(sortedset): + pass + T(1) + + count = [] + for i in range(3): + leak() + gc.collect() + count.append(len(gc.get_objects())) + self.assertEqual(count[1], count[2]) + def test_issue_5647(self): # MutableSet.__iand__ mutated the set during iteration s = WithSet('abcd') Index: Modules/Setup.dist =================================================================== --- Modules/Setup.dist (revision 79493) +++ Modules/Setup.dist (working copy) @@ -118,6 +118,7 @@ # if $HOME is not set _sre _sre.c # Fredrik Lundh's new regular expressions _codecs _codecsmodule.c # access to the builtin codecs and codec registry +_weakref _weakref.c # weak references # The zipimport module is always imported at startup. Having it as a # builtin module avoids some bootstrapping problems and reduces overhead.