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:
parent
c7e3c5e306
commit
bca1cbc6f8
|
@ -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 *,
|
||||||
|
|
|
@ -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():
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue