Add weakref support for C implementation of function wrapper.
This commit is contained in:
@@ -10,6 +10,10 @@ Version 1.10.5
|
||||
target modules were registered in the same entry point list. Only the
|
||||
callback for the last would be called regardless of the target module.
|
||||
|
||||
* If a ``WeakFunctionProxy`` wrapper was used around a method of a class
|
||||
which was decorated using a wrapt decorator, the decorator wasn't being
|
||||
invoked when the method was called via the weakref proxy.
|
||||
|
||||
**Features Changed**
|
||||
|
||||
* The ``register_post_import_hook()`` function, modelled after the
|
||||
|
@@ -15,6 +15,7 @@ typedef struct {
|
||||
|
||||
PyObject *dict;
|
||||
PyObject *wrapped;
|
||||
PyObject *weakreflist;
|
||||
} WraptObjectProxyObject;
|
||||
|
||||
PyTypeObject WraptObjectProxy_Type;
|
||||
@@ -48,6 +49,7 @@ static PyObject *WraptObjectProxy_new(PyTypeObject *type,
|
||||
|
||||
self->dict = PyDict_New();
|
||||
self->wrapped = NULL;
|
||||
self->weakreflist = NULL;
|
||||
|
||||
return (PyObject *)self;
|
||||
}
|
||||
@@ -153,6 +155,9 @@ static void WraptObjectProxy_dealloc(WraptObjectProxyObject *self)
|
||||
{
|
||||
PyObject_GC_UnTrack(self);
|
||||
|
||||
if (self->weakreflist != NULL)
|
||||
PyObject_ClearWeakRefs((PyObject *)self);
|
||||
|
||||
WraptObjectProxy_clear(self);
|
||||
|
||||
Py_TYPE(self)->tp_free(self);
|
||||
@@ -1683,7 +1688,7 @@ PyTypeObject WraptObjectProxy_Type = {
|
||||
(traverseproc)WraptObjectProxy_traverse, /*tp_traverse*/
|
||||
(inquiry)WraptObjectProxy_clear, /*tp_clear*/
|
||||
(richcmpfunc)WraptObjectProxy_richcompare, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/
|
||||
(getiterfunc)WraptObjectProxy_iter, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
WraptObjectProxy_methods, /*tp_methods*/
|
||||
@@ -1754,7 +1759,7 @@ PyTypeObject WraptCallableObjectProxy_Type = {
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
0, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
0, /*tp_methods*/
|
||||
@@ -2249,7 +2254,7 @@ PyTypeObject WraptFunctionWrapperBase_Type = {
|
||||
(traverseproc)WraptFunctionWrapperBase_traverse, /*tp_traverse*/
|
||||
(inquiry)WraptFunctionWrapperBase_clear, /*tp_clear*/
|
||||
0, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
0, /*tp_methods*/
|
||||
@@ -2482,7 +2487,7 @@ PyTypeObject WraptBoundFunctionWrapper_Type = {
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
0, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
0, /*tp_methods*/
|
||||
@@ -2622,7 +2627,7 @@ PyTypeObject WraptFunctionWrapper_Type = {
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
0, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
0, /*tp_methods*/
|
||||
|
@@ -855,6 +855,20 @@ class WeakFunctionProxy(ObjectProxy):
|
||||
|
||||
self._self_expired = False
|
||||
|
||||
if isinstance(wrapped, _FunctionWrapperBase):
|
||||
self._self_instance = weakref.ref(wrapped._self_instance,
|
||||
_callback)
|
||||
|
||||
if wrapped._self_parent is not None:
|
||||
super(WeakFunctionProxy, self).__init__(
|
||||
weakref.proxy(wrapped._self_parent, _callback))
|
||||
|
||||
else:
|
||||
super(WeakFunctionProxy, self).__init__(
|
||||
weakref.proxy(wrapped, _callback))
|
||||
|
||||
return
|
||||
|
||||
try:
|
||||
self._self_instance = weakref.ref(wrapped.__self__, _callback)
|
||||
|
||||
|
@@ -172,5 +172,23 @@ class TestWeakFunctionProxy(unittest.TestCase):
|
||||
self.assertEqual(len(result), 1)
|
||||
self.assertEqual(id(proxy), result[0])
|
||||
|
||||
def test_decorator_method(self):
|
||||
@wrapt.decorator
|
||||
def bark(wrapped, instance, args, kwargs):
|
||||
return 'bark'
|
||||
|
||||
class Animal(object):
|
||||
@bark
|
||||
def squeal(self):
|
||||
return 'squeal'
|
||||
|
||||
animal = Animal()
|
||||
|
||||
self.assertEqual(animal.squeal(), 'bark')
|
||||
|
||||
method = wrapt.WeakFunctionProxy(animal.squeal)
|
||||
|
||||
self.assertEqual(method(), 'bark')
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Reference in New Issue
Block a user