mirror of https://github.com/python/cpython.git
bpo-37151: simplify classmethoddescr_call (GH-13340)
This commit is contained in:
parent
307d4cb957
commit
3f345c3925
|
@ -1613,8 +1613,8 @@ class SubSpam(spam.spamlist): pass
|
||||||
spam_cm(spam.spamlist())
|
spam_cm(spam.spamlist())
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
str(cm.exception),
|
str(cm.exception),
|
||||||
"descriptor 'classmeth' requires a type "
|
"descriptor 'classmeth' for type 'xxsubtype.spamlist' "
|
||||||
"but received a 'xxsubtype.spamlist' instance")
|
"needs a type, not a 'xxsubtype.spamlist' as arg 2")
|
||||||
|
|
||||||
with self.assertRaises(TypeError) as cm:
|
with self.assertRaises(TypeError) as cm:
|
||||||
spam_cm(list)
|
spam_cm(list)
|
||||||
|
|
|
@ -300,16 +300,19 @@ _PyMethodDescr_Vectorcall(PyObject *descrobj,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Instances of classmethod_descriptor are unlikely to be called directly.
|
||||||
|
For one, the analogous class "classmethod" (for Python classes) is not
|
||||||
|
callable. Second, users are not likely to access a classmethod_descriptor
|
||||||
|
directly, since it means pulling it from the class __dict__.
|
||||||
|
|
||||||
|
This is just an excuse to say that this doesn't need to be optimized:
|
||||||
|
we implement this simply by calling __get__ and then calling the result.
|
||||||
|
*/
|
||||||
static PyObject *
|
static PyObject *
|
||||||
classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
|
classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
|
||||||
PyObject *kwds)
|
PyObject *kwds)
|
||||||
{
|
{
|
||||||
Py_ssize_t argc;
|
Py_ssize_t argc = PyTuple_GET_SIZE(args);
|
||||||
PyObject *self, *result;
|
|
||||||
|
|
||||||
/* Make sure that the first argument is acceptable as 'self' */
|
|
||||||
assert(PyTuple_Check(args));
|
|
||||||
argc = PyTuple_GET_SIZE(args);
|
|
||||||
if (argc < 1) {
|
if (argc < 1) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"descriptor '%V' of '%.100s' "
|
"descriptor '%V' of '%.100s' "
|
||||||
|
@ -318,30 +321,15 @@ classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
|
||||||
PyDescr_TYPE(descr)->tp_name);
|
PyDescr_TYPE(descr)->tp_name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
self = PyTuple_GET_ITEM(args, 0);
|
PyObject *self = PyTuple_GET_ITEM(args, 0);
|
||||||
if (!PyType_Check(self)) {
|
PyObject *bound = classmethod_get(descr, NULL, self);
|
||||||
PyErr_Format(PyExc_TypeError,
|
if (bound == NULL) {
|
||||||
"descriptor '%V' requires a type "
|
|
||||||
"but received a '%.100s' instance",
|
|
||||||
descr_name((PyDescrObject *)descr), "?",
|
|
||||||
self->ob_type->tp_name);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!PyType_IsSubtype((PyTypeObject *)self, PyDescr_TYPE(descr))) {
|
PyObject *res = _PyObject_FastCallDict(bound, _PyTuple_ITEMS(args)+1,
|
||||||
PyErr_Format(PyExc_TypeError,
|
argc-1, kwds);
|
||||||
"descriptor '%V' requires a subtype of '%.100s' "
|
Py_DECREF(bound);
|
||||||
"but received '%.100s'",
|
return res;
|
||||||
descr_name((PyDescrObject *)descr), "?",
|
|
||||||
PyDescr_TYPE(descr)->tp_name,
|
|
||||||
((PyTypeObject*)self)->tp_name);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = _PyMethodDef_RawFastCallDict(descr->d_method, self,
|
|
||||||
&_PyTuple_ITEMS(args)[1], argc - 1,
|
|
||||||
kwds);
|
|
||||||
result = _Py_CheckFunctionResult((PyObject *)descr, result, NULL);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_LOCAL_INLINE(PyObject *)
|
Py_LOCAL_INLINE(PyObject *)
|
||||||
|
|
Loading…
Reference in New Issue