Commit 77ee7eec authored by Guido van Rossum's avatar Guido van Rossum

- 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).
parent 652f86b0
...@@ -4,8 +4,6 @@ ...@@ -4,8 +4,6 @@
#include "Python.h" #include "Python.h"
#include "structmember.h" #include "structmember.h"
staticforward int add_members(PyTypeObject *, struct memberlist *);
static struct memberlist type_members[] = { static struct memberlist type_members[] = {
{"__name__", T_STRING, offsetof(PyTypeObject, tp_name), READONLY}, {"__name__", T_STRING, offsetof(PyTypeObject, tp_name), READONLY},
{"__basicsize__", T_INT, offsetof(PyTypeObject,tp_basicsize),READONLY}, {"__basicsize__", T_INT, offsetof(PyTypeObject,tp_basicsize),READONLY},
...@@ -647,7 +645,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) ...@@ -647,7 +645,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
slotoffset += sizeof(PyObject *); slotoffset += sizeof(PyObject *);
} }
type->tp_basicsize = slotoffset; type->tp_basicsize = slotoffset;
add_members(type, et->members); type->tp_members = et->members;
/* Special case some slots */ /* Special case some slots */
if (type->tp_dictoffset != 0 || nslots > 0) { if (type->tp_dictoffset != 0 || nslots > 0) {
...@@ -882,7 +880,7 @@ PyTypeObject PyBaseObject_Type = { ...@@ -882,7 +880,7 @@ PyTypeObject PyBaseObject_Type = {
0, /* tp_call */ 0, /* tp_call */
0, /* tp_str */ 0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */ PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */ PyObject_GenericSetAttr, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
"The most base type", /* tp_doc */ "The most base type", /* tp_doc */
...@@ -928,25 +926,6 @@ add_methods(PyTypeObject *type, PyMethodDef *meth) ...@@ -928,25 +926,6 @@ add_methods(PyTypeObject *type, PyMethodDef *meth)
return 0; return 0;
} }
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 static int
add_members(PyTypeObject *type, struct memberlist *memb) add_members(PyTypeObject *type, struct memberlist *memb)
{ {
...@@ -986,27 +965,90 @@ add_getset(PyTypeObject *type, struct getsetlist *gsp) ...@@ -986,27 +965,90 @@ add_getset(PyTypeObject *type, struct getsetlist *gsp)
return 0; 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) inherit_slots(PyTypeObject *type, PyTypeObject *base)
{ {
int oldsize, newsize; PyTypeObject *basebase;
#undef SLOTDEFINED
#undef COPYSLOT #undef COPYSLOT
#undef COPYNUM #undef COPYNUM
#undef COPYSEQ #undef COPYSEQ
#undef COPYMAP #undef COPYMAP
#define SLOTDEFINED(SLOT) \
(base->SLOT != 0 && \
(basebase == NULL || base->SLOT != basebase->SLOT))
#define COPYSLOT(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 COPYNUM(SLOT) COPYSLOT(tp_as_number->SLOT)
#define COPYSEQ(SLOT) COPYSLOT(tp_as_sequence->SLOT) #define COPYSEQ(SLOT) COPYSLOT(tp_as_sequence->SLOT)
#define COPYMAP(SLOT) COPYSLOT(tp_as_mapping->SLOT) #define COPYMAP(SLOT) COPYSLOT(tp_as_mapping->SLOT)
if (type->tp_as_number == NULL) /* This won't inherit indirect slots (from tp_as_number etc.)
type->tp_as_number = base->tp_as_number; if type doesn't provide the space. */
else if (base->tp_as_number) {
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_add);
COPYNUM(nb_subtract); COPYNUM(nb_subtract);
COPYNUM(nb_multiply); COPYNUM(nb_multiply);
...@@ -1049,9 +1091,10 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base) ...@@ -1049,9 +1091,10 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
} }
} }
if (type->tp_as_sequence == NULL) if (type->tp_as_sequence != NULL && base->tp_as_sequence != NULL) {
type->tp_as_sequence = base->tp_as_sequence; basebase = base->tp_base;
else if (base->tp_as_sequence) { if (basebase->tp_as_sequence == NULL)
basebase = NULL;
COPYSEQ(sq_length); COPYSEQ(sq_length);
COPYSEQ(sq_concat); COPYSEQ(sq_concat);
COPYSEQ(sq_repeat); COPYSEQ(sq_repeat);
...@@ -1064,53 +1107,16 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base) ...@@ -1064,53 +1107,16 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
COPYSEQ(sq_inplace_repeat); COPYSEQ(sq_inplace_repeat);
} }
if (type->tp_as_mapping == NULL) if (type->tp_as_mapping != NULL && base->tp_as_mapping != NULL) {
type->tp_as_mapping = base->tp_as_mapping; basebase = base->tp_base;
else if (base->tp_as_mapping) { if (basebase->tp_as_mapping == NULL)
basebase = NULL;
COPYMAP(mp_length); COPYMAP(mp_length);
COPYMAP(mp_subscript); COPYMAP(mp_subscript);
COPYMAP(mp_ass_subscript); COPYMAP(mp_ass_subscript);
} }
/* Special flag magic */ basebase = base->tp_base;
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);
COPYSLOT(tp_itemsize); COPYSLOT(tp_itemsize);
COPYSLOT(tp_dealloc); COPYSLOT(tp_dealloc);
...@@ -1152,16 +1158,12 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base) ...@@ -1152,16 +1158,12 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
COPYSLOT(tp_dictoffset); COPYSLOT(tp_dictoffset);
COPYSLOT(tp_init); COPYSLOT(tp_init);
COPYSLOT(tp_alloc); COPYSLOT(tp_alloc);
if (base != &PyBaseObject_Type ||
(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
COPYSLOT(tp_new);
}
COPYSLOT(tp_free); COPYSLOT(tp_free);
} }
return 0;
} }
staticforward int add_operators(PyTypeObject *);
int int
PyType_Ready(PyTypeObject *type) PyType_Ready(PyTypeObject *type)
{ {
...@@ -1237,34 +1239,44 @@ PyType_Ready(PyTypeObject *type) ...@@ -1237,34 +1239,44 @@ PyType_Ready(PyTypeObject *type)
goto error; goto error;
} }
/* Inherit special flags from dominant base */
if (type->tp_base != NULL)
inherit_special(type, type->tp_base);
/* Initialize tp_dict properly */ /* Initialize tp_dict properly */
if (!PyType_HasFeature(type, Py_TPFLAGS_DYNAMICTYPE)) { if (!PyType_HasFeature(type, Py_TPFLAGS_DYNAMICTYPE)) {
/* For a static type, tp_dict is the consolidation /* For a static type, tp_dict is the consolidation
of the tp_defined of its bases in MRO. Earlier of the tp_defined of its bases in MRO. */
bases override later bases; since d.update() works
the other way, we walk the MRO sequence backwards. */
Py_DECREF(type->tp_dict); Py_DECREF(type->tp_dict);
type->tp_dict = PyDict_New(); type->tp_dict = PyDict_Copy(type->tp_defined);
if (type->tp_dict == NULL) if (type->tp_dict == NULL)
goto error; goto error;
bases = type->tp_mro; bases = type->tp_mro;
assert(bases != NULL); assert(bases != NULL);
assert(PyTuple_Check(bases)); assert(PyTuple_Check(bases));
n = PyTuple_GET_SIZE(bases); n = PyTuple_GET_SIZE(bases);
for (i = n; --i >= 0; ) { for (i = 1; i < n; i++) {
base = (PyTypeObject *)PyTuple_GET_ITEM(bases, i); base = (PyTypeObject *)PyTuple_GET_ITEM(bases, i);
assert(PyType_Check(base)); assert(PyType_Check(base));
x = base->tp_defined; 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; goto error;
inherit_slots(type, base);
} }
} }
/* Inherit slots from direct base */ /* Some more special stuff */
if (type->tp_base != NULL) base = type->tp_base;
if (inherit_slots(type, type->tp_base) < 0) if (base != NULL) {
goto error; 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); assert(type->tp_dict != NULL);
type->tp_flags = type->tp_flags =
(type->tp_flags & ~Py_TPFLAGS_READYING) | Py_TPFLAGS_READY; (type->tp_flags & ~Py_TPFLAGS_READYING) | Py_TPFLAGS_READY;
...@@ -1911,6 +1923,25 @@ add_tp_new_wrapper(PyTypeObject *type) ...@@ -1911,6 +1923,25 @@ add_tp_new_wrapper(PyTypeObject *type)
return PyDict_SetItemString(type->tp_defined, "__new__", func); 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 /* This function is called by PyType_Ready() to populate the type's
dictionary with method descriptors for function slots. For each dictionary with method descriptors for function slots. For each
function slot (like tp_repr) that's defined in the type, one or function slot (like tp_repr) that's defined in the type, one or
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment