Index: Objects/typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.185 diff -c -r2.185 typeobject.c *** Objects/typeobject.c 18 Oct 2002 16:33:12 -0000 2.185 --- Objects/typeobject.c 9 Nov 2002 14:58:16 -0000 *************** *** 5,10 **** --- 5,13 ---- #include + static PyTypeObject *best_base(PyObject *bases); + static int mro_internal(PyTypeObject *type); + /* The *real* layout of a type object when allocated on the heap */ /* XXX Should we publish this in a header file? */ typedef struct { *************** *** 32,39 **** {"__base__", T_OBJECT, offsetof(PyTypeObject, tp_base), READONLY}, {"__dictoffset__", T_LONG, offsetof(PyTypeObject, tp_dictoffset), READONLY}, - {"__bases__", T_OBJECT, offsetof(PyTypeObject, tp_bases), READONLY}, - {"__mro__", T_OBJECT, offsetof(PyTypeObject, tp_mro), READONLY}, {0} }; --- 35,40 ---- *************** *** 50,55 **** --- 51,97 ---- return PyString_FromString(s); } + static int + type_set_name(PyTypeObject *type, PyObject *value, void *context) + { + etype* et; + + if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE) || + strrchr(type->tp_name, '.')) { + PyErr_Format(PyExc_TypeError, + "can't set %s.__name__", type->tp_name); + return -1; + } + if (!value) { + PyErr_Format(PyExc_TypeError, + "can't delete %s.__name__", type->tp_name); + return -1; + } + if (!PyString_Check(value)) { + PyErr_Format(PyExc_TypeError, + "can only assign string to %s.__name__, not '%s'", + type->tp_name, value->ob_type->tp_name); + return -1; + } + if (strchr(PyString_AS_STRING(value), '.') != NULL) { + PyErr_Format(PyExc_ValueError, + "can't assign dotted string to %s.__name__", + type->tp_name); + return -1; + } + + et = (etype*)type; + + Py_INCREF(value); + + Py_DECREF(et->name); + et->name = value; + + type->tp_name = PyString_AS_STRING(value); + + return 0; + } + static PyObject * type_module(PyTypeObject *type, void *context) { *************** *** 63,69 **** if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) return PyString_FromString("__builtin__"); mod = PyDict_GetItemString(type->tp_dict, "__module__"); ! if (mod != NULL && PyString_Check(mod)) { Py_INCREF(mod); return mod; } --- 105,111 ---- if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) return PyString_FromString("__builtin__"); mod = PyDict_GetItemString(type->tp_dict, "__module__"); ! if (mod != NULL) { Py_INCREF(mod); return mod; } *************** *** 85,94 **** --- 127,259 ---- "can't delete %s.__module__", type->tp_name); return -1; } + return PyDict_SetItemString(type->tp_dict, "__module__", value); } static PyObject * + type_get_mro(PyTypeObject *type, void *context) + { + Py_INCREF(type->tp_mro); + return type->tp_mro; + } + + static int + type_set_mro(PyTypeObject *type, PyObject *value, void *context) + { + int i; + PyObject* ob; + + if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE) || + strrchr(type->tp_name, '.')) { + PyErr_Format(PyExc_TypeError, + "can't set %s.__mro__", type->tp_name); + return -1; + } + if (!value) { + PyErr_Format(PyExc_TypeError, + "can't delete %s.__mro__", type->tp_name); + return -1; + } + if (!PyTuple_Check(value)) { + PyErr_Format(PyExc_TypeError, + "can only assign tuple to %s.__mro__, not '%s'", + type->tp_name, value->ob_type->tp_name); + return -1; + } + for (i = 0; i < PyTuple_GET_SIZE(value); i++) { + ob = PyTuple_GET_ITEM(value, i); + if (!PyInstance_Check(ob) && !PyType_Check(ob)) { + PyErr_Format( + PyExc_TypeError, + "%s.__mro__ must be tuple of old- or new-style classes, not '%s'", + type->tp_name, ob->ob_type->tp_name); + return -1; + } + } + + Py_INCREF(value); + Py_DECREF(type->tp_mro); + + type->tp_mro = value; + + return 0; + } + + static PyObject * + type_get_bases(PyTypeObject *type, void *context) + { + Py_INCREF(type->tp_bases); + return type->tp_bases; + } + + static int + type_set_bases(PyTypeObject *type, PyObject *value, void *context) + { + int i; + PyObject* ob; + PyTypeObject* new_base; + PyObject* old_bases; + + if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE) || + strrchr(type->tp_name, '.')) { + PyErr_Format(PyExc_TypeError, + "can't set %s.__bases__", type->tp_name); + return -1; + } + if (!value) { + PyErr_Format(PyExc_TypeError, + "can't delete %s.__bases__", type->tp_name); + return -1; + } + if (!PyTuple_Check(value)) { + PyErr_Format(PyExc_TypeError, + "can only assign tuple to %s.__bases__, not %s", + type->tp_name, value->ob_type->tp_name); + return -1; + } + for (i = 0; i < PyTuple_GET_SIZE(value); i++) { + ob = PyTuple_GET_ITEM(value, i); + if (!PyInstance_Check(ob) && !PyType_Check(ob)) { + PyErr_Format( + PyExc_TypeError, + "%s.__bases__ must be tuple of old- or new-style classes, not '%s'", + type->tp_name, ob->ob_type->tp_name); + return -1; + } + } + + new_base = best_base(value); + + if (new_base != type->tp_base) { + PyErr_Format( + PyExc_ValueError, + "sorry, assignment to %s.__bases__ not currently" + "allowed to change __base__ from '%s' to '%s'", + type->tp_name, type->tp_base->tp_name, + new_base->tp_name); + return -1; + } + + + old_bases = type->tp_bases; + Py_INCREF(value); + type->tp_bases = value; + + if (mro_internal(type) < 0) { + /* wtf do we do here !? */ + type->tp_bases = old_bases; + Py_DECREF(value); + return mro_internal(type); + } + else { + Py_DECREF(old_bases); + } + + return 0; + } + + static PyObject * type_dict(PyTypeObject *type, void *context) { if (type->tp_dict == NULL) { *************** *** 120,127 **** } static PyGetSetDef type_getsets[] = { ! {"__name__", (getter)type_name, NULL, NULL}, {"__module__", (getter)type_module, (setter)type_set_module, NULL}, {"__dict__", (getter)type_dict, NULL, NULL}, {"__doc__", (getter)type_get_doc, NULL, NULL}, {0} --- 285,294 ---- } static PyGetSetDef type_getsets[] = { ! {"__name__", (getter)type_name, (setter)type_set_name, NULL}, {"__module__", (getter)type_module, (setter)type_set_module, NULL}, + {"__mro__", (getter)type_get_mro, (setter)type_set_mro, NULL}, + {"__bases__", (getter)type_get_bases, (setter)type_set_bases, NULL}, {"__dict__", (getter)type_dict, NULL, NULL}, {"__doc__", (getter)type_get_doc, NULL, NULL}, {0}