summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_weakref.py
diff options
context:
space:
mode:
authorFred Drake <fdrake@acm.org>2004-07-02 18:57:45 (GMT)
committerFred Drake <fdrake@acm.org>2004-07-02 18:57:45 (GMT)
commit0a4dd390bf653128de8bc2e99da64967c8cdf86e (patch)
tree9c3b3989bc85eda1277464459cda1eae87f5d7a5 /Lib/test/test_weakref.py
parent813914049de32303ce31cae11abe9c5a49a08a4e (diff)
downloadcpython-0a4dd390bf653128de8bc2e99da64967c8cdf86e.zip
cpython-0a4dd390bf653128de8bc2e99da64967c8cdf86e.tar.gz
cpython-0a4dd390bf653128de8bc2e99da64967c8cdf86e.tar.bz2
Make weak references subclassable:
- weakref.ref and weakref.ReferenceType will become aliases for each other - weakref.ref will be a modern, new-style class with proper __new__ and __init__ methods - weakref.WeakValueDictionary will have a lighter memory footprint, using a new weakref.ref subclass to associate the key with the value, allowing us to have only a single object of overhead for each dictionary entry (currently, there are 3 objects of overhead per entry: a weakref to the value, a weakref to the dictionary, and a function object used as a weakref callback; the weakref to the dictionary could be avoided without this change) - a new macro, PyWeakref_CheckRefExact(), will be added - PyWeakref_CheckRef() will check for subclasses of weakref.ref This closes SF patch #983019.
Diffstat (limited to 'Lib/test/test_weakref.py')
-rw-r--r--Lib/test/test_weakref.py66
1 files changed, 66 insertions, 0 deletions
diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py
index 0a9e97d..31e2c7f 100644
--- a/Lib/test/test_weakref.py
+++ b/Lib/test/test_weakref.py
@@ -623,6 +623,72 @@ class ReferencesTestCase(TestBase):
finally:
gc.set_threshold(*thresholds)
+
+class SubclassableWeakrefTestCase(unittest.TestCase):
+
+ def test_subclass_refs(self):
+ class MyRef(weakref.ref):
+ def __init__(self, ob, callback=None, value=42):
+ self.value = value
+ super(MyRef, self).__init__(ob, callback)
+ def __call__(self):
+ self.called = True
+ return super(MyRef, self).__call__()
+ o = Object("foo")
+ mr = MyRef(o, value=24)
+ self.assert_(mr() is o)
+ self.assert_(mr.called)
+ self.assertEqual(mr.value, 24)
+ del o
+ self.assert_(mr() is None)
+ self.assert_(mr.called)
+
+ def test_subclass_refs_dont_replace_standard_refs(self):
+ class MyRef(weakref.ref):
+ pass
+ o = Object(42)
+ r1 = MyRef(o)
+ r2 = weakref.ref(o)
+ self.assert_(r1 is not r2)
+ self.assertEqual(weakref.getweakrefs(o), [r2, r1])
+ self.assertEqual(weakref.getweakrefcount(o), 2)
+ r3 = MyRef(o)
+ self.assertEqual(weakref.getweakrefcount(o), 3)
+ refs = weakref.getweakrefs(o)
+ self.assertEqual(len(refs), 3)
+ self.assert_(r2 is refs[0])
+ self.assert_(r1 in refs[1:])
+ self.assert_(r3 in refs[1:])
+
+ def test_subclass_refs_dont_conflate_callbacks(self):
+ class MyRef(weakref.ref):
+ pass
+ o = Object(42)
+ r1 = MyRef(o, id)
+ r2 = MyRef(o, str)
+ self.assert_(r1 is not r2)
+ refs = weakref.getweakrefs(o)
+ self.assert_(r1 in refs)
+ self.assert_(r2 in refs)
+
+ def test_subclass_refs_with_slots(self):
+ class MyRef(weakref.ref):
+ __slots__ = "slot1", "slot2"
+ def __new__(type, ob, callback, slot1, slot2):
+ return weakref.ref.__new__(type, ob, callback)
+ def __init__(self, ob, callback, slot1, slot2):
+ self.slot1 = slot1
+ self.slot2 = slot2
+ def meth(self):
+ return self.slot1 + self.slot2
+ o = Object(42)
+ r = MyRef(o, None, "abc", "def")
+ self.assertEqual(r.slot1, "abc")
+ self.assertEqual(r.slot2, "def")
+ self.assertEqual(r.meth(), "abcdef")
+ self.failIf(hasattr(r, "__dict__"))
+
+
class Object:
def __init__(self, arg):
self.arg = arg