mirror of https://github.com/python/cpython
fix calling the classmethod descriptor directly (closes #14699)
This commit is contained in:
parent
42d7081806
commit
7295c6a871
|
@ -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
|
||||||
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 *
|
||||||
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' */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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)
|
if (func == NULL)
|
||||||
return 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue