diff --git a/src/_wrappers.c b/src/_wrappers.c index 716504a..6355887 100644 --- a/src/_wrappers.c +++ b/src/_wrappers.c @@ -56,43 +56,10 @@ static PyObject *WraptObjectProxy_new(PyTypeObject *type, static int WraptObjectProxy_raw_init(WraptObjectProxyObject *self, PyObject *wrapped) { - PyObject *name = NULL; - PyObject *object = NULL; - Py_INCREF(wrapped); Py_XDECREF(self->wrapped); self->wrapped = wrapped; - object = PyObject_GetAttrString(wrapped, "__name__"); - - if (object) { -#if PY_MAJOR_VERSION >= 3 - name = PyUnicode_FromString("__name__"); -#else - name = PyString_FromString("__name__"); -#endif - PyObject_GenericSetAttr((PyObject *)self, name, object); - Py_DECREF(name); - Py_DECREF(object); - } - else - PyErr_Clear(); - - object = PyObject_GetAttrString(wrapped, "__qualname__"); - - if (object) { -#if PY_MAJOR_VERSION >= 3 - name = PyUnicode_FromString("__qualname__"); -#else - name = PyString_FromString("__qualname__"); -#endif - PyObject_GenericSetAttr((PyObject *)self, name, object); - Py_DECREF(name); - Py_DECREF(object); - } - else - PyErr_Clear(); - return 0; } @@ -1011,6 +978,58 @@ static PyObject *WraptObjectProxy_exit( /* ------------------------------------------------------------------------- */ +static PyObject *WraptObjectProxy_get_name( + WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialised"); + return NULL; + } + + return PyObject_GetAttrString(self->wrapped, "__name__"); +} + +/* ------------------------------------------------------------------------- */ + +static int WraptObjectProxy_set_name(WraptObjectProxyObject *self, + PyObject *value) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialised"); + return -1; + } + + return PyObject_SetAttrString(self->wrapped, "__name__", value); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_get_qualname( + WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialised"); + return NULL; + } + + return PyObject_GetAttrString(self->wrapped, "__qualname__"); +} + +/* ------------------------------------------------------------------------- */ + +static int WraptObjectProxy_set_qualname(WraptObjectProxyObject *self, + PyObject *value) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialised"); + return -1; + } + + return PyObject_SetAttrString(self->wrapped, "__qualname__", value); +} + +/* ------------------------------------------------------------------------- */ + static PyObject *WraptObjectProxy_get_module( WraptObjectProxyObject *self) { @@ -1174,8 +1193,6 @@ static int WraptObjectProxy_setattro( WraptObjectProxyObject *self, PyObject *name, PyObject *value) { PyObject *self_prefix = NULL; - PyObject *attr_name = NULL; - PyObject *attr_qualname = NULL; PyObject *attr_wrapped = NULL; PyObject *match = NULL; @@ -1217,34 +1234,6 @@ static int WraptObjectProxy_setattro( return -1; } -#if PY_MAJOR_VERSION >= 3 - attr_name = PyUnicode_FromString("__name__"); - attr_qualname = PyUnicode_FromString("__qualname__"); -#else - attr_name = PyString_FromString("__name__"); - attr_qualname = PyString_FromString("__qualname__"); -#endif - - if (PyObject_RichCompareBool(name, attr_name, Py_EQ) == 1 || - PyObject_RichCompareBool(name, attr_qualname, Py_EQ) == 1) { - - if (PyObject_GenericSetAttr((PyObject *)self, name, value) == -1) - { - Py_DECREF(attr_name); - Py_DECREF(attr_qualname); - - return -1; - } - - Py_DECREF(attr_name); - Py_DECREF(attr_qualname); - - return PyObject_SetAttr(self->wrapped, name, value); - } - - Py_DECREF(attr_name); - Py_DECREF(attr_qualname); - return PyObject_SetAttr(self->wrapped, name, value); } @@ -1357,6 +1346,10 @@ static PyMethodDef WraptObjectProxy_methods[] = { }; static PyGetSetDef WraptObjectProxy_getset[] = { + { "__name__", (getter)WraptObjectProxy_get_name, + (setter)WraptObjectProxy_set_name, 0 }, + { "__qualname__", (getter)WraptObjectProxy_get_qualname, + (setter)WraptObjectProxy_set_qualname, 0 }, { "__module__", (getter)WraptObjectProxy_get_module, (setter)WraptObjectProxy_set_module, 0 }, { "__doc__", (getter)WraptObjectProxy_get_doc, diff --git a/src/wrappers.py b/src/wrappers.py index 7ee9403..d169fb6 100644 --- a/src/wrappers.py +++ b/src/wrappers.py @@ -51,6 +51,8 @@ class _ObjectProxyMetaType(type): class ObjectProxy(six.with_metaclass(_ObjectProxyMetaType)): + __slots__ = '_self_wrapped' + def __init__(self, wrapped): object.__setattr__(self, '_self_wrapped', wrapped) @@ -63,15 +65,13 @@ class ObjectProxy(six.with_metaclass(_ObjectProxyMetaType)): except AttributeError: pass - # Although __name__ can be overridden with a property in all - # Python versions, updating it writes it back to an internal C - # structure which can be accessed at C code level, so not sure - # if overriding it as a property is sufficient in all cases. + @property + def __name__(self): + return self._self_wrapped.__name__ - try: - object.__setattr__(self, '__name__', wrapped.__name__) - except AttributeError: - pass + @__name__.setter + def __name__(self, value): + self._self_wrapped.__name__ = value @property def __class__(self): @@ -143,7 +143,7 @@ class ObjectProxy(six.with_metaclass(_ObjectProxyMetaType)): def __setattr__(self, name, value): if name.startswith('_self_') or name == '__wrapped__': object.__setattr__(self, name, value) - elif name in ('__name__', '__qualname__'): + elif name == '__qualname__': setattr(self._self_wrapped, name, value) object.__setattr__(self, name, value) else: @@ -155,7 +155,7 @@ class ObjectProxy(six.with_metaclass(_ObjectProxyMetaType)): def __delattr__(self, name): if name.startswith('_self_') or name == '__wrapped__': object.__delattr__(self, name) - elif name in ('__name__', '__qualname__'): + elif name == '__qualname__': object.__delattr__(self, name) delattr(self._self_wrapped, name) else: @@ -365,6 +365,9 @@ class ObjectProxy(six.with_metaclass(_ObjectProxyMetaType)): class _FunctionWrapperBase(ObjectProxy): + __slots__ = ('_self_instance', '_self_wrapper', '_self_adapter', + '_self_bound_type') + def __init__(self, wrapped, instance, wrapper, adapter=None, bound_type=None): @@ -531,6 +534,8 @@ def _weak_function_proxy_callback(ref, proxy, callback): class WeakFunctionProxy(ObjectProxy): + __slots__ = ('_self_expired', '_self_instance') + def __init__(self, wrapped, callback=None): # We need to determine if the wrapped function is actually a # bound method. In the case of a bound method, we need to keep a