]> granicus.if.org Git - python/commitdiff
SF 548651: Fix the METH_CLASS implementation.
authorTim Peters <tim.peters@gmail.com>
Mon, 9 Dec 2002 22:56:13 +0000 (22:56 +0000)
committerTim Peters <tim.peters@gmail.com>
Mon, 9 Dec 2002 22:56:13 +0000 (22:56 +0000)
Most of these patches are from Thomas Heller, with long lines folded
by Tim.  The change to test_descr.py is from Guido.  See the bug report.

Not a bugfix candidate -- METH_CLASS is new in 2.3.

Include/descrobject.h
Lib/test/test_descr.py
Objects/descrobject.c
Objects/dictobject.c
Objects/typeobject.c

index 6fb6a95cc4e83ea2ff80977ebae637563b28434f..a74af6009bc8db43b3dce25481c6ce5dbee73799 100644 (file)
@@ -70,6 +70,7 @@ typedef struct {
 PyAPI_DATA(PyTypeObject) PyWrapperDescr_Type;
 
 PyAPI_FUNC(PyObject *) PyDescr_NewMethod(PyTypeObject *, PyMethodDef *);
+PyAPI_FUNC(PyObject *) PyDescr_NewClassMethod(PyTypeObject *, PyMethodDef *);
 PyAPI_FUNC(PyObject *) PyDescr_NewMember(PyTypeObject *,
                                               struct PyMemberDef *);
 PyAPI_FUNC(PyObject *) PyDescr_NewGetSet(PyTypeObject *,
index 76636a9ec1ab10dc711f9b35277b625bc3f9d56e..ed4593e8cbede79bde219b21e5f648b54520704b 100644 (file)
@@ -1464,12 +1464,12 @@ def classmethods_in_c():
     a = (1, 2, 3)
     d = {'abc': 123}
     x, a1, d1 = spam.spamlist.classmeth(*a, **d)
-    veris(x, None)
-    vereq((spam.spamlist,) + a, a1)
+    veris(x, spam.spamlist)
+    vereq(a, a1)
     vereq(d, d1)
     x, a1, d1 = spam.spamlist().classmeth(*a, **d)
-    veris(x, None)
-    vereq((spam.spamlist,) + a, a1)
+    veris(x, spam.spamlist)
+    vereq(a, a1)
     vereq(d, d1)
 
 def staticmethods():
index 63e94e878b86bbe7773c50aa1e3e641865be54c4..761e1ab854c0e858024efb33e95697428dcecbe7 100644 (file)
@@ -78,6 +78,13 @@ descr_check(PyDescrObject *descr, PyObject *obj, PyTypeObject *type,
        return 0;
 }
 
+static PyObject *
+classmethod_get(PyMethodDescrObject *descr, PyObject *obj,
+               PyTypeObject *type)
+{
+       return PyCFunction_New(descr->d_method, (PyObject *)type);
+}
+
 static PyObject *
 method_get(PyMethodDescrObject *descr, PyObject *obj, PyTypeObject *type)
 {
@@ -212,6 +219,21 @@ methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds)
        return result;
 }
 
+static PyObject *
+classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
+                     PyObject *kwds)
+{
+       PyObject *func, *result;
+
+       func = PyCFunction_New(descr->d_method, (PyObject *)descr->d_type);
+       if (func == NULL)
+               return NULL;
+
+       result = PyEval_CallObjectWithKeywords(func, args, kwds);
+       Py_DECREF(func);
+       return result;
+}
+
 static PyObject *
 wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
 {
@@ -373,6 +395,44 @@ static PyTypeObject PyMethodDescr_Type = {
        0,                                      /* tp_descr_set */
 };
 
+static PyTypeObject PyClassMethodDescr_Type = {
+       PyObject_HEAD_INIT(&PyType_Type)
+       0,
+       "special_method_descriptor",
+       sizeof(PyMethodDescrObject),
+       0,
+       (destructor)descr_dealloc,              /* tp_dealloc */
+       0,                                      /* tp_print */
+       0,                                      /* tp_getattr */
+       0,                                      /* tp_setattr */
+       0,                                      /* tp_compare */
+       (reprfunc)method_repr,                  /* tp_repr */
+       0,                                      /* tp_as_number */
+       0,                                      /* tp_as_sequence */
+       0,                                      /* tp_as_mapping */
+       0,                                      /* tp_hash */
+       (ternaryfunc)classmethoddescr_call,             /* tp_call */
+       0,                                      /* tp_str */
+       PyObject_GenericGetAttr,                /* tp_getattro */
+       0,                                      /* tp_setattro */
+       0,                                      /* tp_as_buffer */
+       Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
+       0,                                      /* tp_doc */
+       descr_traverse,                         /* tp_traverse */
+       0,                                      /* tp_clear */
+       0,                                      /* tp_richcompare */
+       0,                                      /* tp_weaklistoffset */
+       0,                                      /* tp_iter */
+       0,                                      /* tp_iternext */
+       0,                                      /* tp_methods */
+       descr_members,                          /* tp_members */
+       method_getset,                          /* tp_getset */
+       0,                                      /* tp_base */
+       0,                                      /* tp_dict */
+       (descrgetfunc)classmethod_get,          /* tp_descr_get */
+       0,                                      /* tp_descr_set */
+};
+
 static PyTypeObject PyMemberDescr_Type = {
        PyObject_HEAD_INIT(&PyType_Type)
        0,
@@ -517,6 +577,18 @@ PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)
        return (PyObject *)descr;
 }
 
+PyObject *
+PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method)
+{
+       PyMethodDescrObject *descr;
+
+       descr = (PyMethodDescrObject *)descr_new(&PyClassMethodDescr_Type,
+                                                type, method->ml_name);
+       if (descr != NULL)
+               descr->d_method = method;
+       return (PyObject *)descr;
+}
+
 PyObject *
 PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member)
 {
index 69adc50301908ddaedc4cbfb388e36e7f84634b1..712ec2ccc99479f9440fdbce51e1dd29ce0acdb2 100644 (file)
@@ -963,17 +963,16 @@ dict_items(register dictobject *mp)
 }
 
 static PyObject *
-dict_fromkeys(PyObject *mp, PyObject *args)
+dict_fromkeys(PyObject *cls, PyObject *args)
 {
        PyObject *seq;
        PyObject *value = Py_None;
        PyObject *it;   /* iter(seq) */
        PyObject *key;
        PyObject *d;
-       PyObject *cls;
        int status;
 
-       if (!PyArg_ParseTuple(args, "OO|O:fromkeys", &cls, &seq, &value))
+       if (!PyArg_ParseTuple(args, "O|O:fromkeys", &seq, &value))
                return NULL;
 
        d = PyObject_CallObject(cls, NULL);
index 0b7f00d25907e31903107de6a585144afa4ba03c..193b0cc1bc45b832665056cc9454930594cc533c 100644 (file)
@@ -2435,7 +2435,7 @@ add_methods(PyTypeObject *type, PyMethodDef *meth)
                                     "method cannot be both class and static");
                                return -1;
                        }
-                       descr = create_specialmethod(meth, PyClassMethod_New);
+                       descr = PyDescr_NewClassMethod(type, meth);
                }
                else if (meth->ml_flags & METH_STATIC) {
                        descr = create_specialmethod(meth, PyStaticMethod_New);