Use weakrefs to hold onto classes #2521.

This also causes the _weakref module to be built into the core.
This commit is contained in:
Benjamin Peterson 2010-08-21 03:03:22 +00:00
parent b1147f5d0a
commit 52c36051bd
4 changed files with 30 additions and 6 deletions

View file

@ -5,6 +5,7 @@
import types import types
from _weakrefset import WeakSet
# Instance of old-style class # Instance of old-style class
class _C: pass class _C: pass
@ -95,9 +96,9 @@ class ABCMeta(type):
abstracts.add(name) abstracts.add(name)
cls.__abstractmethods__ = frozenset(abstracts) cls.__abstractmethods__ = frozenset(abstracts)
# Set up inheritance registry # Set up inheritance registry
cls._abc_registry = set() cls._abc_registry = WeakSet()
cls._abc_cache = set() cls._abc_cache = WeakSet()
cls._abc_negative_cache = set() cls._abc_negative_cache = WeakSet()
cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
return cls return cls
@ -128,7 +129,7 @@ class ABCMeta(type):
"""Override for isinstance(instance, cls).""" """Override for isinstance(instance, cls)."""
# Inline the cache checking when it's simple. # Inline the cache checking when it's simple.
subclass = getattr(instance, '__class__', None) subclass = getattr(instance, '__class__', None)
if subclass in cls._abc_cache: if subclass is not None and subclass in cls._abc_cache:
return True return True
subtype = type(instance) subtype = type(instance)
# Old-style instances # Old-style instances
@ -152,7 +153,7 @@ class ABCMeta(type):
# Check negative cache; may have to invalidate # Check negative cache; may have to invalidate
if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter: if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter:
# Invalidate the negative cache # Invalidate the negative cache
cls._abc_negative_cache = set() cls._abc_negative_cache = WeakSet()
cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
elif subclass in cls._abc_negative_cache: elif subclass in cls._abc_negative_cache:
return False return False

View file

@ -3,7 +3,7 @@
"""Unit tests for abc.py.""" """Unit tests for abc.py."""
import unittest import unittest, weakref
from test import test_support from test import test_support
import abc import abc
@ -208,6 +208,22 @@ class TestABC(unittest.TestCase):
C() C()
self.assertEqual(B.counter, 1) self.assertEqual(B.counter, 1)
def test_cache_leak(self):
# See issue #2521.
class A(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def f(self):
pass
class C(A):
def f(self):
A.f(self)
r = weakref.ref(C)
# Trigger cache.
C().f()
del C
test_support.gc_collect()
self.assertEqual(r(), None)
def test_main(): def test_main():
test_support.run_unittest(TestABC) test_support.run_unittest(TestABC)

View file

@ -31,6 +31,9 @@ Core and Builtins
Library Library
------- -------
- Issue #2521: Use weakrefs on for caching in the abc module, so that classes
are not held onto after they are deleted elsewhere.
- Issue #9626: the view methods for collections.OrderedDict() were returning - Issue #9626: the view methods for collections.OrderedDict() were returning
the unordered versions inherited from dict. Those methods are now the unordered versions inherited from dict. Those methods are now
overridden to provide ordered views. overridden to provide ordered views.
@ -188,6 +191,9 @@ Library
Extension Modules Extension Modules
----------------- -----------------
- As a result of issue #2521, the _weakref module is now compiled into the
interpreter by default.
- Issue #9324: Add parameter validation to signal.signal on Windows in order - Issue #9324: Add parameter validation to signal.signal on Windows in order
to prevent crashes. to prevent crashes.

View file

@ -118,6 +118,7 @@ pwd pwdmodule.c # this is needed to find out the user's home dir
# if $HOME is not set # if $HOME is not set
_sre _sre.c # Fredrik Lundh's new regular expressions _sre _sre.c # Fredrik Lundh's new regular expressions
_codecs _codecsmodule.c # access to the builtin codecs and codec registry _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 # The zipimport module is always imported at startup. Having it as a
# builtin module avoids some bootstrapping problems and reduces overhead. # builtin module avoids some bootstrapping problems and reduces overhead.