summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Dickinson <dickinsm@gmail.com>2013-04-13 14:45:44 (GMT)
committerMark Dickinson <dickinsm@gmail.com>2013-04-13 14:45:44 (GMT)
commit556e94b8fe068d1d58064fe84467e0620b87f9ed (patch)
tree8d6d21319dd056b30cb089d645ba8a0f729c39f7
parent548677bb8ce759395e2512420c03ccb184a77bf5 (diff)
downloadcpython-556e94b8fe068d1d58064fe84467e0620b87f9ed.zip
cpython-556e94b8fe068d1d58064fe84467e0620b87f9ed.tar.gz
cpython-556e94b8fe068d1d58064fe84467e0620b87f9ed.tar.bz2
Issue #17643: Add __callback__ attribute to weakref.ref.
-rw-r--r--Doc/library/weakref.rst14
-rw-r--r--Lib/test/test_weakref.py24
-rw-r--r--Misc/NEWS2
-rw-r--r--Objects/weakrefobject.c7
4 files changed, 44 insertions, 3 deletions
diff --git a/Doc/library/weakref.rst b/Doc/library/weakref.rst
index 1bf6b58..78ff21d0 100644
--- a/Doc/library/weakref.rst
+++ b/Doc/library/weakref.rst
@@ -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:
diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py
index cdd26c7..e32e248 100644
--- a/Lib/test/test_weakref.py
+++ b/Lib/test/test_weakref.py
@@ -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):
diff --git a/Misc/NEWS b/Misc/NEWS
index 4f42ff5..8adc9ef 100644
--- 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.
diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c
index b49dcee..c083f8f 100644
--- a/Objects/weakrefobject.c
+++ b/Objects/weakrefobject.c
@@ -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*/