From 823649d544eec66a61176dbb76b51a9408c7f4ed Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Wed, 21 Mar 2001 18:40:58 +0000 Subject: Move the code implementing isinstance() and issubclass() to new C APIs, PyObject_IsInstance() and PyObject_IsSubclass() -- both returning an int, or -1 for errors. --- Include/abstract.h | 7 ++++ Objects/abstract.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++ Python/bltinmodule.c | 102 +++------------------------------------------- 3 files changed, 125 insertions(+), 96 deletions(-) diff --git a/Include/abstract.h b/Include/abstract.h index 2c0e735..e0765e5 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -1074,6 +1074,13 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ */ +DL_IMPORT(int) PyObject_IsInstance(PyObject *object, PyObject *typeorclass); + /* isinstance(object, typeorclass) */ + +DL_IMPORT(int) PyObject_IsSubclass(PyObject *object, PyObject *typeorclass); + /* issubclass(object, typeorclass) */ + + #ifdef __cplusplus } #endif diff --git a/Objects/abstract.c b/Objects/abstract.c index 1189ae8..3ccac71 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -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; +} diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index e5db11e..ec680d1 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -2005,101 +2005,19 @@ static char vars_doc[] = Without arguments, equivalent to locals().\n\ With an argument, equivalent to object.__dict__."; -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; -} - static PyObject * builtin_isinstance(PyObject *self, PyObject *args) { PyObject *inst; PyObject *cls; - PyObject *icls; - static PyObject *__class__ = NULL; - int retval = 0; + int retval; if (!PyArg_ParseTuple(args, "OO:isinstance", &inst, &cls)) return NULL; - 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 NULL; - } - 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 NULL; - } - else - retval = -1; - } - else - retval = -1; - - if (retval < 0) { - PyErr_SetString(PyExc_TypeError, - "isinstance() arg 2 must be a class or type"); + retval = PyObject_IsInstance(inst, cls); + if (retval < 0) return NULL; - } return PyInt_FromLong(retval); } @@ -2120,17 +2038,9 @@ builtin_issubclass(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OO:issubclass", &derived, &cls)) return NULL; - if (!PyClass_Check(derived) || !PyClass_Check(cls)) { - retval = abstract_issubclass(derived, cls, 1); - if (retval < 0) - return NULL; - } - else { - /* shortcut */ - if (!(retval = (derived == cls))) - retval = PyClass_IsSubclass(derived, cls); - } - + retval = PyObject_IsSubclass(derived, cls); + if (retval < 0) + return NULL; return PyInt_FromLong(retval); } -- cgit v0.12