summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorBenjamin Peterson <benjamin@python.org>2012-05-01 13:51:09 (GMT)
committerBenjamin Peterson <benjamin@python.org>2012-05-01 13:51:09 (GMT)
commit042c47b2c741dd053e2ed8b17d56659fb87576de (patch)
tree21fb6770a955dd18476a9da3f399553d254436f2 /Objects
parentdc8cb3d08f92c246a62d88d6c4132571fef76573 (diff)
downloadcpython-042c47b2c741dd053e2ed8b17d56659fb87576de.zip
cpython-042c47b2c741dd053e2ed8b17d56659fb87576de.tar.gz
cpython-042c47b2c741dd053e2ed8b17d56659fb87576de.tar.bz2
fix calling the classmethod descriptor directly (closes #14699)
Diffstat (limited to 'Objects')
-rw-r--r--Objects/descrobject.c44
1 files changed, 41 insertions, 3 deletions
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index 8e7ea7d..15109db 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -254,14 +254,52 @@ static PyObject *
classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
PyObject *kwds)
{
- PyObject *func, *result;
+ Py_ssize_t argc;
+ PyObject *self, *func, *result;
- func = PyCFunction_New(descr->d_method, (PyObject *)descr->d_type);
- if (func == NULL)
+ /* Make sure that the first argument is acceptable as 'self' */
+ assert(PyTuple_Check(args));
+ argc = PyTuple_GET_SIZE(args);
+ if (argc < 1) {
+ PyErr_Format(PyExc_TypeError,
+ "descriptor '%V' of '%.100s' "
+ "object needs an argument",
+ descr_name((PyDescrObject *)descr), "?",
+ descr->d_type->tp_name);
+ return NULL;
+ }
+ self = PyTuple_GET_ITEM(args, 0);
+ if (!PyType_Check(self)) {
+ PyErr_Format(PyExc_TypeError,
+ "descriptor '%V' requires a type "
+ "but received a '%.100s'",
+ descr_name((PyDescrObject *)descr), "?",
+ descr->d_type->tp_name,
+ self->ob_type->tp_name);
+ return NULL;
+ }
+ if (!PyType_IsSubtype((PyTypeObject *)self, descr->d_type)) {
+ PyErr_Format(PyExc_TypeError,
+ "descriptor '%V' "
+ "requires a subtype of '%.100s' "
+ "but received '%.100s",
+ descr_name((PyDescrObject *)descr), "?",
+ descr->d_type->tp_name,
+ self->ob_type->tp_name);
return NULL;
+ }
+ func = PyCFunction_New(descr->d_method, self);
+ if (func == NULL)
+ return NULL;
+ args = PyTuple_GetSlice(args, 1, argc);
+ if (args == NULL) {
+ Py_DECREF(func);
+ return NULL;
+ }
result = PyEval_CallObjectWithKeywords(func, args, kwds);
Py_DECREF(func);
+ Py_DECREF(args);
return result;
}