]> granicus.if.org Git - python/commitdiff
Issue #17643: Add __callback__ attribute to weakref.ref.
authorMark Dickinson <dickinsm@gmail.com>
Sat, 13 Apr 2013 14:45:44 +0000 (15:45 +0100)
committerMark Dickinson <dickinsm@gmail.com>
Sat, 13 Apr 2013 14:45:44 +0000 (15:45 +0100)
Doc/library/weakref.rst
Lib/test/test_weakref.py
Misc/NEWS
Objects/weakrefobject.c

index 1bf6b58770878168475c09c2bfe5bdc4633beb9f..78ff21d0c9d6d6a35c155d6ada42f65dbfb55d4b 100644 (file)
@@ -111,6 +111,15 @@ Extension types can easily be made to support weak references; see
 
    This is a subclassable type rather than a factory function.
 
+   .. attribute:: __callback__
+
+      This read-only attribute returns the callback currently associated to the
+      weakref.  If there is no callback or if the referent of the weakref is
+      no longer alive then this attribute will have value ``None``.
+
+      .. versionadded:: 3.4
+         Added the :attr:`__callback__` attribute.
+
 
 .. function:: proxy(object[, callback])
 
@@ -261,8 +270,9 @@ These method have the same issues as the and :meth:`keyrefs` method of
 Weak Reference Objects
 ----------------------
 
-Weak reference objects have no attributes or methods, but do allow the referent
-to be obtained, if it still exists, by calling it:
+Weak reference objects have no methods and no attributes besides
+:attr:`ref.__callback__`. A weak reference object allows the referent to be
+obtained, if it still exists, by calling it:
 
    >>> import weakref
    >>> class Object:
index cdd26c76ae5f75f5f405ddf29c3964541183f2a9..e32e24856153a0e1b1aa90d1362a41652fd2e500 100644 (file)
@@ -802,6 +802,30 @@ class ReferencesTestCase(TestBase):
         del root
         gc.collect()
 
+    def test_callback_attribute(self):
+        x = Object(1)
+        callback = lambda ref: None
+        ref1 = weakref.ref(x, callback)
+        self.assertIs(ref1.__callback__, callback)
+
+        ref2 = weakref.ref(x)
+        self.assertIsNone(ref2.__callback__)
+
+    def test_callback_attribute_after_deletion(self):
+        x = Object(1)
+        ref = weakref.ref(x, self.callback)
+        self.assertIsNotNone(ref.__callback__)
+        del x
+        support.gc_collect()
+        self.assertIsNone(ref.__callback__)
+
+    def test_set_callback_attribute(self):
+        x = Object(1)
+        callback = lambda ref: None
+        ref1 = weakref.ref(x, callback)
+        with self.assertRaises(AttributeError):
+            ref1.__callback__ = lambda ref: None
+
 
 class SubclassableWeakrefTestCase(TestBase):
 
index 4f42ff50b67574234facec0af4600aee50fefc4c..8adc9ef115d44539b2aa1ff94859b2dde7d9b322 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,8 @@ What's New in Python 3.4.0 Alpha 1?
 Core and Builtins
 -----------------
 
+- Issue #17643: Add __callback__ attribute to weakref.ref.
+
 - Issue #16447: Fixed potential segmentation fault when setting __name__ on a
   class.
 
index b49dcee1adea156e47a32fd08bd50340a3c371c1..c083f8fce5e870055c913d378cb857d454d6022a 100644 (file)
@@ -338,6 +338,11 @@ weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
 }
 
 
+static PyMemberDef weakref_members[] = {
+    {"__callback__", T_OBJECT, offsetof(PyWeakReference, wr_callback), READONLY},
+    {NULL} /* Sentinel */
+};
+
 PyTypeObject
 _PyWeakref_RefType = {
     PyVarObject_HEAD_INIT(&PyType_Type, 0)
@@ -369,7 +374,7 @@ _PyWeakref_RefType = {
     0,                          /*tp_iter*/
     0,                          /*tp_iternext*/
     0,                          /*tp_methods*/
-    0,                          /*tp_members*/
+    weakref_members,            /*tp_members*/
     0,                          /*tp_getset*/
     0,                          /*tp_base*/
     0,                          /*tp_dict*/