summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/descrobject.h1
-rw-r--r--Lib/test/test_descr.py8
-rw-r--r--Objects/descrobject.c72
-rw-r--r--Objects/dictobject.c5
-rw-r--r--Objects/typeobject.c2
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);