[Python-checkins] CVS: python/dist/src/Objects descrobject.c,1.1.2.5,1.1.2.6 floatobject.c,2.81,2.81.6.1 intobject.c,2.56,2.56.6.1 longobject.c,1.71,1.71.6.1 typeobject.c,2.16.8.4,2.16.8.5

Guido van Rossum gvanrossum@users.sourceforge.net
Sun, 29 Apr 2001 18:14:58 -0700


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

Modified Files:
      Tag: descr-branch
	descrobject.c floatobject.c intobject.c longobject.c 
	typeobject.c 
Log Message:
Redoing the special-methods code so that the __foo__ wrapper for type
X actually contains a reference to the function in X's tp_foo slot,
rather than simply calling PyObject_Foo().  This will make overriding
__foo__ with a Python function easier, once I get to that.

This isn't completely done, but many things work,
e.g. type(1).__add__(3, 4).



Index: descrobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/Attic/descrobject.c,v
retrieving revision 1.1.2.5
retrieving revision 1.1.2.6
diff -C2 -r1.1.2.5 -r1.1.2.6
*** descrobject.c	2001/04/29 14:53:55	1.1.2.5
--- descrobject.c	2001/04/30 01:14:56	1.1.2.6
***************
*** 4,7 ****
--- 4,12 ----
  #include "structmember.h" /* Why is this not included in Python.h? */
  
+ struct wrapperdescr {
+ 	struct wrapperbase *base;
+ 	void *wrapped; /* This can be any function pointer */
+ };
+ 
  /* Descriptor object */
  struct PyDescrObject {
***************
*** 13,16 ****
--- 18,22 ----
  		struct memberlist *d_member;
  		struct getsetlist *d_getset;
+ 		struct wrapperdescr d_wrapper;
  	} d_union;
  };
***************
*** 21,24 ****
--- 27,31 ----
  #define DF_MEMBER	2
  #define DF_GETSET	3
+ #define DF_WRAPPER	4
  
  static void
***************
*** 38,41 ****
--- 45,50 ----
  	case DF_GETSET:
  		return descr->d_union.d_getset->name;
+ 	case DF_WRAPPER:
+ 		return descr->d_union.d_wrapper.base->name;
  	default:
  		return NULL;
***************
*** 72,75 ****
--- 81,90 ----
  			descr->d_type->tp_name);
  		break;
+ 	case DF_WRAPPER:
+ 		sprintf(buffer,
+ 			"<wrapper '%.300s' of '%.100s' objects>",
+ 			descr->d_union.d_wrapper.base->name,
+ 			descr->d_type->tp_name);
+ 		break;
  	default:
  		sprintf(buffer, "<flavor %d attribute of '%.100s' objects>",
***************
*** 83,96 ****
  
  static PyObject *
! descr_get(PyObject *d, PyObject *obj)
  {
! 	PyDescrObject *descr;
! 
! 	if (obj == NULL || !PyDescr_Check(d)) {
! 		Py_INCREF(d);
! 		return d;
  	}
- 
- 	descr = (PyDescrObject *)d;
   
  	if (!PyObject_IsInstance(obj, (PyObject *)(descr->d_type))) {
--- 98,107 ----
  
  static PyObject *
! descr_get(PyDescrObject *descr, PyObject *obj)
  {
! 	if (obj == NULL) {
! 		Py_INCREF(descr);
! 		return (PyObject *)descr;
  	}
   
  	if (!PyObject_IsInstance(obj, (PyObject *)(descr->d_type))) {
***************
*** 118,121 ****
--- 129,135 ----
  				obj, descr->d_union.d_getset->closure);
  
+ 	case DF_WRAPPER:
+ 		return PyWrapper_New(descr, obj);
+ 
  	}
  
***************
*** 128,137 ****
  
  int
! descr_set(PyObject *d, PyObject *obj, PyObject *value)
  {
- 	PyDescrObject *descr = (PyDescrObject *)d;
- 
- 	assert(PyDescr_Check(d));
- 
  	if (!PyObject_IsInstance(obj, (PyObject *)(descr->d_type))) {
  		PyErr_Format(PyExc_TypeError,
--- 142,147 ----
  
  int
! descr_set(PyDescrObject *descr, PyObject *obj, PyObject *value)
  {
  	if (!PyObject_IsInstance(obj, (PyObject *)(descr->d_type))) {
  		PyErr_Format(PyExc_TypeError,
***************
*** 206,219 ****
  	}
  
! 	if (descr->d_flavor == DF_METHOD) {
  		PyObject *func, *result;
! 		func = PyCFunction_New(descr->d_union.d_method, self);
  		if (func == NULL)
  			return NULL;
  		args = PyTuple_GetSlice(args, 1, argc);
! 		if (args == NULL)
  			return NULL;
  		result = PyEval_CallObjectWithKeywords(func, args, kwds);
  		Py_DECREF(args);
  		return result;
  	}
--- 216,235 ----
  	}
  
! 	if (descr->d_flavor == DF_METHOD || descr->d_flavor == DF_WRAPPER) {
  		PyObject *func, *result;
! 		if (descr->d_flavor == DF_METHOD)
! 			func = PyCFunction_New(descr->d_union.d_method, self);
! 		else
! 			func = PyWrapper_New(descr, self);
  		if (func == NULL)
  			return NULL;
  		args = PyTuple_GetSlice(args, 1, argc);
! 		if (args == NULL) {
! 			Py_DECREF(func);
  			return NULL;
+ 		}
  		result = PyEval_CallObjectWithKeywords(func, args, kwds);
  		Py_DECREF(args);
+ 		Py_DECREF(func);
  		return result;
  	}
***************
*** 231,238 ****
  
  	if (argc == 1)
! 		return descr_get((PyObject *)descr, self);
  	if (argc == 2) {
  		PyObject *value = PyTuple_GET_ITEM(args, 1);
! 		if (descr_set((PyObject *)descr, self, value) < 0)
  			return NULL;
  		Py_INCREF(Py_None);
--- 247,254 ----
  
  	if (argc == 1)
! 		return descr_get(descr, self);
  	if (argc == 2) {
  		PyObject *value = PyTuple_GET_ITEM(args, 1);
! 		if (descr_set(descr, self, value) < 0)
  			return NULL;
  		Py_INCREF(Py_None);
***************
*** 245,249 ****
  
  static PyObject *
! descr_get_api(PyObject *descr, PyObject *args)
  {
  	PyObject *obj;
--- 261,265 ----
  
  static PyObject *
! descr_get_api(PyDescrObject *descr, PyObject *args)
  {
  	PyObject *obj;
***************
*** 255,259 ****
  
  static PyObject *
! descr_set_api(PyObject *descr, PyObject *args)
  {
  	PyObject *obj, *val;
--- 271,275 ----
  
  static PyObject *
! descr_set_api(PyDescrObject *descr, PyObject *args)
  {
  	PyObject *obj, *val;
***************
*** 398,405 ****
  	PyDescrObject *descr = PyDescr_New(type);
  
! 	if (descr == NULL)
! 		return NULL;
! 	descr->d_union.d_method = method;
! 	descr->d_flavor = DF_METHOD;
  	return (PyObject *)descr;
  }
--- 414,421 ----
  	PyDescrObject *descr = PyDescr_New(type);
  
! 	if (descr != NULL) {
! 		descr->d_union.d_method = method;
! 		descr->d_flavor = DF_METHOD;
! 	}
  	return (PyObject *)descr;
  }
***************
*** 410,417 ****
  	PyDescrObject *descr = PyDescr_New(type);
  
! 	if (descr == NULL)
! 		return NULL;
! 	descr->d_union.d_member = member;
! 	descr->d_flavor = DF_MEMBER;
  	return (PyObject *)descr;
  }
--- 426,433 ----
  	PyDescrObject *descr = PyDescr_New(type);
  
! 	if (descr != NULL) {
! 		descr->d_union.d_member = member;
! 		descr->d_flavor = DF_MEMBER;
! 	}
  	return (PyObject *)descr;
  }
***************
*** 422,429 ****
  	PyDescrObject *descr = PyDescr_New(type);
  
! 	if (descr == NULL)
! 		return NULL;
! 	descr->d_union.d_getset = getset;
! 	descr->d_flavor = DF_GETSET;
  	return (PyObject *)descr;
  }
--- 438,459 ----
  	PyDescrObject *descr = PyDescr_New(type);
  
! 	if (descr != NULL) {
! 		descr->d_union.d_getset = getset;
! 		descr->d_flavor = DF_GETSET;
! 	}
! 	return (PyObject *)descr;
! }
! 
! PyObject *
! PyDescr_NewWrapper(PyTypeObject *type,
! 		   struct wrapperbase *base, void *wrapped)
! {
! 	PyDescrObject *descr = PyDescr_New(type);
! 
! 	if (descr != NULL) {
! 		descr->d_union.d_wrapper.base = base;
! 		descr->d_union.d_wrapper.wrapped = wrapped;
! 		descr->d_flavor = DF_WRAPPER;
! 	}
  	return (PyObject *)descr;
  }
***************
*** 608,610 ****
--- 638,758 ----
  	}
  	return (PyObject *)pp;
+ }
+ 
+ 
+ /* --- Wrapper object for "slot" methods --- */
+ 
+ /* This has no reason to be in this file except that adding new files is a
+    bit of a pain */
+ 
+ typedef struct {
+ 	PyObject_HEAD
+ 	PyDescrObject *descr;
+ 	PyObject *self;
+ } wrapperobject;
+ 
+ static void
+ wrapper_dealloc(wrapperobject *wp)
+ {
+ 	Py_DECREF(wp->descr);
+ 	Py_DECREF(wp->self);
+ 	PyObject_DEL(wp);
+ }
+ 
+ static PyMethodDef wrapper_methods[] = {
+ 	{0}
+ };
+ 
+ static PyObject *
+ wrapper_name(wrapperobject *wp)
+ {
+ 	char *s = wp->descr->d_union.d_wrapper.base->name;
+ 
+ 	return PyString_FromString(s);
+ }
+ 
+ static PyObject *
+ wrapper_doc(wrapperobject *wp)
+ {
+ 	char *s = wp->descr->d_union.d_wrapper.base->doc;
+ 
+ 	if (s == NULL) {
+ 		Py_INCREF(Py_None);
+ 		return Py_None;
+ 	}
+ 	else {
+ 		return PyString_FromString(s);
+ 	}
+ }
+ 
+ static struct getsetlist wrapper_getsets[] = {
+ 	{"__name__", (getter)wrapper_name},
+ 	{"__doc__", (getter)wrapper_doc},
+ 	{0}
+ };
+ 
+ static PyObject *
+ wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds)
+ {
+ 	wrapperfunc wrapper = wp->descr->d_union.d_wrapper.base->wrapper;
+ 	PyObject *self = wp->self;
+ 
+ 	return (*wrapper)(self, args, wp->descr->d_union.d_wrapper.wrapped);
+ }
+ 
+ PyTypeObject wrappertype = {
+ 	PyObject_HEAD_INIT(&PyType_Type)
+ 	0,					/* ob_size */
+ 	"method-wrapper",			/* tp_name */
+ 	sizeof(wrapperobject),			/* tp_basicsize */
+ 	0,					/* tp_itemsize */
+ 	/* methods */
+ 	(destructor)wrapper_dealloc, 		/* tp_dealloc */
+ 	0,					/* tp_print */
+ 	0,					/* tp_getattr */
+ 	0,					/* tp_setattr */
+ 	0,					/* tp_compare */
+ 	0,					/* tp_repr */
+ 	0,					/* tp_as_number */
+ 	0,					/* tp_as_sequence */
+ 	0,		       			/* tp_as_mapping */
+ 	0,					/* tp_hash */
+ 	(ternaryfunc)wrapper_call,		/* tp_call */
+ 	0,					/* tp_str */
+ 	PyGeneric_GetAttr,			/* tp_getattro */
+ 	0,					/* tp_setattro */
+ 	0,					/* tp_as_buffer */
+ 	Py_TPFLAGS_DEFAULT,			/* tp_flags */
+  	0,					/* tp_doc */
+  	0,					/* tp_traverse */
+  	0,					/* tp_clear */
+ 	0,					/* tp_richcompare */
+ 	0,					/* tp_weaklistoffset */
+ 	0,					/* tp_iter */
+ 	0,					/* tp_iternext */
+ 	wrapper_methods,			/* tp_methods */
+ 	0,					/* tp_members */
+ 	wrapper_getsets,			/* tp_getset */
+ 	0,					/* tp_base */
+ 	0,					/* tp_dict */
+ 	0,					/* tp_descr_get */
+ 	0,					/* tp_descr_set */
+ };
+ 
+ PyObject *
+ PyWrapper_New(PyDescrObject *descr, PyObject *self)
+ {
+ 	wrapperobject *wp;
+ 
+ 	assert(descr->d_flavor == DF_WRAPPER);
+ 	assert(PyObject_IsInstance(self, (PyObject *)(descr->d_type)));
+ 
+ 	wp = PyObject_NEW(wrapperobject, &wrappertype);
+ 	if (wp != NULL) {
+ 		Py_INCREF(descr);
+ 		wp->descr = descr;
+ 		Py_INCREF(self);
+ 		wp->self = self;
+ 	}
+ 	return (PyObject *)wp;
  }

Index: floatobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/floatobject.c,v
retrieving revision 2.81
retrieving revision 2.81.6.1
diff -C2 -r2.81 -r2.81.6.1
*** floatobject.c	2001/03/11 08:37:29	2.81
--- floatobject.c	2001/04/30 01:14:56	2.81.6.1
***************
*** 680,687 ****
          0,			/*tp_call*/
          (reprfunc)float_str,	/*tp_str*/
! 	0,			/*tp_getattro*/
  	0,			/*tp_setattro*/
  	0,			/*tp_as_buffer*/
! 	Py_TPFLAGS_CHECKTYPES	/*tp_flags*/
  };
  
--- 680,687 ----
          0,			/*tp_call*/
          (reprfunc)float_str,	/*tp_str*/
! 	PyGeneric_GetAttr,	/* tp_getattro */
  	0,			/*tp_setattro*/
  	0,			/*tp_as_buffer*/
! 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES	/*tp_flags*/
  };
  

Index: intobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/intobject.c,v
retrieving revision 2.56
retrieving revision 2.56.6.1
diff -C2 -r2.56 -r2.56.6.1
*** intobject.c	2001/03/06 12:12:02	2.56
--- intobject.c	2001/04/30 01:14:56	2.56.6.1
***************
*** 806,813 ****
          0,			/*tp_call*/
          0,			/*tp_str*/
! 	0,			/*tp_getattro*/
  	0,			/*tp_setattro*/
  	0,			/*tp_as_buffer*/
! 	Py_TPFLAGS_CHECKTYPES	/*tp_flags*/
  };
  
--- 806,813 ----
          0,			/*tp_call*/
          0,			/*tp_str*/
! 	PyGeneric_GetAttr,	/* tp_getattro */
  	0,			/*tp_setattro*/
  	0,			/*tp_as_buffer*/
! 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES	/*tp_flags*/
  };
  

Index: longobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v
retrieving revision 1.71
retrieving revision 1.71.6.1
diff -C2 -r1.71 -r1.71.6.1
*** longobject.c	2001/01/17 15:33:18	1.71
--- longobject.c	2001/04/30 01:14:56	1.71.6.1
***************
*** 1868,1874 ****
          0,              		/*tp_call*/
          (reprfunc)long_str,		/*tp_str*/
! 	0,				/*tp_getattro*/
! 	0,				/*tp_setattro*/
! 	0,				/*tp_as_buffer*/
! 	Py_TPFLAGS_CHECKTYPES		/*tp_flags*/
  };
--- 1868,1874 ----
          0,              		/*tp_call*/
          (reprfunc)long_str,		/*tp_str*/
! 	PyGeneric_GetAttr,	/* tp_getattro */
! 	0,			/*tp_setattro*/
! 	0,			/*tp_as_buffer*/
! 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES	/*tp_flags*/
  };

Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.16.8.4
retrieving revision 2.16.8.5
diff -C2 -r2.16.8.4 -r2.16.8.5
*** typeobject.c	2001/04/29 14:53:55	2.16.8.4
--- typeobject.c	2001/04/30 01:14:56	2.16.8.5
***************
*** 18,21 ****
--- 18,27 ----
  
  static PyObject *
+ type_module(PyTypeObject *type, void *context)
+ {
+ 	return PyString_FromString("__builtin__");
+ }
+ 
+ static PyObject *
  type_dict(PyTypeObject *type, void *context)
  {
***************
*** 29,32 ****
--- 35,39 ----
  struct getsetlist type_getsets[] = {
  	{"__bases__", (getter)type_bases, NULL, NULL},
+ 	{"__module__", (getter)type_module, NULL, NULL},
  	{"__dict__",  (getter)type_dict,  NULL, NULL},
  	{0}
***************
*** 150,153 ****
--- 157,176 ----
  
  static int
+ add_wrappers(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
+ {
+ 	PyObject *dict = type->tp_dict;
+ 
+ 	for (; base->name != NULL; base++) {
+ 		PyObject *descr = PyDescr_NewWrapper(type, base, wrapped);
+ 		if (descr == NULL)
+ 			return -1;
+ 		if (PyDict_SetItemString(dict, base->name, descr) < 0)
+ 			return -1;
+ 		Py_DECREF(descr);
+ 	}
+ 	return 0;
+ }
+ 
+ static int
  add_members(PyTypeObject *type, struct memberlist *memb)
  {
***************
*** 225,336 ****
  /* Generic wrappers for overloadable 'operators' such as __getitem__ */
  
  static PyObject *
! wrap_len(PyObject *self, PyObject *args)
  {
! 	long res;
  
! 	if (!PyArg_ParseTuple(args, ":__len__"))
  		return NULL;
! 	res = PyObject_Size(self);
! 	if (res < 0 && PyErr_Occurred())
  		return NULL;
! 	return PyInt_FromLong(res);
  }
  
! static PyMethodDef tab_len[] = {
! 	{"__len__", wrap_len, METH_VARARGS, "XXX"},
  	{0}
  };
  
  static PyObject *
! wrap_add(PyObject *self, PyObject *args)
  {
  	PyObject *other;
  
! 	if (!PyArg_ParseTuple(args, "O:__add__", &other))
  		return NULL;
! 	return PyNumber_Add(self, other);
  }
  
  static PyObject *
! wrap_radd(PyObject *self, PyObject *args)
  {
  	PyObject *other;
  
! 	if (!PyArg_ParseTuple(args, "O:__radd__", &other))
  		return NULL;
! 	return PyNumber_Add(other, self);
  }
  
! static PyMethodDef tab_sq_concat[] = {
! 	{"__add__", wrap_add, METH_VARARGS, "XXX"},
! 	{"__radd__", wrap_radd, METH_VARARGS, "XXX"},
! 	{0}
! };
  
  static PyObject *
! wrap_mul(PyObject *self, PyObject *args)
  {
! 	PyObject *other;
  
! 	if (!PyArg_ParseTuple(args, "O:__mul__", &other))
  		return NULL;
! 	return PyNumber_Multiply(self, other);
  }
  
  static PyObject *
! wrap_rmul(PyObject *self, PyObject *args)
  {
! 	PyObject *other;
  
! 	if (!PyArg_ParseTuple(args, "O:__rmul__", &other))
  		return NULL;
! 	return PyNumber_Multiply(other, self);
  }
  
! static PyMethodDef tab_sq_repeat[] = {
! 	{"__mul__", wrap_mul, METH_VARARGS, "XXX"},
! 	{"__rmul__", wrap_rmul, METH_VARARGS, "XXX"},
  	{0}
  };
  
  static PyObject *
! wrap_getitem(PyObject *self, PyObject *args)
  {
! 	PyObject *key;
  
! 	if (!PyArg_ParseTuple(args, "O:__getitem__", &key))
  		return NULL;
! 	return PyObject_GetItem(self, key);
  }
  
! static PyMethodDef tab_getitem[] = {
! 	{"__getitem__", wrap_getitem, METH_VARARGS, "XXX"},
  	{0}
  };
  
  static PyObject *
! wrap_getslice(PyObject *self, PyObject *args)
  {
  	int i, j;
  
! 	if (!PyArg_ParseTuple(args, "ii:__getslice__", &i, &j))
  		return NULL;
! 	return PySequence_GetSlice(self, i, j);
  }
  
! static PyMethodDef tab_sq_slice[] = {
! 	{"__getslice__", wrap_getslice, METH_VARARGS, "XXX"},
  	{0}
  };
  
  static PyObject *
! wrap_setitem(PyObject *self, PyObject *args)
  {
! 	PyObject *key, *value;
  
! 	if (!PyArg_ParseTuple(args, "OO:__setitem__", &key, &value))
  		return NULL;
! 	if (PyObject_SetItem(self, key, value) < 0)
  		return NULL;
  	Py_INCREF(Py_None);
--- 248,470 ----
  /* Generic wrappers for overloadable 'operators' such as __getitem__ */
  
+ /* There's a wrapper *function* for each distinct function typedef used
+    for type object slots (e.g. binaryfunc, ternaryfunc, etc.).  There's a
+    wrapper *table* for each distinct operation (e.g. __len__, __add__).
+    Most tables have only one entry; the tables for binary operators have two
+    entries, one regular and one with reversed arguments. */
+ 
  static PyObject *
! wrap_inquiry(PyObject *self, PyObject *args, void *wrapped)
  {
! 	inquiry func = (inquiry)wrapped;
! 	int res;
  
! 	if (!PyArg_ParseTuple(args, ""))
  		return NULL;
! 	res = (*func)(self);
! 	if (res == -1 && PyErr_Occurred())
  		return NULL;
! 	return PyInt_FromLong((long)res);
  }
  
! static struct wrapperbase tab_len[] = {
! 	{"__len__", (wrapperfunc)wrap_inquiry, "x.__len__() <==> len(x)"},
  	{0}
  };
  
  static PyObject *
! wrap_binaryfunc(PyObject *self, PyObject *args, void *wrapped)
  {
+ 	binaryfunc func = (binaryfunc)wrapped;
  	PyObject *other;
  
! 	if (!PyArg_ParseTuple(args, "O", &other))
  		return NULL;
! 	return (*func)(self, other);
  }
  
  static PyObject *
! wrap_binaryfunc_r(PyObject *self, PyObject *args, void *wrapped)
  {
+ 	binaryfunc func = (binaryfunc)wrapped;
  	PyObject *other;
  
! 	if (!PyArg_ParseTuple(args, "O", &other))
  		return NULL;
! 	return (*func)(other, self);
  }
  
! #undef BINARY
! #define BINARY(NAME, OP) \
! static struct wrapperbase tab_##NAME[] = { \
! 	{"__" #NAME "__", \
! 	 (wrapperfunc)wrap_binaryfunc, \
! 	 "x.__" #NAME "__(y) <==> " #OP}, \
! 	{"__r" #NAME "__", \
! 	 (wrapperfunc)wrap_binaryfunc_r, \
! 	 "y.__r" #NAME "__(x) <==> " #OP}, \
! 	{0} \
! }
  
+ BINARY(add, "x+y");
+ BINARY(sub, "x-y");
+ BINARY(mul, "x*y");
+ BINARY(div, "x/y");
+ BINARY(mod, "x%y");
+ BINARY(divmod, "divmod(x,y)");
+ BINARY(lshift, "x<<y");
+ BINARY(rshift, "x>>y");
+ BINARY(and, "x&y");
+ BINARY(xor, "x^y");
+ BINARY(or, "x|y");
+ 
  static PyObject *
! wrap_ternaryfunc(PyObject *self, PyObject *args, void *wrapped)
  {
! 	ternaryfunc func = (ternaryfunc)wrapped;
! 	PyObject *other, *third;
  
! 	if (!PyArg_ParseTuple(args, "OO", &other, &third))
  		return NULL;
! 	return (*func)(self, other, third);
! }
! 
! #undef TERNARY
! #define TERNARY(NAME, OP) \
! static struct wrapperbase tab_##NAME[] = { \
! 	{"__" #NAME "__", \
! 	 (wrapperfunc)wrap_ternaryfunc, \
! 	 "x.__" #NAME "__(y, z) <==> " #OP}, \
! 	{"__r" #NAME "__", \
! 	 (wrapperfunc)wrap_ternaryfunc, \
! 	 "y.__r" #NAME "__(x, z) <==> " #OP}, \
! 	{0} \
  }
  
+ TERNARY(pow, "(x**y) % z");
+ 
+ #undef UNARY
+ #define UNARY(NAME, OP) \
+ static struct wrapperbase tab_##NAME[] = { \
+ 	{"__" #NAME "__", \
+ 	 (wrapperfunc)wrap_unaryfunc, \
+ 	 "x.__" #NAME "__() <==> " #OP}, \
+ 	{0} \
+ }
+ 
  static PyObject *
! wrap_unaryfunc(PyObject *self, PyObject *args, void *wrapped)
  {
! 	unaryfunc func = (unaryfunc)wrapped;
  
! 	if (!PyArg_ParseTuple(args, ""))
  		return NULL;
! 	return (*func)(self);
  }
+ 
+ UNARY(neg, "-x");
+ UNARY(pos, "+x");
+ UNARY(abs, "abs(x)");
+ UNARY(nonzero, "x != 0");
+ UNARY(invert, "~x");
+ UNARY(int, "int(x)");
+ UNARY(long, "long(x)");
+ UNARY(float, "float(x)");
+ UNARY(oct, "oct(x)");
+ UNARY(hex, "hex(x)");
+ 
+ #undef IBINARY
+ #define IBINARY(NAME, OP) \
+ static struct wrapperbase tab_##NAME[] = { \
+ 	{"__" #NAME "__", \
+ 	 (wrapperfunc)wrap_binaryfunc, \
+ 	 "x.__" #NAME "__(y) <==> " #OP}, \
+ 	{0} \
+ }
+ 
+ IBINARY(iadd, "x+=y");
+ IBINARY(isub, "x-=y");
+ IBINARY(imul, "x*=y");
+ IBINARY(idiv, "x/=y");
+ IBINARY(imod, "x%=y");
+ IBINARY(ilshift, "x<<=y");
+ IBINARY(irshift, "x>>=y");
+ IBINARY(iand, "x&=y");
+ IBINARY(ixor, "x^=y");
+ IBINARY(ior, "x|=y");
  
! #undef ITERNARY
! #define ITERNARY(NAME, OP) \
! static struct wrapperbase tab_##NAME[] = { \
! 	{"__" #NAME "__", \
! 	 (wrapperfunc)wrap_ternaryfunc, \
! 	 "x.__" #NAME "__(y) <==> " #OP}, \
! 	{0} \
! }
! 
! ITERNARY(ipow, "x = (x**y) % z");
! 
! static struct wrapperbase tab_getitem[] = {
! 	{"__getitem__", (wrapperfunc)wrap_binaryfunc,
! 	 "x.__getitem__(y) <==> x[y]"},
  	{0}
  };
  
  static PyObject *
! wrap_intargfunc(PyObject *self, PyObject *args, void *wrapped)
  {
! 	intargfunc func = (intargfunc)wrapped;
! 	int i;
  
! 	if (!PyArg_ParseTuple(args, "i", &i))
  		return NULL;
! 	return (*func)(self, i);
  }
+ 
+ static struct wrapperbase tab_mul_int[] = {
+ 	{"__mul__", (wrapperfunc)wrap_intargfunc, "x.__mul__(n) <==> x*n"},
+ 	{"__rmul__", (wrapperfunc)wrap_intargfunc, "x.__rmul__(n) <==> n*x"},
+ 	{0}
+ };
+ 
+ static struct wrapperbase tab_imul_int[] = {
+ 	{"__imul__", (wrapperfunc)wrap_intargfunc, "x.__imul__(n) <==> x*=n"},
+ 	{0}
+ };
  
! static struct wrapperbase tab_getitem_int[] = {
! 	{"__getitem__", (wrapperfunc)wrap_intargfunc,
! 	 "x.__getitem__(i) <==> x[i]"},
  	{0}
  };
  
  static PyObject *
! wrap_intintargfunc(PyObject *self, PyObject *args, void *wrapped)
  {
+ 	intintargfunc func = (intintargfunc)wrapped;
  	int i, j;
  
! 	if (!PyArg_ParseTuple(args, "ii", &i, &j))
  		return NULL;
! 	return (*func)(self, i, j);
  }
  
! static struct wrapperbase tab_getslice[] = {
! 	{"__getslice__", (wrapperfunc)wrap_intintargfunc,
! 	 "x.__getslice__(i, j) <==> x[i:j]"},
  	{0}
  };
  
  static PyObject *
! wrap_intobjargproc(PyObject *self, PyObject *args, void *wrapped)
  {
! 	intobjargproc func = (intobjargproc)wrapped;
! 	int i, res;
! 	PyObject *value;
  
! 	if (!PyArg_ParseTuple(args, "iO", &i, &value))
  		return NULL;
! 	res = (*func)(self, i, value);
! 	if (res == -1 && PyErr_Occurred())
  		return NULL;
  	Py_INCREF(Py_None);
***************
*** 338,355 ****
  }
  
! static PyMethodDef tab_setitem[] = {
! 	{"__setitem__", wrap_setitem, METH_VARARGS, "XXX"},
  	{0}
  };
  
  static PyObject *
! wrap_setslice(PyObject *self, PyObject *args)
  {
! 	int i, j;
  	PyObject *value;
  
! 	if (!PyArg_ParseTuple(args, "iiO:__setslice__", &i, &j, &value))
  		return NULL;
! 	if (PySequence_SetSlice(self, i, j, value) < 0)
  		return NULL;
  	Py_INCREF(Py_None);
--- 472,492 ----
  }
  
! static struct wrapperbase tab_setitem_int[] = {
! 	{"__setitem__", (wrapperfunc)wrap_intobjargproc,
! 	 "x.__setitem__(i, y) <==> x[i]=y"},
  	{0}
  };
  
  static PyObject *
! wrap_intintobjargproc(PyObject *self, PyObject *args, void *wrapped)
  {
! 	intintobjargproc func = (intintobjargproc)wrapped;
! 	int i, j, res;
  	PyObject *value;
  
! 	if (!PyArg_ParseTuple(args, "iiO", &i, &j, &value))
  		return NULL;
! 	res = (*func)(self, i, j, value);
! 	if (res == -1 && PyErr_Occurred())
  		return NULL;
  	Py_INCREF(Py_None);
***************
*** 357,411 ****
  }
  
! static PyMethodDef tab_setslice[] = {
! 	{"__setslice__", wrap_setslice, METH_VARARGS, "XXX"},
  	{0}
  };
  
  static PyObject *
! wrap_contains(PyObject *self, PyObject *args)
  {
  	PyObject *value;
- 	long res;
  
! 	if (!PyArg_ParseTuple(args, "O:__contains__", &value))
  		return NULL;
! 	res = PySequence_Contains(self, value);
! 	if (res < 0 && PyErr_Occurred())
  		return NULL;
! 	return PyInt_FromLong(res);
  }
  
! static PyMethodDef tab_contains[] = {
! 	{"__contains__", wrap_contains, METH_VARARGS, "XXX"},
  	{0}
  };
- 
  static PyObject *
! wrap_iadd(PyObject *self, PyObject *args)
  {
! 	PyObject *other;
  
! 	if (!PyArg_ParseTuple(args, "O:__iadd__", &other))
  		return NULL;
! 	return PyNumber_InPlaceAdd(self, other);
! }
! 
! static PyMethodDef tab_iadd[] = {
! 	{"__iadd__", wrap_iadd, METH_VARARGS, "XXX"},
! 	{0}
! };
! 
! static PyObject *
! wrap_imul(PyObject *self, PyObject *args)
! {
! 	PyObject *other;
! 
! 	if (!PyArg_ParseTuple(args, "O:__imul__", &other))
  		return NULL;
! 	return PyNumber_InPlaceMultiply(self, other);
  }
  
! static PyMethodDef tab_imul[] = {
! 	{"__imul__", wrap_imul, METH_VARARGS, "XXX"},
  	{0}
  };
--- 494,543 ----
  }
  
! static struct wrapperbase tab_setslice[] = {
! 	{"__setslice__", (wrapperfunc)wrap_intintobjargproc,
! 	 "x.__setslice__(i, j, y) <==> x[i:j]=y"},
  	{0}
  };
  
+ /* XXX objobjproc is a misnomer; should be objargpred */
  static PyObject *
! wrap_objobjproc(PyObject *self, PyObject *args, void *wrapped)
  {
+ 	objobjproc func = (objobjproc)wrapped;
+ 	int res;
  	PyObject *value;
  
! 	if (!PyArg_ParseTuple(args, "O", &value))
  		return NULL;
! 	res = (*func)(self, value);
! 	if (res == -1 && PyErr_Occurred())
  		return NULL;
! 	return PyInt_FromLong((long)res);
  }
  
! static struct wrapperbase tab_contains[] = {
! 	{"__contains__", (wrapperfunc)wrap_objobjproc,
! 	 "x.__contains__(y) <==> y in x"},
  	{0}
  };
  static PyObject *
! wrap_objobjargproc(PyObject *self, PyObject *args, void *wrapped)
  {
! 	objobjargproc func = (objobjargproc)wrapped;
! 	int res;
! 	PyObject *key, *value;
  
! 	if (!PyArg_ParseTuple(args, "OO", &key, &value))
  		return NULL;
! 	res = (*func)(self, key, value);
! 	if (res == -1 && PyErr_Occurred())
  		return NULL;
! 	Py_INCREF(Py_None);
! 	return Py_None;
  }
  
! static struct wrapperbase tab_setitem[] = {
! 	{"__setitem__", (wrapperfunc)wrap_objobjargproc,
! 	 "x.__setitem__(y, z) <==> x[y]=z"},
  	{0}
  };
***************
*** 416,424 ****
  	PySequenceMethods *sq;
  	PyMappingMethods *mp;
  
  #undef ADD
  #define ADD(SLOT, TABLE) \
  		if (SLOT) { \
! 			if (add_methods(type, TABLE) < 0) \
  				return -1; \
  		}
--- 548,557 ----
  	PySequenceMethods *sq;
  	PyMappingMethods *mp;
+ 	PyNumberMethods *nb;
  
  #undef ADD
  #define ADD(SLOT, TABLE) \
  		if (SLOT) { \
! 			if (add_wrappers(type, TABLE, SLOT) < 0) \
  				return -1; \
  		}
***************
*** 426,444 ****
  	if ((sq = type->tp_as_sequence) != NULL) {
  		ADD(sq->sq_length, tab_len);
! 		ADD(sq->sq_concat, tab_sq_concat);
! 		ADD(sq->sq_repeat, tab_sq_repeat);
! 		ADD(sq->sq_item, tab_getitem);
! 		ADD(sq->sq_slice, tab_sq_slice);
! 		ADD(sq->sq_ass_item, tab_setitem);
  		ADD(sq->sq_ass_slice, tab_setslice);
  		ADD(sq->sq_contains, tab_contains);
  		ADD(sq->sq_inplace_concat, tab_iadd);
! 		ADD(sq->sq_inplace_repeat, tab_imul);
  	}
  	if ((mp = type->tp_as_mapping) != NULL) {
! 		ADD(mp->mp_length, tab_len);
  		ADD(mp->mp_subscript, tab_getitem);
  		ADD(mp->mp_ass_subscript, tab_setitem);
  	}
  	return 0;
  }
--- 559,619 ----
  	if ((sq = type->tp_as_sequence) != NULL) {
  		ADD(sq->sq_length, tab_len);
! 		ADD(sq->sq_concat, tab_add);
! 		ADD(sq->sq_repeat, tab_mul_int);
! 		ADD(sq->sq_item, tab_getitem_int);
! 		ADD(sq->sq_slice, tab_getslice);
! 		ADD(sq->sq_ass_item, tab_setitem_int);
  		ADD(sq->sq_ass_slice, tab_setslice);
  		ADD(sq->sq_contains, tab_contains);
  		ADD(sq->sq_inplace_concat, tab_iadd);
! 		ADD(sq->sq_inplace_repeat, tab_imul_int);
  	}
+ 
  	if ((mp = type->tp_as_mapping) != NULL) {
! 		if (sq->sq_length == NULL)
! 			ADD(mp->mp_length, tab_len);
  		ADD(mp->mp_subscript, tab_getitem);
  		ADD(mp->mp_ass_subscript, tab_setitem);
  	}
+ 
+ 	if ((type->tp_flags & Py_TPFLAGS_CHECKTYPES) &&
+ 	    (nb = type->tp_as_number) != NULL) {
+ 		ADD(nb->nb_add, tab_add);
+ 		ADD(nb->nb_subtract, tab_sub);
+ 		ADD(nb->nb_multiply, tab_mul);
+ 		ADD(nb->nb_divide, tab_div);
+ 		ADD(nb->nb_remainder, tab_mod);
+ 		ADD(nb->nb_divmod, tab_divmod);
+ 		ADD(nb->nb_power, tab_pow);
+ 		ADD(nb->nb_negative, tab_neg);
+ 		ADD(nb->nb_positive, tab_pos);
+ 		ADD(nb->nb_absolute, tab_abs);
+ 		ADD(nb->nb_nonzero, tab_nonzero);
+ 		ADD(nb->nb_invert, tab_invert);
+ 		ADD(nb->nb_lshift, tab_lshift);
+ 		ADD(nb->nb_rshift, tab_rshift);
+ 		ADD(nb->nb_and, tab_and);
+ 		ADD(nb->nb_xor, tab_xor);
+ 		ADD(nb->nb_or, tab_or);
+ 		ADD(nb->nb_int, tab_int);
+ 		ADD(nb->nb_long, tab_long);
+ 		ADD(nb->nb_float, tab_float);
+ 		ADD(nb->nb_oct, tab_oct);
+ 		ADD(nb->nb_hex, tab_hex);
+ 		ADD(nb->nb_inplace_add, tab_iadd);
+ 		ADD(nb->nb_inplace_subtract, tab_isub);
+ 		ADD(nb->nb_inplace_multiply, tab_imul);
+ 		ADD(nb->nb_inplace_divide, tab_idiv);
+ 		ADD(nb->nb_inplace_remainder, tab_imod);
+ 		ADD(nb->nb_inplace_power, tab_ipow);
+ 		ADD(nb->nb_inplace_lshift, tab_ilshift);
+ 		ADD(nb->nb_inplace_rshift, tab_irshift);
+ 		ADD(nb->nb_inplace_and, tab_iand);
+ 		ADD(nb->nb_inplace_xor, tab_ixor);
+ 		ADD(nb->nb_inplace_or, tab_ior);
+ 	}
+ 
+ 	/* XXX Slots in the type object itself, e.g. tp_str, tp_repr, etc. */
+ 
  	return 0;
  }