Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 47 additions & 32 deletions Objects/abstract.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "pycore_list.h" // _PyList_AppendTakeRef()
#include "pycore_long.h" // _PyLong_IsNegative()
#include "pycore_object.h" // _Py_CheckSlotResult()
#include "pycore_stackref.h" // _PyStackRef
#include "pycore_pybuffer.h" // _PyBuffer_ReleaseInInterpreterAndRawFree()
#include "pycore_pyerrors.h" // _PyErr_Occurred()
#include "pycore_pystate.h" // _PyThreadState_GET()
Expand Down Expand Up @@ -2635,6 +2636,40 @@ object_isinstance(PyObject *inst, PyObject *cls)
return retval;
}

static int
call_special_method(PyThreadState *tstate, PyObject *cls, PyObject *name,
const char *where, PyObject *arg, PyObject **res)
{
_PyCStackRef cref;
_PyThreadState_PushCStackRef(tstate, &cref);
_PyStackRef method_and_self[2] = {
PyStackRef_NULL, PyStackRef_FromPyObjectBorrow(cls)
};
int found = _PyObject_LookupSpecialMethod(name, method_and_self);
cref.ref = method_and_self[0];
if (found > 0) {
*res = NULL;
if (!_Py_EnterRecursiveCallTstate(tstate, where)) {
PyObject *method = PyStackRef_AsPyObjectBorrow(cref.ref);
PyObject *args[2] = {PyStackRef_AsPyObjectBorrow(method_and_self[1]), arg};
if (args[0] != NULL) {
/* Unbound method: prepend self. */
*res = PyObject_Vectorcall(method, args, 2, NULL);
}
else {
*res = PyObject_Vectorcall(method, args + 1, 1, NULL);
}
_Py_LeaveRecursiveCallTstate(tstate);
}
if (*res == NULL) {
found = -1;
}
}
PyStackRef_XCLOSE(method_and_self[1]);
_PyThreadState_PopCStackRef(tstate, &cref);
return found;
}

static int
object_recursive_isinstance(PyThreadState *tstate, PyObject *inst, PyObject *cls)
{
Expand Down Expand Up @@ -2672,26 +2707,16 @@ object_recursive_isinstance(PyThreadState *tstate, PyObject *inst, PyObject *cls
return r;
}

PyObject *checker = _PyObject_LookupSpecial(cls, &_Py_ID(__instancecheck__));
if (checker != NULL) {
if (_Py_EnterRecursiveCallTstate(tstate, " in __instancecheck__")) {
Py_DECREF(checker);
return -1;
}

PyObject *res = PyObject_CallOneArg(checker, inst);
_Py_LeaveRecursiveCallTstate(tstate);
Py_DECREF(checker);

if (res == NULL) {
return -1;
}
PyObject *res;
int found = call_special_method(tstate, cls, &_Py_ID(__instancecheck__),
" in __instancecheck__", inst, &res);
if (found > 0) {
int ok = PyObject_IsTrue(res);
Py_DECREF(res);

return ok;
}
else if (_PyErr_Occurred(tstate)) {
else if (found < 0) {
return -1;
}

Expand Down Expand Up @@ -2731,8 +2756,6 @@ recursive_issubclass(PyObject *derived, PyObject *cls)
static int
object_issubclass(PyThreadState *tstate, PyObject *derived, PyObject *cls)
{
PyObject *checker;

/* We know what type's __subclasscheck__ does. */
if (PyType_CheckExact(cls)) {
/* Quick test for an exact match */
Expand Down Expand Up @@ -2763,23 +2786,15 @@ object_issubclass(PyThreadState *tstate, PyObject *derived, PyObject *cls)
return r;
}

checker = _PyObject_LookupSpecial(cls, &_Py_ID(__subclasscheck__));
if (checker != NULL) {
int ok = -1;
if (_Py_EnterRecursiveCallTstate(tstate, " in __subclasscheck__")) {
Py_DECREF(checker);
return ok;
}
PyObject *res = PyObject_CallOneArg(checker, derived);
_Py_LeaveRecursiveCallTstate(tstate);
Py_DECREF(checker);
if (res != NULL) {
ok = PyObject_IsTrue(res);
Py_DECREF(res);
}
PyObject *res;
int found = call_special_method(tstate, cls, &_Py_ID(__subclasscheck__),
" in __subclasscheck__", derived, &res);
if (found > 0) {
int ok = PyObject_IsTrue(res);
Py_DECREF(res);
return ok;
}
else if (_PyErr_Occurred(tstate)) {
else if (found < 0) {
return -1;
}

Expand Down
Loading