/* Class object implementation */ #include "Python.h"#include "structmember.h" #define TP_DESCR_GET(t) \ (PyType_HasFeature(t, Py_TPFLAGS_HAVE_CLASS) ? (t)->tp_descr_get : NULL) /* Forward */static PyObject *class_lookup(PyClassObject *, PyObject *, PyClassObject **);static PyObject *instance_getattr1(PyInstanceObject *, PyObject *);static PyObject *instance_getattr2(PyInstanceObject *, PyObject *); static PyObject *getattrstr, *setattrstr, *delattrstr; PyObject *PyClass_New(PyObject *bases, PyObject *dict, PyObject *name) /* bases is NULL or tuple of classobjects! */{ PyClassObject *op, *dummy; static PyObject *docstr, *modstr, *namestr; if (docstr == NULL) { docstr= PyString_InternFromString("__doc__"); if (docstr == NULL) return NULL; } if (modstr == NULL) { modstr= PyString_InternFromString("__module__"); if (modstr == NULL) return NULL; } if (namestr == NULL) { namestr= PyString_InternFromString("__name__"); if (namestr == NULL) return NULL; } if (name == NULL || !PyString_Check(name)) { PyErr_SetString(PyExc_TypeError, "PyClass_New: name must be a string"); return NULL; } if (dict == NULL || !PyDict_Check(dict)) { PyErr_SetString(PyExc_TypeError, "PyClass_New: dict must be a dictionary"); return NULL; } if (PyDict_GetItem(dict, docstr) == NULL) { if (PyDict_SetItem(dict, docstr, Py_None) < 0) return NULL; } if (PyDict_GetItem(dict, modstr) == NULL) { PyObject *globals = PyEval_GetGlobals(); if (globals != NULL) { PyObject *modname = PyDict_GetItem(globals, namestr); if (modname != NULL) { if (PyDict_SetItem(dict, modstr, modname) < 0) return NULL; } } } if (bases == NULL) { bases = PyTuple_New(0); if (bases == NULL) return NULL; } else { Py_ssize_t i, n; PyObject *base; if (!PyTuple_Check(bases)) { PyErr_SetString(PyExc_TypeError, "PyClass_New: bases must be a tuple"); return NULL; } n = PyTuple_Size(bases); for (i = 0; i < n; i++) { base = PyTuple_GET_ITEM(bases, i); if (!PyClass_Check(base)) { if (PyCallable_Check( (PyObject *) base->ob_type)) return PyObject_CallFunctionObjArgs( (PyObject *) base->ob_type, name, bases, dict, NULL); PyErr_SetString(PyExc_TypeError, "PyClass_New: base must be a class"); return NULL; } } Py_INCREF(bases); } if (getattrstr == NULL) { getattrstr = PyString_InternFromString("__getattr__"); if (getattrstr == NULL) goto alloc_error; setattrstr = PyString_InternFromString("__setattr__"); if (setattrstr == NULL) goto alloc_error; delattrstr = PyString_InternFromString("__delattr__"); if (delattrstr == NULL) goto alloc_error; } op = PyObject_GC_New(PyClassObject, &PyClass_Type); if (op == NULL) {alloc_error: Py_DECREF(bases); return NULL; } op->cl_bases = bases; Py_INCREF(dict); op->cl_dict = dict; Py_XINCREF(name); op->cl_name = name; op->cl_getattr = class_lookup(op, getattrstr, &dummy); op->cl_setattr = class_lookup(op, setattrstr, &dummy); op->cl_delattr = class_lookup(op, delattrstr, &dummy); Py_XINCREF(op->cl_getattr); Py_XINCREF(op->cl_setattr); Py_XINCREF(op->cl_delattr); _PyObject_GC_TRACK(op); return (PyObject *) op;} PyObject *PyMethod_Function(PyObject *im){ if (!PyMethod_Check(im)) { PyErr_BadInternalCall(); return NULL; } return ((PyMethodObject *)im)->im_func;} PyObject *PyMethod_Self(PyObject *im){ if (!PyMethod_Check(im)) { PyErr_BadInternalCall(); return NULL; } return ((PyMethodObject *)im)->im_self;} PyObject *PyMethod_Class(PyObject *im){ if (!PyMethod_Check(im)) { PyErr_BadInternalCall(); return NULL; } return ((PyMethodObject *)im)->im_class;} PyDoc_STRVAR(class_doc,"classobj(name, bases, dict)\n\\n\Create a class object. The name must be a string; the second argument\n\a tuple of classes, and the third a dictionary."); static PyObject *class_new(PyTypeObject *type, PyObject *args, PyObject *kwds){ PyObject *name, *bases, *dict; static char *kwlist[] = {"name", "bases", "dict", 0}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO", kwlist, &name, &bases, &dict)) return NULL; return PyClass_New(bases, dict, name);} /* Class methods */ static voidclass_dealloc(PyClassObject *op){ _PyObject_GC_UNTRACK(op); Py_DECREF(op->cl_bases); Py_DECREF(op->cl_dict); Py_XDECREF(op->cl_name); Py_XDECREF(op->cl_getattr); Py_XDECREF(op->cl_setattr); Py_XDECREF(op->cl_delattr); PyObject_GC_Del(op);} static PyObject *class_lookup(PyClassObject *cp, PyObject *name, PyClassObject **pclass){ Py_ssize_t i, n; PyObject *value = PyDict_GetItem(cp->cl_dict, name); if (value != NULL) { *pclass = cp; return value; } n = PyTuple_Size(cp->cl_bases); for (i = 0; i < n; i++) { /* XXX What if one of the bases is not a class? */ PyObject *v = class_lookup( (PyClassObject *) PyTuple_GetItem(cp->cl_bases, i), name, pclass); if (v != NULL) return v; } return NULL;} static PyObject *class_getattr(register PyClassObject *op, PyObject *name){ register PyObject *v; register char *sname = PyString_AsString(name); PyClassObject *klass; descrgetfunc f; if (sname[0] == '_' && sname[1] == '_') { if (strcmp(sname, "__dict__") == 0) { if (PyEval_GetRestricted()) { PyErr_SetString(PyExc_RuntimeError, "class.__dict__ not accessible in restricted mode"); return NULL; } Py_INCREF(op->cl_dict); return op->cl_dict; } if (strcmp(sname, "__bases__") == 0) { Py_INCREF(op->cl_bases); return op->cl_bases; } if (strcmp(sname, "__name__") == 0) { if (op->cl_name == NULL) v = Py_None; else v = op->cl_name; Py_INCREF(v); return v; } } v = class_lookup(op, name, &klass); if (v == NULL) { PyErr_Format(PyExc_AttributeError, "class %.50s has no attribute '%.400s'", PyString_AS_STRING(op->cl_name), sname); return NULL; } f = TP_DESCR_GET(v->ob_type); if (f == NULL) Py_INCREF(v); else v = f(v, (PyObject *)NULL, (PyObject *)op); return v;} static voidset_slot(PyObject **slot, PyObject *v){ PyObject *temp = *slot; Py_XINCREF(v); *slot = v; Py_XDECREF(temp);} static voidset_attr_slots(PyClassObject *c){ PyClassObject *dummy; set_slot(&c->cl_getattr, class_lookup(c, getattrstr, &dummy)); set_slot(&c->cl_setattr, class_lookup(c, setattrstr, &dummy)); set_slot(&c->cl_delattr, class_lookup(c, delattrstr, &dummy));} static char *set_dict(PyClassObject *c, PyObject *v){ if (v == NULL || !PyDict_Check(v)) return "__dict__ must be a dictionary object"; set_slot(&c->cl_dict, v); set_attr_slots(c); return "";} static char *set_bases(PyClassObject *c, PyObject *v){ Py_ssize_t i, n; if (v == NULL || !PyTuple_Check(v)) return "__bases__ must be a tuple object"; n = PyTuple_Size(v); for (i = 0; i < n; i++) { PyObject *x = PyTuple_GET_ITEM(v, i); if (!PyClass_Check(x)) return "__bases__ items must be classes"; if (PyClass_IsSubclass(x, (PyObject *)c)) return "a __bases__ item causes an inheritance cycle"; } set_slot(&c->cl_bases, v); set_attr_slots(c); return "";} static char *set_name(PyClassObject *c, PyObject *v){ if (v == NULL || !PyString_Check(v)) return "__name__ must be a string object"; if (strlen(PyString_AS_STRING(v)) != (size_t)PyString_GET_SIZE(v)) return "__name__ must not contain null bytes"; set_slot(&c->cl_name, v); return "";} static intclass_setattr(PyClassObject *op, PyObject *name, PyObject *v){ char *sname; if (PyEval_GetRestricted()) { PyErr_SetString(PyExc_RuntimeError, "classes are read-only in restricted mode"); return -1; } sname = PyString_AsString(name); if (sname[0] == '_' && sname[1] == '_') { Py_ssize_t n = PyString_Size(name); if (sname[n-1] == '_' && sname[n-2] == '_') { char *err = NULL; if (strcmp(sname, "__dict__") == 0) err = set_dict(op, v); else if (strcmp(sname, "__bases__") == 0) err = set_bases(op, v); else if (strcmp(sname, "__name__") == 0) err = set_name(op, v); else if (strcmp(sname, "__getattr__") == 0) set_slot(&op->cl_getattr, v); else if (strcmp(sname, "__setattr__") == 0) set_slot(&op->cl_setattr, v); else if (strcmp(sname, "__delattr__") == 0) set_slot(&op->cl_delattr, v); /* For the last three, we fall through to update the dictionary as well. */ if (err != NULL) { if (*err == '\0') return 0; PyErr_SetString(PyExc_TypeError, err); return -1; } } } if (v == NULL) { int rv = PyDict_DelItem(op->cl_dict, name); if (rv < 0) PyErr_Format(PyExc_AttributeError, "class %.50s has no attribute '%.400s'", PyString_AS_STRING(op->cl_name), sname); return rv; } else return PyDict_SetItem(op->cl_dict, name, v);} static PyObject *class_repr(PyClassObject *op){ PyObject *mod = PyDict_GetItemString(op->cl_dict, "__module__"); char *name; if (op->cl_name == NULL || !PyString_Check(op->cl_name)) name = "?"; else name = PyString_AsString(op->cl_name); if (mod == NULL || !PyString_Check(mod)) return PyString_FromFormat("<class ?.%s at %p>", name, op); else return PyString_FromFormat("<class %s.%s at %p>", PyString_AsString(mod), name, op);} static PyObject *class_str(PyClassObject *op){ PyObject *mod = PyDict_GetItemString(op->cl_dict, "__module__"); PyObject *name = op->cl_name; PyObject *res; Py_ssize_t m, n; if (name == NULL || !PyString_Check(name)) return class_repr(op); if (mod == NULL || !PyString_Check(mod)) { Py_INCREF(name); return name; } m = PyString_GET_SIZE(mod); n = PyString_GET_SIZE(name); res = PyString_FromStringAndSize((char *)NULL, m+1+n); if (res != NULL) { char *s = PyString_AS_STRING(res); memcpy(s, PyString_AS_STRING(mod), m); s += m; *s++ = '.'; memcpy(s, PyString_AS_STRING(name), n); } return res;} static intclass_traverse(PyClassObject *o, visitproc visit, void *arg){ Py_VISIT(o->cl_bases); Py_VISIT(o->cl_dict); Py_VISIT(o->cl_name); Py_VISIT(o->cl_getattr); Py_VISIT(o->cl_setattr); Py_VISIT(o->cl_delattr); return 0;} PyTypeObject PyClass_Type = { PyObject_HEAD_INIT(&PyType_Type) 0, "classobj", sizeof(PyClassObject), 0, (destructor)class_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)class_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ PyInstance_New, /* tp_call */ (reprfunc)class_str, /* tp_str */ (getattrofunc)class_getattr, /* tp_getattro */ (setattrofunc)class_setattr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ class_doc, /* tp_doc */ (traverseproc)class_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ class_new, /* tp_new */}; intPyClass_IsSubclass(PyObject *klass, PyObject *base){ Py_ssize_t i, n; PyClassObject *cp; if (klass == base) return 1; if (PyTuple_Check(base)) { n = PyTuple_GET_SIZE(base); for (i = 0; i < n; i++) { if (PyClass_IsSubclass(klass, PyTuple_GET_ITEM(base, i))) return 1; } return 0; } if (klass == NULL || !PyClass_Check(klass)) return 0; cp = (PyClassObject *)klass; n = PyTuple_Size(cp->cl_bases); for (i = 0; i < n; i++) { if (PyClass_IsSubclass(PyTuple_GetItem(cp->cl_bases, i), base)) return 1; } return 0;} /* Instance objects */ PyObject *PyInstance_NewRaw(PyObject *klass, PyObject *dict){ PyInstanceObject *inst; if (!PyClass_Check(klass)) { PyErr_BadInternalCall();Lines 1–500 of 2580. Load more
/* Class object implementation */ #include "Python.h" #include "structmember.h" #define TP_DESCR_GET(t) \ (PyType_HasFeature(t, Py_TPFLAGS_HAVE_CLASS) ? (t)->tp_descr_get : NULL) /* Forward */ static PyObject *class_lookup(PyClassObject *, PyObject *, PyClassObject **); static PyObject *instance_getattr1(PyInstanceObject *, PyObject *); static PyObject *instance_getattr2(PyInstanceObject *, PyObject *); static PyObject *getattrstr, *setattrstr, *delattrstr; PyObject * PyClass_New(PyObject *bases, PyObject *dict, PyObject *name) /* bases is NULL or tuple of classobjects! */ { PyClassObject *op, *dummy; static PyObject *docstr, *modstr, *namestr; if (docstr == NULL) { docstr= PyString_InternFromString("__doc__"); if (docstr == NULL) return NULL; } if (modstr == NULL) { modstr= PyString_InternFromString("__module__"); if (modstr == NULL) return NULL; } if (namestr == NULL) { namestr= PyString_InternFromString("__name__"); if (namestr == NULL) return NULL; } if (name == NULL || !PyString_Check(name)) { PyErr_SetString(PyExc_TypeError, "PyClass_New: name must be a string"); return NULL; } if (dict == NULL || !PyDict_Check(dict)) { PyErr_SetString(PyExc_TypeError, "PyClass_New: dict must be a dictionary"); return NULL; } if (PyDict_GetItem(dict, docstr) == NULL) { if (PyDict_SetItem(dict, docstr, Py_None) < 0) return NULL; } if (PyDict_GetItem(dict, modstr) == NULL) { PyObject *globals = PyEval_GetGlobals(); if (globals != NULL) { PyObject *modname = PyDict_GetItem(globals, namestr); if (modname != NULL) { if (PyDict_SetItem(dict, modstr, modname) < 0) return NULL; } } } if (bases == NULL) { bases = PyTuple_New(0); if (bases == NULL) return NULL; } else { Py_ssize_t i, n; PyObject *base; if (!PyTuple_Check(bases)) { PyErr_SetString(PyExc_TypeError, "PyClass_New: bases must be a tuple"); return NULL; } n = PyTuple_Size(bases); for (i = 0; i < n; i++) { base = PyTuple_GET_ITEM(bases, i); if (!PyClass_Check(base)) { if (PyCallable_Check( (PyObject *) base->ob_type)) return PyObject_CallFunctionObjArgs( (PyObject *) base->ob_type, name, bases, dict, NULL); PyErr_SetString(PyExc_TypeError, "PyClass_New: base must be a class"); return NULL; } } Py_INCREF(bases); } if (getattrstr == NULL) { getattrstr = PyString_InternFromString("__getattr__"); if (getattrstr == NULL) goto alloc_error; setattrstr = PyString_InternFromString("__setattr__"); if (setattrstr == NULL) goto alloc_error; delattrstr = PyString_InternFromString("__delattr__"); if (delattrstr == NULL) goto alloc_error; } op = PyObject_GC_New(PyClassObject, &PyClass_Type); if (op == NULL) { alloc_error: Py_DECREF(bases); return NULL; } op->cl_bases = bases; Py_INCREF(dict); op->cl_dict = dict; Py_XINCREF(name); op->cl_name = name; op->cl_getattr = class_lookup(op, getattrstr, &dummy); op->cl_setattr = class_lookup(op, setattrstr, &dummy); op->cl_delattr = class_lookup(op, delattrstr, &dummy); Py_XINCREF(op->cl_getattr); Py_XINCREF(op->cl_setattr); Py_XINCREF(op->cl_delattr); _PyObject_GC_TRACK(op); return (PyObject *) op; } PyObject * PyMethod_Function(PyObject *im) { if (!PyMethod_Check(im)) { PyErr_BadInternalCall(); return NULL; } return ((PyMethodObject *)im)->im_func; } PyObject * PyMethod_Self(PyObject *im) { if (!PyMethod_Check(im)) { PyErr_BadInternalCall(); return NULL; } return ((PyMethodObject *)im)->im_self; } PyObject * PyMethod_Class(PyObject *im) { if (!PyMethod_Check(im)) { PyErr_BadInternalCall(); return NULL; } return ((PyMethodObject *)im)->im_class; } PyDoc_STRVAR(class_doc, "classobj(name, bases, dict)\n\ \n\ Create a class object. The name must be a string; the second argument\n\ a tuple of classes, and the third a dictionary."); static PyObject * class_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *name, *bases, *dict; static char *kwlist[] = {"name", "bases", "dict", 0}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO", kwlist, &name, &bases, &dict)) return NULL; return PyClass_New(bases, dict, name); } /* Class methods */ static void class_dealloc(PyClassObject *op) { _PyObject_GC_UNTRACK(op); Py_DECREF(op->cl_bases); Py_DECREF(op->cl_dict); Py_XDECREF(op->cl_name); Py_XDECREF(op->cl_getattr); Py_XDECREF(op->cl_setattr); Py_XDECREF(op->cl_delattr); PyObject_GC_Del(op); } static PyObject * class_lookup(PyClassObject *cp, PyObject *name, PyClassObject **pclass) { Py_ssize_t i, n; PyObject *value = PyDict_GetItem(cp->cl_dict, name); if (value != NULL) { *pclass = cp; return value; } n = PyTuple_Size(cp->cl_bases); for (i = 0; i < n; i++) { /* XXX What if one of the bases is not a class? */ PyObject *v = class_lookup( (PyClassObject *) PyTuple_GetItem(cp->cl_bases, i), name, pclass); if (v != NULL) return v; } return NULL; } static PyObject * class_getattr(register PyClassObject *op, PyObject *name) { register PyObject *v; register char *sname = PyString_AsString(name); PyClassObject *klass; descrgetfunc f; if (sname[0] == '_' && sname[1] == '_') { if (strcmp(sname, "__dict__") == 0) { if (PyEval_GetRestricted()) { PyErr_SetString(PyExc_RuntimeError, "class.__dict__ not accessible in restricted mode"); return NULL; } Py_INCREF(op->cl_dict); return op->cl_dict; } if (strcmp(sname, "__bases__") == 0) { Py_INCREF(op->cl_bases); return op->cl_bases; } if (strcmp(sname, "__name__") == 0) { if (op->cl_name == NULL) v = Py_None; else v = op->cl_name; Py_INCREF(v); return v; } } v = class_lookup(op, name, &klass); if (v == NULL) { PyErr_Format(PyExc_AttributeError, "class %.50s has no attribute '%.400s'", PyString_AS_STRING(op->cl_name), sname); return NULL; } f = TP_DESCR_GET(v->ob_type); if (f == NULL) Py_INCREF(v); else v = f(v, (PyObject *)NULL, (PyObject *)op); return v; } static void set_slot(PyObject **slot, PyObject *v) { PyObject *temp = *slot; Py_XINCREF(v); *slot = v; Py_XDECREF(temp); } static void set_attr_slots(PyClassObject *c) { PyClassObject *dummy; set_slot(&c->cl_getattr, class_lookup(c, getattrstr, &dummy)); set_slot(&c->cl_setattr, class_lookup(c, setattrstr, &dummy)); set_slot(&c->cl_delattr, class_lookup(c, delattrstr, &dummy)); } static char * set_dict(PyClassObject *c, PyObject *v) { if (v == NULL || !PyDict_Check(v)) return "__dict__ must be a dictionary object"; set_slot(&c->cl_dict, v); set_attr_slots(c); return ""; } static char * set_bases(PyClassObject *c, PyObject *v) { Py_ssize_t i, n; if (v == NULL || !PyTuple_Check(v)) return "__bases__ must be a tuple object"; n = PyTuple_Size(v); for (i = 0; i < n; i++) { PyObject *x = PyTuple_GET_ITEM(v, i); if (!PyClass_Check(x)) return "__bases__ items must be classes"; if (PyClass_IsSubclass(x, (PyObject *)c)) return "a __bases__ item causes an inheritance cycle"; } set_slot(&c->cl_bases, v); set_attr_slots(c); return ""; } static char * set_name(PyClassObject *c, PyObject *v) { if (v == NULL || !PyString_Check(v)) return "__name__ must be a string object"; if (strlen(PyString_AS_STRING(v)) != (size_t)PyString_GET_SIZE(v)) return "__name__ must not contain null bytes"; set_slot(&c->cl_name, v); return ""; } static int class_setattr(PyClassObject *op, PyObject *name, PyObject *v) { char *sname; if (PyEval_GetRestricted()) { PyErr_SetString(PyExc_RuntimeError, "classes are read-only in restricted mode"); return -1; } sname = PyString_AsString(name); if (sname[0] == '_' && sname[1] == '_') { Py_ssize_t n = PyString_Size(name); if (sname[n-1] == '_' && sname[n-2] == '_') { char *err = NULL; if (strcmp(sname, "__dict__") == 0) err = set_dict(op, v); else if (strcmp(sname, "__bases__") == 0) err = set_bases(op, v); else if (strcmp(sname, "__name__") == 0) err = set_name(op, v); else if (strcmp(sname, "__getattr__") == 0) set_slot(&op->cl_getattr, v); else if (strcmp(sname, "__setattr__") == 0) set_slot(&op->cl_setattr, v); else if (strcmp(sname, "__delattr__") == 0) set_slot(&op->cl_delattr, v); /* For the last three, we fall through to update the dictionary as well. */ if (err != NULL) { if (*err == '\0') return 0; PyErr_SetString(PyExc_TypeError, err); return -1; } } } if (v == NULL) { int rv = PyDict_DelItem(op->cl_dict, name); if (rv < 0) PyErr_Format(PyExc_AttributeError, "class %.50s has no attribute '%.400s'", PyString_AS_STRING(op->cl_name), sname); return rv; } else return PyDict_SetItem(op->cl_dict, name, v); } static PyObject * class_repr(PyClassObject *op) { PyObject *mod = PyDict_GetItemString(op->cl_dict, "__module__"); char *name; if (op->cl_name == NULL || !PyString_Check(op->cl_name)) name = "?"; else name = PyString_AsString(op->cl_name); if (mod == NULL || !PyString_Check(mod)) return PyString_FromFormat("<class ?.%s at %p>", name, op); else return PyString_FromFormat("<class %s.%s at %p>", PyString_AsString(mod), name, op); } static PyObject * class_str(PyClassObject *op) { PyObject *mod = PyDict_GetItemString(op->cl_dict, "__module__"); PyObject *name = op->cl_name; PyObject *res; Py_ssize_t m, n; if (name == NULL || !PyString_Check(name)) return class_repr(op); if (mod == NULL || !PyString_Check(mod)) { Py_INCREF(name); return name; } m = PyString_GET_SIZE(mod); n = PyString_GET_SIZE(name); res = PyString_FromStringAndSize((char *)NULL, m+1+n); if (res != NULL) { char *s = PyString_AS_STRING(res); memcpy(s, PyString_AS_STRING(mod), m); s += m; *s++ = '.'; memcpy(s, PyString_AS_STRING(name), n); } return res; } static int class_traverse(PyClassObject *o, visitproc visit, void *arg) { Py_VISIT(o->cl_bases); Py_VISIT(o->cl_dict); Py_VISIT(o->cl_name); Py_VISIT(o->cl_getattr); Py_VISIT(o->cl_setattr); Py_VISIT(o->cl_delattr); return 0; } PyTypeObject PyClass_Type = { PyObject_HEAD_INIT(&PyType_Type) 0, "classobj", sizeof(PyClassObject), 0, (destructor)class_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)class_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ PyInstance_New, /* tp_call */ (reprfunc)class_str, /* tp_str */ (getattrofunc)class_getattr, /* tp_getattro */ (setattrofunc)class_setattr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ class_doc, /* tp_doc */ (traverseproc)class_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ class_new, /* tp_new */ }; int PyClass_IsSubclass(PyObject *klass, PyObject *base) { Py_ssize_t i, n; PyClassObject *cp; if (klass == base) return 1; if (PyTuple_Check(base)) { n = PyTuple_GET_SIZE(base); for (i = 0; i < n; i++) { if (PyClass_IsSubclass(klass, PyTuple_GET_ITEM(base, i))) return 1; } return 0; } if (klass == NULL || !PyClass_Check(klass)) return 0; cp = (PyClassObject *)klass; n = PyTuple_Size(cp->cl_bases); for (i = 0; i < n; i++) { if (PyClass_IsSubclass(PyTuple_GetItem(cp->cl_bases, i), base)) return 1; } return 0; } /* Instance objects */ PyObject * PyInstance_NewRaw(PyObject *klass, PyObject *dict) { PyInstanceObject *inst; if (!PyClass_Check(klass)) { PyErr_BadInternalCall();