diff options
author | Guido van Rossum <guido@python.org> | 2001-08-10 21:24:08 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2001-08-10 21:24:08 (GMT) |
commit | 13d52f0b3289e34298fbf5d3912cb642f3d2fbd9 (patch) | |
tree | ddccff20e1c079a0c40b1cb7751fe357cd5f64cf | |
parent | f24b2f32850625dc56d510e2a5d019641bd06b4e (diff) | |
download | cpython-13d52f0b3289e34298fbf5d3912cb642f3d2fbd9.zip cpython-13d52f0b3289e34298fbf5d3912cb642f3d2fbd9.tar.gz cpython-13d52f0b3289e34298fbf5d3912cb642f3d2fbd9.tar.bz2 |
- Big changes to fix SF bug #442833 (a nasty multiple inheritance
problem). inherit_slots() is split in two parts: inherit_special()
which inherits the flags and a few very special members from the
dominant base; inherit_slots() which inherits only regular slots,
and is now called for each base in the MRO in turn. These are now
both void functions since they don't have error returns.
- Added object.__setitem__() back -- for the same reason as
object.__new__(): a subclass of object should be able to call
object.__new__().
- add_wrappers() was moved around to be closer to where it is used (it
was defined together with add_methods() etc., but has nothing to do
with these).
-rw-r--r-- | Objects/typeobject.c | 213 |
1 files changed, 122 insertions, 91 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 926d151..37d9491 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4,8 +4,6 @@ #include "Python.h" #include "structmember.h" -staticforward int add_members(PyTypeObject *, struct memberlist *); - static struct memberlist type_members[] = { {"__name__", T_STRING, offsetof(PyTypeObject, tp_name), READONLY}, {"__basicsize__", T_INT, offsetof(PyTypeObject,tp_basicsize),READONLY}, @@ -647,7 +645,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) slotoffset += sizeof(PyObject *); } type->tp_basicsize = slotoffset; - add_members(type, et->members); + type->tp_members = et->members; /* Special case some slots */ if (type->tp_dictoffset != 0 || nslots > 0) { @@ -882,7 +880,7 @@ PyTypeObject PyBaseObject_Type = { 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ + PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ "The most base type", /* tp_doc */ @@ -929,25 +927,6 @@ add_methods(PyTypeObject *type, PyMethodDef *meth) } static int -add_wrappers(PyTypeObject *type, struct wrapperbase *wraps, void *wrapped) -{ - PyObject *dict = type->tp_defined; - - for (; wraps->name != NULL; wraps++) { - PyObject *descr; - if (PyDict_GetItemString(dict, wraps->name)) - continue; - descr = PyDescr_NewWrapper(type, wraps, wrapped); - if (descr == NULL) - return -1; - if (PyDict_SetItemString(dict, wraps->name, descr) < 0) - return -1; - Py_DECREF(descr); - } - return 0; -} - -static int add_members(PyTypeObject *type, struct memberlist *memb) { PyObject *dict = type->tp_defined; @@ -986,27 +965,90 @@ add_getset(PyTypeObject *type, struct getsetlist *gsp) return 0; } -staticforward int add_operators(PyTypeObject *); +static void +inherit_special(PyTypeObject *type, PyTypeObject *base) +{ + int oldsize, newsize; -static int + /* Special flag magic */ + if (!type->tp_as_buffer && base->tp_as_buffer) { + type->tp_flags &= ~Py_TPFLAGS_HAVE_GETCHARBUFFER; + type->tp_flags |= + base->tp_flags & Py_TPFLAGS_HAVE_GETCHARBUFFER; + } + if (!type->tp_as_sequence && base->tp_as_sequence) { + type->tp_flags &= ~Py_TPFLAGS_HAVE_SEQUENCE_IN; + type->tp_flags |= base->tp_flags & Py_TPFLAGS_HAVE_SEQUENCE_IN; + } + if ((type->tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS) != + (base->tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS)) { + if ((!type->tp_as_number && base->tp_as_number) || + (!type->tp_as_sequence && base->tp_as_sequence)) { + type->tp_flags &= ~Py_TPFLAGS_HAVE_INPLACEOPS; + if (!type->tp_as_number && !type->tp_as_sequence) { + type->tp_flags |= base->tp_flags & + Py_TPFLAGS_HAVE_INPLACEOPS; + } + } + /* Wow */ + } + if (!type->tp_as_number && base->tp_as_number) { + type->tp_flags &= ~Py_TPFLAGS_CHECKTYPES; + type->tp_flags |= base->tp_flags & Py_TPFLAGS_CHECKTYPES; + } + + /* Copying basicsize is connected to the GC flags */ + oldsize = PyType_BASICSIZE(base); + newsize = type->tp_basicsize ? PyType_BASICSIZE(type) : oldsize; + if (!(type->tp_flags & Py_TPFLAGS_GC) && + (base->tp_flags & Py_TPFLAGS_GC) && + (type->tp_flags & Py_TPFLAGS_HAVE_RICHCOMPARE/*GC slots exist*/) && + (!type->tp_traverse && !type->tp_clear)) { + type->tp_flags |= Py_TPFLAGS_GC; + if (type->tp_traverse == NULL) + type->tp_traverse = base->tp_traverse; + if (type->tp_clear == NULL) + type->tp_clear = base->tp_clear; + } + if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_CLASS) { + if (base != &PyBaseObject_Type || + (type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { + if (type->tp_new == NULL) + type->tp_new = base->tp_new; + } + } + PyType_SET_BASICSIZE(type, newsize); +} + +static void inherit_slots(PyTypeObject *type, PyTypeObject *base) { - int oldsize, newsize; + PyTypeObject *basebase; +#undef SLOTDEFINED #undef COPYSLOT #undef COPYNUM #undef COPYSEQ #undef COPYMAP + +#define SLOTDEFINED(SLOT) \ + (base->SLOT != 0 && \ + (basebase == NULL || base->SLOT != basebase->SLOT)) + #define COPYSLOT(SLOT) \ - if (!type->SLOT) type->SLOT = base->SLOT + if (!type->SLOT && SLOTDEFINED(SLOT)) type->SLOT = base->SLOT #define COPYNUM(SLOT) COPYSLOT(tp_as_number->SLOT) #define COPYSEQ(SLOT) COPYSLOT(tp_as_sequence->SLOT) #define COPYMAP(SLOT) COPYSLOT(tp_as_mapping->SLOT) - if (type->tp_as_number == NULL) - type->tp_as_number = base->tp_as_number; - else if (base->tp_as_number) { + /* This won't inherit indirect slots (from tp_as_number etc.) + if type doesn't provide the space. */ + + if (type->tp_as_number != NULL && base->tp_as_number != NULL) { + basebase = base->tp_base; + if (basebase->tp_as_number == NULL) + basebase = NULL; COPYNUM(nb_add); COPYNUM(nb_subtract); COPYNUM(nb_multiply); @@ -1049,9 +1091,10 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base) } } - if (type->tp_as_sequence == NULL) - type->tp_as_sequence = base->tp_as_sequence; - else if (base->tp_as_sequence) { + if (type->tp_as_sequence != NULL && base->tp_as_sequence != NULL) { + basebase = base->tp_base; + if (basebase->tp_as_sequence == NULL) + basebase = NULL; COPYSEQ(sq_length); COPYSEQ(sq_concat); COPYSEQ(sq_repeat); @@ -1064,53 +1107,16 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base) COPYSEQ(sq_inplace_repeat); } - if (type->tp_as_mapping == NULL) - type->tp_as_mapping = base->tp_as_mapping; - else if (base->tp_as_mapping) { + if (type->tp_as_mapping != NULL && base->tp_as_mapping != NULL) { + basebase = base->tp_base; + if (basebase->tp_as_mapping == NULL) + basebase = NULL; COPYMAP(mp_length); COPYMAP(mp_subscript); COPYMAP(mp_ass_subscript); } - /* Special flag magic */ - if (!type->tp_as_buffer && base->tp_as_buffer) { - type->tp_flags &= ~Py_TPFLAGS_HAVE_GETCHARBUFFER; - type->tp_flags |= - base->tp_flags & Py_TPFLAGS_HAVE_GETCHARBUFFER; - } - if (!type->tp_as_sequence && base->tp_as_sequence) { - type->tp_flags &= ~Py_TPFLAGS_HAVE_SEQUENCE_IN; - type->tp_flags |= base->tp_flags & Py_TPFLAGS_HAVE_SEQUENCE_IN; - } - if ((type->tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS) != - (base->tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS)) { - if ((!type->tp_as_number && base->tp_as_number) || - (!type->tp_as_sequence && base->tp_as_sequence)) { - type->tp_flags &= ~Py_TPFLAGS_HAVE_INPLACEOPS; - if (!type->tp_as_number && !type->tp_as_sequence) { - type->tp_flags |= base->tp_flags & - Py_TPFLAGS_HAVE_INPLACEOPS; - } - } - /* Wow */ - } - if (!type->tp_as_number && base->tp_as_number) { - type->tp_flags &= ~Py_TPFLAGS_CHECKTYPES; - type->tp_flags |= base->tp_flags & Py_TPFLAGS_CHECKTYPES; - } - - /* Copying basicsize is connected to the GC flags */ - oldsize = PyType_BASICSIZE(base); - newsize = type->tp_basicsize ? PyType_BASICSIZE(type) : oldsize; - if (!(type->tp_flags & Py_TPFLAGS_GC) && - (base->tp_flags & Py_TPFLAGS_GC) && - (type->tp_flags & Py_TPFLAGS_HAVE_RICHCOMPARE/*GC slots exist*/) && - (!type->tp_traverse && !type->tp_clear)) { - type->tp_flags |= Py_TPFLAGS_GC; - COPYSLOT(tp_traverse); - COPYSLOT(tp_clear); - } - PyType_SET_BASICSIZE(type, newsize); + basebase = base->tp_base; COPYSLOT(tp_itemsize); COPYSLOT(tp_dealloc); @@ -1152,16 +1158,12 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base) COPYSLOT(tp_dictoffset); COPYSLOT(tp_init); COPYSLOT(tp_alloc); - if (base != &PyBaseObject_Type || - (type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { - COPYSLOT(tp_new); - } COPYSLOT(tp_free); } - - return 0; } +staticforward int add_operators(PyTypeObject *); + int PyType_Ready(PyTypeObject *type) { @@ -1237,34 +1239,44 @@ PyType_Ready(PyTypeObject *type) goto error; } + /* Inherit special flags from dominant base */ + if (type->tp_base != NULL) + inherit_special(type, type->tp_base); + /* Initialize tp_dict properly */ if (!PyType_HasFeature(type, Py_TPFLAGS_DYNAMICTYPE)) { /* For a static type, tp_dict is the consolidation - of the tp_defined of its bases in MRO. Earlier - bases override later bases; since d.update() works - the other way, we walk the MRO sequence backwards. */ + of the tp_defined of its bases in MRO. */ Py_DECREF(type->tp_dict); - type->tp_dict = PyDict_New(); + type->tp_dict = PyDict_Copy(type->tp_defined); if (type->tp_dict == NULL) goto error; bases = type->tp_mro; assert(bases != NULL); assert(PyTuple_Check(bases)); n = PyTuple_GET_SIZE(bases); - for (i = n; --i >= 0; ) { + for (i = 1; i < n; i++) { base = (PyTypeObject *)PyTuple_GET_ITEM(bases, i); assert(PyType_Check(base)); x = base->tp_defined; - if (x != NULL && PyDict_Update(type->tp_dict, x) < 0) + if (x != NULL && PyDict_Merge(type->tp_dict, x, 0) < 0) goto error; + inherit_slots(type, base); } } - /* Inherit slots from direct base */ - if (type->tp_base != NULL) - if (inherit_slots(type, type->tp_base) < 0) - goto error; + /* Some more special stuff */ + base = type->tp_base; + if (base != NULL) { + if (type->tp_as_number == NULL) + type->tp_as_number = base->tp_as_number; + if (type->tp_as_sequence == NULL) + type->tp_as_sequence = base->tp_as_sequence; + if (type->tp_as_mapping == NULL) + type->tp_as_mapping = base->tp_as_mapping; + } + /* All done -- set the ready flag */ assert(type->tp_dict != NULL); type->tp_flags = (type->tp_flags & ~Py_TPFLAGS_READYING) | Py_TPFLAGS_READY; @@ -1911,6 +1923,25 @@ add_tp_new_wrapper(PyTypeObject *type) return PyDict_SetItemString(type->tp_defined, "__new__", func); } +static int +add_wrappers(PyTypeObject *type, struct wrapperbase *wraps, void *wrapped) +{ + PyObject *dict = type->tp_defined; + + for (; wraps->name != NULL; wraps++) { + PyObject *descr; + if (PyDict_GetItemString(dict, wraps->name)) + continue; + descr = PyDescr_NewWrapper(type, wraps, wrapped); + if (descr == NULL) + return -1; + if (PyDict_SetItemString(dict, wraps->name, descr) < 0) + return -1; + Py_DECREF(descr); + } + return 0; +} + /* This function is called by PyType_Ready() to populate the type's dictionary with method descriptors for function slots. For each function slot (like tp_repr) that's defined in the type, one or |