Handle name preservation for an adapter when creating the decorator rather than in the wrapper itself.
This commit is contained in:
253
src/_wrappers.c
253
src/_wrappers.c
@@ -14,7 +14,6 @@ typedef struct {
|
||||
PyObject_HEAD
|
||||
PyObject *dict;
|
||||
PyObject *wrapped;
|
||||
PyObject *target;
|
||||
} WraptObjectProxyObject;
|
||||
|
||||
PyTypeObject WraptObjectProxy_Type;
|
||||
@@ -23,7 +22,7 @@ typedef struct {
|
||||
WraptObjectProxyObject object_proxy;
|
||||
PyObject *wrapper;
|
||||
PyObject *params;
|
||||
PyObject *wrapper_type;
|
||||
PyObject *bound_type;
|
||||
} WraptFunctionWrapperObject;
|
||||
|
||||
PyTypeObject WraptFunctionWrapper_Type;
|
||||
@@ -60,7 +59,6 @@ static PyObject *WraptObjectProxy_new(PyTypeObject *type,
|
||||
|
||||
self->dict = NULL;
|
||||
self->wrapped = NULL;
|
||||
self->target = NULL;
|
||||
|
||||
return (PyObject *)self;
|
||||
}
|
||||
@@ -71,21 +69,19 @@ static int WraptObjectProxy_init(WraptObjectProxyObject *self,
|
||||
PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject *wrapped = NULL;
|
||||
PyObject *target = NULL;;
|
||||
|
||||
PyObject *name = NULL;
|
||||
PyObject *object = NULL;
|
||||
|
||||
static char *kwlist[] = { "wrapped", "target", NULL };
|
||||
static char *kwlist[] = { "wrapped", NULL };
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:ObjectProxy",
|
||||
kwlist, &wrapped, &target)) {
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:ObjectProxy",
|
||||
kwlist, &wrapped)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Py_XDECREF(self->dict);
|
||||
Py_XDECREF(self->wrapped);
|
||||
Py_XDECREF(self->target);
|
||||
|
||||
self->dict = PyDict_New();
|
||||
|
||||
@@ -93,86 +89,35 @@ static int WraptObjectProxy_init(WraptObjectProxyObject *self,
|
||||
|
||||
self->wrapped = wrapped;
|
||||
|
||||
if (!target || target == Py_None) {
|
||||
object = PyObject_GetAttrString(wrapped, "__wrapped__");
|
||||
object = PyObject_GetAttrString(wrapped, "__name__");
|
||||
|
||||
if (object) {
|
||||
self->target = object;
|
||||
}
|
||||
else {
|
||||
PyErr_Clear();
|
||||
|
||||
Py_INCREF(wrapped);
|
||||
self->target = wrapped;
|
||||
}
|
||||
|
||||
object = PyObject_GetAttrString(wrapped, "__name__");
|
||||
|
||||
if (object) {
|
||||
if (object) {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
name = PyUnicode_FromString("__name__");
|
||||
name = PyUnicode_FromString("__name__");
|
||||
#else
|
||||
name = PyString_FromString("__name__");
|
||||
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();
|
||||
PyObject_GenericSetAttr((PyObject *)self, name, object);
|
||||
Py_DECREF(name);
|
||||
Py_DECREF(object);
|
||||
}
|
||||
else {
|
||||
if (!target)
|
||||
target = Py_None;
|
||||
else
|
||||
PyErr_Clear();
|
||||
|
||||
Py_INCREF(target);
|
||||
self->target = target;
|
||||
object = PyObject_GetAttrString(wrapped, "__qualname__");
|
||||
|
||||
object = PyObject_GetAttrString(target, "__name__");
|
||||
|
||||
if (object) {
|
||||
if (object) {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
name = PyUnicode_FromString("__name__");
|
||||
name = PyUnicode_FromString("__qualname__");
|
||||
#else
|
||||
name = PyString_FromString("__name__");
|
||||
name = PyString_FromString("__qualname__");
|
||||
#endif
|
||||
PyObject_GenericSetAttr((PyObject *)self, name, object);
|
||||
Py_DECREF(name);
|
||||
Py_DECREF(object);
|
||||
}
|
||||
else
|
||||
PyErr_Clear();
|
||||
|
||||
object = PyObject_GetAttrString(target, "__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();
|
||||
PyObject_GenericSetAttr((PyObject *)self, name, object);
|
||||
Py_DECREF(name);
|
||||
Py_DECREF(object);
|
||||
}
|
||||
else
|
||||
PyErr_Clear();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -183,7 +128,6 @@ static void WraptObjectProxy_dealloc(WraptObjectProxyObject *self)
|
||||
{
|
||||
Py_XDECREF(self->dict);
|
||||
Py_XDECREF(self->wrapped);
|
||||
Py_XDECREF(self->target);
|
||||
|
||||
Py_TYPE(self)->tp_free(self);
|
||||
}
|
||||
@@ -343,6 +287,41 @@ static PyObject *WraptObjectProxy_get_class(
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static PyObject *WraptObjectProxy_get_wrapped(
|
||||
WraptObjectProxyObject *self)
|
||||
{
|
||||
PyObject *result = NULL;
|
||||
|
||||
if (!self->wrapped) {
|
||||
PyErr_SetString(PyExc_ValueError, "wrapper has not been initialised");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = PyObject_GetAttrString(self->wrapped, "__wrapped__");
|
||||
|
||||
if (!result) {
|
||||
Py_INCREF(self->wrapped);
|
||||
result = self->wrapped;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static int WraptObjectProxy_set_wrapped(WraptObjectProxyObject *self,
|
||||
PyObject *value)
|
||||
{
|
||||
if (!self->wrapped) {
|
||||
PyErr_SetString(PyExc_ValueError, "wrapper has not been initialised");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return PyObject_SetAttrString(self->wrapped, "__wrapped__", value);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static PyObject *WraptObjectProxy_get_annotations(
|
||||
WraptObjectProxyObject *self)
|
||||
{
|
||||
@@ -369,7 +348,7 @@ static int WraptObjectProxy_set_annotations(WraptObjectProxyObject *self,
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static PyObject *WraptObjectProxy_get_wrapped(
|
||||
static PyObject *WraptObjectProxy_get_self_wrapped(
|
||||
WraptObjectProxyObject *self, void *closure)
|
||||
{
|
||||
if (!self->wrapped) {
|
||||
@@ -383,20 +362,6 @@ static PyObject *WraptObjectProxy_get_wrapped(
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static PyObject *WraptObjectProxy_get_target(
|
||||
WraptObjectProxyObject *self, void *closure)
|
||||
{
|
||||
if (!self->target) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
Py_INCREF(self->target);
|
||||
return self->target;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static PyObject *WraptObjectProxy_getattro(
|
||||
WraptObjectProxyObject *self, PyObject *name)
|
||||
{
|
||||
@@ -512,9 +477,9 @@ static PyGetSetDef WraptObjectProxy_getset[] = {
|
||||
NULL, 0 },
|
||||
{ "__annotations__", (getter)WraptObjectProxy_get_annotations,
|
||||
(setter)WraptObjectProxy_set_annotations, 0 },
|
||||
{ "_self_wrapped", (getter)WraptObjectProxy_get_wrapped,
|
||||
NULL, 0 },
|
||||
{ "_self_target", (getter)WraptObjectProxy_get_target,
|
||||
{ "__wrapped__", (getter)WraptObjectProxy_get_wrapped,
|
||||
(setter)WraptObjectProxy_set_wrapped, 0 },
|
||||
{ "_self_wrapped", (getter)WraptObjectProxy_get_self_wrapped,
|
||||
NULL, 0 },
|
||||
{ NULL },
|
||||
};
|
||||
@@ -579,7 +544,7 @@ static PyObject *WraptFunctionWrapper_new(PyTypeObject *type,
|
||||
|
||||
self->wrapper = NULL;
|
||||
self->params = NULL;
|
||||
self->wrapper_type = NULL;
|
||||
self->bound_type = NULL;
|
||||
|
||||
return (PyObject *)self;
|
||||
}
|
||||
@@ -591,7 +556,6 @@ static int WraptFunctionWrapper_init(WraptFunctionWrapperObject *self,
|
||||
{
|
||||
PyObject *wrapped = NULL;
|
||||
PyObject *wrapper = NULL;
|
||||
PyObject *target = NULL;
|
||||
PyObject *params = NULL;
|
||||
|
||||
PyObject *base_args = NULL;
|
||||
@@ -599,26 +563,22 @@ static int WraptFunctionWrapper_init(WraptFunctionWrapperObject *self,
|
||||
|
||||
int result = 0;
|
||||
|
||||
static char *kwlist[] = { "wrapped", "wrapper", "target", "params",
|
||||
NULL };
|
||||
static char *kwlist[] = { "wrapped", "wrapper", "params", NULL };
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO:FunctionWrapper",
|
||||
kwlist, &wrapped, &wrapper, &target, ¶ms)) {
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O:FunctionWrapper",
|
||||
kwlist, &wrapped, &wrapper, ¶ms)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Py_XDECREF(self->wrapper);
|
||||
Py_XDECREF(self->params);
|
||||
Py_XDECREF(self->wrapper_type);
|
||||
Py_XDECREF(self->bound_type);
|
||||
|
||||
self->wrapper = NULL;
|
||||
self->params = NULL;
|
||||
self->wrapper_type = NULL;
|
||||
self->bound_type = NULL;
|
||||
|
||||
if (!target)
|
||||
target = Py_None;
|
||||
|
||||
base_args = PyTuple_Pack(2, wrapped, target);
|
||||
base_args = PyTuple_Pack(1, wrapped);
|
||||
base_kwds = PyDict_New();
|
||||
|
||||
result = WraptObjectProxy_init((WraptObjectProxyObject *)self,
|
||||
@@ -639,11 +599,11 @@ static int WraptFunctionWrapper_init(WraptFunctionWrapperObject *self,
|
||||
(PyObject *)&PyClassMethod_Type) || PyObject_IsInstance(
|
||||
wrapped, (PyObject *)&PyStaticMethod_Type)) {
|
||||
Py_INCREF((PyObject *)&WraptBoundFunctionWrapper_Type);
|
||||
self->wrapper_type = (PyObject *)&WraptBoundFunctionWrapper_Type;
|
||||
self->bound_type = (PyObject *)&WraptBoundFunctionWrapper_Type;
|
||||
}
|
||||
else {
|
||||
Py_INCREF((PyObject *)&WraptBoundMethodWrapper_Type);
|
||||
self->wrapper_type = (PyObject *)&WraptBoundMethodWrapper_Type;
|
||||
self->bound_type = (PyObject *)&WraptBoundMethodWrapper_Type;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -659,7 +619,7 @@ static void WraptFunctionWrapper_dealloc(WraptFunctionWrapperObject *self)
|
||||
{
|
||||
Py_XDECREF(self->wrapper);
|
||||
Py_XDECREF(self->params);
|
||||
Py_XDECREF(self->wrapper_type);
|
||||
Py_XDECREF(self->bound_type);
|
||||
|
||||
WraptObjectProxy_dealloc((WraptObjectProxyObject *)self);
|
||||
}
|
||||
@@ -708,9 +668,8 @@ static PyObject *WraptFunctionWrapper_descr_get(
|
||||
type = Py_None;
|
||||
|
||||
if (descriptor) {
|
||||
result = PyObject_CallFunction(self->wrapper_type, "(OOOOO)",
|
||||
descriptor, obj, self->wrapper, self->object_proxy.target,
|
||||
self->params);
|
||||
result = PyObject_CallFunction(self->bound_type, "(OOOO)",
|
||||
descriptor, obj, self->wrapper, self->params);
|
||||
}
|
||||
|
||||
Py_XDECREF(descriptor);
|
||||
@@ -720,7 +679,7 @@ static PyObject *WraptFunctionWrapper_descr_get(
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static PyObject *WraptFunctionWrapper_get_wrapper(
|
||||
static PyObject *WraptFunctionWrapper_get_self_wrapper(
|
||||
WraptFunctionWrapperObject *self, void *closure)
|
||||
{
|
||||
if (!self->wrapper) {
|
||||
@@ -734,7 +693,7 @@ static PyObject *WraptFunctionWrapper_get_wrapper(
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static PyObject *WraptFunctionWrapper_get_params(
|
||||
static PyObject *WraptFunctionWrapper_get_self_params(
|
||||
WraptFunctionWrapperObject *self, void *closure)
|
||||
{
|
||||
if (!self->params) {
|
||||
@@ -748,16 +707,16 @@ static PyObject *WraptFunctionWrapper_get_params(
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static PyObject *WraptFunctionWrapper_get_wrapper_type(
|
||||
static PyObject *WraptFunctionWrapper_get_self_bound_type(
|
||||
WraptFunctionWrapperObject *self, void *closure)
|
||||
{
|
||||
if (!self->wrapper_type) {
|
||||
if (!self->bound_type) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
Py_INCREF(self->wrapper_type);
|
||||
return self->wrapper_type;
|
||||
Py_INCREF(self->bound_type);
|
||||
return self->bound_type;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */;
|
||||
@@ -767,11 +726,11 @@ static PyGetSetDef WraptFunctionWrapper_getset[] = {
|
||||
(setter)WraptObjectProxy_set_module, 0 },
|
||||
{ "__doc__", (getter)WraptObjectProxy_get_doc,
|
||||
(setter)WraptObjectProxy_set_doc, 0 },
|
||||
{ "_self_wrapper", (getter)WraptFunctionWrapper_get_wrapper,
|
||||
{ "_self_wrapper", (getter)WraptFunctionWrapper_get_self_wrapper,
|
||||
NULL, 0 },
|
||||
{ "_self_params", (getter)WraptFunctionWrapper_get_params,
|
||||
{ "_self_params", (getter)WraptFunctionWrapper_get_self_params,
|
||||
NULL, 0 },
|
||||
{ "_self_wrapper_type", (getter)WraptFunctionWrapper_get_wrapper_type,
|
||||
{ "_self_bound_type", (getter)WraptFunctionWrapper_get_self_bound_type,
|
||||
NULL, 0 },
|
||||
{ NULL },
|
||||
};
|
||||
@@ -849,7 +808,6 @@ static int WraptBoundFunctionWrapper_init(
|
||||
PyObject *wrapped = NULL;
|
||||
PyObject *instance = NULL;
|
||||
PyObject *wrapper = NULL;
|
||||
PyObject *target = NULL;
|
||||
PyObject *params = NULL;
|
||||
|
||||
PyObject *base_args = NULL;
|
||||
@@ -858,11 +816,11 @@ static int WraptBoundFunctionWrapper_init(
|
||||
int result = 0;
|
||||
|
||||
static char *kwlist[] = { "wrapped", "instance", "wrapper",
|
||||
"target", "params", NULL };
|
||||
"params", NULL };
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds,
|
||||
"OOO|OO:BoundFunctionWrapper", kwlist, &wrapped, &instance,
|
||||
&wrapper, &target, ¶ms)) {
|
||||
"OOO|O:BoundFunctionWrapper", kwlist, &wrapped, &instance,
|
||||
&wrapper, ¶ms)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -874,10 +832,7 @@ static int WraptBoundFunctionWrapper_init(
|
||||
self->wrapper = NULL;
|
||||
self->params = NULL;
|
||||
|
||||
if (!target)
|
||||
target = Py_None;
|
||||
|
||||
base_args = PyTuple_Pack(2, wrapped, target);
|
||||
base_args = PyTuple_Pack(1, wrapped);
|
||||
base_kwds = PyDict_New();
|
||||
|
||||
result = WraptObjectProxy_init((WraptObjectProxyObject *)self,
|
||||
@@ -945,7 +900,7 @@ static PyObject *WraptBoundFunctionWrapper_call(
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static PyObject *WraptBoundFunctionWrapper_get_instance(
|
||||
static PyObject *WraptBoundFunctionWrapper_get_self_instance(
|
||||
WraptBoundFunctionWrapperObject *self, void *closure)
|
||||
{
|
||||
if (!self->instance) {
|
||||
@@ -959,7 +914,7 @@ static PyObject *WraptBoundFunctionWrapper_get_instance(
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static PyObject *WraptBoundFunctionWrapper_get_wrapper(
|
||||
static PyObject *WraptBoundFunctionWrapper_get_self_wrapper(
|
||||
WraptBoundFunctionWrapperObject *self, void *closure)
|
||||
{
|
||||
if (!self->wrapper) {
|
||||
@@ -973,7 +928,7 @@ static PyObject *WraptBoundFunctionWrapper_get_wrapper(
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static PyObject *WraptBoundFunctionWrapper_get_params(
|
||||
static PyObject *WraptBoundFunctionWrapper_get_self_params(
|
||||
WraptBoundFunctionWrapperObject *self, void *closure)
|
||||
{
|
||||
if (!self->params) {
|
||||
@@ -992,11 +947,11 @@ static PyGetSetDef WraptBoundFunctionWrapper_getset[] = {
|
||||
(setter)WraptObjectProxy_set_module, 0 },
|
||||
{ "__doc__", (getter)WraptObjectProxy_get_doc,
|
||||
(setter)WraptObjectProxy_set_doc, 0 },
|
||||
{ "_self_instance", (getter)WraptBoundFunctionWrapper_get_instance,
|
||||
{ "_self_instance", (getter)WraptBoundFunctionWrapper_get_self_instance,
|
||||
NULL, 0 },
|
||||
{ "_self_wrapper", (getter)WraptBoundFunctionWrapper_get_wrapper,
|
||||
{ "_self_wrapper", (getter)WraptBoundFunctionWrapper_get_self_wrapper,
|
||||
NULL, 0 },
|
||||
{ "_self_params", (getter)WraptBoundFunctionWrapper_get_params,
|
||||
{ "_self_params", (getter)WraptBoundFunctionWrapper_get_self_params,
|
||||
NULL, 0 },
|
||||
{ NULL },
|
||||
};
|
||||
@@ -1074,7 +1029,6 @@ static int WraptBoundMethodWrapper_init(
|
||||
PyObject *wrapped = NULL;
|
||||
PyObject *instance = NULL;
|
||||
PyObject *wrapper = NULL;
|
||||
PyObject *target = NULL;
|
||||
PyObject *params = NULL;
|
||||
|
||||
PyObject *base_args = NULL;
|
||||
@@ -1083,11 +1037,11 @@ static int WraptBoundMethodWrapper_init(
|
||||
int result = 0;
|
||||
|
||||
static char *kwlist[] = { "wrapped", "instance", "wrapper",
|
||||
"target", "params", NULL };
|
||||
"params", NULL };
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds,
|
||||
"OOO|OO:BoundMethodWrapper", kwlist, &wrapped, &instance,
|
||||
&wrapper, &target, ¶ms)) {
|
||||
"OOO|O:BoundMethodWrapper", kwlist, &wrapped, &instance,
|
||||
&wrapper, ¶ms)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1099,10 +1053,7 @@ static int WraptBoundMethodWrapper_init(
|
||||
self->wrapper = NULL;
|
||||
self->params = NULL;
|
||||
|
||||
if (!target)
|
||||
target = Py_None;
|
||||
|
||||
base_args = PyTuple_Pack(2, wrapped, target);
|
||||
base_args = PyTuple_Pack(1, wrapped);
|
||||
base_kwds = PyDict_New();
|
||||
|
||||
result = WraptObjectProxy_init((WraptObjectProxyObject *)self,
|
||||
@@ -1222,7 +1173,7 @@ static PyObject *WraptBoundMethodWrapper_call(
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static PyObject *WraptBoundMethodWrapper_get_instance(
|
||||
static PyObject *WraptBoundMethodWrapper_get_self_instance(
|
||||
WraptBoundMethodWrapperObject *self, void *closure)
|
||||
{
|
||||
if (!self->instance) {
|
||||
@@ -1236,7 +1187,7 @@ static PyObject *WraptBoundMethodWrapper_get_instance(
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static PyObject *WraptBoundMethodWrapper_get_wrapper(
|
||||
static PyObject *WraptBoundMethodWrapper_get_self_wrapper(
|
||||
WraptBoundMethodWrapperObject *self, void *closure)
|
||||
{
|
||||
if (!self->wrapper) {
|
||||
@@ -1250,7 +1201,7 @@ static PyObject *WraptBoundMethodWrapper_get_wrapper(
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static PyObject *WraptBoundMethodWrapper_get_params(
|
||||
static PyObject *WraptBoundMethodWrapper_get_self_params(
|
||||
WraptBoundMethodWrapperObject *self, void *closure)
|
||||
{
|
||||
if (!self->params) {
|
||||
@@ -1269,11 +1220,11 @@ static PyGetSetDef WraptBoundMethodWrapper_getset[] = {
|
||||
(setter)WraptObjectProxy_set_module, 0 },
|
||||
{ "__doc__", (getter)WraptObjectProxy_get_doc,
|
||||
(setter)WraptObjectProxy_set_doc, 0 },
|
||||
{ "_self_instance", (getter)WraptBoundMethodWrapper_get_instance,
|
||||
{ "_self_instance", (getter)WraptBoundMethodWrapper_get_self_instance,
|
||||
NULL, 0 },
|
||||
{ "_self_wrapper", (getter)WraptBoundMethodWrapper_get_wrapper,
|
||||
{ "_self_wrapper", (getter)WraptBoundMethodWrapper_get_self_wrapper,
|
||||
NULL, 0 },
|
||||
{ "_self_params", (getter)WraptBoundMethodWrapper_get_params,
|
||||
{ "_self_params", (getter)WraptBoundMethodWrapper_get_self_params,
|
||||
NULL, 0 },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
@@ -9,16 +9,38 @@ from .wrappers import FunctionWrapper
|
||||
from .exceptions import (UnexpectedDefaultParameters,
|
||||
MissingDefaultParameter, UnexpectedParameters)
|
||||
|
||||
# Copy name attributes from a wrapped function onto an wrapper. This is
|
||||
# only used in mapping the name from the final wrapped function to which
|
||||
# an adapter is applied onto the adapter itself. All other details come
|
||||
# from the adapter function via the function wrapper so we don't update
|
||||
# __dict__ or __wrapped__.
|
||||
|
||||
def _update_adapter(wrapper, target):
|
||||
for attr in ('__module__', '__name__', '__qualname__'):
|
||||
try:
|
||||
value = getattr(target, attr)
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
setattr(wrapper, attr, value)
|
||||
|
||||
# Decorators for creating other decorators. These decorators and the
|
||||
# wrappers which they use are designed to properly preserve any name
|
||||
# attributes, function signatures etc, in addition to the wrappers
|
||||
# themselves acting like a transparent proxy for the original wrapped
|
||||
# function so they the wrapper is effectively indistinguishable from
|
||||
# the original wrapped function.
|
||||
|
||||
WRAPPER_ARGLIST = ('wrapped', 'instance', 'args', 'kwargs')
|
||||
|
||||
def decorator(wrapper=None, target=None, **default_params):
|
||||
# The decorator works out whether the user decorator will have its
|
||||
# own parameters. Parameters for the user decorator must always
|
||||
# be specified using keyword arguments and must always have
|
||||
# defaults. The user cannot use 'wrapper' or 'adapter' for their
|
||||
# defaults. The user cannot use 'wrapper' or 'target' for their
|
||||
# own parameters as we use them ourselves and so they are
|
||||
# effectively reserved. The 'wrapper' argument being how the
|
||||
# user's wrapper function is passed in. The 'adapter' argument
|
||||
# user's wrapper function is passed in. The 'target' argument
|
||||
# is used to optionally denote a function which is an adapter,
|
||||
# which changes the effective prototype of the wrapped function.
|
||||
# The latter is used to ensure that any function argument
|
||||
@@ -111,8 +133,11 @@ def decorator(wrapper=None, target=None, **default_params):
|
||||
# combines the parameters with the wrapped function.
|
||||
|
||||
def _wrapper(func):
|
||||
return FunctionWrapper(wrapped=func, wrapper=wrapper,
|
||||
target=target, params=complete_params)
|
||||
result = FunctionWrapper(wrapped=func, wrapper=wrapper,
|
||||
params=complete_params)
|
||||
if target:
|
||||
_update_adapter(result, target)
|
||||
return result
|
||||
return _wrapper
|
||||
|
||||
# Here is where the partial wrapper is returned. This is
|
||||
@@ -126,8 +151,10 @@ def decorator(wrapper=None, target=None, **default_params):
|
||||
|
||||
@wraps(wrapper)
|
||||
def _wrapper(func):
|
||||
return FunctionWrapper(wrapped=func, wrapper=wrapper,
|
||||
target=target)
|
||||
result = FunctionWrapper(wrapped=func, wrapper=wrapper)
|
||||
if target:
|
||||
_update_adapter(result, target)
|
||||
return result
|
||||
return _wrapper
|
||||
|
||||
else:
|
||||
|
||||
@@ -49,33 +49,15 @@ class _ObjectProxyMetaType(type):
|
||||
|
||||
class ObjectProxy(six.with_metaclass(_ObjectProxyMetaType)):
|
||||
|
||||
def __init__(self, wrapped, target=None):
|
||||
def __init__(self, wrapped):
|
||||
self._self_wrapped = wrapped
|
||||
|
||||
# Python 3.2+ has the __wrapped__ attribute which is meant to
|
||||
# hold a reference to the inner most wrapped object when there
|
||||
# are multiple decorators. We handle __wrapped__ and also
|
||||
# duplicate that functionality for Python 2, although it will
|
||||
# only go as far as what is below our own wrappers when there is
|
||||
# more than one for Python 2.
|
||||
|
||||
if target is None:
|
||||
try:
|
||||
self._self_target = wrapped.__wrapped__
|
||||
except AttributeError:
|
||||
self._self_target = wrapped
|
||||
else:
|
||||
self._self_target = target
|
||||
|
||||
# Python 3.2+ has the __qualname__ attribute, but it does not
|
||||
# allow it to be overridden using a property and it must instead
|
||||
# be an actual string object instead.
|
||||
|
||||
try:
|
||||
if target is None:
|
||||
object.__setattr__(self, '__qualname__', wrapped.__qualname__)
|
||||
else:
|
||||
object.__setattr__(self, '__qualname__', target.__qualname__)
|
||||
object.__setattr__(self, '__qualname__', wrapped.__qualname__)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
@@ -85,10 +67,7 @@ class ObjectProxy(six.with_metaclass(_ObjectProxyMetaType)):
|
||||
# if overriding it as a property is sufficient in all cases.
|
||||
|
||||
try:
|
||||
if target is None:
|
||||
object.__setattr__(self, '__name__', wrapped.__name__)
|
||||
else:
|
||||
object.__setattr__(self, '__name__', target.__name__)
|
||||
object.__setattr__(self, '__name__', wrapped.__name__)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
@@ -122,7 +101,10 @@ class ObjectProxy(six.with_metaclass(_ObjectProxyMetaType)):
|
||||
|
||||
@property
|
||||
def __wrapped__(self):
|
||||
return self._self_target
|
||||
try:
|
||||
return self._self_wrapped.__wrapped__
|
||||
except AttributeError:
|
||||
return self._self_wrapped
|
||||
|
||||
@__wrapped__.setter
|
||||
def __wrapped__(self, value):
|
||||
@@ -169,8 +151,8 @@ class ObjectProxy(six.with_metaclass(_ObjectProxyMetaType)):
|
||||
|
||||
class _BoundFunctionWrapper(ObjectProxy):
|
||||
|
||||
def __init__(self, wrapped, instance, wrapper, target=None, params={}):
|
||||
super(_BoundFunctionWrapper, self).__init__(wrapped, target)
|
||||
def __init__(self, wrapped, instance, wrapper, params={}):
|
||||
super(_BoundFunctionWrapper, self).__init__(wrapped)
|
||||
self._self_instance = instance
|
||||
self._self_wrapper = wrapper
|
||||
self._self_params = params
|
||||
@@ -181,8 +163,8 @@ class _BoundFunctionWrapper(ObjectProxy):
|
||||
|
||||
class _BoundMethodWrapper(ObjectProxy):
|
||||
|
||||
def __init__(self, wrapped, instance, wrapper, target=None, params={}):
|
||||
super(_BoundMethodWrapper, self).__init__(wrapped, target)
|
||||
def __init__(self, wrapped, instance, wrapper, params={}):
|
||||
super(_BoundMethodWrapper, self).__init__(wrapped)
|
||||
self._self_instance = instance
|
||||
self._self_wrapper = wrapper
|
||||
self._self_params = params
|
||||
@@ -206,8 +188,8 @@ class _BoundMethodWrapper(ObjectProxy):
|
||||
|
||||
class FunctionWrapper(ObjectProxy):
|
||||
|
||||
def __init__(self, wrapped, wrapper, target=None, params={}):
|
||||
super(FunctionWrapper, self).__init__(wrapped, target)
|
||||
def __init__(self, wrapped, wrapper, params={}):
|
||||
super(FunctionWrapper, self).__init__(wrapped)
|
||||
self._self_wrapper = wrapper
|
||||
self._self_params = params
|
||||
|
||||
@@ -244,15 +226,15 @@ class FunctionWrapper(ObjectProxy):
|
||||
# later.
|
||||
|
||||
if isinstance(self._self_wrapped, (classmethod, staticmethod)):
|
||||
self._self_wrapper_type = _BoundFunctionWrapper
|
||||
self._self_bound_type = _BoundFunctionWrapper
|
||||
else:
|
||||
self._self_wrapper_type = _BoundMethodWrapper
|
||||
self._self_bound_type = _BoundMethodWrapper
|
||||
|
||||
def __get__(self, instance, owner):
|
||||
descriptor = self._self_wrapped.__get__(instance, owner)
|
||||
|
||||
return self._self_wrapper_type(descriptor, instance,
|
||||
self._self_wrapper, self._self_target, self._self_params)
|
||||
return self._self_bound_type(descriptor, instance, self._self_wrapper,
|
||||
self._self_params)
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
# This is invoked when the wrapped function is being called as a
|
||||
|
||||
@@ -2,26 +2,36 @@ from __future__ import print_function
|
||||
|
||||
import unittest
|
||||
import inspect
|
||||
import imp
|
||||
|
||||
import wrapt
|
||||
|
||||
def function1(arg):
|
||||
'''documentation'''
|
||||
return arg
|
||||
from wrapt import six
|
||||
|
||||
function1o = function1
|
||||
DECORATORS_CODE = """
|
||||
import wrapt
|
||||
|
||||
def adapter1(func):
|
||||
@wrapt.adapter(target=func)
|
||||
def _adapter(arg):
|
||||
"""adapter documentation"""
|
||||
return func()
|
||||
'''adapter documentation'''
|
||||
return func(arg, arg)
|
||||
return _adapter
|
||||
"""
|
||||
|
||||
@adapter1
|
||||
def function1(arg):
|
||||
decorators = imp.new_module('decorators')
|
||||
six.exec_(DECORATORS_CODE, decorators.__dict__, decorators.__dict__)
|
||||
|
||||
def function1(arg1, arg2):
|
||||
'''documentation'''
|
||||
return arg
|
||||
return arg1, arg2
|
||||
|
||||
function1o = function1
|
||||
|
||||
@decorators.adapter1
|
||||
def function1(arg1, arg2):
|
||||
'''documentation'''
|
||||
return arg1, arg2
|
||||
|
||||
function1d = function1
|
||||
|
||||
@@ -54,11 +64,14 @@ class TestNamingAdapter(unittest.TestCase):
|
||||
self.assertEqual(function1d.__doc__, 'adapter documentation')
|
||||
|
||||
def test_argspec(self):
|
||||
# Test preservation of function argument specification.
|
||||
# Test preservation of function argument specification. It
|
||||
# actually needs to match that of the adapter function.
|
||||
|
||||
function1o_argspec = inspect.getargspec(function1o)
|
||||
def _adapter(arg): pass
|
||||
|
||||
function1a_argspec = inspect.getargspec(_adapter)
|
||||
function1d_argspec = inspect.getargspec(function1d)
|
||||
self.assertEqual(function1o_argspec, function1d_argspec)
|
||||
self.assertEqual(function1a_argspec, function1d_argspec)
|
||||
|
||||
def test_isinstance(self):
|
||||
# Test preservation of isinstance() checks.
|
||||
|
||||
@@ -89,9 +89,8 @@ class TestAttributeAccess(unittest.TestCase):
|
||||
|
||||
self.assertEqual(function2._self_wrapped, function1)
|
||||
self.assertEqual(function2._self_wrapper, decorator1)
|
||||
self.assertEqual(function2._self_target, function1)
|
||||
self.assertEqual(function2._self_params, {})
|
||||
self.assertNotEqual(function2._self_wrapper_type, None)
|
||||
self.assertNotEqual(function2._self_bound_type, None)
|
||||
|
||||
def test_instancemethod_attributes(self):
|
||||
def decorator1(wrapped, instance, args, kwargs):
|
||||
@@ -105,9 +104,8 @@ class TestAttributeAccess(unittest.TestCase):
|
||||
|
||||
self.assertEqual(function2._self_wrapped, function1)
|
||||
self.assertEqual(function2._self_wrapper, decorator1)
|
||||
self.assertEqual(function2._self_target, function1)
|
||||
self.assertEqual(function2._self_params, {})
|
||||
self.assertNotEqual(function2._self_wrapper_type, None)
|
||||
self.assertNotEqual(function2._self_bound_type, None)
|
||||
|
||||
instance = Class()
|
||||
|
||||
@@ -129,9 +127,8 @@ class TestAttributeAccess(unittest.TestCase):
|
||||
|
||||
self.assertEqual(function2._self_wrapped, function1)
|
||||
self.assertEqual(function2._self_wrapper, decorator1)
|
||||
self.assertEqual(function2._self_target, function1)
|
||||
self.assertEqual(function2._self_params, {})
|
||||
self.assertNotEqual(function2._self_wrapper_type, None)
|
||||
self.assertNotEqual(function2._self_bound_type, None)
|
||||
|
||||
instance = Class()
|
||||
|
||||
@@ -153,9 +150,8 @@ class TestAttributeAccess(unittest.TestCase):
|
||||
|
||||
self.assertEqual(function2._self_wrapped, function1)
|
||||
self.assertEqual(function2._self_wrapper, decorator1)
|
||||
self.assertEqual(function2._self_target, function1)
|
||||
self.assertEqual(function2._self_params, {})
|
||||
self.assertNotEqual(function2._self_wrapper_type, None)
|
||||
self.assertNotEqual(function2._self_bound_type, None)
|
||||
|
||||
instance = Class()
|
||||
|
||||
|
||||
@@ -27,7 +27,28 @@ class TestAttributeAccess(unittest.TestCase):
|
||||
function2 = wrapt.ObjectProxy(function1)
|
||||
|
||||
self.assertEqual(function2._self_wrapped, function1)
|
||||
self.assertEqual(function2._self_target, function1)
|
||||
|
||||
def test_get_wrapped(self):
|
||||
def function1(*args, **kwargs):
|
||||
return args, kwargs
|
||||
function2 = wrapt.ObjectProxy(function1)
|
||||
|
||||
self.assertEqual(function2.__wrapped__, function1)
|
||||
|
||||
function3 = wrapt.ObjectProxy(function2)
|
||||
|
||||
self.assertEqual(function3.__wrapped__, function1)
|
||||
|
||||
def test_set_wrapped(self):
|
||||
def function1(*args, **kwargs):
|
||||
return args, kwargs
|
||||
function2 = wrapt.ObjectProxy(function1)
|
||||
|
||||
self.assertEqual(function2.__wrapped__, function1)
|
||||
|
||||
function2.__wrapped__ = None
|
||||
|
||||
self.assertEqual(function2.__wrapped__, None)
|
||||
|
||||
class TestNamingObjectProxy(unittest.TestCase):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user