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.
This commit is contained in:
Tim Peters 2002-12-09 22:56:13 +00:00
parent c7e3c5e306
commit bca1cbc6f8
5 changed files with 80 additions and 8 deletions

View File

@ -70,6 +70,7 @@ typedef struct {
PyAPI_DATA(PyTypeObject) PyWrapperDescr_Type; PyAPI_DATA(PyTypeObject) PyWrapperDescr_Type;
PyAPI_FUNC(PyObject *) PyDescr_NewMethod(PyTypeObject *, PyMethodDef *); PyAPI_FUNC(PyObject *) PyDescr_NewMethod(PyTypeObject *, PyMethodDef *);
PyAPI_FUNC(PyObject *) PyDescr_NewClassMethod(PyTypeObject *, PyMethodDef *);
PyAPI_FUNC(PyObject *) PyDescr_NewMember(PyTypeObject *, PyAPI_FUNC(PyObject *) PyDescr_NewMember(PyTypeObject *,
struct PyMemberDef *); struct PyMemberDef *);
PyAPI_FUNC(PyObject *) PyDescr_NewGetSet(PyTypeObject *, PyAPI_FUNC(PyObject *) PyDescr_NewGetSet(PyTypeObject *,

View File

@ -1464,12 +1464,12 @@ def classmethods_in_c():
a = (1, 2, 3) a = (1, 2, 3)
d = {'abc': 123} d = {'abc': 123}
x, a1, d1 = spam.spamlist.classmeth(*a, **d) x, a1, d1 = spam.spamlist.classmeth(*a, **d)
veris(x, None) veris(x, spam.spamlist)
vereq((spam.spamlist,) + a, a1) vereq(a, a1)
vereq(d, d1) vereq(d, d1)
x, a1, d1 = spam.spamlist().classmeth(*a, **d) x, a1, d1 = spam.spamlist().classmeth(*a, **d)
veris(x, None) veris(x, spam.spamlist)
vereq((spam.spamlist,) + a, a1) vereq(a, a1)
vereq(d, d1) vereq(d, d1)
def staticmethods(): def staticmethods():

View File

@ -78,6 +78,13 @@ descr_check(PyDescrObject *descr, PyObject *obj, PyTypeObject *type,
return 0; return 0;
} }
static PyObject *
classmethod_get(PyMethodDescrObject *descr, PyObject *obj,
PyTypeObject *type)
{
return PyCFunction_New(descr->d_method, (PyObject *)type);
}
static PyObject * static PyObject *
method_get(PyMethodDescrObject *descr, PyObject *obj, PyTypeObject *type) method_get(PyMethodDescrObject *descr, PyObject *obj, PyTypeObject *type)
{ {
@ -212,6 +219,21 @@ methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds)
return result; 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 * static PyObject *
wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds) wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
{ {
@ -373,6 +395,44 @@ static PyTypeObject PyMethodDescr_Type = {
0, /* tp_descr_set */ 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 = { static PyTypeObject PyMemberDescr_Type = {
PyObject_HEAD_INIT(&PyType_Type) PyObject_HEAD_INIT(&PyType_Type)
0, 0,
@ -517,6 +577,18 @@ PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)
return (PyObject *)descr; 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 * PyObject *
PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member) PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member)
{ {

View File

@ -963,17 +963,16 @@ dict_items(register dictobject *mp)
} }
static PyObject * static PyObject *
dict_fromkeys(PyObject *mp, PyObject *args) dict_fromkeys(PyObject *cls, PyObject *args)
{ {
PyObject *seq; PyObject *seq;
PyObject *value = Py_None; PyObject *value = Py_None;
PyObject *it; /* iter(seq) */ PyObject *it; /* iter(seq) */
PyObject *key; PyObject *key;
PyObject *d; PyObject *d;
PyObject *cls;
int status; int status;
if (!PyArg_ParseTuple(args, "OO|O:fromkeys", &cls, &seq, &value)) if (!PyArg_ParseTuple(args, "O|O:fromkeys", &seq, &value))
return NULL; return NULL;
d = PyObject_CallObject(cls, NULL); d = PyObject_CallObject(cls, NULL);

View File

@ -2435,7 +2435,7 @@ add_methods(PyTypeObject *type, PyMethodDef *meth)
"method cannot be both class and static"); "method cannot be both class and static");
return -1; return -1;
} }
descr = create_specialmethod(meth, PyClassMethod_New); descr = PyDescr_NewClassMethod(type, meth);
} }
else if (meth->ml_flags & METH_STATIC) { else if (meth->ml_flags & METH_STATIC) {
descr = create_specialmethod(meth, PyStaticMethod_New); descr = create_specialmethod(meth, PyStaticMethod_New);