summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeroen Demeyer <J.Demeyer@UGent.be>2019-06-07 10:20:24 (GMT)
committerPetr Viktorin <encukou@gmail.com>2019-06-07 10:20:23 (GMT)
commit3f345c39255dc3823dd989d4e3c93b12d18c44e0 (patch)
tree3c6780c3b01ff77f57df5bed426ec08cac68b586
parent307d4cb957b9d34fdbbb40730f738c61c2e49be9 (diff)
downloadcpython-3f345c39255dc3823dd989d4e3c93b12d18c44e0.zip
cpython-3f345c39255dc3823dd989d4e3c93b12d18c44e0.tar.gz
cpython-3f345c39255dc3823dd989d4e3c93b12d18c44e0.tar.bz2
bpo-37151: simplify classmethoddescr_call (GH-13340)
-rw-r--r--Lib/test/test_descr.py4
-rw-r--r--Objects/descrobject.c44
2 files changed, 18 insertions, 30 deletions
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index 6b018cc..301a2d2 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -1613,8 +1613,8 @@ order (MRO) for bases """
spam_cm(spam.spamlist())
self.assertEqual(
str(cm.exception),
- "descriptor 'classmeth' requires a type "
- "but received a 'xxsubtype.spamlist' instance")
+ "descriptor 'classmeth' for type 'xxsubtype.spamlist' "
+ "needs a type, not a 'xxsubtype.spamlist' as arg 2")
with self.assertRaises(TypeError) as cm:
spam_cm(list)
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index 6c95a87..806c0af 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -300,16 +300,19 @@ _PyMethodDescr_Vectorcall(PyObject *descrobj,
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 *
classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
PyObject *kwds)
{
- Py_ssize_t argc;
- PyObject *self, *result;
-
- /* Make sure that the first argument is acceptable as 'self' */
- assert(PyTuple_Check(args));
- argc = PyTuple_GET_SIZE(args);
+ Py_ssize_t argc = PyTuple_GET_SIZE(args);
if (argc < 1) {
PyErr_Format(PyExc_TypeError,
"descriptor '%V' of '%.100s' "
@@ -318,30 +321,15 @@ classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
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' instance",
- descr_name((PyDescrObject *)descr), "?",
- 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,
- ((PyTypeObject*)self)->tp_name);
+ PyObject *self = PyTuple_GET_ITEM(args, 0);
+ PyObject *bound = classmethod_get(descr, NULL, self);
+ if (bound == NULL) {
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;
+ PyObject *res = _PyObject_FastCallDict(bound, _PyTuple_ITEMS(args)+1,
+ argc-1, kwds);
+ Py_DECREF(bound);
+ return res;
}
Py_LOCAL_INLINE(PyObject *)