]> granicus.if.org Git - python/commitdiff
Added proper reflection on instances of <type 'method-wrapper'>, e.g.
authorArmin Rigo <arigo@tunes.org>
Mon, 7 Nov 2005 08:38:00 +0000 (08:38 +0000)
committerArmin Rigo <arigo@tunes.org>
Mon, 7 Nov 2005 08:38:00 +0000 (08:38 +0000)
'[].__add__', to match what the other internal descriptor types provide:
'__objclass__' attribute, '__self__' member, and reasonable repr and
comparison.

Added a test.

Lib/test/test_descr.py
Objects/descrobject.c

index 05fd72e4780511496ab71d1de98b6f5cc1bf4e41..f594ca88750dc4bec937604bbb1610a272c40535 100644 (file)
@@ -3977,6 +3977,18 @@ def test_init():
     else:
         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():
     weakref_segfault() # Must be first, somehow
@@ -4071,6 +4083,7 @@ def test_main():
     filefault()
     vicious_descriptor_nonsense()
     test_init()
+    methodwrapper()
 
     if verbose: print "All OK"
 
index 4aa131378d2b6db93104c1ee9e84598ac9c7cb62..df7435aade2dbbd38076ce5d5bc2e7e6c4db2d62 100644 (file)
@@ -50,7 +50,7 @@ getset_repr(PyGetSetDescrObject *descr)
 }
 
 static PyObject *
-wrapper_repr(PyWrapperDescrObject *descr)
+wrapperdescr_repr(PyWrapperDescrObject *descr)
 {
        return descr_repr((PyDescrObject *)descr, 
                          "<slot wrapper '%s' of '%s' objects>");
@@ -152,7 +152,7 @@ getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type)
 }
 
 static PyObject *
-wrapper_get(PyWrapperDescrObject *descr, PyObject *obj, PyObject *type)
+wrapperdescr_get(PyWrapperDescrObject *descr, PyObject *obj, PyObject *type)
 {
        PyObject *res;
 
@@ -359,7 +359,7 @@ static PyGetSetDef getset_getset[] = {
 };
 
 static PyObject *
-wrapper_get_doc(PyWrapperDescrObject *descr, void *closure)
+wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure)
 {
        if (descr->d_base->doc == NULL) {
                Py_INCREF(Py_None);
@@ -368,8 +368,8 @@ wrapper_get_doc(PyWrapperDescrObject *descr, void *closure)
        return PyString_FromString(descr->d_base->doc);
 }
 
-static PyGetSetDef wrapper_getset[] = {
-       {"__doc__", (getter)wrapper_get_doc},
+static PyGetSetDef wrapperdescr_getset[] = {
+       {"__doc__", (getter)wrapperdescr_get_doc},
        {0}
 };
 
@@ -551,7 +551,7 @@ PyTypeObject PyWrapperDescr_Type = {
        0,                                      /* tp_getattr */
        0,                                      /* tp_setattr */
        0,                                      /* tp_compare */
-       (reprfunc)wrapper_repr,                 /* tp_repr */
+       (reprfunc)wrapperdescr_repr,            /* tp_repr */
        0,                                      /* tp_as_number */
        0,                                      /* tp_as_sequence */
        0,                                      /* tp_as_mapping */
@@ -571,10 +571,10 @@ PyTypeObject PyWrapperDescr_Type = {
        0,                                      /* tp_iternext */
        0,                                      /* tp_methods */
        descr_members,                          /* tp_members */
-       wrapper_getset,                         /* tp_getset */
+       wrapperdescr_getset,                    /* tp_getset */
        0,                                      /* tp_base */
        0,                                      /* tp_dict */
-       (descrgetfunc)wrapper_get,              /* tp_descr_get */
+       (descrgetfunc)wrapperdescr_get,         /* tp_descr_get */
        0,                                      /* tp_descr_set */
 };
 
@@ -910,10 +910,42 @@ wrapper_dealloc(wrapperobject *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}
 };
 
+static PyObject *
+wrapper_objclass(wrapperobject *wp)
+{
+       PyObject *c = (PyObject *)wp->descr->d_type;
+
+       Py_INCREF(c);
+       return c;
+}
+
 static PyObject *
 wrapper_name(wrapperobject *wp)
 {
@@ -937,6 +969,7 @@ wrapper_doc(wrapperobject *wp)
 }
 
 static PyGetSetDef wrapper_getsets[] = {
+       {"__objclass__", (getter)wrapper_objclass},
        {"__name__", (getter)wrapper_name},
        {"__doc__", (getter)wrapper_doc},
        {0}
@@ -992,8 +1025,8 @@ static PyTypeObject wrappertype = {
        0,                                      /* tp_print */
        0,                                      /* tp_getattr */
        0,                                      /* tp_setattr */
-       0,                                      /* tp_compare */
-       0,                                      /* tp_repr */
+       (cmpfunc)wrapper_compare,               /* tp_compare */
+       (reprfunc)wrapper_repr,                 /* tp_repr */
        0,                                      /* tp_as_number */
        0,                                      /* tp_as_sequence */
        0,                                      /* tp_as_mapping */
@@ -1011,8 +1044,8 @@ static PyTypeObject wrappertype = {
        0,                                      /* tp_weaklistoffset */
        0,                                      /* tp_iter */
        0,                                      /* tp_iternext */
-       wrapper_methods,                        /* tp_methods */
-       0,                                      /* tp_members */
+       0,                                      /* tp_methods */
+       wrapper_members,                        /* tp_members */
        wrapper_getsets,                        /* tp_getset */
        0,                                      /* tp_base */
        0,                                      /* tp_dict */