[Python-checkins] cpython: Issue #17643: Add __callback__ attribute to weakref.ref.

mark.dickinson python-checkins at python.org
Sat Apr 13 16:45:58 CEST 2013


http://hg.python.org/cpython/rev/9e7d31b04d78
changeset:   83286:9e7d31b04d78
user:        Mark Dickinson <dickinsm at gmail.com>
date:        Sat Apr 13 15:45:44 2013 +0100
summary:
  Issue #17643: Add __callback__ attribute to weakref.ref.

files:
  Doc/library/weakref.rst  |  14 ++++++++++++--
  Lib/test/test_weakref.py |  24 ++++++++++++++++++++++++
  Misc/NEWS                |   2 ++
  Objects/weakrefobject.c  |   7 ++++++-
  4 files changed, 44 insertions(+), 3 deletions(-)


diff --git a/Doc/library/weakref.rst b/Doc/library/weakref.rst
--- a/Doc/library/weakref.rst
+++ b/Doc/library/weakref.rst
@@ -111,6 +111,15 @@
 
    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 @@
 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:
diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py
--- a/Lib/test/test_weakref.py
+++ b/Lib/test/test_weakref.py
@@ -802,6 +802,30 @@
         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):
 
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,8 @@
 Core and Builtins
 -----------------
 
+- Issue #17643: Add __callback__ attribute to weakref.ref.
+
 - Issue #16447: Fixed potential segmentation fault when setting __name__ on a
   class.
 
diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c
--- a/Objects/weakrefobject.c
+++ b/Objects/weakrefobject.c
@@ -338,6 +338,11 @@
 }
 
 
+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 @@
     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*/

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list