From bca1cbc6f895c7f9f003877b1cfc0c649387ae1c Mon Sep 17 00:00:00 2001 From: Tim Peters Date: Mon, 9 Dec 2002 22:56:13 +0000 Subject: [PATCH] SF 548651: Fix the METH_CLASS implementation. 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 | 1 + Lib/test/test_descr.py | 8 ++--- Objects/descrobject.c | 72 ++++++++++++++++++++++++++++++++++++++++++ Objects/dictobject.c | 5 ++- Objects/typeobject.c | 2 +- 5 files changed, 80 insertions(+), 8 deletions(-) diff --git a/Include/descrobject.h b/Include/descrobject.h index 6fb6a95cc4e..a74af6009bc 100644 --- a/Include/descrobject.h +++ b/Include/descrobject.h @@ -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 *, diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 76636a9ec1a..ed4593e8cbe 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -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(): diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 63e94e878b8..761e1ab854c 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -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) { diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 69adc503019..712ec2ccc99 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -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); diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 0b7f00d2590..193b0cc1bc4 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -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);