| 
									
										
										
										
											1991-02-19 12:39:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | /* Type object implementation */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-05-02 03:12:38 +00:00
										 |  |  | #include "Python.h"
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | #include "structmember.h"
 | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static struct memberlist type_members[] = { | 
					
						
							|  |  |  | 	{"__name__", T_STRING, offsetof(PyTypeObject, tp_name), READONLY}, | 
					
						
							|  |  |  | 	{"__basicsize__", T_INT, offsetof(PyTypeObject,tp_basicsize),READONLY}, | 
					
						
							|  |  |  | 	{"__itemsize__", T_INT, offsetof(PyTypeObject, tp_itemsize), READONLY}, | 
					
						
							|  |  |  | 	{"__flags__", T_LONG, offsetof(PyTypeObject, tp_flags), READONLY}, | 
					
						
							|  |  |  | 	{"__doc__", T_STRING, offsetof(PyTypeObject, tp_doc), READONLY}, | 
					
						
							|  |  |  | 	{"__weaklistoffset__", T_LONG, | 
					
						
							|  |  |  | 	 offsetof(PyTypeObject, tp_weaklistoffset), READONLY}, | 
					
						
							|  |  |  | 	{"__base__", T_OBJECT, offsetof(PyTypeObject, tp_base), READONLY}, | 
					
						
							|  |  |  | 	{"__dictoffset__", T_LONG, | 
					
						
							|  |  |  | 	 offsetof(PyTypeObject, tp_dictoffset), READONLY}, | 
					
						
							|  |  |  | 	{"__bases__", T_OBJECT, offsetof(PyTypeObject, tp_bases), READONLY}, | 
					
						
							|  |  |  | 	{"__mro__", T_OBJECT, offsetof(PyTypeObject, tp_mro), READONLY}, | 
					
						
							|  |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | type_module(PyTypeObject *type, void *context) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return PyString_FromString("__builtin__"); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-05-02 03:12:38 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | type_dict(PyTypeObject *type, void *context) | 
					
						
							| 
									
										
										
										
											1995-01-07 11:58:15 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	if (type->tp_dict == NULL) { | 
					
						
							| 
									
										
										
										
											1997-05-02 03:12:38 +00:00
										 |  |  | 		Py_INCREF(Py_None); | 
					
						
							|  |  |  | 		return Py_None; | 
					
						
							| 
									
										
										
										
											1995-01-07 11:58:15 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  |  	if (type->tp_flags & Py_TPFLAGS_DYNAMICTYPE) { | 
					
						
							|  |  |  | 		Py_INCREF(type->tp_dict); | 
					
						
							|  |  |  | 		return type->tp_dict; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return PyDictProxy_New(type->tp_dict); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | type_defined(PyTypeObject *type, void *context) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (type->tp_defined == NULL) { | 
					
						
							|  |  |  | 		Py_INCREF(Py_None); | 
					
						
							|  |  |  | 		return Py_None; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (type->tp_flags & Py_TPFLAGS_DYNAMICTYPE) { | 
					
						
							|  |  |  | 		Py_INCREF(type->tp_defined); | 
					
						
							|  |  |  | 		return type->tp_defined; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return PyDictProxy_New(type->tp_defined); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | type_dynamic(PyTypeObject *type, void *context) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	res = (type->tp_flags & Py_TPFLAGS_DYNAMICTYPE) ? Py_True : Py_False; | 
					
						
							|  |  |  | 	Py_INCREF(res); | 
					
						
							|  |  |  | 	return res; | 
					
						
							| 
									
										
										
										
											1995-01-07 11:58:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | struct getsetlist type_getsets[] = { | 
					
						
							|  |  |  | 	{"__module__", (getter)type_module, NULL, NULL}, | 
					
						
							|  |  |  | 	{"__dict__",  (getter)type_dict,  NULL, NULL}, | 
					
						
							|  |  |  | 	{"__defined__",  (getter)type_defined,  NULL, NULL}, | 
					
						
							|  |  |  | 	{"__dynamic__", (getter)type_dynamic, NULL, NULL}, | 
					
						
							|  |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-06-09 07:34:05 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | type_compare(PyObject *v, PyObject *w) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* This is called with type objects only. So we
 | 
					
						
							|  |  |  | 	   can just compare the addresses. */ | 
					
						
							|  |  |  | 	Py_uintptr_t vv = (Py_uintptr_t)v; | 
					
						
							|  |  |  | 	Py_uintptr_t ww = (Py_uintptr_t)w; | 
					
						
							|  |  |  | 	return (vv < ww) ? -1 : (vv > ww) ? 1 : 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-05-02 03:12:38 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | type_repr(PyTypeObject *type) | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	char buf[100]; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	sprintf(buf, "<type '%.80s'>", type->tp_name); | 
					
						
							| 
									
										
										
										
											1997-05-02 03:12:38 +00:00
										 |  |  | 	return PyString_FromString(buf); | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | type_call(PyTypeObject *type, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *obj; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (type->tp_new == NULL) { | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "cannot create '%.100s' instances", | 
					
						
							|  |  |  | 			     type->tp_name); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	obj = type->tp_new(type, args, NULL); | 
					
						
							|  |  |  | 	if (obj != NULL) { | 
					
						
							|  |  |  | 		type = obj->ob_type; | 
					
						
							|  |  |  | 		if (type->tp_init != NULL && | 
					
						
							|  |  |  | 		    type->tp_init(obj, args, kwds) < 0) { | 
					
						
							|  |  |  | 			Py_DECREF(obj); | 
					
						
							|  |  |  | 			obj = NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | PyType_GenericAlloc(PyTypeObject *type, int nitems) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int size; | 
					
						
							|  |  |  | 	void *mem; | 
					
						
							|  |  |  | 	PyObject *obj; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Inline PyObject_New() so we can zero the memory */ | 
					
						
							|  |  |  | 	size = _PyObject_VAR_SIZE(type, nitems); | 
					
						
							|  |  |  | 	mem = PyObject_MALLOC(size); | 
					
						
							|  |  |  | 	if (mem == NULL) | 
					
						
							|  |  |  | 		return PyErr_NoMemory(); | 
					
						
							|  |  |  | 	memset(mem, '\0', size); | 
					
						
							|  |  |  | 	if (PyType_IS_GC(type)) | 
					
						
							|  |  |  | 		obj = PyObject_FROM_GC(mem); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		obj = (PyObject *)mem; | 
					
						
							|  |  |  | 	if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) | 
					
						
							|  |  |  | 		Py_INCREF(type); | 
					
						
							|  |  |  | 	if (type->tp_itemsize == 0) | 
					
						
							|  |  |  | 		PyObject_INIT(obj, type); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		(void) PyObject_INIT_VAR((PyVarObject *)obj, type, nitems); | 
					
						
							|  |  |  | 	if (PyType_IS_GC(type)) | 
					
						
							|  |  |  | 		PyObject_GC_Init(obj); | 
					
						
							|  |  |  | 	return obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | PyType_GenericNew(PyTypeObject *type, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return type->tp_alloc(type, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Helper for subtyping */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | subtype_dealloc(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int dictoffset = self->ob_type->tp_dictoffset; | 
					
						
							|  |  |  | 	PyTypeObject *type, *base; | 
					
						
							|  |  |  | 	destructor f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* This exists so we can DECREF self->ob_type */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Find the nearest base with a different tp_dealloc */ | 
					
						
							|  |  |  | 	type = self->ob_type; | 
					
						
							|  |  |  | 	base = type->tp_base; | 
					
						
							|  |  |  | 	while ((f = base->tp_dealloc) == subtype_dealloc) { | 
					
						
							|  |  |  | 		base = base->tp_base; | 
					
						
							|  |  |  | 		assert(base); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* If we added a dict, DECREF it */ | 
					
						
							|  |  |  | 	if (dictoffset && !base->tp_dictoffset) { | 
					
						
							|  |  |  | 		PyObject **dictptr = (PyObject **) ((char *)self + dictoffset); | 
					
						
							|  |  |  | 		PyObject *dict = *dictptr; | 
					
						
							|  |  |  | 		if (dict != NULL) { | 
					
						
							|  |  |  | 			Py_DECREF(dict); | 
					
						
							|  |  |  | 			*dictptr = NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Finalize GC if the base doesn't do GC and we do */ | 
					
						
							|  |  |  | 	if (PyType_IS_GC(type) && !PyType_IS_GC(base)) | 
					
						
							|  |  |  | 		PyObject_GC_Fini(self); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Call the base tp_dealloc() */ | 
					
						
							|  |  |  | 	assert(f); | 
					
						
							|  |  |  | 	f(self); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Can't reference self beyond this point */ | 
					
						
							|  |  |  | 	if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { | 
					
						
							|  |  |  | 		Py_DECREF(type); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | staticforward void override_slots(PyTypeObject *type, PyObject *dict); | 
					
						
							|  |  |  | staticforward PyTypeObject *solid_base(PyTypeObject *type); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  | 	PyTypeObject type; | 
					
						
							|  |  |  | 	PyNumberMethods as_number; | 
					
						
							|  |  |  | 	PySequenceMethods as_sequence; | 
					
						
							|  |  |  | 	PyMappingMethods as_mapping; | 
					
						
							|  |  |  | 	PyBufferProcs as_buffer; | 
					
						
							|  |  |  | 	PyObject *name, *slots; | 
					
						
							|  |  |  | 	struct memberlist members[1]; | 
					
						
							|  |  |  | } etype; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* type test with subclassing support */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | PyType_IsSubtype(PyTypeObject *a, PyTypeObject *b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *mro; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mro = a->tp_mro; | 
					
						
							|  |  |  | 	if (mro != NULL) { | 
					
						
							|  |  |  | 		/* Deal with multiple inheritance without recursion
 | 
					
						
							|  |  |  | 		   by walking the MRO tuple */ | 
					
						
							|  |  |  | 		int i, n; | 
					
						
							|  |  |  | 		assert(PyTuple_Check(mro)); | 
					
						
							|  |  |  | 		n = PyTuple_GET_SIZE(mro); | 
					
						
							|  |  |  | 		for (i = 0; i < n; i++) { | 
					
						
							|  |  |  | 			if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) | 
					
						
							|  |  |  | 				return 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		/* a is not completely initilized yet; follow tp_base */ | 
					
						
							|  |  |  | 		do { | 
					
						
							|  |  |  | 			if (a == b) | 
					
						
							|  |  |  | 				return 1; | 
					
						
							|  |  |  | 			a = a->tp_base; | 
					
						
							|  |  |  | 		} while (a != NULL); | 
					
						
							|  |  |  | 		return b == &PyBaseObject_Type; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Method resolution order algorithm from "Putting Metaclasses to Work"
 | 
					
						
							|  |  |  |    by Forman and Danforth (Addison-Wesley 1999). */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | conservative_merge(PyObject *left, PyObject *right) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int left_size; | 
					
						
							|  |  |  | 	int right_size; | 
					
						
							|  |  |  | 	int i, j, r, ok; | 
					
						
							|  |  |  | 	PyObject *temp, *rr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert(PyList_Check(left)); | 
					
						
							|  |  |  | 	assert(PyList_Check(right)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   again: | 
					
						
							|  |  |  | 	left_size = PyList_GET_SIZE(left); | 
					
						
							|  |  |  | 	right_size = PyList_GET_SIZE(right); | 
					
						
							|  |  |  | 	for (i = 0; i < left_size; i++) { | 
					
						
							|  |  |  | 		for (j = 0; j < right_size; j++) { | 
					
						
							|  |  |  | 			if (PyList_GET_ITEM(left, i) == | 
					
						
							|  |  |  | 			    PyList_GET_ITEM(right, j)) { | 
					
						
							|  |  |  | 				/* found a merge point */ | 
					
						
							|  |  |  | 				temp = PyList_New(0); | 
					
						
							|  |  |  | 				if (temp == NULL) | 
					
						
							|  |  |  | 					return -1; | 
					
						
							|  |  |  | 				for (r = 0; r < j; r++) { | 
					
						
							|  |  |  | 					rr = PyList_GET_ITEM(right, r); | 
					
						
							|  |  |  | 					ok = PySequence_Contains(left, rr); | 
					
						
							|  |  |  | 					if (ok < 0) { | 
					
						
							|  |  |  | 						Py_DECREF(temp); | 
					
						
							|  |  |  | 						return -1; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					if (!ok) { | 
					
						
							|  |  |  | 						ok = PyList_Append(temp, rr); | 
					
						
							|  |  |  | 						if (ok < 0) { | 
					
						
							|  |  |  | 							Py_DECREF(temp); | 
					
						
							|  |  |  | 							return -1; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				ok = PyList_SetSlice(left, i, i, temp); | 
					
						
							|  |  |  | 				Py_DECREF(temp); | 
					
						
							|  |  |  | 				if (ok < 0) | 
					
						
							|  |  |  | 					return -1; | 
					
						
							|  |  |  | 				ok = PyList_SetSlice(right, 0, j+1, NULL); | 
					
						
							|  |  |  | 				if (ok < 0) | 
					
						
							|  |  |  | 					return -1; | 
					
						
							|  |  |  | 				goto again; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return PyList_SetSlice(left, left_size, left_size, right); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | serious_order_disagreements(PyObject *left, PyObject *right) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return 0; /* XXX later -- for now, we cheat: "don't do that" */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | mro_implementation(PyTypeObject *type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i, n, ok; | 
					
						
							|  |  |  | 	PyObject *bases, *result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bases = type->tp_bases; | 
					
						
							|  |  |  | 	n = PyTuple_GET_SIZE(bases); | 
					
						
							|  |  |  | 	result = Py_BuildValue("[O]", (PyObject *)type); | 
					
						
							|  |  |  | 	if (result == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	for (i = 0; i < n; i++) { | 
					
						
							|  |  |  | 		PyTypeObject *base = | 
					
						
							|  |  |  | 			(PyTypeObject *) PyTuple_GET_ITEM(bases, i); | 
					
						
							|  |  |  | 		PyObject *parentMRO = PySequence_List(base->tp_mro); | 
					
						
							|  |  |  | 		if (parentMRO == NULL) { | 
					
						
							|  |  |  | 			Py_DECREF(result); | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (serious_order_disagreements(result, parentMRO)) { | 
					
						
							|  |  |  | 			Py_DECREF(result); | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		ok = conservative_merge(result, parentMRO); | 
					
						
							|  |  |  | 		Py_DECREF(parentMRO); | 
					
						
							|  |  |  | 		if (ok < 0) { | 
					
						
							|  |  |  | 			Py_DECREF(result); | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | mro_external(PyObject *self, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyTypeObject *type = (PyTypeObject *)self; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyArg_ParseTuple(args, "")) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	return mro_implementation(type); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | mro_internal(PyTypeObject *type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *mro, *result, *tuple; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (type->ob_type == &PyType_Type) { | 
					
						
							|  |  |  | 		result = mro_implementation(type); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		mro = PyObject_GetAttrString((PyObject *)type, "mro"); | 
					
						
							|  |  |  | 		if (mro == NULL) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		result = PyObject_CallObject(mro, NULL); | 
					
						
							|  |  |  | 		Py_DECREF(mro); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (result == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	tuple = PySequence_Tuple(result); | 
					
						
							|  |  |  | 	Py_DECREF(result); | 
					
						
							|  |  |  | 	type->tp_mro = tuple; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Calculate the best base amongst multiple base classes.
 | 
					
						
							|  |  |  |    This is the first one that's on the path to the "solid base". */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyTypeObject * | 
					
						
							|  |  |  | best_base(PyObject *bases) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i, n; | 
					
						
							|  |  |  | 	PyTypeObject *base, *winner, *candidate, *base_i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert(PyTuple_Check(bases)); | 
					
						
							|  |  |  | 	n = PyTuple_GET_SIZE(bases); | 
					
						
							|  |  |  | 	assert(n > 0); | 
					
						
							|  |  |  | 	base = (PyTypeObject *)PyTuple_GET_ITEM(bases, 0); | 
					
						
							|  |  |  | 	winner = &PyBaseObject_Type; | 
					
						
							|  |  |  | 	for (i = 0; i < n; i++) { | 
					
						
							|  |  |  | 		base_i = (PyTypeObject *)PyTuple_GET_ITEM(bases, i); | 
					
						
							|  |  |  | 		if (!PyType_Check((PyObject *)base_i)) { | 
					
						
							|  |  |  | 			PyErr_SetString( | 
					
						
							|  |  |  | 				PyExc_TypeError, | 
					
						
							|  |  |  | 				"bases must be types"); | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (base_i->tp_dict == NULL) { | 
					
						
							| 
									
										
										
										
											2001-08-07 17:24:28 +00:00
										 |  |  | 			if (PyType_Ready(base_i) < 0) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 				return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		candidate = solid_base(base_i); | 
					
						
							|  |  |  | 		if (PyType_IsSubtype(winner, candidate)) | 
					
						
							|  |  |  | 			; | 
					
						
							|  |  |  | 		else if (PyType_IsSubtype(candidate, winner)) { | 
					
						
							|  |  |  | 			winner = candidate; | 
					
						
							|  |  |  | 			base = base_i; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			PyErr_SetString( | 
					
						
							|  |  |  | 				PyExc_TypeError, | 
					
						
							|  |  |  | 				"multiple bases have " | 
					
						
							|  |  |  | 				"instance lay-out conflict"); | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	assert(base != NULL); | 
					
						
							|  |  |  | 	return base; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | extra_ivars(PyTypeObject *type, PyTypeObject *base) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int t_size = PyType_BASICSIZE(type); | 
					
						
							|  |  |  | 	int b_size = PyType_BASICSIZE(base); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert(t_size >= b_size); /* type smaller than base! */ | 
					
						
							|  |  |  | 	if (type->tp_itemsize || base->tp_itemsize) { | 
					
						
							|  |  |  | 		/* If itemsize is involved, stricter rules */ | 
					
						
							|  |  |  | 		return t_size != b_size || | 
					
						
							|  |  |  | 			type->tp_itemsize != base->tp_itemsize; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (t_size == b_size) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	if (type->tp_dictoffset != 0 && base->tp_dictoffset == 0 && | 
					
						
							|  |  |  | 	    type->tp_dictoffset == b_size && | 
					
						
							|  |  |  | 	    (size_t)t_size == b_size + sizeof(PyObject *)) | 
					
						
							|  |  |  | 		return 0; /* "Forgive" adding a __dict__ only */ | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyTypeObject * | 
					
						
							|  |  |  | solid_base(PyTypeObject *type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyTypeObject *base; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (type->tp_base) | 
					
						
							|  |  |  | 		base = solid_base(type->tp_base); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		base = &PyBaseObject_Type; | 
					
						
							|  |  |  | 	if (extra_ivars(type, base)) | 
					
						
							|  |  |  | 		return type; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return base; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | staticforward void object_dealloc(PyObject *); | 
					
						
							|  |  |  | staticforward int object_init(PyObject *, PyObject *, PyObject *); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *name, *bases, *dict; | 
					
						
							|  |  |  | 	static char *kwlist[] = {"name", "bases", "dict", 0}; | 
					
						
							|  |  |  | 	PyObject *slots, *tmp; | 
					
						
							|  |  |  | 	PyTypeObject *type, *base, *tmptype; | 
					
						
							|  |  |  | 	etype *et; | 
					
						
							|  |  |  | 	struct memberlist *mp; | 
					
						
							|  |  |  | 	int i, nbases, nslots, slotoffset, dynamic; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (metatype == &PyType_Type && | 
					
						
							|  |  |  | 	    PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 && | 
					
						
							|  |  |  | 	    (kwds == NULL || (PyDict_Check(kwds) && PyDict_Size(kwds) == 0))) { | 
					
						
							|  |  |  | 		/* type(x) -> x.__class__ */ | 
					
						
							|  |  |  | 		PyObject *x = PyTuple_GET_ITEM(args, 0); | 
					
						
							|  |  |  | 		Py_INCREF(x->ob_type); | 
					
						
							|  |  |  | 		return (PyObject *) x->ob_type; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Check arguments */ | 
					
						
							|  |  |  | 	if (!PyArg_ParseTupleAndKeywords(args, kwds, "SO!O!:type", kwlist, | 
					
						
							|  |  |  | 					 &name, | 
					
						
							|  |  |  | 					 &PyTuple_Type, &bases, | 
					
						
							|  |  |  | 					 &PyDict_Type, &dict)) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Determine the proper metatype to deal with this,
 | 
					
						
							|  |  |  | 	   and check for metatype conflicts while we're at it. | 
					
						
							|  |  |  | 	   Note that if some other metatype wins to contract, | 
					
						
							|  |  |  | 	   it's possible that its instances are not types. */ | 
					
						
							|  |  |  | 	nbases = PyTuple_GET_SIZE(bases); | 
					
						
							|  |  |  | 	for (i = 0; i < nbases; i++) { | 
					
						
							|  |  |  | 		tmp = PyTuple_GET_ITEM(bases, i); | 
					
						
							|  |  |  | 		tmptype = tmp->ob_type; | 
					
						
							|  |  |  | 		if (PyType_IsSubtype(metatype, tmptype)) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		if (PyType_IsSubtype(tmptype, metatype)) { | 
					
						
							|  |  |  | 			metatype = tmptype; | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  | 				"metatype conflict among bases"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (metatype->tp_new != type_new) /* Pass it to the winner */ | 
					
						
							|  |  |  | 		return metatype->tp_new(metatype, args, kwds); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Adjust for empty tuple bases */ | 
					
						
							|  |  |  | 	if (nbases == 0) { | 
					
						
							|  |  |  | 		bases = Py_BuildValue("(O)", &PyBaseObject_Type); | 
					
						
							|  |  |  | 		if (bases == NULL) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		nbases = 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		Py_INCREF(bases); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* XXX From here until type is allocated, "return NULL" leaks bases! */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Calculate best base, and check that all bases are type objects */ | 
					
						
							|  |  |  | 	base = best_base(bases); | 
					
						
							|  |  |  | 	if (base == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	if (!PyType_HasFeature(base, Py_TPFLAGS_BASETYPE)) { | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "type '%.100s' is not an acceptable base type", | 
					
						
							|  |  |  | 			     base->tp_name); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Should this be a dynamic class (i.e. modifiable __dict__)? */ | 
					
						
							|  |  |  | 	tmp = PyDict_GetItemString(dict, "__dynamic__"); | 
					
						
							|  |  |  | 	if (tmp != NULL) { | 
					
						
							|  |  |  | 		/* The class author has a preference */ | 
					
						
							|  |  |  | 		dynamic = PyObject_IsTrue(tmp); | 
					
						
							|  |  |  | 		Py_DECREF(tmp); | 
					
						
							|  |  |  | 		if (dynamic < 0) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		/* Make a new class dynamic if any of its bases is dynamic.
 | 
					
						
							|  |  |  | 		   This is not always the same as inheriting the __dynamic__ | 
					
						
							|  |  |  | 		   class attribute! */ | 
					
						
							|  |  |  | 		dynamic = 0; | 
					
						
							|  |  |  | 		for (i = 0; i < nbases; i++) { | 
					
						
							|  |  |  | 			tmptype = (PyTypeObject *)PyTuple_GET_ITEM(bases, i); | 
					
						
							|  |  |  | 			if (tmptype->tp_flags & Py_TPFLAGS_DYNAMICTYPE) { | 
					
						
							|  |  |  | 				dynamic = 1; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Check for a __slots__ sequence variable in dict, and count it */ | 
					
						
							|  |  |  | 	slots = PyDict_GetItemString(dict, "__slots__"); | 
					
						
							|  |  |  | 	nslots = 0; | 
					
						
							|  |  |  | 	if (slots != NULL) { | 
					
						
							|  |  |  | 		/* Make it into a tuple */ | 
					
						
							|  |  |  | 		if (PyString_Check(slots)) | 
					
						
							|  |  |  | 			slots = Py_BuildValue("(O)", slots); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			slots = PySequence_Tuple(slots); | 
					
						
							|  |  |  | 		if (slots == NULL) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		nslots = PyTuple_GET_SIZE(slots); | 
					
						
							|  |  |  | 		for (i = 0; i < nslots; i++) { | 
					
						
							|  |  |  | 			if (!PyString_Check(PyTuple_GET_ITEM(slots, i))) { | 
					
						
							|  |  |  | 				PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  | 				"__slots__ must be a sequence of strings"); | 
					
						
							|  |  |  | 				Py_DECREF(slots); | 
					
						
							|  |  |  | 				return NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (slots == NULL && base->tp_dictoffset == 0 && | 
					
						
							|  |  |  | 	    (base->tp_setattro == PyObject_GenericSetAttr || | 
					
						
							|  |  |  | 	     base->tp_setattro == NULL)) | 
					
						
							|  |  |  | 		nslots = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* XXX From here until type is safely allocated,
 | 
					
						
							|  |  |  | 	   "return NULL" may leak slots! */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Allocate the type object */ | 
					
						
							|  |  |  | 	type = (PyTypeObject *)metatype->tp_alloc(metatype, nslots); | 
					
						
							|  |  |  | 	if (type == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Keep name and slots alive in the extended type object */ | 
					
						
							|  |  |  | 	et = (etype *)type; | 
					
						
							|  |  |  | 	Py_INCREF(name); | 
					
						
							|  |  |  | 	et->name = name; | 
					
						
							|  |  |  | 	et->slots = slots; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | 	/* Initialize tp_flags */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE | | 
					
						
							|  |  |  | 		Py_TPFLAGS_BASETYPE; | 
					
						
							|  |  |  | 	if (dynamic) | 
					
						
							|  |  |  | 		type->tp_flags |= Py_TPFLAGS_DYNAMICTYPE; | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* It's a new-style number unless it specifically inherits any
 | 
					
						
							|  |  |  | 	   old-style numeric behavior */ | 
					
						
							|  |  |  | 	if ((base->tp_flags & Py_TPFLAGS_CHECKTYPES) || | 
					
						
							|  |  |  | 	    (base->tp_as_number == NULL)) | 
					
						
							|  |  |  | 		type->tp_flags |= Py_TPFLAGS_CHECKTYPES; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Initialize essential fields */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	type->tp_as_number = &et->as_number; | 
					
						
							|  |  |  | 	type->tp_as_sequence = &et->as_sequence; | 
					
						
							|  |  |  | 	type->tp_as_mapping = &et->as_mapping; | 
					
						
							|  |  |  | 	type->tp_as_buffer = &et->as_buffer; | 
					
						
							|  |  |  | 	type->tp_name = PyString_AS_STRING(name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Set tp_base and tp_bases */ | 
					
						
							|  |  |  | 	type->tp_bases = bases; | 
					
						
							|  |  |  | 	Py_INCREF(base); | 
					
						
							|  |  |  | 	type->tp_base = base; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Initialize tp_defined from passed-in dict */ | 
					
						
							|  |  |  | 	type->tp_defined = dict = PyDict_Copy(dict); | 
					
						
							|  |  |  | 	if (dict == NULL) { | 
					
						
							|  |  |  | 		Py_DECREF(type); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Special-case __new__: if it's a plain function,
 | 
					
						
							|  |  |  | 	   make it a static function */ | 
					
						
							|  |  |  | 	tmp = PyDict_GetItemString(dict, "__new__"); | 
					
						
							|  |  |  | 	if (tmp != NULL && PyFunction_Check(tmp)) { | 
					
						
							|  |  |  | 		tmp = PyStaticMethod_New(tmp); | 
					
						
							|  |  |  | 		if (tmp == NULL) { | 
					
						
							|  |  |  | 			Py_DECREF(type); | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		PyDict_SetItemString(dict, "__new__", tmp); | 
					
						
							|  |  |  | 		Py_DECREF(tmp); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Add descriptors for custom slots from __slots__, or for __dict__ */ | 
					
						
							|  |  |  | 	mp = et->members; | 
					
						
							|  |  |  | 	slotoffset = PyType_BASICSIZE(base); | 
					
						
							|  |  |  | 	if (slots != NULL) { | 
					
						
							|  |  |  | 		for (i = 0; i < nslots; i++, mp++) { | 
					
						
							|  |  |  | 			mp->name = PyString_AS_STRING( | 
					
						
							|  |  |  | 				PyTuple_GET_ITEM(slots, i)); | 
					
						
							|  |  |  | 			mp->type = T_OBJECT; | 
					
						
							|  |  |  | 			mp->offset = slotoffset; | 
					
						
							|  |  |  | 			slotoffset += sizeof(PyObject *); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (nslots) { | 
					
						
							|  |  |  | 		type->tp_dictoffset = slotoffset; | 
					
						
							|  |  |  | 		mp->name = "__dict__"; | 
					
						
							|  |  |  | 		mp->type = T_OBJECT; | 
					
						
							|  |  |  | 		mp->offset = slotoffset; | 
					
						
							|  |  |  | 		mp->readonly = 1; | 
					
						
							|  |  |  | 		slotoffset += sizeof(PyObject *); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	type->tp_basicsize = slotoffset; | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 	type->tp_members = et->members; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Special case some slots */ | 
					
						
							|  |  |  | 	if (type->tp_dictoffset != 0 || nslots > 0) { | 
					
						
							|  |  |  | 		if (base->tp_getattr == NULL && base->tp_getattro == NULL) | 
					
						
							|  |  |  | 			type->tp_getattro = PyObject_GenericGetAttr; | 
					
						
							|  |  |  | 		if (base->tp_setattr == NULL && base->tp_setattro == NULL) | 
					
						
							|  |  |  | 			type->tp_setattro = PyObject_GenericSetAttr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	type->tp_dealloc = subtype_dealloc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Always override allocation strategy to use regular heap */ | 
					
						
							|  |  |  | 	type->tp_alloc = PyType_GenericAlloc; | 
					
						
							|  |  |  | 	type->tp_free = _PyObject_Del; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Initialize the rest */ | 
					
						
							| 
									
										
										
										
											2001-08-07 17:24:28 +00:00
										 |  |  | 	if (PyType_Ready(type) < 0) { | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		Py_DECREF(type); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Override slots that deserve it */ | 
					
						
							|  |  |  | 	override_slots(type, type->tp_defined); | 
					
						
							| 
									
										
										
										
											2001-08-07 16:40:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	return (PyObject *)type; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Internal API to look for a name through the MRO.
 | 
					
						
							|  |  |  |    This returns a borrowed reference, and doesn't set an exception! */ | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | _PyType_Lookup(PyTypeObject *type, PyObject *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i, n; | 
					
						
							|  |  |  | 	PyObject *mro, *res, *dict; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* For static types, look in tp_dict */ | 
					
						
							|  |  |  | 	if (!(type->tp_flags & Py_TPFLAGS_DYNAMICTYPE)) { | 
					
						
							|  |  |  | 		dict = type->tp_dict; | 
					
						
							|  |  |  | 		assert(dict && PyDict_Check(dict)); | 
					
						
							|  |  |  | 		return PyDict_GetItem(dict, name); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* For dynamic types, look in tp_defined of types in MRO */ | 
					
						
							|  |  |  | 	mro = type->tp_mro; | 
					
						
							|  |  |  | 	assert(PyTuple_Check(mro)); | 
					
						
							|  |  |  | 	n = PyTuple_GET_SIZE(mro); | 
					
						
							|  |  |  | 	for (i = 0; i < n; i++) { | 
					
						
							|  |  |  | 		type = (PyTypeObject *) PyTuple_GET_ITEM(mro, i); | 
					
						
							|  |  |  | 		assert(PyType_Check(type)); | 
					
						
							|  |  |  | 		dict = type->tp_defined; | 
					
						
							|  |  |  | 		assert(dict && PyDict_Check(dict)); | 
					
						
							|  |  |  | 		res = PyDict_GetItem(dict, name); | 
					
						
							|  |  |  | 		if (res != NULL) | 
					
						
							|  |  |  | 			return res; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* This is similar to PyObject_GenericGetAttr(),
 | 
					
						
							|  |  |  |    but uses _PyType_Lookup() instead of just looking in type->tp_dict. */ | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | type_getattro(PyTypeObject *type, PyObject *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyTypeObject *metatype = type->ob_type; | 
					
						
							|  |  |  | 	PyObject *descr, *res; | 
					
						
							|  |  |  | 	descrgetfunc f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Initialize this type (we'll assume the metatype is initialized) */ | 
					
						
							|  |  |  | 	if (type->tp_dict == NULL) { | 
					
						
							| 
									
										
										
										
											2001-08-07 17:24:28 +00:00
										 |  |  | 		if (PyType_Ready(type) < 0) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 			return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Get a descriptor from the metatype */ | 
					
						
							|  |  |  | 	descr = _PyType_Lookup(metatype, name); | 
					
						
							|  |  |  | 	f = NULL; | 
					
						
							|  |  |  | 	if (descr != NULL) { | 
					
						
							|  |  |  | 		f = descr->ob_type->tp_descr_get; | 
					
						
							|  |  |  | 		if (f != NULL && PyDescr_IsData(descr)) | 
					
						
							|  |  |  | 			return f(descr, | 
					
						
							|  |  |  | 				 (PyObject *)type, (PyObject *)metatype); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Look in tp_defined of this type and its bases */ | 
					
						
							|  |  |  | 	res = _PyType_Lookup(type, name); | 
					
						
							|  |  |  | 	if (res != NULL) { | 
					
						
							|  |  |  | 		f = res->ob_type->tp_descr_get; | 
					
						
							|  |  |  | 		if (f != NULL) | 
					
						
							|  |  |  | 			return f(res, (PyObject *)NULL, (PyObject *)type); | 
					
						
							|  |  |  | 		Py_INCREF(res); | 
					
						
							|  |  |  | 		return res; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Use the descriptor from the metatype */ | 
					
						
							|  |  |  | 	if (f != NULL) { | 
					
						
							|  |  |  | 		res = f(descr, (PyObject *)type, (PyObject *)metatype); | 
					
						
							|  |  |  | 		return res; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (descr != NULL) { | 
					
						
							|  |  |  | 		Py_INCREF(descr); | 
					
						
							|  |  |  | 		return descr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Give up */ | 
					
						
							|  |  |  | 	PyErr_Format(PyExc_AttributeError, | 
					
						
							|  |  |  | 		     "type object '%.50s' has no attribute '%.400s'", | 
					
						
							|  |  |  | 		     type->tp_name, PyString_AS_STRING(name)); | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | type_dealloc(PyTypeObject *type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	etype *et; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Assert this is a heap-allocated type object */ | 
					
						
							|  |  |  | 	assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE); | 
					
						
							|  |  |  | 	et = (etype *)type; | 
					
						
							|  |  |  | 	Py_XDECREF(type->tp_base); | 
					
						
							|  |  |  | 	Py_XDECREF(type->tp_dict); | 
					
						
							|  |  |  | 	Py_XDECREF(type->tp_bases); | 
					
						
							|  |  |  | 	Py_XDECREF(type->tp_mro); | 
					
						
							|  |  |  | 	Py_XDECREF(type->tp_defined); | 
					
						
							|  |  |  | 	/* XXX more? */ | 
					
						
							|  |  |  | 	Py_XDECREF(et->name); | 
					
						
							|  |  |  | 	Py_XDECREF(et->slots); | 
					
						
							|  |  |  | 	type->ob_type->tp_free((PyObject *)type); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMethodDef type_methods[] = { | 
					
						
							|  |  |  | 	{"mro", mro_external, METH_VARARGS, | 
					
						
							|  |  |  | 	 "mro() -> list\nreturn a type's method resolution order"}, | 
					
						
							|  |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char type_doc[] = | 
					
						
							|  |  |  | "type(object) -> the object's type\n" | 
					
						
							|  |  |  | "type(name, bases, dict) -> a new type"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-05-02 03:12:38 +00:00
										 |  |  | PyTypeObject PyType_Type = { | 
					
						
							|  |  |  | 	PyObject_HEAD_INIT(&PyType_Type) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	0,					/* ob_size */ | 
					
						
							|  |  |  | 	"type",					/* tp_name */ | 
					
						
							|  |  |  | 	sizeof(etype),				/* tp_basicsize */ | 
					
						
							|  |  |  | 	sizeof(struct memberlist),		/* tp_itemsize */ | 
					
						
							|  |  |  | 	(destructor)type_dealloc,		/* tp_dealloc */ | 
					
						
							|  |  |  | 	0,					/* tp_print */ | 
					
						
							|  |  |  | 	0,			 		/* tp_getattr */ | 
					
						
							|  |  |  | 	0,					/* tp_setattr */ | 
					
						
							|  |  |  | 	type_compare,				/* tp_compare */ | 
					
						
							|  |  |  | 	(reprfunc)type_repr,			/* tp_repr */ | 
					
						
							|  |  |  | 	0,					/* tp_as_number */ | 
					
						
							|  |  |  | 	0,					/* tp_as_sequence */ | 
					
						
							|  |  |  | 	0,					/* tp_as_mapping */ | 
					
						
							|  |  |  | 	(hashfunc)_Py_HashPointer,		/* tp_hash */ | 
					
						
							|  |  |  | 	(ternaryfunc)type_call,			/* tp_call */ | 
					
						
							|  |  |  | 	0,					/* tp_str */ | 
					
						
							|  |  |  | 	(getattrofunc)type_getattro,		/* tp_getattro */ | 
					
						
							|  |  |  | 	(setattrofunc)type_setattro,		/* tp_setattro */ | 
					
						
							|  |  |  | 	0,					/* tp_as_buffer */ | 
					
						
							|  |  |  | 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | 
					
						
							|  |  |  | 	type_doc,				/* tp_doc */ | 
					
						
							|  |  |  | 	0,					/* tp_traverse */ | 
					
						
							|  |  |  | 	0,					/* tp_clear */ | 
					
						
							|  |  |  | 	0,					/* tp_richcompare */ | 
					
						
							|  |  |  | 	0,					/* tp_weaklistoffset */ | 
					
						
							|  |  |  | 	0,					/* tp_iter */ | 
					
						
							|  |  |  | 	0,					/* tp_iternext */ | 
					
						
							|  |  |  | 	type_methods,				/* tp_methods */ | 
					
						
							|  |  |  | 	type_members,				/* tp_members */ | 
					
						
							|  |  |  | 	type_getsets,				/* tp_getset */ | 
					
						
							|  |  |  | 	0,					/* tp_base */ | 
					
						
							|  |  |  | 	0,					/* tp_dict */ | 
					
						
							|  |  |  | 	0,					/* tp_descr_get */ | 
					
						
							|  |  |  | 	0,					/* tp_descr_set */ | 
					
						
							|  |  |  | 	offsetof(PyTypeObject, tp_dict),	/* tp_dictoffset */ | 
					
						
							|  |  |  | 	0,					/* tp_init */ | 
					
						
							|  |  |  | 	0,					/* tp_alloc */ | 
					
						
							|  |  |  | 	type_new,				/* tp_new */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* The base type of all types (eventually)... except itself. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | object_init(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | object_dealloc(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	self->ob_type->tp_free(self); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | object_free(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject_Del(self); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct memberlist object_members[] = { | 
					
						
							|  |  |  | 	{"__class__", T_OBJECT, offsetof(PyObject, ob_type), READONLY}, | 
					
						
							|  |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyTypeObject PyBaseObject_Type = { | 
					
						
							|  |  |  | 	PyObject_HEAD_INIT(&PyType_Type) | 
					
						
							|  |  |  |  	0,					/* ob_size */ | 
					
						
							|  |  |  | 	"object",				/* tp_name */ | 
					
						
							|  |  |  | 	sizeof(PyObject),			/* tp_basicsize */ | 
					
						
							|  |  |  | 	0,					/* tp_itemsize */ | 
					
						
							|  |  |  | 	(destructor)object_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 */ | 
					
						
							|  |  |  | 	0,					/* tp_call */ | 
					
						
							|  |  |  | 	0,					/* tp_str */ | 
					
						
							|  |  |  | 	PyObject_GenericGetAttr,		/* tp_getattro */ | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 	PyObject_GenericSetAttr,		/* tp_setattro */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	0,					/* tp_as_buffer */ | 
					
						
							|  |  |  | 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | 
					
						
							|  |  |  | 	"The most base type",			/* tp_doc */ | 
					
						
							|  |  |  | 	0,					/* tp_traverse */ | 
					
						
							|  |  |  | 	0,					/* tp_clear */ | 
					
						
							|  |  |  | 	0,					/* tp_richcompare */ | 
					
						
							|  |  |  | 	0,					/* tp_weaklistoffset */ | 
					
						
							|  |  |  | 	0,					/* tp_iter */ | 
					
						
							|  |  |  | 	0,					/* tp_iternext */ | 
					
						
							|  |  |  | 	0,					/* tp_methods */ | 
					
						
							|  |  |  | 	object_members,				/* tp_members */ | 
					
						
							|  |  |  | 	0,					/* tp_getset */ | 
					
						
							|  |  |  | 	0,					/* tp_base */ | 
					
						
							|  |  |  | 	0,					/* tp_dict */ | 
					
						
							|  |  |  | 	0,					/* tp_descr_get */ | 
					
						
							|  |  |  | 	0,					/* tp_descr_set */ | 
					
						
							|  |  |  | 	0,					/* tp_dictoffset */ | 
					
						
							|  |  |  | 	object_init,				/* tp_init */ | 
					
						
							|  |  |  | 	PyType_GenericAlloc,			/* tp_alloc */ | 
					
						
							| 
									
										
										
										
											2001-08-09 19:38:15 +00:00
										 |  |  | 	PyType_GenericNew,			/* tp_new */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	object_free,				/* tp_free */ | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Initialize the __dict__ in a type object */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | add_methods(PyTypeObject *type, PyMethodDef *meth) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *dict = type->tp_defined; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (; meth->ml_name != NULL; meth++) { | 
					
						
							|  |  |  | 		PyObject *descr; | 
					
						
							|  |  |  | 		if (PyDict_GetItemString(dict, meth->ml_name)) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		descr = PyDescr_NewMethod(type, meth); | 
					
						
							|  |  |  | 		if (descr == NULL) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		if (PyDict_SetItemString(dict,meth->ml_name,descr) < 0) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		Py_DECREF(descr); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | add_members(PyTypeObject *type, struct memberlist *memb) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *dict = type->tp_defined; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (; memb->name != NULL; memb++) { | 
					
						
							|  |  |  | 		PyObject *descr; | 
					
						
							|  |  |  | 		if (PyDict_GetItemString(dict, memb->name)) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		descr = PyDescr_NewMember(type, memb); | 
					
						
							|  |  |  | 		if (descr == NULL) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		if (PyDict_SetItemString(dict, memb->name, descr) < 0) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		Py_DECREF(descr); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | add_getset(PyTypeObject *type, struct getsetlist *gsp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *dict = type->tp_defined; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (; gsp->name != NULL; gsp++) { | 
					
						
							|  |  |  | 		PyObject *descr; | 
					
						
							|  |  |  | 		if (PyDict_GetItemString(dict, gsp->name)) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		descr = PyDescr_NewGetSet(type, gsp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (descr == NULL) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		if (PyDict_SetItemString(dict, gsp->name, descr) < 0) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		Py_DECREF(descr); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | inherit_special(PyTypeObject *type, PyTypeObject *base) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int oldsize, newsize; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 	/* 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 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | inherit_slots(PyTypeObject *type, PyTypeObject *base) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 	PyTypeObject *basebase; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | #undef SLOTDEFINED
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | #undef COPYSLOT
 | 
					
						
							|  |  |  | #undef COPYNUM
 | 
					
						
							|  |  |  | #undef COPYSEQ
 | 
					
						
							|  |  |  | #undef COPYMAP
 | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define SLOTDEFINED(SLOT) \
 | 
					
						
							|  |  |  | 	(base->SLOT != 0 && \ | 
					
						
							|  |  |  | 	 (basebase == NULL || base->SLOT != basebase->SLOT)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | #define COPYSLOT(SLOT) \
 | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 	if (!type->SLOT && SLOTDEFINED(SLOT)) type->SLOT = base->SLOT | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define COPYNUM(SLOT) COPYSLOT(tp_as_number->SLOT)
 | 
					
						
							|  |  |  | #define COPYSEQ(SLOT) COPYSLOT(tp_as_sequence->SLOT)
 | 
					
						
							|  |  |  | #define COPYMAP(SLOT) COPYSLOT(tp_as_mapping->SLOT)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 	/* 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; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		COPYNUM(nb_add); | 
					
						
							|  |  |  | 		COPYNUM(nb_subtract); | 
					
						
							|  |  |  | 		COPYNUM(nb_multiply); | 
					
						
							|  |  |  | 		COPYNUM(nb_divide); | 
					
						
							|  |  |  | 		COPYNUM(nb_remainder); | 
					
						
							|  |  |  | 		COPYNUM(nb_divmod); | 
					
						
							|  |  |  | 		COPYNUM(nb_power); | 
					
						
							|  |  |  | 		COPYNUM(nb_negative); | 
					
						
							|  |  |  | 		COPYNUM(nb_positive); | 
					
						
							|  |  |  | 		COPYNUM(nb_absolute); | 
					
						
							|  |  |  | 		COPYNUM(nb_nonzero); | 
					
						
							|  |  |  | 		COPYNUM(nb_invert); | 
					
						
							|  |  |  | 		COPYNUM(nb_lshift); | 
					
						
							|  |  |  | 		COPYNUM(nb_rshift); | 
					
						
							|  |  |  | 		COPYNUM(nb_and); | 
					
						
							|  |  |  | 		COPYNUM(nb_xor); | 
					
						
							|  |  |  | 		COPYNUM(nb_or); | 
					
						
							|  |  |  | 		COPYNUM(nb_coerce); | 
					
						
							|  |  |  | 		COPYNUM(nb_int); | 
					
						
							|  |  |  | 		COPYNUM(nb_long); | 
					
						
							|  |  |  | 		COPYNUM(nb_float); | 
					
						
							|  |  |  | 		COPYNUM(nb_oct); | 
					
						
							|  |  |  | 		COPYNUM(nb_hex); | 
					
						
							|  |  |  | 		COPYNUM(nb_inplace_add); | 
					
						
							|  |  |  | 		COPYNUM(nb_inplace_subtract); | 
					
						
							|  |  |  | 		COPYNUM(nb_inplace_multiply); | 
					
						
							|  |  |  | 		COPYNUM(nb_inplace_divide); | 
					
						
							|  |  |  | 		COPYNUM(nb_inplace_remainder); | 
					
						
							|  |  |  | 		COPYNUM(nb_inplace_power); | 
					
						
							|  |  |  | 		COPYNUM(nb_inplace_lshift); | 
					
						
							|  |  |  | 		COPYNUM(nb_inplace_rshift); | 
					
						
							|  |  |  | 		COPYNUM(nb_inplace_and); | 
					
						
							|  |  |  | 		COPYNUM(nb_inplace_xor); | 
					
						
							|  |  |  | 		COPYNUM(nb_inplace_or); | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | 		if (base->tp_flags & Py_TPFLAGS_CHECKTYPES) { | 
					
						
							|  |  |  | 			COPYNUM(nb_true_divide); | 
					
						
							|  |  |  | 			COPYNUM(nb_floor_divide); | 
					
						
							|  |  |  | 			COPYNUM(nb_inplace_true_divide); | 
					
						
							|  |  |  | 			COPYNUM(nb_inplace_floor_divide); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 	if (type->tp_as_sequence != NULL && base->tp_as_sequence != NULL) { | 
					
						
							|  |  |  | 		basebase = base->tp_base; | 
					
						
							|  |  |  | 		if (basebase->tp_as_sequence == NULL) | 
					
						
							|  |  |  | 			basebase = NULL; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		COPYSEQ(sq_length); | 
					
						
							|  |  |  | 		COPYSEQ(sq_concat); | 
					
						
							|  |  |  | 		COPYSEQ(sq_repeat); | 
					
						
							|  |  |  | 		COPYSEQ(sq_item); | 
					
						
							|  |  |  | 		COPYSEQ(sq_slice); | 
					
						
							|  |  |  | 		COPYSEQ(sq_ass_item); | 
					
						
							|  |  |  | 		COPYSEQ(sq_ass_slice); | 
					
						
							|  |  |  | 		COPYSEQ(sq_contains); | 
					
						
							|  |  |  | 		COPYSEQ(sq_inplace_concat); | 
					
						
							|  |  |  | 		COPYSEQ(sq_inplace_repeat); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 	if (type->tp_as_mapping != NULL && base->tp_as_mapping != NULL) { | 
					
						
							|  |  |  | 		basebase = base->tp_base; | 
					
						
							|  |  |  | 		if (basebase->tp_as_mapping == NULL) | 
					
						
							|  |  |  | 			basebase = NULL; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		COPYMAP(mp_length); | 
					
						
							|  |  |  | 		COPYMAP(mp_subscript); | 
					
						
							|  |  |  | 		COPYMAP(mp_ass_subscript); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 	basebase = base->tp_base; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	COPYSLOT(tp_itemsize); | 
					
						
							|  |  |  | 	COPYSLOT(tp_dealloc); | 
					
						
							|  |  |  | 	COPYSLOT(tp_print); | 
					
						
							|  |  |  | 	if (type->tp_getattr == NULL && type->tp_getattro == NULL) { | 
					
						
							|  |  |  | 		type->tp_getattr = base->tp_getattr; | 
					
						
							|  |  |  | 		type->tp_getattro = base->tp_getattro; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (type->tp_setattr == NULL && type->tp_setattro == NULL) { | 
					
						
							|  |  |  | 		type->tp_setattr = base->tp_setattr; | 
					
						
							|  |  |  | 		type->tp_setattro = base->tp_setattro; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* tp_compare see tp_richcompare */ | 
					
						
							|  |  |  | 	COPYSLOT(tp_repr); | 
					
						
							|  |  |  | 	COPYSLOT(tp_hash); | 
					
						
							|  |  |  | 	COPYSLOT(tp_call); | 
					
						
							|  |  |  | 	COPYSLOT(tp_str); | 
					
						
							|  |  |  | 	COPYSLOT(tp_as_buffer); | 
					
						
							|  |  |  | 	COPYSLOT(tp_flags); | 
					
						
							|  |  |  | 	if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_RICHCOMPARE) { | 
					
						
							|  |  |  | 		if (type->tp_compare == NULL && type->tp_richcompare == NULL) { | 
					
						
							|  |  |  | 			type->tp_compare = base->tp_compare; | 
					
						
							|  |  |  | 			type->tp_richcompare = base->tp_richcompare; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		COPYSLOT(tp_compare); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_WEAKREFS) { | 
					
						
							|  |  |  | 		COPYSLOT(tp_weaklistoffset); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_ITER) { | 
					
						
							|  |  |  | 		COPYSLOT(tp_iter); | 
					
						
							|  |  |  | 		COPYSLOT(tp_iternext); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_CLASS) { | 
					
						
							|  |  |  | 		COPYSLOT(tp_descr_get); | 
					
						
							|  |  |  | 		COPYSLOT(tp_descr_set); | 
					
						
							|  |  |  | 		COPYSLOT(tp_dictoffset); | 
					
						
							|  |  |  | 		COPYSLOT(tp_init); | 
					
						
							|  |  |  | 		COPYSLOT(tp_alloc); | 
					
						
							|  |  |  | 		COPYSLOT(tp_free); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | staticforward int add_operators(PyTypeObject *); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2001-08-07 17:24:28 +00:00
										 |  |  | PyType_Ready(PyTypeObject *type) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PyObject *dict, *bases, *x; | 
					
						
							|  |  |  | 	PyTypeObject *base; | 
					
						
							|  |  |  | 	int i, n; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-10 17:39:49 +00:00
										 |  |  | 	if (type->tp_flags & Py_TPFLAGS_READY) { | 
					
						
							|  |  |  | 		assert(type->tp_dict != NULL); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	assert((type->tp_flags & Py_TPFLAGS_READYING) == 0); | 
					
						
							|  |  |  | 	assert(type->tp_dict == NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	type->tp_flags |= Py_TPFLAGS_READYING; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Initialize tp_base (defaults to BaseObject unless that's us) */ | 
					
						
							|  |  |  | 	base = type->tp_base; | 
					
						
							|  |  |  | 	if (base == NULL && type != &PyBaseObject_Type) | 
					
						
							|  |  |  | 		base = type->tp_base = &PyBaseObject_Type; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Initialize tp_bases */ | 
					
						
							|  |  |  | 	bases = type->tp_bases; | 
					
						
							|  |  |  | 	if (bases == NULL) { | 
					
						
							|  |  |  | 		if (base == NULL) | 
					
						
							|  |  |  | 			bases = PyTuple_New(0); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			bases = Py_BuildValue("(O)", base); | 
					
						
							|  |  |  | 		if (bases == NULL) | 
					
						
							| 
									
										
										
										
											2001-08-10 17:39:49 +00:00
										 |  |  | 			goto error; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		type->tp_bases = bases; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Initialize the base class */ | 
					
						
							| 
									
										
										
										
											2001-08-06 16:50:37 +00:00
										 |  |  | 	if (base && base->tp_dict == NULL) { | 
					
						
							| 
									
										
										
										
											2001-08-07 17:24:28 +00:00
										 |  |  | 		if (PyType_Ready(base) < 0) | 
					
						
							| 
									
										
										
										
											2001-08-10 17:39:49 +00:00
										 |  |  | 			goto error; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Initialize tp_defined */ | 
					
						
							|  |  |  | 	dict = type->tp_defined; | 
					
						
							|  |  |  | 	if (dict == NULL) { | 
					
						
							|  |  |  | 		dict = PyDict_New(); | 
					
						
							|  |  |  | 		if (dict == NULL) | 
					
						
							| 
									
										
										
										
											2001-08-10 17:39:49 +00:00
										 |  |  | 			goto error; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		type->tp_defined = dict; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Add type-specific descriptors to tp_defined */ | 
					
						
							|  |  |  | 	if (add_operators(type) < 0) | 
					
						
							| 
									
										
										
										
											2001-08-10 17:39:49 +00:00
										 |  |  | 		goto error; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	if (type->tp_methods != NULL) { | 
					
						
							|  |  |  | 		if (add_methods(type, type->tp_methods) < 0) | 
					
						
							| 
									
										
										
										
											2001-08-10 17:39:49 +00:00
										 |  |  | 			goto error; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (type->tp_members != NULL) { | 
					
						
							|  |  |  | 		if (add_members(type, type->tp_members) < 0) | 
					
						
							| 
									
										
										
										
											2001-08-10 17:39:49 +00:00
										 |  |  | 			goto error; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (type->tp_getset != NULL) { | 
					
						
							|  |  |  | 		if (add_getset(type, type->tp_getset) < 0) | 
					
						
							| 
									
										
										
										
											2001-08-10 17:39:49 +00:00
										 |  |  | 			goto error; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Temporarily make tp_dict the same object as tp_defined.
 | 
					
						
							|  |  |  | 	   (This is needed to call mro(), and can stay this way for | 
					
						
							|  |  |  | 	   dynamic types). */ | 
					
						
							|  |  |  | 	Py_INCREF(type->tp_defined); | 
					
						
							|  |  |  | 	type->tp_dict = type->tp_defined; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Calculate method resolution order */ | 
					
						
							|  |  |  | 	if (mro_internal(type) < 0) { | 
					
						
							| 
									
										
										
										
											2001-08-10 17:39:49 +00:00
										 |  |  | 		goto error; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 	/* Inherit special flags from dominant base */ | 
					
						
							|  |  |  | 	if (type->tp_base != NULL) | 
					
						
							|  |  |  | 		inherit_special(type, type->tp_base); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	/* Initialize tp_dict properly */ | 
					
						
							|  |  |  | 	if (!PyType_HasFeature(type, Py_TPFLAGS_DYNAMICTYPE)) { | 
					
						
							|  |  |  | 		/* For a static type, tp_dict is the consolidation
 | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 		   of the tp_defined of its bases in MRO. */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		Py_DECREF(type->tp_dict); | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 		type->tp_dict = PyDict_Copy(type->tp_defined); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		if (type->tp_dict == NULL) | 
					
						
							| 
									
										
										
										
											2001-08-10 17:39:49 +00:00
										 |  |  | 			goto error; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		bases = type->tp_mro; | 
					
						
							|  |  |  | 		assert(bases != NULL); | 
					
						
							|  |  |  | 		assert(PyTuple_Check(bases)); | 
					
						
							|  |  |  | 		n = PyTuple_GET_SIZE(bases); | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 		for (i = 1; i < n; i++) { | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 			base = (PyTypeObject *)PyTuple_GET_ITEM(bases, i); | 
					
						
							|  |  |  | 			assert(PyType_Check(base)); | 
					
						
							|  |  |  | 			x = base->tp_defined; | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 			if (x != NULL && PyDict_Merge(type->tp_dict, x, 0) < 0) | 
					
						
							| 
									
										
										
										
											2001-08-10 17:39:49 +00:00
										 |  |  | 				goto error; | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 			inherit_slots(type, base); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 	/* 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; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 	/* All done -- set the ready flag */ | 
					
						
							| 
									
										
										
										
											2001-08-10 17:39:49 +00:00
										 |  |  | 	assert(type->tp_dict != NULL); | 
					
						
							|  |  |  | 	type->tp_flags = | 
					
						
							|  |  |  | 		(type->tp_flags & ~Py_TPFLAGS_READYING) | Py_TPFLAGS_READY; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2001-08-10 17:39:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   error: | 
					
						
							|  |  |  | 	type->tp_flags &= ~Py_TPFLAGS_READYING; | 
					
						
							|  |  |  | 	return -1; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* 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; | 
					
						
							|  |  |  | 	PyObject *third = Py_None; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Note: This wrapper only works for __pow__() */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyArg_ParseTuple(args, "O|O", &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_concat[] = { | 
					
						
							|  |  |  | 	{"__add__", (wrapperfunc)wrap_binaryfunc, "x.__add__(y) <==> x+y"}, | 
					
						
							|  |  |  | 	{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); | 
					
						
							|  |  |  | 	return Py_None; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 15:31:58 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_delitem_int(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	intobjargproc func = (intobjargproc)wrapped; | 
					
						
							|  |  |  | 	int i, res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyArg_ParseTuple(args, "i", &i)) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	res = (*func)(self, i, NULL); | 
					
						
							|  |  |  | 	if (res == -1 && PyErr_Occurred()) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	Py_INCREF(Py_None); | 
					
						
							|  |  |  | 	return Py_None; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static struct wrapperbase tab_setitem_int[] = { | 
					
						
							|  |  |  | 	{"__setitem__", (wrapperfunc)wrap_intobjargproc, | 
					
						
							|  |  |  | 	 "x.__setitem__(i, y) <==> x[i]=y"}, | 
					
						
							| 
									
										
										
										
											2001-08-02 15:31:58 +00:00
										 |  |  | 	{"__delitem__", (wrapperfunc)wrap_delitem_int, | 
					
						
							|  |  |  | 	 "x.__delitem__(y) <==> del x[y]"}, | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	{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); | 
					
						
							|  |  |  | 	return Py_None; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 15:31:58 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_delitem(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	objobjargproc func = (objobjargproc)wrapped; | 
					
						
							|  |  |  | 	int res; | 
					
						
							|  |  |  | 	PyObject *key; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyArg_ParseTuple(args, "O", &key)) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	res = (*func)(self, key, NULL); | 
					
						
							|  |  |  | 	if (res == -1 && PyErr_Occurred()) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	Py_INCREF(Py_None); | 
					
						
							|  |  |  | 	return Py_None; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static struct wrapperbase tab_setitem[] = { | 
					
						
							|  |  |  | 	{"__setitem__", (wrapperfunc)wrap_objobjargproc, | 
					
						
							|  |  |  | 	 "x.__setitem__(y, z) <==> x[y]=z"}, | 
					
						
							| 
									
										
										
										
											2001-08-02 15:31:58 +00:00
										 |  |  | 	{"__delitem__", (wrapperfunc)wrap_delitem, | 
					
						
							|  |  |  | 	 "x.__delitem__(y) <==> del x[y]"}, | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_cmpfunc(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	cmpfunc func = (cmpfunc)wrapped; | 
					
						
							|  |  |  | 	int res; | 
					
						
							|  |  |  | 	PyObject *other; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyArg_ParseTuple(args, "O", &other)) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	res = (*func)(self, other); | 
					
						
							|  |  |  | 	if (PyErr_Occurred()) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	return PyInt_FromLong((long)res); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct wrapperbase tab_cmp[] = { | 
					
						
							|  |  |  | 	{"__cmp__", (wrapperfunc)wrap_cmpfunc, | 
					
						
							|  |  |  | 	 "x.__cmp__(y) <==> cmp(x,y)"}, | 
					
						
							|  |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct wrapperbase tab_repr[] = { | 
					
						
							|  |  |  | 	{"__repr__", (wrapperfunc)wrap_unaryfunc, | 
					
						
							|  |  |  | 	 "x.__repr__() <==> repr(x)"}, | 
					
						
							|  |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct wrapperbase tab_getattr[] = { | 
					
						
							|  |  |  | 	{"__getattr__", (wrapperfunc)wrap_binaryfunc, | 
					
						
							|  |  |  | 	 "x.__getattr__('name') <==> x.name"}, | 
					
						
							|  |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_setattr(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	setattrofunc func = (setattrofunc)wrapped; | 
					
						
							|  |  |  | 	int res; | 
					
						
							|  |  |  | 	PyObject *name, *value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyArg_ParseTuple(args, "OO", &name, &value)) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	res = (*func)(self, name, value); | 
					
						
							|  |  |  | 	if (res < 0) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	Py_INCREF(Py_None); | 
					
						
							|  |  |  | 	return Py_None; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_delattr(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	setattrofunc func = (setattrofunc)wrapped; | 
					
						
							|  |  |  | 	int res; | 
					
						
							|  |  |  | 	PyObject *name; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyArg_ParseTuple(args, "O", &name)) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	res = (*func)(self, name, NULL); | 
					
						
							|  |  |  | 	if (res < 0) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	Py_INCREF(Py_None); | 
					
						
							|  |  |  | 	return Py_None; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct wrapperbase tab_setattr[] = { | 
					
						
							|  |  |  | 	{"__setattr__", (wrapperfunc)wrap_setattr, | 
					
						
							|  |  |  | 	 "x.__setattr__('name', value) <==> x.name = value"}, | 
					
						
							|  |  |  | 	{"__delattr__", (wrapperfunc)wrap_delattr, | 
					
						
							|  |  |  | 	 "x.__delattr__('name') <==> del x.name"}, | 
					
						
							|  |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_hashfunc(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hashfunc func = (hashfunc)wrapped; | 
					
						
							|  |  |  | 	long res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyArg_ParseTuple(args, "")) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	res = (*func)(self); | 
					
						
							|  |  |  | 	if (res == -1 && PyErr_Occurred()) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	return PyInt_FromLong(res); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct wrapperbase tab_hash[] = { | 
					
						
							|  |  |  | 	{"__hash__", (wrapperfunc)wrap_hashfunc, | 
					
						
							|  |  |  | 	 "x.__hash__() <==> hash(x)"}, | 
					
						
							|  |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_call(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ternaryfunc func = (ternaryfunc)wrapped; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* XXX What about keyword arguments? */ | 
					
						
							|  |  |  | 	return (*func)(self, args, NULL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct wrapperbase tab_call[] = { | 
					
						
							|  |  |  | 	{"__call__", (wrapperfunc)wrap_call, | 
					
						
							|  |  |  | 	 "x.__call__(...) <==> x(...)"}, | 
					
						
							|  |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct wrapperbase tab_str[] = { | 
					
						
							|  |  |  | 	{"__str__", (wrapperfunc)wrap_unaryfunc, | 
					
						
							|  |  |  | 	 "x.__str__() <==> str(x)"}, | 
					
						
							|  |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_richcmpfunc(PyObject *self, PyObject *args, void *wrapped, int op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	richcmpfunc func = (richcmpfunc)wrapped; | 
					
						
							|  |  |  | 	PyObject *other; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyArg_ParseTuple(args, "O", &other)) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	return (*func)(self, other, op); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef RICHCMP_WRAPPER
 | 
					
						
							|  |  |  | #define RICHCMP_WRAPPER(NAME, OP) \
 | 
					
						
							|  |  |  | static PyObject * \ | 
					
						
							|  |  |  | richcmp_##NAME(PyObject *self, PyObject *args, void *wrapped) \ | 
					
						
							|  |  |  | { \ | 
					
						
							|  |  |  | 	return wrap_richcmpfunc(self, args, wrapped, OP); \ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 15:29:49 +00:00
										 |  |  | RICHCMP_WRAPPER(lt, Py_LT) | 
					
						
							|  |  |  | RICHCMP_WRAPPER(le, Py_LE) | 
					
						
							|  |  |  | RICHCMP_WRAPPER(eq, Py_EQ) | 
					
						
							|  |  |  | RICHCMP_WRAPPER(ne, Py_NE) | 
					
						
							|  |  |  | RICHCMP_WRAPPER(gt, Py_GT) | 
					
						
							|  |  |  | RICHCMP_WRAPPER(ge, Py_GE) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #undef RICHCMP_ENTRY
 | 
					
						
							|  |  |  | #define RICHCMP_ENTRY(NAME, EXPR) \
 | 
					
						
							|  |  |  | 	{"__" #NAME "__", (wrapperfunc)richcmp_##NAME, \ | 
					
						
							|  |  |  | 	 "x.__" #NAME "__(y) <==> " EXPR} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct wrapperbase tab_richcmp[] = { | 
					
						
							|  |  |  | 	RICHCMP_ENTRY(lt, "x<y"), | 
					
						
							|  |  |  | 	RICHCMP_ENTRY(le, "x<=y"), | 
					
						
							|  |  |  | 	RICHCMP_ENTRY(eq, "x==y"), | 
					
						
							|  |  |  | 	RICHCMP_ENTRY(ne, "x!=y"), | 
					
						
							|  |  |  | 	RICHCMP_ENTRY(gt, "x>y"), | 
					
						
							|  |  |  | 	RICHCMP_ENTRY(ge, "x>=y"), | 
					
						
							|  |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct wrapperbase tab_iter[] = { | 
					
						
							|  |  |  | 	{"__iter__", (wrapperfunc)wrap_unaryfunc, "x.__iter__() <==> iter(x)"}, | 
					
						
							|  |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_next(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unaryfunc func = (unaryfunc)wrapped; | 
					
						
							|  |  |  | 	PyObject *res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyArg_ParseTuple(args, "")) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	res = (*func)(self); | 
					
						
							|  |  |  | 	if (res == NULL && !PyErr_Occurred()) | 
					
						
							|  |  |  | 		PyErr_SetNone(PyExc_StopIteration); | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct wrapperbase tab_next[] = { | 
					
						
							|  |  |  | 	{"next", (wrapperfunc)wrap_next, | 
					
						
							|  |  |  | 		"x.next() -> the next value, or raise StopIteration"}, | 
					
						
							|  |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_descr_get(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	descrgetfunc func = (descrgetfunc)wrapped; | 
					
						
							|  |  |  | 	PyObject *obj; | 
					
						
							|  |  |  | 	PyObject *type = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyArg_ParseTuple(args, "O|O", &obj, &type)) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	if (type == NULL) | 
					
						
							|  |  |  | 		type = (PyObject *)obj->ob_type; | 
					
						
							|  |  |  | 	return (*func)(self, obj, type); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct wrapperbase tab_descr_get[] = { | 
					
						
							|  |  |  | 	{"__get__", (wrapperfunc)wrap_descr_get, | 
					
						
							|  |  |  | 	 "descr.__get__(obj, type) -> value"}, | 
					
						
							|  |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_descrsetfunc(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	descrsetfunc func = (descrsetfunc)wrapped; | 
					
						
							|  |  |  | 	PyObject *obj, *value; | 
					
						
							|  |  |  | 	int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyArg_ParseTuple(args, "OO", &obj, &value)) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	ret = (*func)(self, obj, value); | 
					
						
							|  |  |  | 	if (ret < 0) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	Py_INCREF(Py_None); | 
					
						
							|  |  |  | 	return Py_None; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct wrapperbase tab_descr_set[] = { | 
					
						
							|  |  |  | 	{"__set__", (wrapperfunc)wrap_descrsetfunc, | 
					
						
							|  |  |  | 	 "descr.__set__(obj, value)"}, | 
					
						
							|  |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_init(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	initproc func = (initproc)wrapped; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* XXX What about keyword arguments? */ | 
					
						
							|  |  |  | 	if (func(self, args, NULL) < 0) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	Py_INCREF(Py_None); | 
					
						
							|  |  |  | 	return Py_None; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct wrapperbase tab_init[] = { | 
					
						
							|  |  |  | 	{"__init__", (wrapperfunc)wrap_init, | 
					
						
							|  |  |  | 	 "x.__init__(...) initializes x; " | 
					
						
							|  |  |  | 	 "see x.__type__.__doc__ for signature"}, | 
					
						
							|  |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2001-08-06 16:50:37 +00:00
										 |  |  | tp_new_wrapper(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2001-08-06 16:50:37 +00:00
										 |  |  | 	PyTypeObject *type, *subtype; | 
					
						
							|  |  |  | 	PyObject *arg0, *res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (self == NULL || !PyType_Check(self)) | 
					
						
							|  |  |  | 		Py_FatalError("__new__() called with non-type 'self'"); | 
					
						
							|  |  |  | 	type = (PyTypeObject *)self; | 
					
						
							|  |  |  | 	if (!PyTuple_Check(args) || PyTuple_GET_SIZE(args) < 1) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  | 				"T.__new__(): not enough arguments"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	arg0 = PyTuple_GET_ITEM(args, 0); | 
					
						
							|  |  |  | 	if (!PyType_Check(arg0)) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  | 				"T.__new__(S): S is not a type object"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	subtype = (PyTypeObject *)arg0; | 
					
						
							|  |  |  | 	if (!PyType_IsSubtype(subtype, type)) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  | 				"T.__new__(S): S is not a subtype of T"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args)); | 
					
						
							|  |  |  | 	if (args == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	res = type->tp_new(subtype, args, kwds); | 
					
						
							|  |  |  | 	Py_DECREF(args); | 
					
						
							|  |  |  | 	return res; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-06 16:50:37 +00:00
										 |  |  | static struct PyMethodDef tp_new_methoddef[] = { | 
					
						
							|  |  |  | 	{"__new__", (PyCFunction)tp_new_wrapper, METH_KEYWORDS, | 
					
						
							|  |  |  | 	 "T.__new__(S, ...) -> a new object with type S, a subtype of T"}, | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-06 16:50:37 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | add_tp_new_wrapper(PyTypeObject *type) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2001-08-07 16:40:56 +00:00
										 |  |  | 	PyObject *func; | 
					
						
							| 
									
										
										
										
											2001-08-06 16:50:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-07 16:40:56 +00:00
										 |  |  | 	if (PyDict_GetItemString(type->tp_defined, "__new__") != NULL) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	func = PyCFunction_New(tp_new_methoddef, (PyObject *)type); | 
					
						
							| 
									
										
										
										
											2001-08-06 16:50:37 +00:00
										 |  |  | 	if (func == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	return PyDict_SetItemString(type->tp_defined, "__new__", func); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-07 17:24:28 +00:00
										 |  |  | /* This function is called by PyType_Ready() to populate the type's
 | 
					
						
							| 
									
										
										
										
											2001-08-07 16:40:56 +00:00
										 |  |  |    dictionary with method descriptors for function slots.  For each | 
					
						
							|  |  |  |    function slot (like tp_repr) that's defined in the type, one or | 
					
						
							|  |  |  |    more corresponding descriptors are added in the type's tp_defined | 
					
						
							|  |  |  |    dictionary under the appropriate name (like __repr__).  Some | 
					
						
							|  |  |  |    function slots cause more than one descriptor to be added (for | 
					
						
							|  |  |  |    example, the nb_add slot adds both __add__ and __radd__ | 
					
						
							|  |  |  |    descriptors) and some function slots compete for the same | 
					
						
							|  |  |  |    descriptor (for example both sq_item and mp_subscript generate a | 
					
						
							|  |  |  |    __getitem__ descriptor).  This only adds new descriptors and | 
					
						
							|  |  |  |    doesn't overwrite entries in tp_defined that were previously | 
					
						
							|  |  |  |    defined.  The descriptors contain a reference to the C function | 
					
						
							|  |  |  |    they must call, so that it's safe if they are copied into a | 
					
						
							|  |  |  |    subtype's __dict__ and the subtype has a different C function in | 
					
						
							|  |  |  |    its slot -- calling the method defined by the descriptor will call | 
					
						
							|  |  |  |    the C function that was used to create it, rather than the C | 
					
						
							|  |  |  |    function present in the slot when it is called.  (This is important | 
					
						
							|  |  |  |    because a subtype may have a C function in the slot that calls the | 
					
						
							|  |  |  |    method from the dictionary, and we want to avoid infinite recursion | 
					
						
							|  |  |  |    here.) */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | add_operators(PyTypeObject *type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PySequenceMethods *sq; | 
					
						
							|  |  |  | 	PyMappingMethods *mp; | 
					
						
							|  |  |  | 	PyNumberMethods *nb; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef ADD
 | 
					
						
							|  |  |  | #define ADD(SLOT, TABLE) \
 | 
					
						
							|  |  |  | 		if (SLOT) { \ | 
					
						
							|  |  |  | 			if (add_wrappers(type, TABLE, (void *)(SLOT)) < 0) \ | 
					
						
							|  |  |  | 				return -1; \ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ((sq = type->tp_as_sequence) != NULL) { | 
					
						
							|  |  |  | 		ADD(sq->sq_length, tab_len); | 
					
						
							|  |  |  | 		ADD(sq->sq_concat, tab_concat); | 
					
						
							|  |  |  | 		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); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* We don't support "old-style numbers" because their binary
 | 
					
						
							|  |  |  | 	   operators require that both arguments have the same type; | 
					
						
							|  |  |  | 	   the wrappers here only work for new-style numbers. */ | 
					
						
							|  |  |  | 	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); | 
					
						
							|  |  |  | 		/* We don't support coerce() -- see above comment */ | 
					
						
							|  |  |  | 		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); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ADD(type->tp_getattro, tab_getattr); | 
					
						
							|  |  |  | 	ADD(type->tp_setattro, tab_setattr); | 
					
						
							|  |  |  | 	ADD(type->tp_compare, tab_cmp); | 
					
						
							|  |  |  | 	ADD(type->tp_repr, tab_repr); | 
					
						
							|  |  |  | 	ADD(type->tp_hash, tab_hash); | 
					
						
							|  |  |  | 	ADD(type->tp_call, tab_call); | 
					
						
							|  |  |  | 	ADD(type->tp_str, tab_str); | 
					
						
							|  |  |  | 	ADD(type->tp_richcompare, tab_richcmp); | 
					
						
							|  |  |  | 	ADD(type->tp_iter, tab_iter); | 
					
						
							|  |  |  | 	ADD(type->tp_iternext, tab_next); | 
					
						
							|  |  |  | 	ADD(type->tp_descr_get, tab_descr_get); | 
					
						
							|  |  |  | 	ADD(type->tp_descr_set, tab_descr_set); | 
					
						
							|  |  |  | 	ADD(type->tp_init, tab_init); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-07 16:40:56 +00:00
										 |  |  | 	if (type->tp_new != NULL) { | 
					
						
							|  |  |  | 		if (add_tp_new_wrapper(type) < 0) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-07 16:40:56 +00:00
										 |  |  | /* Slot wrappers that call the corresponding __foo__ slot.  See comments
 | 
					
						
							|  |  |  |    below at override_slots() for more explanation. */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | #define SLOT0(FUNCNAME, OPSTR) \
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static PyObject * \ | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | FUNCNAME(PyObject *self) \ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | { \ | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | 	return PyObject_CallMethod(self, OPSTR, ""); \ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | #define SLOT1(FUNCNAME, OPSTR, ARG1TYPE, ARGCODES) \
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static PyObject * \ | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | FUNCNAME(PyObject *self, ARG1TYPE arg1) \ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | { \ | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | 	return PyObject_CallMethod(self, OPSTR, ARGCODES, arg1); \ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define SLOT1BINFULL(FUNCNAME, TESTFUNC, SLOTNAME, OPSTR, ROPSTR) \
 | 
					
						
							|  |  |  | static PyObject * \ | 
					
						
							|  |  |  | FUNCNAME(PyObject *self, PyObject *other) \ | 
					
						
							|  |  |  | { \ | 
					
						
							|  |  |  | 	if (self->ob_type->tp_as_number != NULL && \ | 
					
						
							|  |  |  | 	    self->ob_type->tp_as_number->SLOTNAME == TESTFUNC) { \ | 
					
						
							|  |  |  | 		PyObject *r; \ | 
					
						
							|  |  |  | 		r = PyObject_CallMethod( \ | 
					
						
							|  |  |  | 			self, OPSTR, "O", other); \ | 
					
						
							|  |  |  | 		if (r != Py_NotImplemented || \ | 
					
						
							|  |  |  | 		    other->ob_type == self->ob_type) \ | 
					
						
							|  |  |  | 			return r; \ | 
					
						
							|  |  |  | 		Py_DECREF(r); \ | 
					
						
							|  |  |  | 	} \ | 
					
						
							|  |  |  | 	if (other->ob_type->tp_as_number != NULL && \ | 
					
						
							|  |  |  | 	    other->ob_type->tp_as_number->SLOTNAME == TESTFUNC) { \ | 
					
						
							|  |  |  | 		return PyObject_CallMethod( \ | 
					
						
							|  |  |  | 			other, ROPSTR, "O", self); \ | 
					
						
							|  |  |  | 	} \ | 
					
						
							|  |  |  | 	Py_INCREF(Py_NotImplemented); \ | 
					
						
							|  |  |  | 	return Py_NotImplemented; \ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define SLOT1BIN(FUNCNAME, SLOTNAME, OPSTR, ROPSTR) \
 | 
					
						
							|  |  |  | 	SLOT1BINFULL(FUNCNAME, FUNCNAME, SLOTNAME, OPSTR, ROPSTR) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define SLOT2(FUNCNAME, OPSTR, ARG1TYPE, ARG2TYPE, ARGCODES) \
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static PyObject * \ | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | FUNCNAME(PyObject *self, ARG1TYPE arg1, ARG2TYPE arg2) \ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | { \ | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | 	return PyObject_CallMethod(self, OPSTR, ARGCODES, arg1, arg2); \ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | slot_sq_length(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *res = PyObject_CallMethod(self, "__len__", ""); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (res == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	return (int)PyInt_AsLong(res); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | SLOT1(slot_sq_concat, "__add__", PyObject *, "O") | 
					
						
							|  |  |  | SLOT1(slot_sq_repeat, "__mul__", int, "i") | 
					
						
							|  |  |  | SLOT1(slot_sq_item, "__getitem__", int, "i") | 
					
						
							|  |  |  | SLOT2(slot_sq_slice, "__getslice__", int, int, "ii") | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | slot_sq_ass_item(PyObject *self, int index, PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (value == NULL) | 
					
						
							|  |  |  | 		res = PyObject_CallMethod(self, "__delitem__", "i", index); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		res = PyObject_CallMethod(self, "__setitem__", | 
					
						
							|  |  |  | 					  "iO", index, value); | 
					
						
							|  |  |  | 	if (res == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	Py_DECREF(res); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | slot_sq_ass_slice(PyObject *self, int i, int j, PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (value == NULL) | 
					
						
							|  |  |  | 		res = PyObject_CallMethod(self, "__delslice__", "ii", i, j); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		res = PyObject_CallMethod(self, "__setslice__", | 
					
						
							|  |  |  | 					  "iiO", i, j, value); | 
					
						
							|  |  |  | 	if (res == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	Py_DECREF(res); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | slot_sq_contains(PyObject *self, PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *res = PyObject_CallMethod(self, "__contains__", "O", value); | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (res == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	r = PyInt_AsLong(res); | 
					
						
							|  |  |  | 	Py_DECREF(res); | 
					
						
							|  |  |  | 	return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | SLOT1(slot_sq_inplace_concat, "__iadd__", PyObject *, "O") | 
					
						
							|  |  |  | SLOT1(slot_sq_inplace_repeat, "__imul__", int, "i") | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define slot_mp_length slot_sq_length
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | SLOT1(slot_mp_subscript, "__getitem__", PyObject *, "O") | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | slot_mp_ass_subscript(PyObject *self, PyObject *key, PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (value == NULL) | 
					
						
							|  |  |  | 		res = PyObject_CallMethod(self, "__delitem__", "O", key); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		res = PyObject_CallMethod(self, "__setitem__", | 
					
						
							|  |  |  | 					  "OO", key, value); | 
					
						
							|  |  |  | 	if (res == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	Py_DECREF(res); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | SLOT1BIN(slot_nb_add, nb_add, "__add__", "__radd__") | 
					
						
							|  |  |  | SLOT1BIN(slot_nb_subtract, nb_subtract, "__sub__", "__rsub__") | 
					
						
							|  |  |  | SLOT1BIN(slot_nb_multiply, nb_multiply, "__mul__", "__rmul__") | 
					
						
							|  |  |  | SLOT1BIN(slot_nb_divide, nb_divide, "__div__", "__rdiv__") | 
					
						
							|  |  |  | SLOT1BIN(slot_nb_remainder, nb_remainder, "__mod__", "__rmod__") | 
					
						
							|  |  |  | SLOT1BIN(slot_nb_divmod, nb_divmod, "__divmod__", "__rdivmod__") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | staticforward PyObject *slot_nb_power(PyObject *, PyObject *, PyObject *); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SLOT1BINFULL(slot_nb_power_binary, slot_nb_power, | 
					
						
							|  |  |  | 	     nb_power, "__pow__", "__rpow__") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | slot_nb_power(PyObject *self, PyObject *other, PyObject *modulus) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (modulus == Py_None) | 
					
						
							|  |  |  | 		return slot_nb_power_binary(self, other); | 
					
						
							|  |  |  | 	/* Three-arg power doesn't use __rpow__ */ | 
					
						
							|  |  |  | 	return PyObject_CallMethod(self, "__pow__", "OO", other, modulus); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SLOT0(slot_nb_negative, "__neg__") | 
					
						
							|  |  |  | SLOT0(slot_nb_positive, "__pos__") | 
					
						
							|  |  |  | SLOT0(slot_nb_absolute, "__abs__") | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | slot_nb_nonzero(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *res = PyObject_CallMethod(self, "__nonzero__", ""); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (res == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	return (int)PyInt_AsLong(res); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | SLOT0(slot_nb_invert, "__invert__") | 
					
						
							|  |  |  | SLOT1BIN(slot_nb_lshift, nb_lshift, "__lshift__", "__rlshift__") | 
					
						
							|  |  |  | SLOT1BIN(slot_nb_rshift, nb_rshift, "__rshift__", "__rrshift__") | 
					
						
							|  |  |  | SLOT1BIN(slot_nb_and, nb_and, "__and__", "__rand__") | 
					
						
							|  |  |  | SLOT1BIN(slot_nb_xor, nb_xor, "__xor__", "__rxor__") | 
					
						
							|  |  |  | SLOT1BIN(slot_nb_or, nb_or, "__or__", "__ror__") | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | /* Not coerce() */ | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | SLOT0(slot_nb_int, "__int__") | 
					
						
							|  |  |  | SLOT0(slot_nb_long, "__long__") | 
					
						
							|  |  |  | SLOT0(slot_nb_float, "__float__") | 
					
						
							|  |  |  | SLOT0(slot_nb_oct, "__oct__") | 
					
						
							|  |  |  | SLOT0(slot_nb_hex, "__hex__") | 
					
						
							|  |  |  | SLOT1(slot_nb_inplace_add, "__iadd__", PyObject *, "O") | 
					
						
							|  |  |  | SLOT1(slot_nb_inplace_subtract, "__isub__", PyObject *, "O") | 
					
						
							|  |  |  | SLOT1(slot_nb_inplace_multiply, "__imul__", PyObject *, "O") | 
					
						
							|  |  |  | SLOT1(slot_nb_inplace_divide, "__idiv__", PyObject *, "O") | 
					
						
							|  |  |  | SLOT1(slot_nb_inplace_remainder, "__imod__", PyObject *, "O") | 
					
						
							|  |  |  | SLOT2(slot_nb_inplace_power, "__ipow__", PyObject *, PyObject *, "OO") | 
					
						
							|  |  |  | SLOT1(slot_nb_inplace_lshift, "__ilshift__", PyObject *, "O") | 
					
						
							|  |  |  | SLOT1(slot_nb_inplace_rshift, "__irshift__", PyObject *, "O") | 
					
						
							|  |  |  | SLOT1(slot_nb_inplace_and, "__iand__", PyObject *, "O") | 
					
						
							|  |  |  | SLOT1(slot_nb_inplace_xor, "__ixor__", PyObject *, "O") | 
					
						
							|  |  |  | SLOT1(slot_nb_inplace_or, "__ior__", PyObject *, "O") | 
					
						
							|  |  |  | SLOT1BIN(slot_nb_floor_divide, nb_floor_divide, | 
					
						
							|  |  |  | 	 "__floordiv__", "__rfloordiv__") | 
					
						
							|  |  |  | SLOT1BIN(slot_nb_true_divide, nb_true_divide, "__truediv__", "__rtruediv__") | 
					
						
							|  |  |  | SLOT1(slot_nb_inplace_floor_divide, "__ifloordiv__", PyObject *, "O") | 
					
						
							|  |  |  | SLOT1(slot_nb_inplace_true_divide, "__itruediv__", PyObject *, "O") | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | slot_tp_compare(PyObject *self, PyObject *other) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *res = PyObject_CallMethod(self, "__cmp__", "O", other); | 
					
						
							|  |  |  | 	long r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (res == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	r = PyInt_AsLong(res); | 
					
						
							|  |  |  | 	Py_DECREF(res); | 
					
						
							|  |  |  | 	return (int)r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | SLOT0(slot_tp_repr, "__repr__") | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static long | 
					
						
							|  |  |  | slot_tp_hash(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *res = PyObject_CallMethod(self, "__hash__", ""); | 
					
						
							|  |  |  | 	long h; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (res == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	h = PyInt_AsLong(res); | 
					
						
							|  |  |  | 	if (h == -1 && !PyErr_Occurred()) | 
					
						
							|  |  |  | 		h = -2; | 
					
						
							|  |  |  | 	return h; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | slot_tp_call(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *meth = PyObject_GetAttrString(self, "__call__"); | 
					
						
							|  |  |  | 	PyObject *res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (meth == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	res = PyObject_Call(meth, args, kwds); | 
					
						
							|  |  |  | 	Py_DECREF(meth); | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | SLOT0(slot_tp_str, "__str__") | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | slot_tp_getattro(PyObject *self, PyObject *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyTypeObject *tp = self->ob_type; | 
					
						
							|  |  |  | 	PyObject *dict = NULL; | 
					
						
							|  |  |  | 	PyObject *getattr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (tp->tp_flags & Py_TPFLAGS_HEAPTYPE) | 
					
						
							|  |  |  | 		dict = tp->tp_dict; | 
					
						
							|  |  |  | 	if (dict == NULL) { | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_SystemError, | 
					
						
							|  |  |  | 			     "'%.100s' type object has no __dict__???", | 
					
						
							|  |  |  | 			     tp->tp_name); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	getattr = PyDict_GetItemString(dict, "__getattr__"); | 
					
						
							|  |  |  | 	if (getattr == NULL) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_AttributeError, "__getattr__"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return PyObject_CallFunction(getattr, "OO", self, name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | slot_tp_setattro(PyObject *self, PyObject *name, PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (value == NULL) | 
					
						
							|  |  |  | 		res = PyObject_CallMethod(self, "__delattr__", "O", name); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		res = PyObject_CallMethod(self, "__setattr__", | 
					
						
							|  |  |  | 					  "OO", name, value); | 
					
						
							|  |  |  | 	if (res == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	Py_DECREF(res); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Map rich comparison operators to their __xx__ namesakes */ | 
					
						
							|  |  |  | static char *name_op[] = { | 
					
						
							|  |  |  | 	"__lt__", | 
					
						
							|  |  |  | 	"__le__", | 
					
						
							|  |  |  | 	"__eq__", | 
					
						
							|  |  |  | 	"__ne__", | 
					
						
							|  |  |  | 	"__gt__", | 
					
						
							|  |  |  | 	"__ge__", | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | slot_tp_richcompare(PyObject *self, PyObject *other, int op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *meth = PyObject_GetAttrString(self, name_op[op]); | 
					
						
							|  |  |  | 	PyObject *res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (meth == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	res = PyObject_CallFunction(meth, "O", other); | 
					
						
							|  |  |  | 	Py_DECREF(meth); | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | SLOT0(slot_tp_iter, "__iter__") | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | slot_tp_iternext(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return PyObject_CallMethod(self, "next", ""); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | SLOT2(slot_tp_descr_get, "__get__", PyObject *, PyObject *, "OO") | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | slot_tp_descr_set(PyObject *self, PyObject *target, PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *res = PyObject_CallMethod(self, "__set__", | 
					
						
							|  |  |  | 					    "OO", target, value); | 
					
						
							|  |  |  | 	if (res == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	Py_DECREF(res); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | slot_tp_init(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *meth = PyObject_GetAttrString(self, "__init__"); | 
					
						
							|  |  |  | 	PyObject *res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (meth == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	res = PyObject_Call(meth, args, kwds); | 
					
						
							|  |  |  | 	Py_DECREF(meth); | 
					
						
							|  |  |  | 	if (res == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	Py_DECREF(res); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *func = PyObject_GetAttrString((PyObject *)type, "__new__"); | 
					
						
							|  |  |  | 	PyObject *newargs, *x; | 
					
						
							|  |  |  | 	int i, n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (func == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	assert(PyTuple_Check(args)); | 
					
						
							|  |  |  | 	n = PyTuple_GET_SIZE(args); | 
					
						
							|  |  |  | 	newargs = PyTuple_New(n+1); | 
					
						
							|  |  |  | 	if (newargs == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	Py_INCREF(type); | 
					
						
							|  |  |  | 	PyTuple_SET_ITEM(newargs, 0, (PyObject *)type); | 
					
						
							|  |  |  | 	for (i = 0; i < n; i++) { | 
					
						
							|  |  |  | 		x = PyTuple_GET_ITEM(args, i); | 
					
						
							|  |  |  | 		Py_INCREF(x); | 
					
						
							|  |  |  | 		PyTuple_SET_ITEM(newargs, i+1, x); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	x = PyObject_Call(func, newargs, kwds); | 
					
						
							|  |  |  | 	Py_DECREF(func); | 
					
						
							|  |  |  | 	return x; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-07 16:40:56 +00:00
										 |  |  | /* This is called at the very end of type_new() (even after
 | 
					
						
							| 
									
										
										
										
											2001-08-07 17:24:28 +00:00
										 |  |  |    PyType_Ready()) to complete the initialization of dynamic types. | 
					
						
							| 
									
										
										
										
											2001-08-07 16:40:56 +00:00
										 |  |  |    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__). */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | #define SQSLOT(OPNAME, SLOTNAME, FUNCNAME) \
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	if (PyDict_GetItemString(dict, OPNAME)) { \ | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | 		sq->SLOTNAME = FUNCNAME; \ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | #define MPSLOT(OPNAME, SLOTNAME, FUNCNAME) \
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	if (PyDict_GetItemString(dict, OPNAME)) { \ | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | 		mp->SLOTNAME = FUNCNAME; \ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | #define NBSLOT(OPNAME, SLOTNAME, FUNCNAME) \
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	if (PyDict_GetItemString(dict, OPNAME)) { \ | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | 		nb->SLOTNAME = FUNCNAME; \ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | #define TPSLOT(OPNAME, SLOTNAME, FUNCNAME) \
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	if (PyDict_GetItemString(dict, OPNAME)) { \ | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | 		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); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	/* Not coerce() */ | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (PyDict_GetItemString(dict, "__str__") || | 
					
						
							|  |  |  | 	    PyDict_GetItemString(dict, "__repr__")) | 
					
						
							|  |  |  | 		type->tp_print = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | 	TPSLOT("__cmp__", tp_compare, slot_tp_compare); | 
					
						
							|  |  |  | 	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("__getattr__", tp_getattro, slot_tp_getattro); | 
					
						
							|  |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } |