diff options
-rw-r--r-- | Include/descrobject.h | 1 | ||||
-rw-r--r-- | Lib/test/test_descr.py | 8 | ||||
-rw-r--r-- | Objects/descrobject.c | 72 | ||||
-rw-r--r-- | Objects/dictobject.c | 5 | ||||
-rw-r--r-- | Objects/typeobject.c | 2 |
5 files changed, 80 insertions, 8 deletions
diff --git a/Include/descrobject.h b/Include/descrobject.h index 6fb6a95..a74af60 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 76636a9..ed4593e 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 63e94e8..761e1ab 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -79,6 +79,13 @@ descr_check(PyDescrObject *descr, PyObject *obj, PyTypeObject *type, } 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) { PyObject *res; @@ -213,6 +220,21 @@ methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds) } 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) { int argc; @@ -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, @@ -518,6 +578,18 @@ PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method) } 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) { PyMemberDescrObject *descr; diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 69adc50..712ec2c 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 0b7f00d..193b0cc 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); |