diff options
author | Guido van Rossum <guido@python.org> | 2001-03-21 18:40:58 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2001-03-21 18:40:58 (GMT) |
commit | 823649d544eec66a61176dbb76b51a9408c7f4ed (patch) | |
tree | 5421f4de7101fe676693edea46cc886661db96b7 /Objects | |
parent | 91751143ebae8db295a7e15b4aeb831ea43ca123 (diff) | |
download | cpython-823649d544eec66a61176dbb76b51a9408c7f4ed.zip cpython-823649d544eec66a61176dbb76b51a9408c7f4ed.tar.gz cpython-823649d544eec66a61176dbb76b51a9408c7f4ed.tar.bz2 |
Move the code implementing isinstance() and issubclass() to new C
APIs, PyObject_IsInstance() and PyObject_IsSubclass() -- both
returning an int, or -1 for errors.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/abstract.c | 112 |
1 files changed, 112 insertions, 0 deletions
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; +} |