[Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.28,2.29

Guido van Rossum gvanrossum@users.sourceforge.net
Fri, 10 Aug 2001 14:24:10 -0700


Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv12100

Modified Files:
	typeobject.c 
Log Message:
- 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).


Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.28
retrieving revision 2.29
diff -C2 -d -r2.28 -r2.29
*** typeobject.c	2001/08/10 17:39:49	2.28
--- typeobject.c	2001/08/10 21:24:08	2.29
***************
*** 5,10 ****
  #include "structmember.h"
  
- staticforward int add_members(PyTypeObject *, struct memberlist *);
- 
  static struct memberlist type_members[] = {
  	{"__name__", T_STRING, offsetof(PyTypeObject, tp_name), READONLY},
--- 5,8 ----
***************
*** 648,652 ****
  	}
  	type->tp_basicsize = slotoffset;
! 	add_members(type, et->members);
  
  	/* Special case some slots */
--- 646,650 ----
  	}
  	type->tp_basicsize = slotoffset;
! 	type->tp_members = et->members;
  
  	/* Special case some slots */
***************
*** 883,887 ****
  	0,					/* tp_str */
  	PyObject_GenericGetAttr,		/* tp_getattro */
! 	0,					/* tp_setattro */
  	0,					/* tp_as_buffer */
  	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
--- 881,885 ----
  	0,					/* tp_str */
  	PyObject_GenericGetAttr,		/* tp_getattro */
! 	PyObject_GenericSetAttr,		/* tp_setattro */
  	0,					/* tp_as_buffer */
  	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
***************
*** 930,952 ****
  
  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)
  {
--- 928,931 ----
***************
*** 987,1003 ****
  }
  
! staticforward int add_operators(PyTypeObject *);
  
! static int
  inherit_slots(PyTypeObject *type, PyTypeObject *base)
  {
! 	int oldsize, newsize;
  
  #undef COPYSLOT
  #undef COPYNUM
  #undef COPYSEQ
  #undef COPYMAP
  #define COPYSLOT(SLOT) \
! 	if (!type->SLOT) type->SLOT = base->SLOT
  
  #define COPYNUM(SLOT) COPYSLOT(tp_as_number->SLOT)
--- 966,1041 ----
  }
  
! static void
! inherit_special(PyTypeObject *type, PyTypeObject *base)
! {
! 	int oldsize, newsize;
  
! 	/* 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)
  {
! 	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 && SLOTDEFINED(SLOT)) type->SLOT = base->SLOT
  
  #define COPYNUM(SLOT) COPYSLOT(tp_as_number->SLOT)
***************
*** 1005,1011 ****
  #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) {
  		COPYNUM(nb_add);
  		COPYNUM(nb_subtract);
--- 1043,1053 ----
  #define COPYMAP(SLOT) COPYSLOT(tp_as_mapping->SLOT)
  
! 	/* 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);
***************
*** 1050,1056 ****
  	}
  
! 	if (type->tp_as_sequence == NULL)
! 		type->tp_as_sequence = base->tp_as_sequence;
! 	else if (base->tp_as_sequence) {
  		COPYSEQ(sq_length);
  		COPYSEQ(sq_concat);
--- 1092,1099 ----
  	}
  
! 	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);
***************
*** 1065,1071 ****
  	}
  
! 	if (type->tp_as_mapping == NULL)
! 		type->tp_as_mapping = base->tp_as_mapping;
! 	else if (base->tp_as_mapping) {
  		COPYMAP(mp_length);
  		COPYMAP(mp_subscript);
--- 1108,1115 ----
  	}
  
! 	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);
***************
*** 1073,1115 ****
  	}
  
! 	/* 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);
  
  	COPYSLOT(tp_itemsize);
--- 1117,1121 ----
  	}
  
! 	basebase = base->tp_base;
  
  	COPYSLOT(tp_itemsize);
***************
*** 1153,1166 ****
  		COPYSLOT(tp_init);
  		COPYSLOT(tp_alloc);
- 		if (base != &PyBaseObject_Type ||
- 		    (type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
- 			COPYSLOT(tp_new);
- 		}
  		COPYSLOT(tp_free);
  	}
- 
- 	return 0;
  }
  
  int
  PyType_Ready(PyTypeObject *type)
--- 1159,1168 ----
  		COPYSLOT(tp_init);
  		COPYSLOT(tp_alloc);
  		COPYSLOT(tp_free);
  	}
  }
  
+ staticforward int add_operators(PyTypeObject *);
+ 
  int
  PyType_Ready(PyTypeObject *type)
***************
*** 1238,1249 ****
  	}
  
  	/* 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. */
  		Py_DECREF(type->tp_dict);
! 		type->tp_dict = PyDict_New();
  		if (type->tp_dict == NULL)
  			goto error;
--- 1240,1253 ----
  	}
  
+ 	/* 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. */
  		Py_DECREF(type->tp_dict);
! 		type->tp_dict = PyDict_Copy(type->tp_defined);
  		if (type->tp_dict == NULL)
  			goto error;
***************
*** 1252,1269 ****
  		assert(PyTuple_Check(bases));
  		n = PyTuple_GET_SIZE(bases);
! 		for (i = n; --i >= 0; ) {
  			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)
  				goto error;
  		}
  	}
  
! 	/* Inherit slots from direct base */
! 	if (type->tp_base != NULL)
! 		if (inherit_slots(type, type->tp_base) < 0)
! 			goto error;
  
  	assert(type->tp_dict != NULL);
  	type->tp_flags =
--- 1256,1281 ----
  		assert(PyTuple_Check(bases));
  		n = PyTuple_GET_SIZE(bases);
! 		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_Merge(type->tp_dict, x, 0) < 0)
  				goto error;
+ 			inherit_slots(type, base);
  		}
  	}
  
! 	/* 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 =
***************
*** 1910,1913 ****
--- 1922,1944 ----
  		return -1;
  	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;
  }