Fix order in which builltin and method variant of __getattr__() is applied for C ObjectProxy.

This commit is contained in:
Graham Dumpleton
2013-10-03 14:40:38 +10:00
parent bf0dab2001
commit f69551dd6b
3 changed files with 64 additions and 17 deletions

View File

@@ -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
-------------

View File

@@ -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);
}
/* ------------------------------------------------------------------------- */

View File

@@ -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()