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

Guido van Rossum gvanrossum@users.sourceforge.net
Tue, 09 Oct 2001 12:39:48 -0700


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

Modified Files:
	typeobject.c 
Log Message:
Halfway checkin.  This is still messy, but it's beginning to address
the problem that slots weren't inherited properly.  override_slots()
no longer exists; in its place comes fixup_slot_dispatchers() which
does more and different work and is table-based.  (Eventually I want
this table also to replace all the little tab_foo tables.)

Also add a wrapper for __delslice__; this required a change in
test_descrtut.py.



Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.96
retrieving revision 2.97
diff -C2 -d -r2.96 -r2.97
*** typeobject.c	2001/10/09 11:07:24	2.96
--- typeobject.c	2001/10/09 19:39:46	2.97
***************
*** 300,304 ****
  }
  
- staticforward void override_slots(PyTypeObject *type, PyObject *dict);
  staticforward PyTypeObject *solid_base(PyTypeObject *type);
  
--- 300,303 ----
***************
*** 678,681 ****
--- 677,682 ----
  staticforward void object_dealloc(PyObject *);
  staticforward int object_init(PyObject *, PyObject *, PyObject *);
+ staticforward int update_slot(PyTypeObject *, PyObject *, PyObject *);
+ staticforward void fixup_slot_dispatchers(PyTypeObject *);
  
  static PyObject *
***************
*** 1012,1018 ****
  	}
  
! 	/* Override slots that deserve it */
! 	if (!PyType_HasFeature(type, Py_TPFLAGS_DYNAMICTYPE))
! 		override_slots(type, type->tp_defined);
  
  	return (PyObject *)type;
--- 1013,1018 ----
  	}
  
! 	/* Put the proper slots in place */
! 	fixup_slot_dispatchers(type);
  
  	return (PyObject *)type;
***************
*** 1105,1111 ****
  type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
  {
! 	if (type->tp_flags & Py_TPFLAGS_DYNAMICTYPE)
! 		return PyObject_GenericSetAttr((PyObject *)type, name, value);
! 	PyErr_SetString(PyExc_TypeError, "can't set type attributes");
  	return -1;
  }
--- 1105,1114 ----
  type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
  {
! 	if (type->tp_flags & Py_TPFLAGS_DYNAMICTYPE) {
! 		if (PyObject_GenericSetAttr((PyObject *)type, name, value) < 0)
! 			return -1;
! 		return update_slot(type, name, value);
! 	}
! 	PyErr_SetString(PyExc_TypeError, "can't set static type attributes");
  	return -1;
  }
***************
*** 1858,1866 ****
  
  	/* Initialize tp_dict properly */
! 	if (PyType_HasFeature(type, Py_TPFLAGS_DYNAMICTYPE)) {
! 		/* For a dynamic type, all slots are overridden */
! 		override_slots(type, NULL);
! 	}
! 	else {
  		/* For a static type, tp_dict is the consolidation
  		   of the tp_defined of its bases in MRO. */
--- 1861,1865 ----
  
  	/* 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. */
***************
*** 1882,1885 ****
--- 1881,1896 ----
  		}
  	}
+ 	else {
+ 		/* For a dynamic type, we simply inherit the base slots. */
+ 		bases = type->tp_mro;
+ 		assert(bases != NULL);
+ 		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));
+ 			inherit_slots(type, base);
+ 		}
+ 	}
  
  	/* Some more special stuff */
***************
*** 1988,1992 ****
  		return NULL;
  	if (!(self->ob_type->tp_flags & Py_TPFLAGS_CHECKTYPES) &&
! 	    self->ob_type != other->ob_type) {
  		Py_INCREF(Py_NotImplemented);
  		return Py_NotImplemented;
--- 1999,2003 ----
  		return NULL;
  	if (!(self->ob_type->tp_flags & Py_TPFLAGS_CHECKTYPES) &&
! 	    !PyType_IsSubtype(other->ob_type, self->ob_type)) {
  		Py_INCREF(Py_NotImplemented);
  		return Py_NotImplemented;
***************
*** 2004,2008 ****
  		return NULL;
  	if (!(self->ob_type->tp_flags & Py_TPFLAGS_CHECKTYPES) &&
! 	    self->ob_type != other->ob_type) {
  		Py_INCREF(Py_NotImplemented);
  		return Py_NotImplemented;
--- 2015,2019 ----
  		return NULL;
  	if (!(self->ob_type->tp_flags & Py_TPFLAGS_CHECKTYPES) &&
! 	    !PyType_IsSubtype(other->ob_type, self->ob_type)) {
  		Py_INCREF(Py_NotImplemented);
  		return Py_NotImplemented;
***************
*** 2333,2339 ****
--- 2344,2367 ----
  }
  
+ static PyObject *
+ wrap_delslice(PyObject *self, PyObject *args, void *wrapped)
+ {
+ 	intintobjargproc func = (intintobjargproc)wrapped;
+ 	int i, j, res;
+ 
+ 	if (!PyArg_ParseTuple(args, "ii", &i, &j))
+ 		return NULL;
+ 	res = (*func)(self, i, j, NULL);
+ 	if (res == -1 && PyErr_Occurred())
+ 		return NULL;
+ 	Py_INCREF(Py_None);
+ 	return Py_None;
+ }
+ 
  static struct wrapperbase tab_setslice[] = {
  	{"__setslice__", (wrapperfunc)wrap_intintobjargproc,
  	 "x.__setslice__(i, j, y) <==> x[i:j]=y"},
+ 	{"__delslice__", (wrapperfunc)wrap_delslice,
+ 	 "x.__delslice__(i, j) <==> del x[i:j]"},
  	{0}
  };
***************
*** 2610,2614 ****
  
  static PyObject *
! wrap_descrsetfunc(PyObject *self, PyObject *args, void *wrapped)
  {
  	descrsetfunc func = (descrsetfunc)wrapped;
--- 2638,2642 ----
  
  static PyObject *
! wrap_descr_set(PyObject *self, PyObject *args, void *wrapped)
  {
  	descrsetfunc func = (descrsetfunc)wrapped;
***************
*** 2626,2630 ****
  
  static struct wrapperbase tab_descr_set[] = {
! 	{"__set__", (wrapperfunc)wrap_descrsetfunc,
  	 "descr.__set__(obj, value)"},
  	{0}
--- 2654,2658 ----
  
  static struct wrapperbase tab_descr_set[] = {
! 	{"__set__", (wrapperfunc)wrap_descr_set,
  	 "descr.__set__(obj, value)"},
  	{0}
***************
*** 3639,3769 ****
  }
  
- /* This is called at the very end of type_new() (even after
-    PyType_Ready()) to complete the initialization of dynamic types.
-    The dict argument is the dictionary argument passed to type_new(),
-    which is the local namespace of the class statement, in other
-    words, it contains the methods.  For each special method (like
-    __repr__) defined in the dictionary, the corresponding function
-    slot in the type object (like tp_repr) is set to a special function
-    whose name is 'slot_' followed by the slot name and whose signature
-    is whatever is required for that slot.  These slot functions look
-    up the corresponding method in the type's dictionary and call it.
-    The slot functions have to take care of the various peculiarities
-    of the mapping between slots and special methods, such as mapping
-    one slot to multiple methods (tp_richcompare <--> __le__, __lt__
-    etc.)  or mapping multiple slots to a single method (sq_item,
-    mp_subscript <--> __getitem__). */
  
! static void
! override_slots(PyTypeObject *type, PyObject *dict)
! {
! 	PySequenceMethods *sq = type->tp_as_sequence;
! 	PyMappingMethods *mp = type->tp_as_mapping;
! 	PyNumberMethods *nb = type->tp_as_number;
! 
! #define SQSLOT(OPNAME, SLOTNAME, FUNCNAME) \
! 	if (dict == NULL || PyDict_GetItemString(dict, OPNAME)) { \
! 		sq->SLOTNAME = FUNCNAME; \
! 	}
  
! #define MPSLOT(OPNAME, SLOTNAME, FUNCNAME) \
! 	if (dict == NULL || PyDict_GetItemString(dict, OPNAME)) { \
! 		mp->SLOTNAME = FUNCNAME; \
! 	}
  
! #define NBSLOT(OPNAME, SLOTNAME, FUNCNAME) \
! 	if (dict == NULL || PyDict_GetItemString(dict, OPNAME)) { \
! 		nb->SLOTNAME = FUNCNAME; \
! 	}
  
! #define TPSLOT(OPNAME, SLOTNAME, FUNCNAME) \
! 	if (dict == NULL || PyDict_GetItemString(dict, OPNAME)) { \
! 		type->SLOTNAME = FUNCNAME; \
! 	}
  
! 	SQSLOT("__len__", sq_length, slot_sq_length);
! 	SQSLOT("__add__", sq_concat, slot_sq_concat);
! 	SQSLOT("__mul__", sq_repeat, slot_sq_repeat);
! 	SQSLOT("__getitem__", sq_item, slot_sq_item);
! 	SQSLOT("__getslice__", sq_slice, slot_sq_slice);
! 	SQSLOT("__setitem__", sq_ass_item, slot_sq_ass_item);
! 	SQSLOT("__delitem__", sq_ass_item, slot_sq_ass_item);
! 	SQSLOT("__setslice__", sq_ass_slice, slot_sq_ass_slice);
! 	SQSLOT("__delslice__", sq_ass_slice, slot_sq_ass_slice);
! 	SQSLOT("__contains__", sq_contains, slot_sq_contains);
! 	SQSLOT("__iadd__", sq_inplace_concat, slot_sq_inplace_concat);
! 	SQSLOT("__imul__", sq_inplace_repeat, slot_sq_inplace_repeat);
  
! 	MPSLOT("__len__", mp_length, slot_mp_length);
! 	MPSLOT("__getitem__", mp_subscript, slot_mp_subscript);
! 	MPSLOT("__setitem__", mp_ass_subscript, slot_mp_ass_subscript);
! 	MPSLOT("__delitem__", mp_ass_subscript, slot_mp_ass_subscript);
  
! 	NBSLOT("__add__", nb_add, slot_nb_add);
! 	NBSLOT("__sub__", nb_subtract, slot_nb_subtract);
! 	NBSLOT("__mul__", nb_multiply, slot_nb_multiply);
! 	NBSLOT("__div__", nb_divide, slot_nb_divide);
! 	NBSLOT("__mod__", nb_remainder, slot_nb_remainder);
! 	NBSLOT("__divmod__", nb_divmod, slot_nb_divmod);
! 	NBSLOT("__pow__", nb_power, slot_nb_power);
! 	NBSLOT("__neg__", nb_negative, slot_nb_negative);
! 	NBSLOT("__pos__", nb_positive, slot_nb_positive);
! 	NBSLOT("__abs__", nb_absolute, slot_nb_absolute);
! 	NBSLOT("__nonzero__", nb_nonzero, slot_nb_nonzero);
! 	NBSLOT("__invert__", nb_invert, slot_nb_invert);
! 	NBSLOT("__lshift__", nb_lshift, slot_nb_lshift);
! 	NBSLOT("__rshift__", nb_rshift, slot_nb_rshift);
! 	NBSLOT("__and__", nb_and, slot_nb_and);
! 	NBSLOT("__xor__", nb_xor, slot_nb_xor);
! 	NBSLOT("__or__", nb_or, slot_nb_or);
! 	NBSLOT("__coerce__", nb_coerce, slot_nb_coerce);
! 	NBSLOT("__int__", nb_int, slot_nb_int);
! 	NBSLOT("__long__", nb_long, slot_nb_long);
! 	NBSLOT("__float__", nb_float, slot_nb_float);
! 	NBSLOT("__oct__", nb_oct, slot_nb_oct);
! 	NBSLOT("__hex__", nb_hex, slot_nb_hex);
! 	NBSLOT("__iadd__", nb_inplace_add, slot_nb_inplace_add);
! 	NBSLOT("__isub__", nb_inplace_subtract, slot_nb_inplace_subtract);
! 	NBSLOT("__imul__", nb_inplace_multiply, slot_nb_inplace_multiply);
! 	NBSLOT("__idiv__", nb_inplace_divide, slot_nb_inplace_divide);
! 	NBSLOT("__imod__", nb_inplace_remainder, slot_nb_inplace_remainder);
! 	NBSLOT("__ipow__", nb_inplace_power, slot_nb_inplace_power);
! 	NBSLOT("__ilshift__", nb_inplace_lshift, slot_nb_inplace_lshift);
! 	NBSLOT("__irshift__", nb_inplace_rshift, slot_nb_inplace_rshift);
! 	NBSLOT("__iand__", nb_inplace_and, slot_nb_inplace_and);
! 	NBSLOT("__ixor__", nb_inplace_xor, slot_nb_inplace_xor);
! 	NBSLOT("__ior__", nb_inplace_or, slot_nb_inplace_or);
! 	NBSLOT("__floordiv__", nb_floor_divide, slot_nb_floor_divide);
! 	NBSLOT("__truediv__", nb_true_divide, slot_nb_true_divide);
  	NBSLOT("__ifloordiv__", nb_inplace_floor_divide,
! 	       slot_nb_inplace_floor_divide);
  	NBSLOT("__itruediv__", nb_inplace_true_divide,
! 	       slot_nb_inplace_true_divide);
  
! 	if (dict == NULL ||
! 	    PyDict_GetItemString(dict, "__str__") ||
! 	    PyDict_GetItemString(dict, "__repr__"))
! 		type->tp_print = NULL;
  
! 	TPSLOT("__cmp__", tp_compare, _PyObject_SlotCompare);
! 	TPSLOT("__repr__", tp_repr, slot_tp_repr);
! 	TPSLOT("__hash__", tp_hash, slot_tp_hash);
! 	TPSLOT("__call__", tp_call, slot_tp_call);
! 	TPSLOT("__str__", tp_str, slot_tp_str);
! 	TPSLOT("__getattribute__", tp_getattro, slot_tp_getattro);
! 	TPSLOT("__getattr__", tp_getattro, slot_tp_getattr_hook);
! 	TPSLOT("__setattr__", tp_setattro, slot_tp_setattro);
! 	TPSLOT("__lt__", tp_richcompare, slot_tp_richcompare);
! 	TPSLOT("__le__", tp_richcompare, slot_tp_richcompare);
! 	TPSLOT("__eq__", tp_richcompare, slot_tp_richcompare);
! 	TPSLOT("__ne__", tp_richcompare, slot_tp_richcompare);
! 	TPSLOT("__gt__", tp_richcompare, slot_tp_richcompare);
! 	TPSLOT("__ge__", tp_richcompare, slot_tp_richcompare);
! 	TPSLOT("__iter__", tp_iter, slot_tp_iter);
! 	TPSLOT("next", tp_iternext, slot_tp_iternext);
! 	TPSLOT("__get__", tp_descr_get, slot_tp_descr_get);
! 	TPSLOT("__set__", tp_descr_set, slot_tp_descr_set);
! 	TPSLOT("__init__", tp_init, slot_tp_init);
! 	TPSLOT("__new__", tp_new, slot_tp_new);
  }
  
--- 3667,3930 ----
  }
  
  
! /* Table mapping __foo__ names to tp_foo offsets and slot_tp_foo wrapper
!    functions.  The offsets here are relative to the 'etype' structure, which
!    incorporates the additional structures used for numbers, sequences and
!    mappings.  Note that multiple names may map to the same slot (e.g. __eq__,
!    __ne__ etc. all map to tp_richcompare) and one name may map to multiple
!    slots (e.g. __str__ affects tp_str as well as tp_repr). */
  
! typedef struct {
! 	char *name;
! 	int offset;
! 	void *function;
! 	wrapperfunc wrapper;
! } slotdef;
  
! #undef TPSLOT
! #undef ETSLOT
! #undef SQSLOT
! #undef MPSLOT
! #undef NBSLOT
! #undef BINSLOT
! #undef RBINSLOT
  
! #define TPSLOT(NAME, SLOT, FUNCTION, WRAPPER) \
! 	{NAME, offsetof(PyTypeObject, SLOT), FUNCTION, WRAPPER}
! #define ETSLOT(NAME, SLOT, FUNCTION, WRAPPER) \
! 	{NAME, offsetof(etype, SLOT), FUNCTION, WRAPPER}
! #define SQSLOT(NAME, SLOT, FUNCTION, WRAPPER) \
! 	ETSLOT(NAME, as_sequence.SLOT, FUNCTION, WRAPPER)
! #define MPSLOT(NAME, SLOT, FUNCTION, WRAPPER) \
! 	ETSLOT(NAME, as_mapping.SLOT, FUNCTION, WRAPPER)
! #define NBSLOT(NAME, SLOT, FUNCTION, WRAPPER) \
! 	ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER)
! #define BINSLOT(NAME, SLOT, FUNCTION) \
! 	ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_l)
! #define RBINSLOT(NAME, SLOT, FUNCTION) \
! 	ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_r)
  
! static slotdef slotdefs[] = {
! 	SQSLOT("__len__", sq_length, slot_sq_length, wrap_inquiry),
! 	SQSLOT("__add__", sq_concat, slot_sq_concat, wrap_binaryfunc),
! 	SQSLOT("__mul__", sq_repeat, slot_sq_repeat, wrap_intargfunc),
! 	SQSLOT("__rmul__", sq_repeat, slot_sq_repeat, wrap_intargfunc),
! 	SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item),
! 	SQSLOT("__getslice__", sq_slice, slot_sq_slice, wrap_intintargfunc),
! 	SQSLOT("__setitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_setitem),
! 	SQSLOT("__delitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_delitem),
! 	SQSLOT("__setslice__", sq_ass_slice, slot_sq_ass_slice,
! 	       wrap_intintobjargproc),
! 	SQSLOT("__delslice__", sq_ass_slice, slot_sq_ass_slice, wrap_delslice),
! 	SQSLOT("__contains__", sq_contains, slot_sq_contains, wrap_objobjproc),
! 	SQSLOT("__iadd__", sq_inplace_concat, slot_sq_inplace_concat,
! 	       wrap_binaryfunc),
! 	SQSLOT("__imul__", sq_inplace_repeat, slot_sq_inplace_repeat,
! 	       wrap_intargfunc),
  
! 	MPSLOT("__len__", mp_length, slot_mp_length, wrap_inquiry),
! 	MPSLOT("__getitem__", mp_subscript, slot_mp_subscript, wrap_sq_item),
! 	MPSLOT("__setitem__", mp_ass_subscript, slot_mp_ass_subscript,
! 	       wrap_objobjargproc),
! 	MPSLOT("__delitem__", mp_ass_subscript, slot_mp_ass_subscript,
! 	       wrap_delitem),
  
! 	BINSLOT("__add__", nb_add, slot_nb_add),
! 	RBINSLOT("__radd__", nb_add, slot_nb_add),
! 	BINSLOT("__sub__", nb_subtract, slot_nb_subtract),
! 	RBINSLOT("__rsub__", nb_subtract, slot_nb_subtract),
! 	BINSLOT("__mul__", nb_multiply, slot_nb_multiply),
! 	RBINSLOT("__rmul__", nb_multiply, slot_nb_multiply),
! 	BINSLOT("__div__", nb_divide, slot_nb_divide),
! 	RBINSLOT("__rdiv__", nb_divide, slot_nb_divide),
! 	BINSLOT("__mod__", nb_remainder, slot_nb_remainder),
! 	RBINSLOT("__rmod__", nb_remainder, slot_nb_remainder),
! 	BINSLOT("__divmod__", nb_divmod, slot_nb_divmod),
! 	RBINSLOT("__rdivmod__", nb_divmod, slot_nb_divmod),
! 	NBSLOT("__pow__", nb_power, slot_nb_power, wrap_ternaryfunc),
! 	NBSLOT("__rpow__", nb_power, slot_nb_power, wrap_ternaryfunc_r),
! 	NBSLOT("__neg__", nb_negative, slot_nb_negative, wrap_unaryfunc),
! 	NBSLOT("__pos__", nb_positive, slot_nb_positive, wrap_unaryfunc),
! 	NBSLOT("__abs__", nb_absolute, slot_nb_absolute, wrap_unaryfunc),
! 	NBSLOT("__nonzero__", nb_nonzero, slot_nb_nonzero, wrap_unaryfunc),
! 	NBSLOT("__invert__", nb_invert, slot_nb_invert, wrap_unaryfunc),
! 	BINSLOT("__lshift__", nb_lshift, slot_nb_lshift),
! 	RBINSLOT("__rlshift__", nb_lshift, slot_nb_lshift),
! 	BINSLOT("__rshift__", nb_rshift, slot_nb_rshift),
! 	RBINSLOT("__rrshift__", nb_rshift, slot_nb_rshift),
! 	BINSLOT("__and__", nb_and, slot_nb_and),
! 	RBINSLOT("__rand__", nb_and, slot_nb_and),
! 	BINSLOT("__xor__", nb_xor, slot_nb_xor),
! 	RBINSLOT("__rxor__", nb_xor, slot_nb_xor),
! 	BINSLOT("__or__", nb_or, slot_nb_or),
! 	RBINSLOT("__ror__", nb_or, slot_nb_or),
! 	NBSLOT("__coerce__", nb_coerce, slot_nb_coerce, wrap_coercefunc),
! 	NBSLOT("__int__", nb_int, slot_nb_int, wrap_unaryfunc),
! 	NBSLOT("__long__", nb_long, slot_nb_long, wrap_unaryfunc),
! 	NBSLOT("__float__", nb_float, slot_nb_float, wrap_unaryfunc),
! 	NBSLOT("__oct__", nb_oct, slot_nb_oct, wrap_unaryfunc),
! 	NBSLOT("__hex__", nb_hex, slot_nb_hex, wrap_unaryfunc),
! 	NBSLOT("__iadd__", nb_inplace_add, slot_nb_inplace_add,
! 	       wrap_binaryfunc),
! 	NBSLOT("__isub__", nb_inplace_subtract, slot_nb_inplace_subtract,
! 	       wrap_binaryfunc),
! 	NBSLOT("__imul__", nb_inplace_multiply, slot_nb_inplace_multiply,
! 	       wrap_binaryfunc),
! 	NBSLOT("__idiv__", nb_inplace_divide, slot_nb_inplace_divide,
! 	       wrap_binaryfunc),
! 	NBSLOT("__imod__", nb_inplace_remainder, slot_nb_inplace_remainder,
! 	       wrap_binaryfunc),
! 	NBSLOT("__ipow__", nb_inplace_power, slot_nb_inplace_power,
! 	       wrap_ternaryfunc),
! 	NBSLOT("__ilshift__", nb_inplace_lshift, slot_nb_inplace_lshift,
! 	       wrap_binaryfunc),
! 	NBSLOT("__irshift__", nb_inplace_rshift, slot_nb_inplace_rshift,
! 	       wrap_binaryfunc),
! 	NBSLOT("__iand__", nb_inplace_and, slot_nb_inplace_and,
! 	       wrap_binaryfunc),
! 	NBSLOT("__ixor__", nb_inplace_xor, slot_nb_inplace_xor,
! 	       wrap_binaryfunc),
! 	NBSLOT("__ior__", nb_inplace_or, slot_nb_inplace_or,
! 	       wrap_binaryfunc),
! 	BINSLOT("__floordiv__", nb_floor_divide, slot_nb_floor_divide),
! 	RBINSLOT("__rfloordiv__", nb_floor_divide, slot_nb_floor_divide),
! 	BINSLOT("__truediv__", nb_true_divide, slot_nb_true_divide),
! 	RBINSLOT("__rtruediv__", nb_true_divide, slot_nb_true_divide),
  	NBSLOT("__ifloordiv__", nb_inplace_floor_divide,
! 	       slot_nb_inplace_floor_divide, wrap_binaryfunc),
  	NBSLOT("__itruediv__", nb_inplace_true_divide,
! 	       slot_nb_inplace_true_divide, wrap_binaryfunc),
  
! 	TPSLOT("__str__", tp_str, slot_tp_str, wrap_unaryfunc),
! 	TPSLOT("__str__", tp_print, NULL, NULL),
! 	TPSLOT("__repr__", tp_repr, slot_tp_repr, wrap_unaryfunc),
! 	TPSLOT("__repr__", tp_print, NULL, NULL),
! 	TPSLOT("__cmp__", tp_compare, _PyObject_SlotCompare, wrap_cmpfunc),
! 	TPSLOT("__hash__", tp_hash, slot_tp_hash, wrap_hashfunc),
! 	TPSLOT("__call__", tp_call, slot_tp_call, wrap_call),
! 	TPSLOT("__getattribute__", tp_getattro, slot_tp_getattro,
! 	       wrap_binaryfunc),
! 	TPSLOT("__getattribute__", tp_getattr, NULL, NULL),
! 	TPSLOT("__getattr__", tp_getattro, slot_tp_getattr_hook, NULL),
! 	TPSLOT("__getattr__", tp_getattr, NULL, NULL),
! 	TPSLOT("__setattr__", tp_setattro, slot_tp_setattro, wrap_setattr),
! 	TPSLOT("__setattr__", tp_setattr, NULL, NULL),
! 	TPSLOT("__delattr__", tp_setattro, slot_tp_setattro, wrap_delattr),
! 	TPSLOT("__delattr__", tp_setattr, NULL, NULL),
! 	TPSLOT("__lt__", tp_richcompare, slot_tp_richcompare, richcmp_lt),
! 	TPSLOT("__le__", tp_richcompare, slot_tp_richcompare, richcmp_le),
! 	TPSLOT("__eq__", tp_richcompare, slot_tp_richcompare, richcmp_eq),
! 	TPSLOT("__ne__", tp_richcompare, slot_tp_richcompare, richcmp_ne),
! 	TPSLOT("__gt__", tp_richcompare, slot_tp_richcompare, richcmp_gt),
! 	TPSLOT("__ge__", tp_richcompare, slot_tp_richcompare, richcmp_ge),
! 	TPSLOT("__iter__", tp_iter, slot_tp_iter, wrap_unaryfunc),
! 	TPSLOT("next", tp_iternext, slot_tp_iternext, wrap_next),
! 	TPSLOT("__get__", tp_descr_get, slot_tp_descr_get, wrap_descr_get),
! 	TPSLOT("__set__", tp_descr_set, slot_tp_descr_set, wrap_descr_set),
! 	TPSLOT("__init__", tp_init, slot_tp_init, wrap_init),
! 	TPSLOT("__new__", tp_new, slot_tp_new, NULL),
! 	{NULL}
! };
  
! static int
! update_slot(PyTypeObject *type, PyObject *name, PyObject *value)
! {
! 	char *s;
! 	int n;
! 	slotdef *p;
! 	void **ptr;
! 
! 	assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);
! 	if (value == NULL)
! 		return 0; /* Can't unset a slot */
! 	s = PyString_AsString(name);
! 	n = PyString_Size(name);
! 	if (s == NULL || n < 0) {
! 		/* Shouldn't happen, but can't be bothered */
! 		PyErr_Clear();
! 		return 0;
! 	}
! 	if (!(s[0] == '_' && s[1] == '_' && s[n-1] == '_' && s[n-2] == '_'))
! 		return 0;
! 	for (p = slotdefs; p->name; p++) {
! 		if (!strcmp(p->name, s)) {
! 			ptr = (void **) ((char *)type + p->offset);
! 			*ptr = p->function;
! 		}
! 	}
! 	return 0;
! }
! 
! static void **
! slotptr(PyTypeObject *type, int offset)
! {
! 	char *ptr;
! 
! 	assert(offset >= 0);
! 	assert(offset < offsetof(etype, as_buffer));
! 	if (offset >= offsetof(etype, as_mapping)) {
! 		ptr = (void *)type->tp_as_mapping;
! 		offset -= offsetof(etype, as_mapping);
! 	}
! 	else if (offset >= offsetof(etype, as_sequence)) {
! 		ptr = (void *)type->tp_as_sequence;
! 		offset -= offsetof(etype, as_sequence);
! 	}
! 	else if (offset >= offsetof(etype, as_number)) {
! 		ptr = (void *)type->tp_as_number;
! 		offset -= offsetof(etype, as_number);
! 	}
! 	else {
! 		ptr = (void *)type;
! 	}
! 	if (ptr != NULL)
! 		ptr += offset;
! 	return (void **)ptr;
! }
! 
! static void
! fixup_slot_dispatchers(PyTypeObject *type)
! {
! 	slotdef *p;
! 	PyObject *mro, *descr;
! 	PyTypeObject *base;
! 	PyWrapperDescrObject *d;
! 	int i, n;
! 	void **ptr;
! 
! 	for (p = slotdefs; p->name; p++) {
! 		ptr = slotptr(type, p->offset);
! 		if (ptr)
! 			*ptr = NULL;
! 	}
! 	mro = type->tp_mro;
! 	assert(PyTuple_Check(mro));
! 	n = PyTuple_GET_SIZE(mro);
! 	for (p = slotdefs; p->name; p++) {
! 		for (i = 0; i < n; i++) {
! 			base = (PyTypeObject *)PyTuple_GET_ITEM(mro, i);
! 			assert(PyType_Check(base));
! 			descr = PyDict_GetItemString(
! 				base->tp_defined, p->name);
! 			if (descr == NULL)
! 				continue;
! 			ptr = slotptr(type, p->offset);
! 			if (ptr == NULL)
! 				continue;
! 			if (descr->ob_type == &PyWrapperDescr_Type) {
! 				d = (PyWrapperDescrObject *)descr;
! 				if (d->d_base->wrapper == p->wrapper) {
! 					if (*ptr == NULL) {
! 						*ptr = d->d_wrapped;
! 						continue;
! 					}
! 					if (p->wrapper == wrap_binaryfunc_r)
! 						continue;
! 				}
! 			}
! 			*ptr = p->function;
! 			break;
! 		}
! 	}
  }