Commit 7295c6a8 authored by Benjamin Peterson's avatar Benjamin Peterson

fix calling the classmethod descriptor directly (closes #14699)

parent 42d70818
...@@ -1458,6 +1458,22 @@ order (MRO) for bases """ ...@@ -1458,6 +1458,22 @@ order (MRO) for bases """
self.assertEqual(x, spam.spamlist) self.assertEqual(x, spam.spamlist)
self.assertEqual(a, a1) self.assertEqual(a, a1)
self.assertEqual(d, d1) self.assertEqual(d, d1)
spam_cm = spam.spamlist.__dict__['classmeth']
x2, a2, d2 = spam_cm(spam.spamlist, *a, **d)
self.assertEqual(x2, spam.spamlist)
self.assertEqual(a2, a1)
self.assertEqual(d2, d1)
class SubSpam(spam.spamlist): pass
x2, a2, d2 = spam_cm(SubSpam, *a, **d)
self.assertEqual(x2, SubSpam)
self.assertEqual(a2, a1)
self.assertEqual(d2, d1)
with self.assertRaises(TypeError):
spam_cm()
with self.assertRaises(TypeError):
spam_cm(spam.spamlist())
with self.assertRaises(TypeError):
spam_cm(list)
def test_staticmethods(self): def test_staticmethods(self):
# Testing static methods... # Testing static methods...
......
...@@ -10,6 +10,8 @@ What's New in Python 3.2.4 ...@@ -10,6 +10,8 @@ What's New in Python 3.2.4
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #14699: Fix calling the classmethod descriptor directly.
- Issue #14433: Prevent msvcrt crash in interactive prompt when stdin - Issue #14433: Prevent msvcrt crash in interactive prompt when stdin
is closed. is closed.
......
...@@ -256,14 +256,52 @@ static PyObject * ...@@ -256,14 +256,52 @@ static PyObject *
classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args, classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
PyObject *kwds) PyObject *kwds)
{ {
PyObject *func, *result; Py_ssize_t argc;
PyObject *self, *func, *result;
func = PyCFunction_New(descr->d_method, (PyObject *)PyDescr_TYPE(descr)); /* Make sure that the first argument is acceptable as 'self' */
if (func == NULL) 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), "?",
PyDescr_TYPE(descr)->tp_name);
return NULL; 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), "?",
PyDescr_TYPE(descr)->tp_name,
self->ob_type->tp_name);
return NULL;
}
if (!PyType_IsSubtype((PyTypeObject *)self, PyDescr_TYPE(descr))) {
PyErr_Format(PyExc_TypeError,
"descriptor '%V' "
"requires a subtype of '%.100s' "
"but received '%.100s",
descr_name((PyDescrObject *)descr), "?",
PyDescr_TYPE(descr)->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); result = PyEval_CallObjectWithKeywords(func, args, kwds);
Py_DECREF(func); Py_DECREF(func);
Py_DECREF(args);
return result; return result;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment