mirror of
https://github.com/python/cpython.git
synced 2024-11-24 18:34:43 +08:00
Added proper reflection on instances of <type 'method-wrapper'>, e.g.
'[].__add__', to match what the other internal descriptor types provide: '__objclass__' attribute, '__self__' member, and reasonable repr and comparison. Added a test.
This commit is contained in:
parent
64b414ad4c
commit
c6686b7c7e
@ -3977,6 +3977,18 @@ def test_init():
|
|||||||
else:
|
else:
|
||||||
raise TestFailed, "did not test __init__() for None return"
|
raise TestFailed, "did not test __init__() for None return"
|
||||||
|
|
||||||
|
def methodwrapper():
|
||||||
|
# <type 'method-wrapper'> did not support any reflection before 2.5
|
||||||
|
if verbose:
|
||||||
|
print "Testing method-wrapper objects..."
|
||||||
|
|
||||||
|
l = []
|
||||||
|
vereq(l.__add__, l.__add__)
|
||||||
|
verify(l.__add__ != [].__add__)
|
||||||
|
verify(l.__add__.__name__ == '__add__')
|
||||||
|
verify(l.__add__.__self__ is l)
|
||||||
|
verify(l.__add__.__objclass__ is list)
|
||||||
|
vereq(l.__add__.__doc__, list.__add__.__doc__)
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
weakref_segfault() # Must be first, somehow
|
weakref_segfault() # Must be first, somehow
|
||||||
@ -4071,6 +4083,7 @@ def test_main():
|
|||||||
filefault()
|
filefault()
|
||||||
vicious_descriptor_nonsense()
|
vicious_descriptor_nonsense()
|
||||||
test_init()
|
test_init()
|
||||||
|
methodwrapper()
|
||||||
|
|
||||||
if verbose: print "All OK"
|
if verbose: print "All OK"
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ getset_repr(PyGetSetDescrObject *descr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
wrapper_repr(PyWrapperDescrObject *descr)
|
wrapperdescr_repr(PyWrapperDescrObject *descr)
|
||||||
{
|
{
|
||||||
return descr_repr((PyDescrObject *)descr,
|
return descr_repr((PyDescrObject *)descr,
|
||||||
"<slot wrapper '%s' of '%s' objects>");
|
"<slot wrapper '%s' of '%s' objects>");
|
||||||
@ -152,7 +152,7 @@ getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
wrapper_get(PyWrapperDescrObject *descr, PyObject *obj, PyObject *type)
|
wrapperdescr_get(PyWrapperDescrObject *descr, PyObject *obj, PyObject *type)
|
||||||
{
|
{
|
||||||
PyObject *res;
|
PyObject *res;
|
||||||
|
|
||||||
@ -359,7 +359,7 @@ static PyGetSetDef getset_getset[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
wrapper_get_doc(PyWrapperDescrObject *descr, void *closure)
|
wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure)
|
||||||
{
|
{
|
||||||
if (descr->d_base->doc == NULL) {
|
if (descr->d_base->doc == NULL) {
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
@ -368,8 +368,8 @@ wrapper_get_doc(PyWrapperDescrObject *descr, void *closure)
|
|||||||
return PyString_FromString(descr->d_base->doc);
|
return PyString_FromString(descr->d_base->doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyGetSetDef wrapper_getset[] = {
|
static PyGetSetDef wrapperdescr_getset[] = {
|
||||||
{"__doc__", (getter)wrapper_get_doc},
|
{"__doc__", (getter)wrapperdescr_get_doc},
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -551,7 +551,7 @@ PyTypeObject PyWrapperDescr_Type = {
|
|||||||
0, /* tp_getattr */
|
0, /* tp_getattr */
|
||||||
0, /* tp_setattr */
|
0, /* tp_setattr */
|
||||||
0, /* tp_compare */
|
0, /* tp_compare */
|
||||||
(reprfunc)wrapper_repr, /* tp_repr */
|
(reprfunc)wrapperdescr_repr, /* tp_repr */
|
||||||
0, /* tp_as_number */
|
0, /* tp_as_number */
|
||||||
0, /* tp_as_sequence */
|
0, /* tp_as_sequence */
|
||||||
0, /* tp_as_mapping */
|
0, /* tp_as_mapping */
|
||||||
@ -571,10 +571,10 @@ PyTypeObject PyWrapperDescr_Type = {
|
|||||||
0, /* tp_iternext */
|
0, /* tp_iternext */
|
||||||
0, /* tp_methods */
|
0, /* tp_methods */
|
||||||
descr_members, /* tp_members */
|
descr_members, /* tp_members */
|
||||||
wrapper_getset, /* tp_getset */
|
wrapperdescr_getset, /* tp_getset */
|
||||||
0, /* tp_base */
|
0, /* tp_base */
|
||||||
0, /* tp_dict */
|
0, /* tp_dict */
|
||||||
(descrgetfunc)wrapper_get, /* tp_descr_get */
|
(descrgetfunc)wrapperdescr_get, /* tp_descr_get */
|
||||||
0, /* tp_descr_set */
|
0, /* tp_descr_set */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -910,10 +910,42 @@ wrapper_dealloc(wrapperobject *wp)
|
|||||||
PyObject_GC_Del(wp);
|
PyObject_GC_Del(wp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyMethodDef wrapper_methods[] = {
|
static int
|
||||||
|
wrapper_compare(wrapperobject *a, wrapperobject *b)
|
||||||
|
{
|
||||||
|
if (a->descr == b->descr) {
|
||||||
|
if (a->self == b->self)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return (a->self < b->self) ? -1 : 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return (a->descr < b->descr) ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
wrapper_repr(wrapperobject *wp)
|
||||||
|
{
|
||||||
|
return PyString_FromFormat("<method-wrapper '%s' of %s object at %p>",
|
||||||
|
wp->descr->d_base->name,
|
||||||
|
wp->self->ob_type->tp_name,
|
||||||
|
wp->self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyMemberDef wrapper_members[] = {
|
||||||
|
{"__self__", T_OBJECT, offsetof(wrapperobject, self), READONLY},
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
wrapper_objclass(wrapperobject *wp)
|
||||||
|
{
|
||||||
|
PyObject *c = (PyObject *)wp->descr->d_type;
|
||||||
|
|
||||||
|
Py_INCREF(c);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
wrapper_name(wrapperobject *wp)
|
wrapper_name(wrapperobject *wp)
|
||||||
{
|
{
|
||||||
@ -937,6 +969,7 @@ wrapper_doc(wrapperobject *wp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static PyGetSetDef wrapper_getsets[] = {
|
static PyGetSetDef wrapper_getsets[] = {
|
||||||
|
{"__objclass__", (getter)wrapper_objclass},
|
||||||
{"__name__", (getter)wrapper_name},
|
{"__name__", (getter)wrapper_name},
|
||||||
{"__doc__", (getter)wrapper_doc},
|
{"__doc__", (getter)wrapper_doc},
|
||||||
{0}
|
{0}
|
||||||
@ -992,8 +1025,8 @@ static PyTypeObject wrappertype = {
|
|||||||
0, /* tp_print */
|
0, /* tp_print */
|
||||||
0, /* tp_getattr */
|
0, /* tp_getattr */
|
||||||
0, /* tp_setattr */
|
0, /* tp_setattr */
|
||||||
0, /* tp_compare */
|
(cmpfunc)wrapper_compare, /* tp_compare */
|
||||||
0, /* tp_repr */
|
(reprfunc)wrapper_repr, /* tp_repr */
|
||||||
0, /* tp_as_number */
|
0, /* tp_as_number */
|
||||||
0, /* tp_as_sequence */
|
0, /* tp_as_sequence */
|
||||||
0, /* tp_as_mapping */
|
0, /* tp_as_mapping */
|
||||||
@ -1011,8 +1044,8 @@ static PyTypeObject wrappertype = {
|
|||||||
0, /* tp_weaklistoffset */
|
0, /* tp_weaklistoffset */
|
||||||
0, /* tp_iter */
|
0, /* tp_iter */
|
||||||
0, /* tp_iternext */
|
0, /* tp_iternext */
|
||||||
wrapper_methods, /* tp_methods */
|
0, /* tp_methods */
|
||||||
0, /* tp_members */
|
wrapper_members, /* tp_members */
|
||||||
wrapper_getsets, /* tp_getset */
|
wrapper_getsets, /* tp_getset */
|
||||||
0, /* tp_base */
|
0, /* tp_base */
|
||||||
0, /* tp_dict */
|
0, /* tp_dict */
|
||||||
|
Loading…
Reference in New Issue
Block a user