mirror of
https://github.com/python/cpython.git
synced 2025-07-24 11:44:31 +00:00
Move the code implementing isinstance() and issubclass() to new C
APIs, PyObject_IsInstance() and PyObject_IsSubclass() -- both returning an int, or -1 for errors.
This commit is contained in:
parent
91751143eb
commit
823649d544
3 changed files with 125 additions and 96 deletions
|
@ -1626,3 +1626,115 @@ PyObject_CallMethod(PyObject *o, char *name, char *format, ...)
|
|||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/* isinstance(), issubclass() */
|
||||
|
||||
static int
|
||||
abstract_issubclass(PyObject *derived, PyObject *cls, int first)
|
||||
{
|
||||
static PyObject *__bases__ = NULL;
|
||||
PyObject *bases;
|
||||
int i, n;
|
||||
int r = 0;
|
||||
|
||||
if (__bases__ == NULL) {
|
||||
__bases__ = PyString_FromString("__bases__");
|
||||
if (__bases__ == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (first) {
|
||||
bases = PyObject_GetAttr(cls, __bases__);
|
||||
if (bases == NULL || !PyTuple_Check(bases)) {
|
||||
Py_XDECREF(bases);
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"issubclass() arg 2 must be a class");
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(bases);
|
||||
}
|
||||
|
||||
if (derived == cls)
|
||||
return 1;
|
||||
|
||||
bases = PyObject_GetAttr(derived, __bases__);
|
||||
if (bases == NULL || !PyTuple_Check(bases)) {
|
||||
Py_XDECREF(bases);
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"issubclass() arg 1 must be a class");
|
||||
return -1;
|
||||
}
|
||||
|
||||
n = PyTuple_GET_SIZE(bases);
|
||||
for (i = 0; i < n; i++) {
|
||||
r = abstract_issubclass(PyTuple_GET_ITEM(bases, i), cls, 0);
|
||||
if (r != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
Py_DECREF(bases);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
PyObject_IsInstance(PyObject *inst, PyObject *cls)
|
||||
{
|
||||
PyObject *icls;
|
||||
static PyObject *__class__ = NULL;
|
||||
int retval = 0;
|
||||
|
||||
if (PyClass_Check(cls)) {
|
||||
if (PyInstance_Check(inst)) {
|
||||
PyObject *inclass =
|
||||
(PyObject*)((PyInstanceObject*)inst)->in_class;
|
||||
retval = PyClass_IsSubclass(inclass, cls);
|
||||
}
|
||||
}
|
||||
else if (PyType_Check(cls)) {
|
||||
retval = ((PyObject *)(inst->ob_type) == cls);
|
||||
}
|
||||
else if (!PyInstance_Check(inst)) {
|
||||
if (__class__ == NULL) {
|
||||
__class__ = PyString_FromString("__class__");
|
||||
if (__class__ == NULL)
|
||||
return -1;
|
||||
}
|
||||
icls = PyObject_GetAttr(inst, __class__);
|
||||
if (icls != NULL) {
|
||||
retval = abstract_issubclass(icls, cls, 1);
|
||||
Py_DECREF(icls);
|
||||
if (retval < 0 &&
|
||||
!PyErr_ExceptionMatches(PyExc_TypeError))
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
retval = -1;
|
||||
}
|
||||
else
|
||||
retval = -1;
|
||||
|
||||
if (retval < 0) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"isinstance() arg 2 must be a class or type");
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
PyObject_IsSubclass(PyObject *derived, PyObject *cls)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!PyClass_Check(derived) || !PyClass_Check(cls)) {
|
||||
retval = abstract_issubclass(derived, cls, 1);
|
||||
}
|
||||
else {
|
||||
/* shortcut */
|
||||
if (!(retval = (derived == cls)))
|
||||
retval = PyClass_IsSubclass(derived, cls);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue