diff options
author | Benjamin Peterson <benjamin@python.org> | 2010-08-21 03:03:22 (GMT) |
---|---|---|
committer | Benjamin Peterson <benjamin@python.org> | 2010-08-21 03:03:22 (GMT) |
commit | 52c36051bded16cf8616996e271a1aafbe2ec908 (patch) | |
tree | 60a50ec3271030d68c7fe64088cbdc553fd1b9df | |
parent | b1147f5d0a89a24a978d9db93750ad5cc3829542 (diff) | |
download | cpython-52c36051bded16cf8616996e271a1aafbe2ec908.zip cpython-52c36051bded16cf8616996e271a1aafbe2ec908.tar.gz cpython-52c36051bded16cf8616996e271a1aafbe2ec908.tar.bz2 |
Use weakrefs to hold onto classes #2521.
This also causes the _weakref module to be built into the core.
-rw-r--r-- | Lib/abc.py | 11 | ||||
-rw-r--r-- | Lib/test/test_abc.py | 18 | ||||
-rw-r--r-- | Misc/NEWS | 6 | ||||
-rw-r--r-- | Modules/Setup.dist | 1 |
4 files changed, 30 insertions, 6 deletions
@@ -5,6 +5,7 @@ import types +from _weakrefset import WeakSet # Instance of old-style class class _C: pass @@ -95,9 +96,9 @@ class ABCMeta(type): 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 @@ -128,7 +129,7 @@ class ABCMeta(type): """Override for isinstance(instance, cls).""" # Inline the cache checking when it's simple. subclass = getattr(instance, '__class__', None) - if subclass in cls._abc_cache: + if subclass is not None and subclass in cls._abc_cache: return True subtype = type(instance) # Old-style instances @@ -152,7 +153,7 @@ class ABCMeta(type): # 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 diff --git a/Lib/test/test_abc.py b/Lib/test/test_abc.py index b5af46b..6a8c3a1 100644 --- a/Lib/test/test_abc.py +++ b/Lib/test/test_abc.py @@ -3,7 +3,7 @@ """Unit tests for abc.py.""" -import unittest +import unittest, weakref from test import test_support import abc @@ -208,6 +208,22 @@ class TestABC(unittest.TestCase): C() 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(): test_support.run_unittest(TestABC) @@ -31,6 +31,9 @@ Core and Builtins 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 the unordered versions inherited from dict. Those methods are now overridden to provide ordered views. @@ -188,6 +191,9 @@ Library 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 to prevent crashes. diff --git a/Modules/Setup.dist b/Modules/Setup.dist index e76e0df..e2b0c59 100644 --- a/Modules/Setup.dist +++ b/Modules/Setup.dist @@ -118,6 +118,7 @@ pwd pwdmodule.c # this is needed to find out the user's home dir # 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. |