Fix order in which builltin and method variant of __getattr__() is applied for C ObjectProxy.
This commit is contained in:
@@ -22,7 +22,8 @@ Version 1.2.0
|
||||
* When creating a custom proxy by deriving from ObjectProxy and the custom
|
||||
proxy needed to override __getattr__(), it was not possible to called the
|
||||
base class ObjectProxy.__getattr__() when the C implementation of
|
||||
ObjectProxy was being used.
|
||||
ObjectProxy was being used. The derived class __getattr__() could also
|
||||
get ignored.
|
||||
|
||||
Version 1.1.3
|
||||
-------------
|
||||
|
||||
@@ -1164,6 +1164,9 @@ static PyObject *WraptObjectProxy_getattro(
|
||||
WraptObjectProxyObject *self, PyObject *name)
|
||||
{
|
||||
PyObject *object = NULL;
|
||||
PyObject *result = NULL;
|
||||
|
||||
static PyObject *getattr_str = NULL;
|
||||
|
||||
object = PyObject_GenericGetAttr((PyObject *)self, name);
|
||||
|
||||
@@ -1172,12 +1175,24 @@ static PyObject *WraptObjectProxy_getattro(
|
||||
|
||||
PyErr_Clear();
|
||||
|
||||
if (!self->wrapped) {
|
||||
PyErr_SetString(PyExc_ValueError, "wrapper has not been initialised");
|
||||
return NULL;
|
||||
if (!getattr_str) {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
getattr_str = PyUnicode_InternFromString("__getattr__");
|
||||
#else
|
||||
getattr_str = PyString_InternFromString("__getattr__");
|
||||
#endif
|
||||
}
|
||||
|
||||
return PyObject_GetAttr(self->wrapped, name);
|
||||
object = PyObject_GenericGetAttr((PyObject *)self, getattr_str);
|
||||
|
||||
if (!object)
|
||||
return NULL;
|
||||
|
||||
result = PyObject_CallFunction(object, "(O)", name);
|
||||
|
||||
Py_DECREF(object);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
@@ -1195,7 +1210,12 @@ static PyObject *WraptObjectProxy_getattr(
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
return WraptObjectProxy_getattro(self, name);
|
||||
if (!self->wrapped) {
|
||||
PyErr_SetString(PyExc_ValueError, "wrapper has not been initialised");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PyObject_GetAttr(self->wrapped, name);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
@@ -1292,17 +1292,6 @@ class TestDerivedClassCreation(unittest.TestCase):
|
||||
|
||||
class DerivedClassAttributes(unittest.TestCase):
|
||||
|
||||
def test_attr_functions(self):
|
||||
|
||||
def function():
|
||||
pass
|
||||
|
||||
proxy = wrapt.ObjectProxy(function)
|
||||
|
||||
self.assertTrue(hasattr(proxy, '__getattr__'))
|
||||
self.assertTrue(hasattr(proxy, '__setattr__'))
|
||||
self.assertTrue(hasattr(proxy, '__delattr__'))
|
||||
|
||||
def test_setup_class_attributes(self):
|
||||
|
||||
def function():
|
||||
@@ -1397,5 +1386,42 @@ class DerivedClassAttributes(unittest.TestCase):
|
||||
self.assertFalse(hasattr(obj, 'ATTRIBUTE'))
|
||||
self.assertFalse(hasattr(function, 'ATTRIBUTE'))
|
||||
|
||||
class OverrideAttributeAccess(unittest.TestCase):
|
||||
|
||||
def test_attr_functions(self):
|
||||
|
||||
def function():
|
||||
pass
|
||||
|
||||
proxy = wrapt.ObjectProxy(function)
|
||||
|
||||
self.assertTrue(hasattr(proxy, '__getattr__'))
|
||||
self.assertTrue(hasattr(proxy, '__setattr__'))
|
||||
self.assertTrue(hasattr(proxy, '__delattr__'))
|
||||
|
||||
def test_override_getattr(self):
|
||||
|
||||
def function():
|
||||
pass
|
||||
|
||||
accessed = []
|
||||
|
||||
class DerivedObjectProxy(wrapt.ObjectProxy):
|
||||
def __getattr__(self, name):
|
||||
accessed.append(name)
|
||||
try:
|
||||
__getattr__ = super(DerivedObjectProxy, self).__getattr__
|
||||
except AttributeError as e:
|
||||
raise RuntimeError(str(e))
|
||||
return __getattr__(name)
|
||||
|
||||
function.attribute = 1
|
||||
|
||||
proxy = DerivedObjectProxy(function)
|
||||
|
||||
self.assertEqual(proxy.attribute, 1)
|
||||
|
||||
self.assertTrue('attribute' in accessed)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user