| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | #include <ctype.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | static PyMemberDef type_members[] = { | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	{"__basicsize__", T_INT, offsetof(PyTypeObject,tp_basicsize),READONLY}, | 
					
						
							|  |  |  | 	{"__itemsize__", T_INT, offsetof(PyTypeObject, tp_itemsize), READONLY}, | 
					
						
							|  |  |  | 	{"__flags__", T_LONG, offsetof(PyTypeObject, tp_flags), READONLY}, | 
					
						
							| 
									
										
										
										
											2001-08-17 20:32:36 +00:00
										 |  |  | 	{"__weakrefoffset__", T_LONG, | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	 offsetof(PyTypeObject, tp_weaklistoffset), READONLY}, | 
					
						
							|  |  |  | 	{"__base__", T_OBJECT, offsetof(PyTypeObject, tp_base), READONLY}, | 
					
						
							|  |  |  | 	{"__dictoffset__", T_LONG, | 
					
						
							|  |  |  | 	 offsetof(PyTypeObject, tp_dictoffset), READONLY}, | 
					
						
							|  |  |  | 	{"__mro__", T_OBJECT, offsetof(PyTypeObject, tp_mro), READONLY}, | 
					
						
							|  |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-16 09:18:56 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | type_name(PyTypeObject *type, void *context) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-12-10 18:50:16 +00:00
										 |  |  | 	const char *s; | 
					
						
							| 
									
										
										
										
											2001-08-16 09:18:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-27 16:29:26 +00:00
										 |  |  | 	if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  | 		PyHeapTypeObject* et = (PyHeapTypeObject*)type; | 
					
						
							| 
									
										
										
										
											2002-12-07 21:39:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-20 22:27:28 +00:00
										 |  |  | 		Py_INCREF(et->ht_name); | 
					
						
							|  |  |  | 		return et->ht_name; | 
					
						
							| 
									
										
										
										
											2002-11-27 16:29:26 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		s = strrchr(type->tp_name, '.'); | 
					
						
							|  |  |  | 		if (s == NULL) | 
					
						
							|  |  |  | 			s = type->tp_name; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			s++; | 
					
						
							|  |  |  | 		return PyString_FromString(s); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-16 09:18:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | type_set_name(PyTypeObject *type, PyObject *value, void *context) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  | 	PyHeapTypeObject* et; | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "can't set %s.__name__", type->tp_name); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (!value) { | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "can't delete %s.__name__", type->tp_name); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (!PyString_Check(value)) { | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "can only assign string to %s.__name__, not '%s'", | 
					
						
							|  |  |  | 			     type->tp_name, value->ob_type->tp_name); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-12-07 21:39:16 +00:00
										 |  |  | 	if (strlen(PyString_AS_STRING(value)) | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 	    != (size_t)PyString_GET_SIZE(value)) { | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_ValueError, | 
					
						
							|  |  |  | 			     "__name__ must not contain null bytes"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  | 	et = (PyHeapTypeObject*)type; | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	Py_INCREF(value); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-20 22:27:28 +00:00
										 |  |  | 	Py_DECREF(et->ht_name); | 
					
						
							|  |  |  | 	et->ht_name = value; | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	type->tp_name = PyString_AS_STRING(value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | type_module(PyTypeObject *type, void *context) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2001-08-16 09:18:56 +00:00
										 |  |  | 	PyObject *mod; | 
					
						
							|  |  |  | 	char *s; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-27 16:29:26 +00:00
										 |  |  | 	if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { | 
					
						
							|  |  |  | 		mod = PyDict_GetItemString(type->tp_dict, "__module__"); | 
					
						
							| 
									
										
										
										
											2004-06-11 14:41:18 +00:00
										 |  |  | 		if (!mod) {  | 
					
						
							|  |  |  | 			PyErr_Format(PyExc_AttributeError, "__module__"); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2002-11-27 16:29:26 +00:00
										 |  |  | 		Py_XINCREF(mod); | 
					
						
							| 
									
										
										
										
											2001-08-16 09:18:56 +00:00
										 |  |  | 		return mod; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-11-27 16:29:26 +00:00
										 |  |  | 	else { | 
					
						
							|  |  |  | 		s = strrchr(type->tp_name, '.'); | 
					
						
							|  |  |  | 		if (s != NULL) | 
					
						
							|  |  |  | 			return PyString_FromStringAndSize( | 
					
						
							| 
									
										
										
										
											2006-10-04 12:17:45 +00:00
										 |  |  | 			    type->tp_name, (Py_ssize_t)(s - type->tp_name)); | 
					
						
							| 
									
										
										
										
											2002-11-27 16:29:26 +00:00
										 |  |  | 		return PyString_FromString("__builtin__"); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-25 16:25:58 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | type_set_module(PyTypeObject *type, PyObject *value, void *context) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 	if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { | 
					
						
							| 
									
										
										
										
											2001-09-25 16:25:58 +00:00
										 |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "can't set %s.__module__", type->tp_name); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (!value) { | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "can't delete %s.__module__", type->tp_name); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-25 16:25:58 +00:00
										 |  |  | 	return PyDict_SetItemString(type->tp_dict, "__module__", value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | type_get_bases(PyTypeObject *type, void *context) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Py_INCREF(type->tp_bases); | 
					
						
							|  |  |  | 	return type->tp_bases; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyTypeObject *best_base(PyObject *); | 
					
						
							|  |  |  | static int mro_internal(PyTypeObject *); | 
					
						
							|  |  |  | static int compatible_for_assignment(PyTypeObject *, PyTypeObject *, char *); | 
					
						
							|  |  |  | static int add_subclass(PyTypeObject*, PyTypeObject*); | 
					
						
							|  |  |  | static void remove_subclass(PyTypeObject *, PyTypeObject *); | 
					
						
							|  |  |  | static void update_all_slots(PyTypeObject *); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-24 23:49:49 +00:00
										 |  |  | typedef int (*update_callback)(PyTypeObject *, void *); | 
					
						
							|  |  |  | static int update_subclasses(PyTypeObject *type, PyObject *name, | 
					
						
							|  |  |  | 			     update_callback callback, void *data); | 
					
						
							|  |  |  | static int recurse_down_subclasses(PyTypeObject *type, PyObject *name, | 
					
						
							|  |  |  | 				   update_callback callback, void *data); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2002-11-27 15:20:19 +00:00
										 |  |  | mro_subclasses(PyTypeObject *type, PyObject* temp) | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PyTypeObject *subclass; | 
					
						
							|  |  |  | 	PyObject *ref, *subclasses, *old_mro; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i, n; | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	subclasses = type->tp_subclasses; | 
					
						
							|  |  |  | 	if (subclasses == NULL) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	assert(PyList_Check(subclasses)); | 
					
						
							|  |  |  | 	n = PyList_GET_SIZE(subclasses); | 
					
						
							|  |  |  | 	for (i = 0; i < n; i++) { | 
					
						
							|  |  |  | 		ref = PyList_GET_ITEM(subclasses, i); | 
					
						
							|  |  |  | 		assert(PyWeakref_CheckRef(ref)); | 
					
						
							|  |  |  | 		subclass = (PyTypeObject *)PyWeakref_GET_OBJECT(ref); | 
					
						
							|  |  |  | 		assert(subclass != NULL); | 
					
						
							|  |  |  | 		if ((PyObject *)subclass == Py_None) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		assert(PyType_Check(subclass)); | 
					
						
							|  |  |  | 		old_mro = subclass->tp_mro; | 
					
						
							|  |  |  | 		if (mro_internal(subclass) < 0) { | 
					
						
							|  |  |  | 			subclass->tp_mro = old_mro; | 
					
						
							| 
									
										
										
										
											2002-11-27 15:20:19 +00:00
										 |  |  | 			return -1; | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2002-11-27 15:20:19 +00:00
										 |  |  | 			PyObject* tuple; | 
					
						
							| 
									
										
										
										
											2003-10-12 19:09:37 +00:00
										 |  |  | 			tuple = PyTuple_Pack(2, subclass, old_mro); | 
					
						
							| 
									
										
										
										
											2003-04-15 22:09:45 +00:00
										 |  |  | 			Py_DECREF(old_mro); | 
					
						
							| 
									
										
										
										
											2002-11-27 15:20:19 +00:00
										 |  |  | 			if (!tuple) | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			if (PyList_Append(temp, tuple) < 0) | 
					
						
							|  |  |  | 				return -1; | 
					
						
							| 
									
										
										
										
											2003-04-15 22:09:45 +00:00
										 |  |  | 			Py_DECREF(tuple); | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2002-11-27 15:20:19 +00:00
										 |  |  | 		if (mro_subclasses(subclass, temp) < 0) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-11-27 15:20:19 +00:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | type_set_bases(PyTypeObject *type, PyObject *value, void *context) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i; | 
					
						
							|  |  |  | 	int r = 0; | 
					
						
							| 
									
										
										
										
											2002-11-27 15:20:19 +00:00
										 |  |  | 	PyObject *ob, *temp; | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 	PyTypeObject *new_base, *old_base; | 
					
						
							|  |  |  | 	PyObject *old_bases, *old_mro; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "can't set %s.__bases__", type->tp_name); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (!value) { | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "can't delete %s.__bases__", type->tp_name); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (!PyTuple_Check(value)) { | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 		     "can only assign tuple to %s.__bases__, not %s", | 
					
						
							|  |  |  | 			     type->tp_name, value->ob_type->tp_name); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-12-13 17:49:38 +00:00
										 |  |  | 	if (PyTuple_GET_SIZE(value) == 0) { | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 		     "can only assign non-empty tuple to %s.__bases__, not ()", | 
					
						
							|  |  |  | 			     type->tp_name); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 	for (i = 0; i < PyTuple_GET_SIZE(value); i++) { | 
					
						
							|  |  |  | 		ob = PyTuple_GET_ITEM(value, i); | 
					
						
							|  |  |  | 		if (!PyClass_Check(ob) && !PyType_Check(ob)) { | 
					
						
							|  |  |  | 			PyErr_Format( | 
					
						
							|  |  |  | 				PyExc_TypeError, | 
					
						
							|  |  |  | 	"%s.__bases__ must be tuple of old- or new-style classes, not '%s'", | 
					
						
							|  |  |  | 				type->tp_name, ob->ob_type->tp_name); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2002-11-27 10:24:44 +00:00
										 |  |  | 		if (PyType_Check(ob)) { | 
					
						
							|  |  |  | 			if (PyType_IsSubtype((PyTypeObject*)ob, type)) { | 
					
						
							|  |  |  | 				PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  | 			"a __bases__ item causes an inheritance cycle"); | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	new_base = best_base(value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!new_base) { | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!compatible_for_assignment(type->tp_base, new_base, "__bases__")) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Py_INCREF(new_base); | 
					
						
							|  |  |  | 	Py_INCREF(value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	old_bases = type->tp_bases; | 
					
						
							|  |  |  | 	old_base = type->tp_base; | 
					
						
							|  |  |  | 	old_mro = type->tp_mro; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	type->tp_bases = value; | 
					
						
							|  |  |  | 	type->tp_base = new_base; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (mro_internal(type) < 0) { | 
					
						
							| 
									
										
										
										
											2002-11-27 15:40:09 +00:00
										 |  |  | 		goto bail; | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-27 15:20:19 +00:00
										 |  |  | 	temp = PyList_New(0); | 
					
						
							| 
									
										
										
										
											2002-11-27 15:40:09 +00:00
										 |  |  | 	if (!temp) | 
					
						
							|  |  |  | 		goto bail; | 
					
						
							| 
									
										
										
										
											2002-11-27 15:20:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	r = mro_subclasses(type, temp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (r < 0) { | 
					
						
							|  |  |  | 		for (i = 0; i < PyList_Size(temp); i++) { | 
					
						
							|  |  |  | 			PyTypeObject* cls; | 
					
						
							|  |  |  | 			PyObject* mro; | 
					
						
							| 
									
										
										
										
											2003-10-12 19:09:37 +00:00
										 |  |  | 			PyArg_UnpackTuple(PyList_GET_ITEM(temp, i), | 
					
						
							|  |  |  | 					 "", 2, 2, &cls, &mro); | 
					
						
							| 
									
										
										
										
											2002-11-27 15:20:19 +00:00
										 |  |  | 			Py_DECREF(cls->tp_mro); | 
					
						
							|  |  |  | 			cls->tp_mro = mro; | 
					
						
							|  |  |  | 			Py_INCREF(cls->tp_mro); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		Py_DECREF(temp); | 
					
						
							| 
									
										
										
										
											2002-11-27 15:40:09 +00:00
										 |  |  | 		goto bail; | 
					
						
							| 
									
										
										
										
											2002-11-27 15:20:19 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Py_DECREF(temp); | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* any base that was in __bases__ but now isn't, we
 | 
					
						
							| 
									
										
										
										
											2002-12-14 17:17:56 +00:00
										 |  |  | 	   need to remove |type| from its tp_subclasses. | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 	   conversely, any class now in __bases__ that wasn't | 
					
						
							| 
									
										
										
										
											2002-12-14 17:17:56 +00:00
										 |  |  | 	   needs to have |type| added to its subclasses. */ | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* for now, sod that: just remove from all old_bases,
 | 
					
						
							|  |  |  | 	   add to all new_bases */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = PyTuple_GET_SIZE(old_bases) - 1; i >= 0; i--) { | 
					
						
							|  |  |  | 		ob = PyTuple_GET_ITEM(old_bases, i); | 
					
						
							|  |  |  | 		if (PyType_Check(ob)) { | 
					
						
							|  |  |  | 			remove_subclass( | 
					
						
							|  |  |  | 				(PyTypeObject*)ob, type); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = PyTuple_GET_SIZE(value) - 1; i >= 0; i--) { | 
					
						
							|  |  |  | 		ob = PyTuple_GET_ITEM(value, i); | 
					
						
							|  |  |  | 		if (PyType_Check(ob)) { | 
					
						
							|  |  |  | 			if (add_subclass((PyTypeObject*)ob, type) < 0) | 
					
						
							|  |  |  | 				r = -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	update_all_slots(type); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Py_DECREF(old_bases); | 
					
						
							|  |  |  | 	Py_DECREF(old_base); | 
					
						
							|  |  |  | 	Py_DECREF(old_mro); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return r; | 
					
						
							| 
									
										
										
										
											2002-11-27 15:40:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   bail: | 
					
						
							| 
									
										
										
										
											2003-08-07 14:58:10 +00:00
										 |  |  | 	Py_DECREF(type->tp_bases); | 
					
						
							|  |  |  | 	Py_DECREF(type->tp_base); | 
					
						
							|  |  |  | 	if (type->tp_mro != old_mro) { | 
					
						
							|  |  |  | 		Py_DECREF(type->tp_mro); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-27 15:40:09 +00:00
										 |  |  | 	type->tp_bases = old_bases; | 
					
						
							|  |  |  | 	type->tp_base = old_base; | 
					
						
							|  |  |  | 	type->tp_mro = old_mro; | 
					
						
							| 
									
										
										
										
											2002-12-07 21:39:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-27 15:40:09 +00:00
										 |  |  | 	return -1; | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +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
										 |  |  | 	return PyDictProxy_New(type->tp_dict); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-03-17 18:56:20 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | type_get_doc(PyTypeObject *type, void *context) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *result; | 
					
						
							| 
									
										
										
										
											2002-04-18 00:22:00 +00:00
										 |  |  | 	if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE) && type->tp_doc != NULL) | 
					
						
							| 
									
										
										
										
											2002-03-17 18:56:20 +00:00
										 |  |  | 		return PyString_FromString(type->tp_doc); | 
					
						
							|  |  |  | 	result = PyDict_GetItemString(type->tp_dict, "__doc__"); | 
					
						
							| 
									
										
										
										
											2002-04-18 00:22:00 +00:00
										 |  |  | 	if (result == NULL) { | 
					
						
							|  |  |  | 		result = Py_None; | 
					
						
							|  |  |  | 		Py_INCREF(result); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (result->ob_type->tp_descr_get) { | 
					
						
							| 
									
										
										
										
											2002-04-18 04:12:28 +00:00
										 |  |  | 		result = result->ob_type->tp_descr_get(result, NULL, | 
					
						
							|  |  |  | 						       (PyObject *)type); | 
					
						
							| 
									
										
										
										
											2002-04-18 00:22:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		Py_INCREF(result); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-03-17 18:56:20 +00:00
										 |  |  | 	return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-21 22:28:58 +00:00
										 |  |  | static PyGetSetDef type_getsets[] = { | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 	{"__name__", (getter)type_name, (setter)type_set_name, NULL}, | 
					
						
							|  |  |  | 	{"__bases__", (getter)type_get_bases, (setter)type_set_bases, NULL}, | 
					
						
							| 
									
										
										
										
											2001-09-25 16:25:58 +00:00
										 |  |  | 	{"__module__", (getter)type_module, (setter)type_set_module, NULL}, | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	{"__dict__",  (getter)type_dict,  NULL, NULL}, | 
					
						
							| 
									
										
										
										
											2002-03-17 18:56:20 +00:00
										 |  |  | 	{"__doc__", (getter)type_get_doc, NULL, NULL}, | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	{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
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2001-08-24 18:34:26 +00:00
										 |  |  | 	PyObject *mod, *name, *rtn; | 
					
						
							| 
									
										
										
										
											2001-09-25 03:56:29 +00:00
										 |  |  | 	char *kind; | 
					
						
							| 
									
										
										
										
											2001-08-16 09:18:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	mod = type_module(type, NULL); | 
					
						
							|  |  |  | 	if (mod == NULL) | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							|  |  |  | 	else if (!PyString_Check(mod)) { | 
					
						
							|  |  |  | 		Py_DECREF(mod); | 
					
						
							|  |  |  | 		mod = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	name = type_name(type, NULL); | 
					
						
							|  |  |  | 	if (name == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2001-08-24 18:34:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-25 03:56:29 +00:00
										 |  |  | 	if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) | 
					
						
							|  |  |  | 		kind = "class"; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		kind = "type"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-24 18:34:26 +00:00
										 |  |  | 	if (mod != NULL && strcmp(PyString_AS_STRING(mod), "__builtin__")) { | 
					
						
							| 
									
										
										
										
											2001-09-25 03:56:29 +00:00
										 |  |  | 		rtn = PyString_FromFormat("<%s '%s.%s'>", | 
					
						
							|  |  |  | 					  kind, | 
					
						
							| 
									
										
										
										
											2001-08-24 18:34:26 +00:00
										 |  |  | 					  PyString_AS_STRING(mod), | 
					
						
							|  |  |  | 					  PyString_AS_STRING(name)); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-16 09:18:56 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2001-09-25 03:56:29 +00:00
										 |  |  | 		rtn = PyString_FromFormat("<%s '%s'>", kind, type->tp_name); | 
					
						
							| 
									
										
										
										
											2001-08-24 18:34:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-16 09:18:56 +00:00
										 |  |  | 	Py_XDECREF(mod); | 
					
						
							|  |  |  | 	Py_DECREF(name); | 
					
						
							| 
									
										
										
										
											2001-08-24 18:34:26 +00:00
										 |  |  | 	return rtn; | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-13 19:18:27 +00:00
										 |  |  | 	obj = type->tp_new(type, args, kwds); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	if (obj != NULL) { | 
					
						
							| 
									
										
										
										
											2001-10-18 15:49:21 +00:00
										 |  |  | 		/* Ugly exception: when the call was type(something),
 | 
					
						
							|  |  |  | 		   don't call tp_init on the result. */ | 
					
						
							|  |  |  | 		if (type == &PyType_Type && | 
					
						
							|  |  |  | 		    PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 && | 
					
						
							|  |  |  | 		    (kwds == NULL || | 
					
						
							|  |  |  | 		     (PyDict_Check(kwds) && PyDict_Size(kwds) == 0))) | 
					
						
							|  |  |  | 			return obj; | 
					
						
							| 
									
										
										
										
											2002-04-06 01:05:01 +00:00
										 |  |  | 		/* If the returned object is not an instance of type,
 | 
					
						
							|  |  |  | 		   it won't be initialized. */ | 
					
						
							|  |  |  | 		if (!PyType_IsSubtype(obj->ob_type, type)) | 
					
						
							|  |  |  | 			return obj; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		type = obj->ob_type; | 
					
						
							| 
									
										
										
										
											2002-07-16 19:39:38 +00:00
										 |  |  | 		if (PyType_HasFeature(type, Py_TPFLAGS_HAVE_CLASS) && | 
					
						
							|  |  |  | 		    type->tp_init != NULL && | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		    type->tp_init(obj, args, kwds) < 0) { | 
					
						
							|  |  |  | 			Py_DECREF(obj); | 
					
						
							|  |  |  | 			obj = NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PyObject *obj; | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  | 	const size_t size = _PyObject_VAR_SIZE(type, nitems+1); | 
					
						
							|  |  |  | 	/* note that we need to add one, for the sentinel */ | 
					
						
							| 
									
										
										
										
											2001-10-06 19:04:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (PyType_IS_GC(type)) | 
					
						
							| 
									
										
										
										
											2002-04-12 03:06:53 +00:00
										 |  |  | 		obj = _PyObject_GC_Malloc(size); | 
					
						
							| 
									
										
										
										
											2001-10-06 19:04:01 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2006-04-11 07:42:36 +00:00
										 |  |  | 		obj = (PyObject *)PyObject_MALLOC(size); | 
					
						
							| 
									
										
										
										
											2001-10-06 19:04:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-29 23:54:54 +00:00
										 |  |  | 	if (obj == NULL) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return PyErr_NoMemory(); | 
					
						
							| 
									
										
										
										
											2001-10-06 19:04:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-29 23:54:54 +00:00
										 |  |  | 	memset(obj, '\0', size); | 
					
						
							| 
									
										
										
										
											2001-10-06 19:04:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) | 
					
						
							|  |  |  | 		Py_INCREF(type); | 
					
						
							| 
									
										
										
										
											2001-10-06 19:04:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	if (type->tp_itemsize == 0) | 
					
						
							|  |  |  | 		PyObject_INIT(obj, type); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		(void) PyObject_INIT_VAR((PyVarObject *)obj, type, nitems); | 
					
						
							| 
									
										
										
										
											2001-10-06 19:04:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	if (PyType_IS_GC(type)) | 
					
						
							| 
									
										
										
										
											2001-08-29 23:54:54 +00:00
										 |  |  | 		_PyObject_GC_TRACK(obj); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	return obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | PyType_GenericNew(PyTypeObject *type, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return type->tp_alloc(type, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-05 20:51:39 +00:00
										 |  |  | /* Helpers for subtyping */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | traverse_slots(PyTypeObject *type, PyObject *self, visitproc visit, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i, n; | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | 	PyMemberDef *mp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	n = type->ob_size; | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  | 	mp = PyHeapType_GET_MEMBERS((PyHeapTypeObject *)type); | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | 	for (i = 0; i < n; i++, mp++) { | 
					
						
							|  |  |  | 		if (mp->type == T_OBJECT_EX) { | 
					
						
							|  |  |  | 			char *addr = (char *)self + mp->offset; | 
					
						
							|  |  |  | 			PyObject *obj = *(PyObject **)addr; | 
					
						
							|  |  |  | 			if (obj != NULL) { | 
					
						
							|  |  |  | 				int err = visit(obj, arg); | 
					
						
							|  |  |  | 				if (err) | 
					
						
							|  |  |  | 					return err; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-05 20:51:39 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | subtype_traverse(PyObject *self, visitproc visit, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyTypeObject *type, *base; | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | 	traverseproc basetraverse; | 
					
						
							| 
									
										
										
										
											2001-10-05 20:51:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | 	/* Find the nearest base with a different tp_traverse,
 | 
					
						
							|  |  |  | 	   and traverse slots while we're at it */ | 
					
						
							| 
									
										
										
										
											2001-10-05 20:51:39 +00:00
										 |  |  | 	type = self->ob_type; | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | 	base = type; | 
					
						
							|  |  |  | 	while ((basetraverse = base->tp_traverse) == subtype_traverse) { | 
					
						
							|  |  |  | 		if (base->ob_size) { | 
					
						
							|  |  |  | 			int err = traverse_slots(base, self, visit, arg); | 
					
						
							|  |  |  | 			if (err) | 
					
						
							|  |  |  | 				return err; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2001-10-05 20:51:39 +00:00
										 |  |  | 		base = base->tp_base; | 
					
						
							|  |  |  | 		assert(base); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (type->tp_dictoffset != base->tp_dictoffset) { | 
					
						
							|  |  |  | 		PyObject **dictptr = _PyObject_GetDictPtr(self); | 
					
						
							| 
									
										
										
										
											2006-04-15 21:47:09 +00:00
										 |  |  | 		if (dictptr && *dictptr) | 
					
						
							|  |  |  | 			Py_VISIT(*dictptr); | 
					
						
							| 
									
										
										
										
											2001-10-05 20:51:39 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-15 21:47:09 +00:00
										 |  |  | 	if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) | 
					
						
							| 
									
										
										
										
											2002-06-10 15:24:42 +00:00
										 |  |  | 		/* For a heaptype, the instances count as references
 | 
					
						
							|  |  |  | 		   to the type.  Traverse the type so the collector | 
					
						
							|  |  |  | 		   can find cycles involving this link. */ | 
					
						
							| 
									
										
										
										
											2006-04-15 21:47:09 +00:00
										 |  |  | 		Py_VISIT(type); | 
					
						
							| 
									
										
										
										
											2002-06-10 15:24:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | 	if (basetraverse) | 
					
						
							|  |  |  | 		return basetraverse(self, visit, arg); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | clear_slots(PyTypeObject *type, PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i, n; | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | 	PyMemberDef *mp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	n = type->ob_size; | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  | 	mp = PyHeapType_GET_MEMBERS((PyHeapTypeObject *)type); | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | 	for (i = 0; i < n; i++, mp++) { | 
					
						
							|  |  |  | 		if (mp->type == T_OBJECT_EX && !(mp->flags & READONLY)) { | 
					
						
							|  |  |  | 			char *addr = (char *)self + mp->offset; | 
					
						
							|  |  |  | 			PyObject *obj = *(PyObject **)addr; | 
					
						
							|  |  |  | 			if (obj != NULL) { | 
					
						
							|  |  |  | 				*(PyObject **)addr = NULL; | 
					
						
							| 
									
										
										
										
											2006-04-15 17:28:34 +00:00
										 |  |  | 				Py_DECREF(obj); | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | subtype_clear(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyTypeObject *type, *base; | 
					
						
							|  |  |  | 	inquiry baseclear; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Find the nearest base with a different tp_clear
 | 
					
						
							|  |  |  | 	   and clear slots while we're at it */ | 
					
						
							|  |  |  | 	type = self->ob_type; | 
					
						
							|  |  |  | 	base = type; | 
					
						
							|  |  |  | 	while ((baseclear = base->tp_clear) == subtype_clear) { | 
					
						
							|  |  |  | 		if (base->ob_size) | 
					
						
							|  |  |  | 			clear_slots(base, self); | 
					
						
							|  |  |  | 		base = base->tp_base; | 
					
						
							|  |  |  | 		assert(base); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-10 15:24:42 +00:00
										 |  |  | 	/* There's no need to clear the instance dict (if any);
 | 
					
						
							|  |  |  | 	   the collector will call its tp_clear handler. */ | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (baseclear) | 
					
						
							|  |  |  | 		return baseclear(self); | 
					
						
							| 
									
										
										
										
											2001-10-05 20:51:39 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | subtype_dealloc(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2001-12-06 02:35:58 +00:00
										 |  |  | 	PyTypeObject *type, *base; | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | 	destructor basedealloc; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-08-06 21:41:44 +00:00
										 |  |  | 	/* Extract the type; we expect it to be a heap type */ | 
					
						
							|  |  |  | 	type = self->ob_type; | 
					
						
							|  |  |  | 	assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Test whether the type has GC exactly once */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyType_IS_GC(type)) { | 
					
						
							|  |  |  | 		/* It's really rare to find a dynamic type that doesn't have
 | 
					
						
							|  |  |  | 		   GC; it can only happen when deriving from 'object' and not | 
					
						
							|  |  |  | 		   adding any slots or instance variables.  This allows | 
					
						
							|  |  |  | 		   certain simplifications: there's no need to call | 
					
						
							|  |  |  | 		   clear_slots(), or DECREF the dict, or clear weakrefs. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Maybe call finalizer; exit early if resurrected */ | 
					
						
							| 
									
										
										
										
											2002-08-08 20:55:20 +00:00
										 |  |  | 		if (type->tp_del) { | 
					
						
							|  |  |  | 			type->tp_del(self); | 
					
						
							|  |  |  | 			if (self->ob_refcnt > 0) | 
					
						
							|  |  |  | 				return; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2002-08-06 21:41:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* Find the nearest base with a different tp_dealloc */ | 
					
						
							|  |  |  | 		base = type; | 
					
						
							|  |  |  | 		while ((basedealloc = base->tp_dealloc) == subtype_dealloc) { | 
					
						
							|  |  |  | 			assert(base->ob_size == 0); | 
					
						
							|  |  |  | 			base = base->tp_base; | 
					
						
							|  |  |  | 			assert(base); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Call the base tp_dealloc() */ | 
					
						
							|  |  |  | 		assert(basedealloc); | 
					
						
							|  |  |  | 		basedealloc(self); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Can't reference self beyond this point */ | 
					
						
							|  |  |  | 		Py_DECREF(type); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Done */ | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* We get here only if the type has GC */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* UnTrack and re-Track around the trashcan macro, alas */ | 
					
						
							| 
									
										
										
										
											2003-02-06 15:22:49 +00:00
										 |  |  | 	/* See explanation at end of function for full disclosure */ | 
					
						
							| 
									
										
											  
											
												Fix a subtle bug in the trashcan code I added yesterday to
subtype_dealloc().
When call_finalizer() failed, it would return without going through
the trashcan end macro, thereby unbalancing the trashcan nesting level
counter, and thereby defeating the test case (slottrash() in
test_descr.py).  This in turn meant that the assert in the GC_UNTRACK
macro wasn't triggered by the slottrash() test despite a bug in the
code: _PyTrash_destroy_chain() calls the dealloc routine with an
object that's untracked, and the assert in the GC_UNTRACK macro would
fail on this; but because of an earlier test that resurrects an
object, causing call_finalizer() to fail and the trashcan nesting
level to be unbalanced, so _PyTrash_destroy_chain() was never called.
Calling the slottrash() test in isolation *did* trigger the assert,
however.
So the fix is twofold: (1) call the GC_UnTrack() function instead of
the GC_UNTRACK macro, because the function is safe when the object is
already untracked; (2) when call_finalizer() fails, jump to a label
that exits through the trashcan end macro, keeping the trashcan
nesting balanced.
											
										 
											2002-08-07 20:42:09 +00:00
										 |  |  | 	PyObject_GC_UnTrack(self); | 
					
						
							| 
									
										
										
										
											2003-02-05 22:39:45 +00:00
										 |  |  | 	++_PyTrash_delete_nesting; | 
					
						
							| 
									
										
										
										
											2002-08-06 21:41:44 +00:00
										 |  |  | 	Py_TRASHCAN_SAFE_BEGIN(self); | 
					
						
							| 
									
										
										
										
											2003-02-05 22:39:45 +00:00
										 |  |  | 	--_PyTrash_delete_nesting; | 
					
						
							| 
									
										
										
										
											2003-11-13 21:59:32 +00:00
										 |  |  | 	/* DO NOT restore GC tracking at this point.  weakref callbacks
 | 
					
						
							|  |  |  | 	 * (if any, and whether directly here or indirectly in something we | 
					
						
							|  |  |  | 	 * call) may trigger GC, and if self is tracked at that point, it | 
					
						
							|  |  |  | 	 * will look like trash to GC and GC will try to delete self again. | 
					
						
							| 
									
										
										
										
											2003-11-12 20:43:28 +00:00
										 |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-06-13 20:54:40 +00:00
										 |  |  | 	/* Find the nearest base with a different tp_dealloc */ | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | 	base = type; | 
					
						
							|  |  |  | 	while ((basedealloc = base->tp_dealloc) == subtype_dealloc) { | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		base = base->tp_base; | 
					
						
							|  |  |  | 		assert(base); | 
					
						
							| 
									
										
										
										
											2001-12-06 02:35:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-05-29 14:29:23 +00:00
										 |  |  | 	/* If we added a weaklist, we clear it.  Do this *before* calling
 | 
					
						
							| 
									
										
										
										
											2003-06-13 20:54:40 +00:00
										 |  |  | 	   the finalizer (__del__), clearing slots, or clearing the instance | 
					
						
							|  |  |  | 	   dict. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-05-29 14:29:23 +00:00
										 |  |  | 	if (type->tp_weaklistoffset && !base->tp_weaklistoffset) | 
					
						
							|  |  |  | 		PyObject_ClearWeakRefs(self); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Maybe call finalizer; exit early if resurrected */ | 
					
						
							|  |  |  | 	if (type->tp_del) { | 
					
						
							| 
									
										
										
										
											2003-11-13 21:59:32 +00:00
										 |  |  | 		_PyObject_GC_TRACK(self); | 
					
						
							| 
									
										
										
										
											2003-05-29 14:29:23 +00:00
										 |  |  | 		type->tp_del(self); | 
					
						
							|  |  |  | 		if (self->ob_refcnt > 0) | 
					
						
							| 
									
										
										
										
											2003-11-13 21:59:32 +00:00
										 |  |  | 			goto endlabel;	/* resurrected */ | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			_PyObject_GC_UNTRACK(self); | 
					
						
							| 
									
										
										
										
											2007-01-23 23:21:22 +00:00
										 |  |  | 		/* New weakrefs could be created during the finalizer call.
 | 
					
						
							|  |  |  | 		    If this occurs, clear them out without calling their | 
					
						
							|  |  |  | 		    finalizers since they might rely on part of the object | 
					
						
							|  |  |  | 		    being finalized that has already been destroyed. */ | 
					
						
							|  |  |  | 		if (type->tp_weaklistoffset && !base->tp_weaklistoffset) { | 
					
						
							|  |  |  | 			/* Modeled after GET_WEAKREFS_LISTPTR() */ | 
					
						
							|  |  |  | 			PyWeakReference **list = (PyWeakReference **) \ | 
					
						
							|  |  |  | 				PyObject_GET_WEAKREFS_LISTPTR(self); | 
					
						
							|  |  |  | 			while (*list) | 
					
						
							|  |  |  | 				_PyWeakref_ClearRef(*list); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2003-05-29 14:29:23 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-06-13 20:54:40 +00:00
										 |  |  | 	/*  Clear slots up to the nearest base with a different tp_dealloc */ | 
					
						
							|  |  |  | 	base = type; | 
					
						
							|  |  |  | 	while ((basedealloc = base->tp_dealloc) == subtype_dealloc) { | 
					
						
							|  |  |  | 		if (base->ob_size) | 
					
						
							|  |  |  | 			clear_slots(base, self); | 
					
						
							|  |  |  | 		base = base->tp_base; | 
					
						
							|  |  |  | 		assert(base); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	/* If we added a dict, DECREF it */ | 
					
						
							| 
									
										
										
										
											2001-08-30 20:00:07 +00:00
										 |  |  | 	if (type->tp_dictoffset && !base->tp_dictoffset) { | 
					
						
							|  |  |  | 		PyObject **dictptr = _PyObject_GetDictPtr(self); | 
					
						
							|  |  |  | 		if (dictptr != NULL) { | 
					
						
							|  |  |  | 			PyObject *dict = *dictptr; | 
					
						
							|  |  |  | 			if (dict != NULL) { | 
					
						
							|  |  |  | 				Py_DECREF(dict); | 
					
						
							|  |  |  | 				*dictptr = NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-13 22:50:00 +00:00
										 |  |  | 	/* Call the base tp_dealloc(); first retrack self if
 | 
					
						
							|  |  |  | 	 * basedealloc knows about gc. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if (PyType_IS_GC(base)) | 
					
						
							|  |  |  | 		_PyObject_GC_TRACK(self); | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | 	assert(basedealloc); | 
					
						
							|  |  |  | 	basedealloc(self); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Can't reference self beyond this point */ | 
					
						
							| 
									
										
										
										
											2002-08-06 21:41:44 +00:00
										 |  |  | 	Py_DECREF(type); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Fix a subtle bug in the trashcan code I added yesterday to
subtype_dealloc().
When call_finalizer() failed, it would return without going through
the trashcan end macro, thereby unbalancing the trashcan nesting level
counter, and thereby defeating the test case (slottrash() in
test_descr.py).  This in turn meant that the assert in the GC_UNTRACK
macro wasn't triggered by the slottrash() test despite a bug in the
code: _PyTrash_destroy_chain() calls the dealloc routine with an
object that's untracked, and the assert in the GC_UNTRACK macro would
fail on this; but because of an earlier test that resurrects an
object, causing call_finalizer() to fail and the trashcan nesting
level to be unbalanced, so _PyTrash_destroy_chain() was never called.
Calling the slottrash() test in isolation *did* trigger the assert,
however.
So the fix is twofold: (1) call the GC_UnTrack() function instead of
the GC_UNTRACK macro, because the function is safe when the object is
already untracked; (2) when call_finalizer() fails, jump to a label
that exits through the trashcan end macro, keeping the trashcan
nesting balanced.
											
										 
											2002-08-07 20:42:09 +00:00
										 |  |  |   endlabel: | 
					
						
							| 
									
										
										
										
											2003-02-05 22:39:45 +00:00
										 |  |  | 	++_PyTrash_delete_nesting; | 
					
						
							| 
									
										
										
										
											2002-08-06 21:41:44 +00:00
										 |  |  | 	Py_TRASHCAN_SAFE_END(self); | 
					
						
							| 
									
										
										
										
											2003-02-05 22:39:45 +00:00
										 |  |  | 	--_PyTrash_delete_nesting; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Explanation of the weirdness around the trashcan macros:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	   Q. What do the trashcan macros do? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	   A. Read the comment titled "Trashcan mechanism" in object.h. | 
					
						
							|  |  |  | 	      For one, this explains why there must be a call to GC-untrack | 
					
						
							|  |  |  | 	      before the trashcan begin macro.  Without understanding the | 
					
						
							|  |  |  | 	      trashcan code, the answers to the following questions don't make | 
					
						
							|  |  |  | 	      sense. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	   Q. Why do we GC-untrack before the trashcan and then immediately | 
					
						
							|  |  |  | 	      GC-track again afterward? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	   A. In the case that the base class is GC-aware, the base class | 
					
						
							|  |  |  | 	      probably GC-untracks the object.  If it does that using the | 
					
						
							|  |  |  | 	      UNTRACK macro, this will crash when the object is already | 
					
						
							|  |  |  | 	      untracked.  Because we don't know what the base class does, the | 
					
						
							|  |  |  | 	      only safe thing is to make sure the object is tracked when we | 
					
						
							|  |  |  | 	      call the base class dealloc.  But...  The trashcan begin macro | 
					
						
							|  |  |  | 	      requires that the object is *untracked* before it is called.  So | 
					
						
							|  |  |  | 	      the dance becomes: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	         GC untrack | 
					
						
							|  |  |  | 		 trashcan begin | 
					
						
							|  |  |  | 		 GC track | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-13 21:59:32 +00:00
										 |  |  |            Q. Why did the last question say "immediately GC-track again"? | 
					
						
							|  |  |  |               It's nowhere near immediately. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            A. Because the code *used* to re-track immediately.  Bad Idea. | 
					
						
							|  |  |  |               self has a refcount of 0, and if gc ever gets its hands on it | 
					
						
							|  |  |  |               (which can happen if any weakref callback gets invoked), it | 
					
						
							|  |  |  |               looks like trash to gc too, and gc also tries to delete self | 
					
						
							|  |  |  |               then.  But we're already deleting self.  Double dealloction is | 
					
						
							|  |  |  |               a subtle disaster. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-02-05 22:39:45 +00:00
										 |  |  | 	   Q. Why the bizarre (net-zero) manipulation of | 
					
						
							|  |  |  | 	      _PyTrash_delete_nesting around the trashcan macros? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	   A. Some base classes (e.g. list) also use the trashcan mechanism. | 
					
						
							|  |  |  | 	      The following scenario used to be possible: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      - suppose the trashcan level is one below the trashcan limit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      - subtype_dealloc() is called | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      - the trashcan limit is not yet reached, so the trashcan level | 
					
						
							|  |  |  | 	        is incremented and the code between trashcan begin and end is | 
					
						
							|  |  |  | 	        executed | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      - this destroys much of the object's contents, including its | 
					
						
							|  |  |  | 	        slots and __dict__ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      - basedealloc() is called; this is really list_dealloc(), or | 
					
						
							|  |  |  | 	        some other type which also uses the trashcan macros | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      - the trashcan limit is now reached, so the object is put on the | 
					
						
							|  |  |  | 	        trashcan's to-be-deleted-later list | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      - basedealloc() returns | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      - subtype_dealloc() decrefs the object's type | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      - subtype_dealloc() returns | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      - later, the trashcan code starts deleting the objects from its | 
					
						
							|  |  |  | 	        to-be-deleted-later list | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      - subtype_dealloc() is called *AGAIN* for the same object | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      - at the very least (if the destroyed slots and __dict__ don't | 
					
						
							|  |  |  | 	        cause problems) the object's type gets decref'ed a second | 
					
						
							|  |  |  | 	        time, which is *BAD*!!! | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      The remedy is to make sure that if the code between trashcan | 
					
						
							|  |  |  | 	      begin and end in subtype_dealloc() is called, the code between | 
					
						
							|  |  |  | 	      trashcan begin and end in basedealloc() will also be called. | 
					
						
							|  |  |  | 	      This is done by decrementing the level after passing into the | 
					
						
							|  |  |  | 	      trashcan block, and incrementing it just before leaving the | 
					
						
							|  |  |  | 	      block. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      But now it's possible that a chain of objects consisting solely | 
					
						
							|  |  |  | 	      of objects whose deallocator is subtype_dealloc() will defeat | 
					
						
							|  |  |  | 	      the trashcan mechanism completely: the decremented level means | 
					
						
							|  |  |  | 	      that the effective level never reaches the limit.  Therefore, we | 
					
						
							|  |  |  | 	      *increment* the level *before* entering the trashcan block, and | 
					
						
							|  |  |  | 	      matchingly decrement it after leaving.  This means the trashcan | 
					
						
							|  |  |  | 	      code will trigger a little early, but that's no big deal. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	   Q. Are there any live examples of code in need of all this | 
					
						
							|  |  |  | 	      complexity? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	   A. Yes.  See SF bug 668433 for code that crashed (when Python was | 
					
						
							|  |  |  | 	      compiled in debug mode) before the trashcan level manipulations | 
					
						
							|  |  |  | 	      were added.  For more discussion, see SF patches 581742, 575073 | 
					
						
							|  |  |  | 	      and bug 574207. | 
					
						
							|  |  |  | 	*/ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 16:30:39 +00:00
										 |  |  | static PyTypeObject *solid_base(PyTypeObject *type); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* type test with subclassing support */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | PyType_IsSubtype(PyTypeObject *a, PyTypeObject *b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *mro; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-07 18:52:13 +00:00
										 |  |  | 	if (!(a->tp_flags & Py_TPFLAGS_HAVE_CLASS)) | 
					
						
							|  |  |  | 		return b == a || b == &PyBaseObject_Type; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	mro = a->tp_mro; | 
					
						
							|  |  |  | 	if (mro != NULL) { | 
					
						
							|  |  |  | 		/* Deal with multiple inheritance without recursion
 | 
					
						
							|  |  |  | 		   by walking the MRO tuple */ | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 		Py_ssize_t i, n; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-14 17:51:50 +00:00
										 |  |  | /* Internal routines to do a method lookup in the type
 | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  |    without looking in the instance dictionary | 
					
						
							|  |  |  |    (so we can't use PyObject_GetAttr) but still binding | 
					
						
							|  |  |  |    it to the instance.  The arguments are the object, | 
					
						
							|  |  |  |    the method name as a C string, and the address of a | 
					
						
							| 
									
										
										
										
											2001-09-14 17:51:50 +00:00
										 |  |  |    static variable used to cache the interned Python string. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    Two variants: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    - lookup_maybe() returns NULL without raising an exception | 
					
						
							|  |  |  |      when the _PyType_Lookup() call fails; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    - lookup_method() always raises an exception upon errors. | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2001-09-14 17:51:50 +00:00
										 |  |  | lookup_maybe(PyObject *self, char *attrstr, PyObject **attrobj) | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PyObject *res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (*attrobj == NULL) { | 
					
						
							|  |  |  | 		*attrobj = PyString_InternFromString(attrstr); | 
					
						
							|  |  |  | 		if (*attrobj == NULL) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	res = _PyType_Lookup(self->ob_type, *attrobj); | 
					
						
							| 
									
										
										
										
											2001-09-14 17:51:50 +00:00
										 |  |  | 	if (res != NULL) { | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 		descrgetfunc f; | 
					
						
							|  |  |  | 		if ((f = res->ob_type->tp_descr_get) == NULL) | 
					
						
							|  |  |  | 			Py_INCREF(res); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			res = f(res, self, (PyObject *)(self->ob_type)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-14 17:51:50 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | lookup_method(PyObject *self, char *attrstr, PyObject **attrobj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *res = lookup_maybe(self, attrstr, attrobj); | 
					
						
							|  |  |  | 	if (res == NULL && !PyErr_Occurred()) | 
					
						
							|  |  |  | 		PyErr_SetObject(PyExc_AttributeError, *attrobj); | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | /* A variation of PyObject_CallMethod that uses lookup_method()
 | 
					
						
							|  |  |  |    instead of PyObject_GetAttrString().  This uses the same convention | 
					
						
							|  |  |  |    as lookup_method to cache the interned name string object. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-21 22:28:58 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | call_method(PyObject *o, char *name, PyObject **nameobj, char *format, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	va_list va; | 
					
						
							|  |  |  | 	PyObject *args, *func = 0, *retval; | 
					
						
							|  |  |  | 	va_start(va, format); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-03 00:50:18 +00:00
										 |  |  | 	func = lookup_maybe(o, name, nameobj); | 
					
						
							| 
									
										
										
										
											2001-09-14 17:51:50 +00:00
										 |  |  | 	if (func == NULL) { | 
					
						
							|  |  |  | 		va_end(va); | 
					
						
							|  |  |  | 		if (!PyErr_Occurred()) | 
					
						
							| 
									
										
										
										
											2001-10-03 00:50:18 +00:00
										 |  |  | 			PyErr_SetObject(PyExc_AttributeError, *nameobj); | 
					
						
							| 
									
										
										
										
											2001-09-14 17:51:50 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (format && *format) | 
					
						
							|  |  |  | 		args = Py_VaBuildValue(format, va); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		args = PyTuple_New(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	va_end(va); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (args == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert(PyTuple_Check(args)); | 
					
						
							|  |  |  | 	retval = PyObject_Call(func, args, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Py_DECREF(args); | 
					
						
							|  |  |  | 	Py_DECREF(func); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return retval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Clone of call_method() that returns NotImplemented when the lookup fails. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-21 22:28:58 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2001-09-14 17:51:50 +00:00
										 |  |  | call_maybe(PyObject *o, char *name, PyObject **nameobj, char *format, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	va_list va; | 
					
						
							|  |  |  | 	PyObject *args, *func = 0, *retval; | 
					
						
							|  |  |  | 	va_start(va, format); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-03 00:50:18 +00:00
										 |  |  | 	func = lookup_maybe(o, name, nameobj); | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 	if (func == NULL) { | 
					
						
							|  |  |  | 		va_end(va); | 
					
						
							| 
									
										
										
										
											2001-09-14 17:51:50 +00:00
										 |  |  | 		if (!PyErr_Occurred()) { | 
					
						
							|  |  |  | 			Py_INCREF(Py_NotImplemented); | 
					
						
							|  |  |  | 			return Py_NotImplemented; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2001-09-14 16:58:08 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (format && *format) | 
					
						
							|  |  |  | 		args = Py_VaBuildValue(format, va); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		args = PyTuple_New(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	va_end(va); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-14 16:58:08 +00:00
										 |  |  | 	if (args == NULL) | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-14 16:58:08 +00:00
										 |  |  | 	assert(PyTuple_Check(args)); | 
					
						
							|  |  |  | 	retval = PyObject_Call(func, args, NULL); | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	Py_DECREF(args); | 
					
						
							|  |  |  | 	Py_DECREF(func); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return retval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-14 23:32:33 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | fill_classic_mro(PyObject *mro, PyObject *cls) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *bases, *base; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i, n; | 
					
						
							| 
									
										
										
										
											2001-11-14 23:32:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	assert(PyList_Check(mro)); | 
					
						
							|  |  |  | 	assert(PyClass_Check(cls)); | 
					
						
							|  |  |  | 	i = PySequence_Contains(mro, cls); | 
					
						
							|  |  |  | 	if (i < 0) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	if (!i) { | 
					
						
							|  |  |  | 		if (PyList_Append(mro, cls) < 0) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	bases = ((PyClassObject *)cls)->cl_bases; | 
					
						
							|  |  |  | 	assert(bases && PyTuple_Check(bases)); | 
					
						
							|  |  |  | 	n = PyTuple_GET_SIZE(bases); | 
					
						
							|  |  |  | 	for (i = 0; i < n; i++) { | 
					
						
							|  |  |  | 		base = PyTuple_GET_ITEM(bases, i); | 
					
						
							|  |  |  | 		if (fill_classic_mro(mro, base) < 0) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | classic_mro(PyObject *cls) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *mro; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert(PyClass_Check(cls)); | 
					
						
							|  |  |  | 	mro = PyList_New(0); | 
					
						
							|  |  |  | 	if (mro != NULL) { | 
					
						
							|  |  |  | 		if (fill_classic_mro(mro, cls) == 0) | 
					
						
							|  |  |  | 			return mro; | 
					
						
							|  |  |  | 		Py_DECREF(mro); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-07 21:39:16 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  |     Method resolution order algorithm C3 described in | 
					
						
							|  |  |  |     "A Monotonic Superclass Linearization for Dylan", | 
					
						
							|  |  |  |     by Kim Barrett, Bob Cassel, Paul Haahr, | 
					
						
							| 
									
										
										
										
											2002-12-07 21:39:16 +00:00
										 |  |  |     David A. Moon, Keith Playford, and P. Tucker Withington. | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  |     (OOPSLA 1996) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  |     Some notes about the rules implied by C3: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-07 21:39:16 +00:00
										 |  |  |     No duplicate bases. | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  |     It isn't legal to repeat a class in a list of base classes. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     The next three properties are the 3 constraints in "C3". | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-07 21:39:16 +00:00
										 |  |  |     Local precendece order. | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  |     If A precedes B in C's MRO, then A will precede B in the MRO of all | 
					
						
							|  |  |  |     subclasses of C. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Monotonicity. | 
					
						
							|  |  |  |     The MRO of a class must be an extension without reordering of the | 
					
						
							|  |  |  |     MRO of each of its superclasses. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Extended Precedence Graph (EPG). | 
					
						
							|  |  |  |     Linearization is consistent if there is a path in the EPG from | 
					
						
							|  |  |  |     each class to all its successors in the linearization.  See | 
					
						
							|  |  |  |     the paper for definition of EPG. | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-07 21:39:16 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | tail_contains(PyObject *list, int whence, PyObject *o) { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t j, size; | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | 	size = PyList_GET_SIZE(list); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (j = whence+1; j < size; j++) { | 
					
						
							|  |  |  | 		if (PyList_GET_ITEM(list, j) == o) | 
					
						
							|  |  |  | 			return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | class_name(PyObject *cls) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *name = PyObject_GetAttrString(cls, "__name__"); | 
					
						
							|  |  |  | 	if (name == NULL) { | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							|  |  |  | 		Py_XDECREF(name); | 
					
						
							|  |  |  | 		name = PyObject_Repr(cls); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (name == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	if (!PyString_Check(name)) { | 
					
						
							|  |  |  | 		Py_DECREF(name); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return name; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | check_duplicates(PyObject *list) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i, j, n; | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  | 	/* Let's use a quadratic time algorithm,
 | 
					
						
							|  |  |  | 	   assuming that the bases lists is short. | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 	n = PyList_GET_SIZE(list); | 
					
						
							|  |  |  | 	for (i = 0; i < n; i++) { | 
					
						
							|  |  |  | 		PyObject *o = PyList_GET_ITEM(list, i); | 
					
						
							|  |  |  | 		for (j = i + 1; j < n; j++) { | 
					
						
							|  |  |  | 			if (PyList_GET_ITEM(list, j) == o) { | 
					
						
							|  |  |  | 				o = class_name(o); | 
					
						
							|  |  |  | 				PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 					     "duplicate base class %s", | 
					
						
							|  |  |  | 					     o ? PyString_AS_STRING(o) : "?"); | 
					
						
							|  |  |  | 				Py_XDECREF(o); | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Raise a TypeError for an MRO order disagreement.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    It's hard to produce a good error message.  In the absence of better | 
					
						
							|  |  |  |    insight into error reporting, report the classes that were candidates | 
					
						
							|  |  |  |    to be put next into the MRO.  There is some conflict between the | 
					
						
							|  |  |  |    order in which they should be put in the MRO, but it's hard to | 
					
						
							|  |  |  |    diagnose what constraint can't be satisfied. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | set_mro_error(PyObject *to_merge, int *remain) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i, n, off, to_merge_size; | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  | 	char buf[1000]; | 
					
						
							|  |  |  | 	PyObject *k, *v; | 
					
						
							|  |  |  | 	PyObject *set = PyDict_New(); | 
					
						
							| 
									
										
										
										
											2006-03-17 19:03:25 +00:00
										 |  |  | 	if (!set) return; | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	to_merge_size = PyList_GET_SIZE(to_merge); | 
					
						
							|  |  |  | 	for (i = 0; i < to_merge_size; i++) { | 
					
						
							|  |  |  | 		PyObject *L = PyList_GET_ITEM(to_merge, i); | 
					
						
							|  |  |  | 		if (remain[i] < PyList_GET_SIZE(L)) { | 
					
						
							|  |  |  | 			PyObject *c = PyList_GET_ITEM(L, remain[i]); | 
					
						
							| 
									
										
										
										
											2006-03-17 19:03:25 +00:00
										 |  |  | 			if (PyDict_SetItem(set, c, Py_None) < 0) { | 
					
						
							|  |  |  | 				Py_DECREF(set); | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  | 				return; | 
					
						
							| 
									
										
										
										
											2006-03-17 19:03:25 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	n = PyDict_Size(set); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-06 19:13:41 +00:00
										 |  |  | 	off = PyOS_snprintf(buf, sizeof(buf), "Cannot create a \
 | 
					
						
							|  |  |  | consistent method resolution\norder (MRO) for bases"); | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  | 	i = 0; | 
					
						
							| 
									
										
										
										
											2006-04-18 00:35:43 +00:00
										 |  |  | 	while (PyDict_Next(set, &i, &k, &v) && (size_t)off < sizeof(buf)) { | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  | 		PyObject *name = class_name(k); | 
					
						
							|  |  |  | 		off += PyOS_snprintf(buf + off, sizeof(buf) - off, " %s", | 
					
						
							|  |  |  | 				     name ? PyString_AS_STRING(name) : "?"); | 
					
						
							|  |  |  | 		Py_XDECREF(name); | 
					
						
							| 
									
										
										
										
											2006-04-18 00:35:43 +00:00
										 |  |  | 		if (--n && (size_t)(off+1) < sizeof(buf)) { | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  | 			buf[off++] = ','; | 
					
						
							|  |  |  | 			buf[off] = '\0'; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	PyErr_SetString(PyExc_TypeError, buf); | 
					
						
							|  |  |  | 	Py_DECREF(set); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-07 21:39:16 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | pmerge(PyObject *acc, PyObject* to_merge) { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i, j, to_merge_size, empty_cnt; | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | 	int *remain; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	int ok; | 
					
						
							| 
									
										
										
										
											2002-12-07 21:39:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | 	to_merge_size = PyList_GET_SIZE(to_merge); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  | 	/* remain stores an index into each sublist of to_merge.
 | 
					
						
							|  |  |  | 	   remain[i] is the index of the next base in to_merge[i] | 
					
						
							|  |  |  | 	   that is not included in acc. | 
					
						
							|  |  |  | 	*/ | 
					
						
							| 
									
										
										
										
											2006-04-11 07:42:36 +00:00
										 |  |  | 	remain = (int *)PyMem_MALLOC(SIZEOF_INT*to_merge_size); | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | 	if (remain == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	for (i = 0; i < to_merge_size; i++) | 
					
						
							|  |  |  | 		remain[i] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   again: | 
					
						
							|  |  |  | 	empty_cnt = 0; | 
					
						
							|  |  |  | 	for (i = 0; i < to_merge_size; i++) { | 
					
						
							|  |  |  | 		PyObject *candidate; | 
					
						
							| 
									
										
										
										
											2002-12-07 21:39:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | 		PyObject *cur_list = PyList_GET_ITEM(to_merge, i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (remain[i] >= PyList_GET_SIZE(cur_list)) { | 
					
						
							|  |  |  | 			empty_cnt++; | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  | 		/* Choose next candidate for MRO.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		   The input sequences alone can determine the choice. | 
					
						
							|  |  |  | 		   If not, choose the class which appears in the MRO | 
					
						
							|  |  |  | 		   of the earliest direct superclass of the new class. | 
					
						
							|  |  |  | 		*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | 		candidate = PyList_GET_ITEM(cur_list, remain[i]); | 
					
						
							|  |  |  | 		for (j = 0; j < to_merge_size; j++) { | 
					
						
							|  |  |  | 			PyObject *j_lst = PyList_GET_ITEM(to_merge, j); | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  | 			if (tail_contains(j_lst, remain[j], candidate)) { | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | 				goto skip; /* continue outer loop */ | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		ok = PyList_Append(acc, candidate); | 
					
						
							|  |  |  | 		if (ok < 0) { | 
					
						
							|  |  |  | 			PyMem_Free(remain); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for (j = 0; j < to_merge_size; j++) { | 
					
						
							|  |  |  | 			PyObject *j_lst = PyList_GET_ITEM(to_merge, j); | 
					
						
							| 
									
										
										
										
											2002-12-31 16:33:01 +00:00
										 |  |  | 			if (remain[j] < PyList_GET_SIZE(j_lst) && | 
					
						
							|  |  |  | 			    PyList_GET_ITEM(j_lst, remain[j]) == candidate) { | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | 				remain[j]++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		goto again; | 
					
						
							| 
									
										
										
										
											2002-11-14 23:22:33 +00:00
										 |  |  | 	  skip: ; | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  | 	if (empty_cnt == to_merge_size) { | 
					
						
							|  |  |  | 		PyMem_FREE(remain); | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	set_mro_error(to_merge, remain); | 
					
						
							|  |  |  | 	PyMem_FREE(remain); | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | mro_implementation(PyTypeObject *type) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i, n; | 
					
						
							|  |  |  | 	int ok; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	PyObject *bases, *result; | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | 	PyObject *to_merge, *bases_aslist; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-18 16:44:57 +00:00
										 |  |  | 	if(type->tp_dict == NULL) { | 
					
						
							|  |  |  | 		if(PyType_Ready(type) < 0) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  | 	/* Find a superclass linearization that honors the constraints
 | 
					
						
							|  |  |  | 	   of the explicit lists of bases and the constraints implied by | 
					
						
							| 
									
										
										
										
											2002-12-07 21:39:16 +00:00
										 |  |  | 	   each base class. | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	   to_merge is a list of lists, where each list is a superclass | 
					
						
							|  |  |  | 	   linearization implied by a base class.  The last element of | 
					
						
							|  |  |  | 	   to_merge is the declared list of bases. | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	bases = type->tp_bases; | 
					
						
							|  |  |  | 	n = PyTuple_GET_SIZE(bases); | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	to_merge = PyList_New(n+1); | 
					
						
							|  |  |  | 	if (to_merge == NULL) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	for (i = 0; i < n; i++) { | 
					
						
							| 
									
										
										
										
											2001-11-14 23:32:33 +00:00
										 |  |  | 		PyObject *base = PyTuple_GET_ITEM(bases, i); | 
					
						
							|  |  |  | 		PyObject *parentMRO; | 
					
						
							|  |  |  | 		if (PyType_Check(base)) | 
					
						
							|  |  |  | 			parentMRO = PySequence_List( | 
					
						
							|  |  |  | 				((PyTypeObject*)base)->tp_mro); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			parentMRO = classic_mro(base); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		if (parentMRO == NULL) { | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | 			Py_DECREF(to_merge); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 			return NULL; | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | 	        } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		PyList_SET_ITEM(to_merge, i, parentMRO); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bases_aslist = PySequence_List(bases); | 
					
						
							|  |  |  | 	if (bases_aslist == NULL) { | 
					
						
							|  |  |  | 		Py_DECREF(to_merge); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-11-25 21:36:54 +00:00
										 |  |  | 	/* This is just a basic sanity check. */ | 
					
						
							|  |  |  | 	if (check_duplicates(bases_aslist) < 0) { | 
					
						
							|  |  |  | 		Py_DECREF(to_merge); | 
					
						
							|  |  |  | 		Py_DECREF(bases_aslist); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | 	PyList_SET_ITEM(to_merge, n, bases_aslist); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	result = Py_BuildValue("[O]", (PyObject *)type); | 
					
						
							|  |  |  | 	if (result == NULL) { | 
					
						
							|  |  |  | 		Py_DECREF(to_merge); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-11-14 19:49:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ok = pmerge(result, to_merge); | 
					
						
							|  |  |  | 	Py_DECREF(to_merge); | 
					
						
							|  |  |  | 	if (ok < 0) { | 
					
						
							|  |  |  | 		Py_DECREF(result); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2001-08-16 13:15:00 +00:00
										 |  |  | mro_external(PyObject *self) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PyTypeObject *type = (PyTypeObject *)self; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return mro_implementation(type); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | mro_internal(PyTypeObject *type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *mro, *result, *tuple; | 
					
						
							| 
									
										
										
										
											2005-12-29 17:07:39 +00:00
										 |  |  | 	int checkit = 0; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (type->ob_type == &PyType_Type) { | 
					
						
							|  |  |  | 		result = mro_implementation(type); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 		static PyObject *mro_str; | 
					
						
							| 
									
										
										
										
											2005-12-29 17:07:39 +00:00
										 |  |  | 		checkit = 1; | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 		mro = lookup_method((PyObject *)type, "mro", &mro_str); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		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); | 
					
						
							| 
									
										
										
										
											2005-12-29 17:07:39 +00:00
										 |  |  | 	if (tuple == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	if (checkit) { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 		Py_ssize_t i, len; | 
					
						
							| 
									
										
										
										
											2005-12-29 17:07:39 +00:00
										 |  |  | 		PyObject *cls; | 
					
						
							|  |  |  | 		PyTypeObject *solid; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		solid = solid_base(type); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		len = PyTuple_GET_SIZE(tuple); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (i = 0; i < len; i++) { | 
					
						
							|  |  |  | 			PyTypeObject *t; | 
					
						
							|  |  |  | 			cls = PyTuple_GET_ITEM(tuple, i); | 
					
						
							|  |  |  | 			if (PyClass_Check(cls))  | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			else if (!PyType_Check(cls)) { | 
					
						
							|  |  |  | 				PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "mro() returned a non-class ('%.500s')", | 
					
						
							|  |  |  | 					     cls->ob_type->tp_name); | 
					
						
							| 
									
										
										
										
											2006-01-02 02:46:54 +00:00
										 |  |  | 				Py_DECREF(tuple); | 
					
						
							| 
									
										
										
										
											2005-12-29 17:07:39 +00:00
										 |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			t = (PyTypeObject*)cls; | 
					
						
							|  |  |  | 			if (!PyType_IsSubtype(solid, solid_base(t))) { | 
					
						
							|  |  |  | 				PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 		     "mro() returned base with unsuitable layout ('%.500s')", | 
					
						
							|  |  |  | 					     t->tp_name); | 
					
						
							| 
									
										
										
										
											2006-01-02 02:46:54 +00:00
										 |  |  | 				Py_DECREF(tuple); | 
					
						
							| 
									
										
										
										
											2005-12-29 17:07:39 +00:00
										 |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i, n; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	PyTypeObject *base, *winner, *candidate, *base_i; | 
					
						
							| 
									
										
										
										
											2001-11-14 23:32:33 +00:00
										 |  |  | 	PyObject *base_proto; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	assert(PyTuple_Check(bases)); | 
					
						
							|  |  |  | 	n = PyTuple_GET_SIZE(bases); | 
					
						
							|  |  |  | 	assert(n > 0); | 
					
						
							| 
									
										
										
										
											2001-11-14 23:32:33 +00:00
										 |  |  | 	base = NULL; | 
					
						
							|  |  |  | 	winner = NULL; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	for (i = 0; i < n; i++) { | 
					
						
							| 
									
										
										
										
											2001-11-14 23:32:33 +00:00
										 |  |  | 		base_proto = PyTuple_GET_ITEM(bases, i); | 
					
						
							|  |  |  | 		if (PyClass_Check(base_proto)) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		if (!PyType_Check(base_proto)) { | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 			PyErr_SetString( | 
					
						
							|  |  |  | 				PyExc_TypeError, | 
					
						
							|  |  |  | 				"bases must be types"); | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2001-11-14 23:32:33 +00:00
										 |  |  | 		base_i = (PyTypeObject *)base_proto; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		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); | 
					
						
							| 
									
										
										
										
											2001-11-14 23:32:33 +00:00
										 |  |  | 		if (winner == NULL) { | 
					
						
							|  |  |  | 			winner = candidate; | 
					
						
							|  |  |  | 			base = base_i; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if (PyType_IsSubtype(winner, candidate)) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 			; | 
					
						
							|  |  |  | 		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; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-12-14 04:19:56 +00:00
										 |  |  | 	if (base == NULL) | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  | 			"a new-style class can't have only classic bases"); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	return base; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | extra_ivars(PyTypeObject *type, PyTypeObject *base) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2001-08-29 23:54:54 +00:00
										 |  |  | 	size_t t_size = type->tp_basicsize; | 
					
						
							|  |  |  | 	size_t b_size = base->tp_basicsize; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-17 20:32:36 +00:00
										 |  |  | 	assert(t_size >= b_size); /* Else type smaller than base! */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	if (type->tp_itemsize || base->tp_itemsize) { | 
					
						
							|  |  |  | 		/* If itemsize is involved, stricter rules */ | 
					
						
							|  |  |  | 		return t_size != b_size || | 
					
						
							|  |  |  | 			type->tp_itemsize != base->tp_itemsize; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-17 20:32:36 +00:00
										 |  |  | 	if (type->tp_weaklistoffset && base->tp_weaklistoffset == 0 && | 
					
						
							|  |  |  | 	    type->tp_weaklistoffset + sizeof(PyObject *) == t_size) | 
					
						
							|  |  |  | 		t_size -= sizeof(PyObject *); | 
					
						
							|  |  |  | 	if (type->tp_dictoffset && base->tp_dictoffset == 0 && | 
					
						
							|  |  |  | 	    type->tp_dictoffset + sizeof(PyObject *) == t_size) | 
					
						
							|  |  |  | 		t_size -= sizeof(PyObject *); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return t_size != b_size; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 16:30:39 +00:00
										 |  |  | static void object_dealloc(PyObject *); | 
					
						
							|  |  |  | static int object_init(PyObject *, PyObject *, PyObject *); | 
					
						
							|  |  |  | static int update_slot(PyTypeObject *, PyObject *); | 
					
						
							|  |  |  | static void fixup_slot_dispatchers(PyTypeObject *); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-30 20:00:07 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | subtype_dict(PyObject *obj, void *context) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject **dictptr = _PyObject_GetDictPtr(obj); | 
					
						
							|  |  |  | 	PyObject *dict; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (dictptr == NULL) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_AttributeError, | 
					
						
							|  |  |  | 				"This object has no __dict__"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	dict = *dictptr; | 
					
						
							| 
									
										
										
										
											2001-09-25 16:25:58 +00:00
										 |  |  | 	if (dict == NULL) | 
					
						
							|  |  |  | 		*dictptr = dict = PyDict_New(); | 
					
						
							|  |  |  | 	Py_XINCREF(dict); | 
					
						
							|  |  |  | 	return dict; | 
					
						
							| 
									
										
										
										
											2001-08-30 20:00:07 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-26 04:26:12 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | subtype_setdict(PyObject *obj, PyObject *value, void *context) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject **dictptr = _PyObject_GetDictPtr(obj); | 
					
						
							|  |  |  | 	PyObject *dict; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (dictptr == NULL) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_AttributeError, | 
					
						
							|  |  |  | 				"This object has no __dict__"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-12-05 19:46:42 +00:00
										 |  |  | 	if (value != NULL && !PyDict_Check(value)) { | 
					
						
							| 
									
										
										
										
											2006-06-18 22:17:29 +00:00
										 |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "__dict__ must be set to a dictionary, " | 
					
						
							|  |  |  | 			     "not a '%.200s'", value->ob_type->tp_name); | 
					
						
							| 
									
										
										
										
											2001-10-26 04:26:12 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	dict = *dictptr; | 
					
						
							| 
									
										
										
										
											2001-12-05 19:46:42 +00:00
										 |  |  | 	Py_XINCREF(value); | 
					
						
							| 
									
										
										
										
											2001-10-26 04:26:12 +00:00
										 |  |  | 	*dictptr = value; | 
					
						
							|  |  |  | 	Py_XDECREF(dict); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | subtype_getweakref(PyObject *obj, void *context) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject **weaklistptr; | 
					
						
							|  |  |  | 	PyObject *result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (obj->ob_type->tp_weaklistoffset == 0) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_AttributeError, | 
					
						
							| 
									
										
										
										
											2006-08-04 05:17:21 +00:00
										 |  |  | 				"This object has no __weakref__"); | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	assert(obj->ob_type->tp_weaklistoffset > 0); | 
					
						
							|  |  |  | 	assert(obj->ob_type->tp_weaklistoffset + sizeof(PyObject *) <= | 
					
						
							| 
									
										
										
										
											2002-08-12 19:25:08 +00:00
										 |  |  | 	       (size_t)(obj->ob_type->tp_basicsize)); | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 	weaklistptr = (PyObject **) | 
					
						
							| 
									
										
										
										
											2002-08-12 19:25:08 +00:00
										 |  |  | 		((char *)obj + obj->ob_type->tp_weaklistoffset); | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 	if (*weaklistptr == NULL) | 
					
						
							|  |  |  | 		result = Py_None; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		result = *weaklistptr; | 
					
						
							|  |  |  | 	Py_INCREF(result); | 
					
						
							|  |  |  | 	return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-01-07 13:41:37 +00:00
										 |  |  | /* Three variants on the subtype_getsets list. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyGetSetDef subtype_getsets_full[] = { | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 	{"__dict__", subtype_dict, subtype_setdict, | 
					
						
							| 
									
										
										
										
											2002-08-13 17:18:45 +00:00
										 |  |  | 	 PyDoc_STR("dictionary for instance variables (if defined)")}, | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 	{"__weakref__", subtype_getweakref, NULL, | 
					
						
							| 
									
										
										
										
											2002-08-13 17:18:45 +00:00
										 |  |  | 	 PyDoc_STR("list of weak references to the object (if defined)")}, | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 	{0} | 
					
						
							| 
									
										
										
										
											2001-08-30 20:00:07 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-01-07 13:41:37 +00:00
										 |  |  | static PyGetSetDef subtype_getsets_dict_only[] = { | 
					
						
							|  |  |  | 	{"__dict__", subtype_dict, subtype_setdict, | 
					
						
							|  |  |  | 	 PyDoc_STR("dictionary for instance variables (if defined)")}, | 
					
						
							|  |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyGetSetDef subtype_getsets_weakref_only[] = { | 
					
						
							|  |  |  | 	{"__weakref__", subtype_getweakref, NULL, | 
					
						
							|  |  |  | 	 PyDoc_STR("list of weak references to the object (if defined)")}, | 
					
						
							|  |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | valid_identifier(PyObject *s) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-16 14:30:28 +00:00
										 |  |  | 	unsigned char *p; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i, n; | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyString_Check(s)) { | 
					
						
							| 
									
										
										
										
											2006-06-18 22:17:29 +00:00
										 |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "__slots__ items must be strings, not '%.200s'", | 
					
						
							|  |  |  | 			     s->ob_type->tp_name); | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-07-16 14:30:28 +00:00
										 |  |  | 	p = (unsigned char *) PyString_AS_STRING(s); | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | 	n = PyString_GET_SIZE(s); | 
					
						
							|  |  |  | 	/* We must reject an empty name.  As a hack, we bump the
 | 
					
						
							|  |  |  | 	   length to 1 so that the loop will balk on the trailing \0. */ | 
					
						
							|  |  |  | 	if (n == 0) | 
					
						
							|  |  |  | 		n = 1; | 
					
						
							|  |  |  | 	for (i = 0; i < n; i++, p++) { | 
					
						
							|  |  |  | 		if (!(i == 0 ? isalpha(*p) : isalnum(*p)) && *p != '_') { | 
					
						
							|  |  |  | 			PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  | 					"__slots__ must be identifiers"); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-14 21:07:28 +00:00
										 |  |  | #ifdef Py_USING_UNICODE
 | 
					
						
							|  |  |  | /* Replace Unicode objects in slots.  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2006-02-16 14:32:27 +00:00
										 |  |  | _unicode_to_string(PyObject *slots, Py_ssize_t nslots) | 
					
						
							| 
									
										
										
										
											2002-10-14 21:07:28 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PyObject *tmp = slots; | 
					
						
							|  |  |  | 	PyObject *o, *o1; | 
					
						
							| 
									
										
										
										
											2006-02-16 14:32:27 +00:00
										 |  |  | 	Py_ssize_t i; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	ssizessizeargfunc copy = slots->ob_type->tp_as_sequence->sq_slice; | 
					
						
							| 
									
										
										
										
											2002-10-14 21:07:28 +00:00
										 |  |  | 	for (i = 0; i < nslots; i++) { | 
					
						
							|  |  |  | 		if (PyUnicode_Check(o = PyTuple_GET_ITEM(tmp, i))) { | 
					
						
							|  |  |  | 			if (tmp == slots) { | 
					
						
							|  |  |  | 				tmp = copy(slots, 0, PyTuple_GET_SIZE(slots)); | 
					
						
							|  |  |  | 				if (tmp == NULL) | 
					
						
							|  |  |  | 					return NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			o1 = _PyUnicode_AsDefaultEncodedString | 
					
						
							|  |  |  | 					(o, NULL); | 
					
						
							|  |  |  | 			if (o1 == NULL) { | 
					
						
							|  |  |  | 				Py_DECREF(tmp); | 
					
						
							|  |  |  | 				return 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			Py_INCREF(o1); | 
					
						
							|  |  |  | 			Py_DECREF(o); | 
					
						
							|  |  |  | 			PyTuple_SET_ITEM(tmp, i, o1); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return tmp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *name, *bases, *dict; | 
					
						
							| 
									
										
										
										
											2006-02-27 16:46:16 +00:00
										 |  |  | 	static char *kwlist[] = {"name", "bases", "dict", 0}; | 
					
						
							| 
									
										
										
										
											2002-06-20 22:23:15 +00:00
										 |  |  | 	PyObject *slots, *tmp, *newslots; | 
					
						
							| 
									
										
										
										
											2001-08-17 11:18:38 +00:00
										 |  |  | 	PyTypeObject *type, *base, *tmptype, *winner; | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  | 	PyHeapTypeObject *et; | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | 	PyMemberDef *mp; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i, nbases, nslots, slotoffset, add_dict, add_weak; | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 	int j, may_add_dict, may_add_weak; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-27 19:37:48 +00:00
										 |  |  | 	assert(args != NULL && PyTuple_Check(args)); | 
					
						
							|  |  |  | 	assert(kwds == NULL || PyDict_Check(kwds)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-17 11:18:38 +00:00
										 |  |  | 	/* Special case: type(x) should return x->ob_type */ | 
					
						
							| 
									
										
										
										
											2001-10-27 19:37:48 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 		const Py_ssize_t nargs = PyTuple_GET_SIZE(args); | 
					
						
							|  |  |  | 		const Py_ssize_t nkwds = kwds == NULL ? 0 : PyDict_Size(kwds); | 
					
						
							| 
									
										
										
										
											2001-10-27 19:37:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (PyType_CheckExact(metatype) && nargs == 1 && nkwds == 0) { | 
					
						
							|  |  |  | 			PyObject *x = PyTuple_GET_ITEM(args, 0); | 
					
						
							|  |  |  | 			Py_INCREF(x->ob_type); | 
					
						
							|  |  |  | 			return (PyObject *) x->ob_type; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* SF bug 475327 -- if that didn't trigger, we need 3
 | 
					
						
							|  |  |  | 		   arguments. but PyArg_ParseTupleAndKeywords below may give | 
					
						
							|  |  |  | 		   a msg saying type() needs exactly 3. */ | 
					
						
							|  |  |  | 		if (nargs + nkwds != 3) { | 
					
						
							|  |  |  | 			PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  | 					"type() takes 1 or 3 arguments"); | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-17 11:18:38 +00:00
										 |  |  | 	/* Check arguments: (name, bases, dict) */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2001-08-17 11:18:38 +00:00
										 |  |  | 	winner = metatype; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	for (i = 0; i < nbases; i++) { | 
					
						
							|  |  |  | 		tmp = PyTuple_GET_ITEM(bases, i); | 
					
						
							|  |  |  | 		tmptype = tmp->ob_type; | 
					
						
							| 
									
										
										
										
											2001-11-14 23:32:33 +00:00
										 |  |  | 		if (tmptype == &PyClass_Type) | 
					
						
							|  |  |  | 			continue; /* Special case classic classes */ | 
					
						
							| 
									
										
										
										
											2001-08-17 11:18:38 +00:00
										 |  |  | 		if (PyType_IsSubtype(winner, tmptype)) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2001-08-17 11:18:38 +00:00
										 |  |  | 		if (PyType_IsSubtype(tmptype, winner)) { | 
					
						
							|  |  |  | 			winner = tmptype; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_TypeError, | 
					
						
							| 
									
										
										
										
											2003-04-23 12:07:22 +00:00
										 |  |  | 				"metaclass conflict: " | 
					
						
							|  |  |  | 				"the metaclass of a derived class " | 
					
						
							|  |  |  | 				"must be a (non-strict) subclass " | 
					
						
							|  |  |  | 				"of the metaclasses of all its bases"); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-17 11:18:38 +00:00
										 |  |  | 	if (winner != metatype) { | 
					
						
							|  |  |  | 		if (winner->tp_new != type_new) /* Pass it to the winner */ | 
					
						
							|  |  |  | 			return winner->tp_new(winner, args, kwds); | 
					
						
							|  |  |  | 		metatype = winner; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Adjust for empty tuple bases */ | 
					
						
							|  |  |  | 	if (nbases == 0) { | 
					
						
							| 
									
										
										
										
											2003-10-12 19:09:37 +00:00
										 |  |  | 		bases = PyTuple_Pack(1, &PyBaseObject_Type); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		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); | 
					
						
							| 
									
										
										
										
											2003-08-08 13:57:22 +00:00
										 |  |  | 	if (base == NULL) { | 
					
						
							|  |  |  | 		Py_DECREF(bases); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2003-08-08 13:57:22 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	if (!PyType_HasFeature(base, Py_TPFLAGS_BASETYPE)) { | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "type '%.100s' is not an acceptable base type", | 
					
						
							|  |  |  | 			     base->tp_name); | 
					
						
							| 
									
										
										
										
											2003-08-08 13:57:22 +00:00
										 |  |  | 		Py_DECREF(bases); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Check for a __slots__ sequence variable in dict, and count it */ | 
					
						
							|  |  |  | 	slots = PyDict_GetItemString(dict, "__slots__"); | 
					
						
							|  |  |  | 	nslots = 0; | 
					
						
							| 
									
										
										
										
											2001-08-17 20:32:36 +00:00
										 |  |  | 	add_dict = 0; | 
					
						
							|  |  |  | 	add_weak = 0; | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 	may_add_dict = base->tp_dictoffset == 0; | 
					
						
							|  |  |  | 	may_add_weak = base->tp_weaklistoffset == 0 && base->tp_itemsize == 0; | 
					
						
							|  |  |  | 	if (slots == NULL) { | 
					
						
							|  |  |  | 		if (may_add_dict) { | 
					
						
							|  |  |  | 			add_dict++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (may_add_weak) { | 
					
						
							|  |  |  | 			add_weak++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		/* Have slots */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		/* Make it into a tuple */ | 
					
						
							|  |  |  | 		if (PyString_Check(slots)) | 
					
						
							| 
									
										
										
										
											2003-10-12 19:09:37 +00:00
										 |  |  | 			slots = PyTuple_Pack(1, slots); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		else | 
					
						
							|  |  |  | 			slots = PySequence_Tuple(slots); | 
					
						
							| 
									
										
										
										
											2003-08-08 13:57:22 +00:00
										 |  |  | 		if (slots == NULL) { | 
					
						
							|  |  |  | 			Py_DECREF(bases); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 			return NULL; | 
					
						
							| 
									
										
										
										
											2003-08-08 13:57:22 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 		assert(PyTuple_Check(slots)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Are slots allowed? */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		nslots = PyTuple_GET_SIZE(slots); | 
					
						
							| 
									
										
										
										
											2003-07-16 16:08:23 +00:00
										 |  |  | 		if (nslots > 0 && base->tp_itemsize != 0) { | 
					
						
							| 
									
										
										
										
											2001-08-30 04:43:35 +00:00
										 |  |  | 			PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 				     "nonempty __slots__ " | 
					
						
							|  |  |  | 				     "not supported for subtype of '%s'", | 
					
						
							|  |  |  | 				     base->tp_name); | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 		  bad_slots: | 
					
						
							| 
									
										
										
										
											2003-08-08 13:57:22 +00:00
										 |  |  | 			Py_DECREF(bases); | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 			Py_DECREF(slots); | 
					
						
							| 
									
										
										
										
											2001-08-30 04:43:35 +00:00
										 |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-14 21:07:28 +00:00
										 |  |  | #ifdef Py_USING_UNICODE
 | 
					
						
							|  |  |  | 		tmp = _unicode_to_string(slots, nslots); | 
					
						
							| 
									
										
										
										
											2002-10-14 21:11:34 +00:00
										 |  |  | 		if (tmp != slots) { | 
					
						
							|  |  |  | 			Py_DECREF(slots); | 
					
						
							|  |  |  | 			slots = tmp; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2002-10-14 21:07:28 +00:00
										 |  |  | 		if (!tmp) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 		/* Check for valid slot names and two special cases */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		for (i = 0; i < nslots; i++) { | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 			PyObject *tmp = PyTuple_GET_ITEM(slots, i); | 
					
						
							|  |  |  | 			char *s; | 
					
						
							|  |  |  | 			if (!valid_identifier(tmp)) | 
					
						
							|  |  |  | 				goto bad_slots; | 
					
						
							|  |  |  | 			assert(PyString_Check(tmp)); | 
					
						
							|  |  |  | 			s = PyString_AS_STRING(tmp); | 
					
						
							|  |  |  | 			if (strcmp(s, "__dict__") == 0) { | 
					
						
							|  |  |  | 				if (!may_add_dict || add_dict) { | 
					
						
							|  |  |  | 					PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  | 						"__dict__ slot disallowed: " | 
					
						
							|  |  |  | 						"we already got one"); | 
					
						
							|  |  |  | 					goto bad_slots; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				add_dict++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (strcmp(s, "__weakref__") == 0) { | 
					
						
							|  |  |  | 				if (!may_add_weak || add_weak) { | 
					
						
							|  |  |  | 					PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  | 						"__weakref__ slot disallowed: " | 
					
						
							|  |  |  | 						"either we already got one, " | 
					
						
							|  |  |  | 						"or __itemsize__ != 0"); | 
					
						
							|  |  |  | 					goto bad_slots; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				add_weak++; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2002-06-20 22:23:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 		/* Copy slots into yet another tuple, demangling names */ | 
					
						
							|  |  |  | 		newslots = PyTuple_New(nslots - add_dict - add_weak); | 
					
						
							| 
									
										
										
										
											2002-06-20 22:23:15 +00:00
										 |  |  | 		if (newslots == NULL) | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 			goto bad_slots; | 
					
						
							|  |  |  | 		for (i = j = 0; i < nslots; i++) { | 
					
						
							|  |  |  | 			char *s; | 
					
						
							| 
									
										
										
										
											2002-06-20 22:23:15 +00:00
										 |  |  | 			tmp = PyTuple_GET_ITEM(slots, i); | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 			s = PyString_AS_STRING(tmp); | 
					
						
							|  |  |  | 			if ((add_dict && strcmp(s, "__dict__") == 0) || | 
					
						
							|  |  |  | 			    (add_weak && strcmp(s, "__weakref__") == 0)) | 
					
						
							|  |  |  | 				continue; | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | 			tmp =_Py_Mangle(name, tmp); | 
					
						
							|  |  |  |                         if (!tmp) | 
					
						
							|  |  |  |                             goto bad_slots; | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 			PyTuple_SET_ITEM(newslots, j, tmp); | 
					
						
							|  |  |  | 			j++; | 
					
						
							| 
									
										
										
										
											2002-06-20 22:23:15 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 		assert(j == nslots - add_dict - add_weak); | 
					
						
							|  |  |  | 		nslots = j; | 
					
						
							| 
									
										
										
										
											2002-06-20 22:23:15 +00:00
										 |  |  | 		Py_DECREF(slots); | 
					
						
							|  |  |  | 		slots = newslots; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 		/* Secondary bases may provide weakrefs or dict */ | 
					
						
							|  |  |  | 		if (nbases > 1 && | 
					
						
							|  |  |  | 		    ((may_add_dict && !add_dict) || | 
					
						
							|  |  |  | 		     (may_add_weak && !add_weak))) { | 
					
						
							|  |  |  | 			for (i = 0; i < nbases; i++) { | 
					
						
							|  |  |  | 				tmp = PyTuple_GET_ITEM(bases, i); | 
					
						
							|  |  |  | 				if (tmp == (PyObject *)base) | 
					
						
							|  |  |  | 					continue; /* Skip primary base */ | 
					
						
							|  |  |  | 				if (PyClass_Check(tmp)) { | 
					
						
							|  |  |  | 					/* Classic base class provides both */ | 
					
						
							|  |  |  | 					if (may_add_dict && !add_dict) | 
					
						
							|  |  |  | 						add_dict++; | 
					
						
							|  |  |  | 					if (may_add_weak && !add_weak) | 
					
						
							|  |  |  | 						add_weak++; | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				assert(PyType_Check(tmp)); | 
					
						
							|  |  |  | 				tmptype = (PyTypeObject *)tmp; | 
					
						
							|  |  |  | 				if (may_add_dict && !add_dict && | 
					
						
							|  |  |  | 				    tmptype->tp_dictoffset != 0) | 
					
						
							|  |  |  | 					add_dict++; | 
					
						
							|  |  |  | 				if (may_add_weak && !add_weak && | 
					
						
							|  |  |  | 				    tmptype->tp_weaklistoffset != 0) | 
					
						
							|  |  |  | 					add_weak++; | 
					
						
							|  |  |  | 				if (may_add_dict && !add_dict) | 
					
						
							|  |  |  | 					continue; | 
					
						
							|  |  |  | 				if (may_add_weak && !add_weak) | 
					
						
							|  |  |  | 					continue; | 
					
						
							|  |  |  | 				/* Nothing more to check */ | 
					
						
							|  |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2002-03-14 23:03:14 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2001-08-17 20:32:36 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* XXX From here until type is safely allocated,
 | 
					
						
							|  |  |  | 	   "return NULL" may leak slots! */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Allocate the type object */ | 
					
						
							|  |  |  | 	type = (PyTypeObject *)metatype->tp_alloc(metatype, nslots); | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 	if (type == NULL) { | 
					
						
							|  |  |  | 		Py_XDECREF(slots); | 
					
						
							| 
									
										
										
										
											2003-08-08 13:57:22 +00:00
										 |  |  | 		Py_DECREF(bases); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Keep name and slots alive in the extended type object */ | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  | 	et = (PyHeapTypeObject *)type; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	Py_INCREF(name); | 
					
						
							| 
									
										
										
										
											2006-02-20 22:27:28 +00:00
										 |  |  | 	et->ht_name = name; | 
					
						
							|  |  |  | 	et->ht_slots = slots; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							| 
									
										
											  
											
												Add Garbage Collection support to new-style classes (not yet to their
instances).
Also added GC support to various auxiliary types: super, property,
descriptors, wrappers, dictproxy.  (Only type objects have a tp_clear
field; the other types are.)
One change was necessary to the GC infrastructure.  We have statically
allocated type objects that don't have a GC header (and can't easily
be given one) and heap-allocated type objects that do have a GC
header.  Giving these different metatypes would be really ugly: I
tried, and I had to modify pickle.py, cPickle.c, copy.py, add a new
invent a new name for the new metatype and make it a built-in, change
affected tests...  In short, a mess.  So instead, we add a new type
slot tp_is_gc, which is a simple Boolean function that determines
whether a particular instance has GC headers or not.  This slot is
only relevant for types that have the (new) GC flag bit set.  If the
tp_is_gc slot is NULL (by far the most common case), all instances of
the type are deemed to have GC headers.  This slot is called by the
PyObject_IS_GC() macro (which is only used twice, both times in
gcmodule.c).
I also changed the extern declarations for a bunch of GC-related
functions (_PyObject_GC_Del etc.): these always exist but objimpl.h
only declared them when WITH_CYCLE_GC was defined, but I needed to be
able to reference them without #ifdefs.  (When WITH_CYCLE_GC is not
defined, they do the same as their non-GC counterparts anyway.)
											
										 
											2001-10-02 21:24:57 +00:00
										 |  |  | 	if (base->tp_flags & Py_TPFLAGS_HAVE_GC) | 
					
						
							|  |  |  | 		type->tp_flags |= Py_TPFLAGS_HAVE_GC; | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-15 22:03:32 +00:00
										 |  |  | 	/* Initialize tp_dict from passed-in dict */ | 
					
						
							|  |  |  | 	type->tp_dict = dict = PyDict_Copy(dict); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	if (dict == NULL) { | 
					
						
							|  |  |  | 		Py_DECREF(type); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-16 09:18:56 +00:00
										 |  |  | 	/* Set __module__ in the dict */ | 
					
						
							|  |  |  | 	if (PyDict_GetItemString(dict, "__module__") == NULL) { | 
					
						
							|  |  |  | 		tmp = PyEval_GetGlobals(); | 
					
						
							|  |  |  | 		if (tmp != NULL) { | 
					
						
							|  |  |  | 			tmp = PyDict_GetItemString(tmp, "__name__"); | 
					
						
							|  |  |  | 			if (tmp != NULL) { | 
					
						
							|  |  |  | 				if (PyDict_SetItemString(dict, "__module__", | 
					
						
							|  |  |  | 							 tmp) < 0) | 
					
						
							|  |  |  | 					return NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-04 05:27:00 +00:00
										 |  |  | 	/* Set tp_doc to a copy of dict['__doc__'], if the latter is there
 | 
					
						
							| 
									
										
										
										
											2002-03-17 18:56:20 +00:00
										 |  |  | 	   and is a string.  The __doc__ accessor will first look for tp_doc; | 
					
						
							|  |  |  | 	   if that fails, it will still look into __dict__. | 
					
						
							| 
									
										
										
										
											2001-10-04 05:27:00 +00:00
										 |  |  | 	*/ | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		PyObject *doc = PyDict_GetItemString(dict, "__doc__"); | 
					
						
							|  |  |  | 		if (doc != NULL && PyString_Check(doc)) { | 
					
						
							|  |  |  | 			const size_t n = (size_t)PyString_GET_SIZE(doc); | 
					
						
							| 
									
										
										
										
											2006-04-11 07:42:36 +00:00
										 |  |  |                         char *tp_doc = (char *)PyObject_MALLOC(n+1); | 
					
						
							| 
									
										
										
										
											2005-12-10 18:50:16 +00:00
										 |  |  | 			if (tp_doc == NULL) { | 
					
						
							| 
									
										
										
										
											2001-10-04 05:27:00 +00:00
										 |  |  | 				Py_DECREF(type); | 
					
						
							|  |  |  | 				return NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2005-12-10 18:50:16 +00:00
										 |  |  | 			memcpy(tp_doc, PyString_AS_STRING(doc), n+1); | 
					
						
							|  |  |  |                         type->tp_doc = tp_doc; | 
					
						
							| 
									
										
										
										
											2001-10-04 05:27:00 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	/* 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__ */ | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  | 	mp = PyHeapType_GET_MEMBERS(et); | 
					
						
							| 
									
										
										
										
											2001-08-29 23:54:54 +00:00
										 |  |  | 	slotoffset = base->tp_basicsize; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	if (slots != NULL) { | 
					
						
							|  |  |  | 		for (i = 0; i < nslots; i++, mp++) { | 
					
						
							|  |  |  | 			mp->name = PyString_AS_STRING( | 
					
						
							|  |  |  | 				PyTuple_GET_ITEM(slots, i)); | 
					
						
							| 
									
										
										
										
											2001-12-04 17:13:22 +00:00
										 |  |  | 			mp->type = T_OBJECT_EX; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 			mp->offset = slotoffset; | 
					
						
							| 
									
										
										
										
											2001-08-17 20:32:36 +00:00
										 |  |  | 			if (base->tp_weaklistoffset == 0 && | 
					
						
							| 
									
										
										
										
											2001-12-04 17:13:22 +00:00
										 |  |  | 			    strcmp(mp->name, "__weakref__") == 0) { | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 				add_weak++; | 
					
						
							| 
									
										
										
										
											2001-12-04 17:13:22 +00:00
										 |  |  | 				mp->type = T_OBJECT; | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | 				mp->flags = READONLY; | 
					
						
							| 
									
										
										
										
											2001-08-17 20:32:36 +00:00
										 |  |  | 				type->tp_weaklistoffset = slotoffset; | 
					
						
							| 
									
										
										
										
											2001-12-04 17:13:22 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 			slotoffset += sizeof(PyObject *); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-08-12 19:05:44 +00:00
										 |  |  | 	if (add_dict) { | 
					
						
							|  |  |  | 		if (base->tp_itemsize) | 
					
						
							|  |  |  | 			type->tp_dictoffset = -(long)sizeof(PyObject *); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			type->tp_dictoffset = slotoffset; | 
					
						
							|  |  |  | 		slotoffset += sizeof(PyObject *); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (add_weak) { | 
					
						
							|  |  |  | 		assert(!base->tp_itemsize); | 
					
						
							|  |  |  | 		type->tp_weaklistoffset = slotoffset; | 
					
						
							|  |  |  | 		slotoffset += sizeof(PyObject *); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	type->tp_basicsize = slotoffset; | 
					
						
							| 
									
										
										
										
											2001-08-30 20:00:07 +00:00
										 |  |  | 	type->tp_itemsize = base->tp_itemsize; | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  | 	type->tp_members = PyHeapType_GET_MEMBERS(et); | 
					
						
							| 
									
										
										
										
											2003-01-07 13:41:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (type->tp_weaklistoffset && type->tp_dictoffset) | 
					
						
							|  |  |  | 		type->tp_getset = subtype_getsets_full; | 
					
						
							|  |  |  | 	else if (type->tp_weaklistoffset && !type->tp_dictoffset) | 
					
						
							|  |  |  | 		type->tp_getset = subtype_getsets_weakref_only; | 
					
						
							|  |  |  | 	else if (!type->tp_weaklistoffset && type->tp_dictoffset) | 
					
						
							|  |  |  | 		type->tp_getset = subtype_getsets_dict_only; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		type->tp_getset = NULL; | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-05 20:51:39 +00:00
										 |  |  | 	/* Enable GC unless there are really no instance variables possible */ | 
					
						
							|  |  |  | 	if (!(type->tp_basicsize == sizeof(PyObject) && | 
					
						
							|  |  |  | 	      type->tp_itemsize == 0)) | 
					
						
							|  |  |  | 		type->tp_flags |= Py_TPFLAGS_HAVE_GC; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	/* Always override allocation strategy to use regular heap */ | 
					
						
							|  |  |  | 	type->tp_alloc = PyType_GenericAlloc; | 
					
						
							| 
									
										
											  
											
												Add Garbage Collection support to new-style classes (not yet to their
instances).
Also added GC support to various auxiliary types: super, property,
descriptors, wrappers, dictproxy.  (Only type objects have a tp_clear
field; the other types are.)
One change was necessary to the GC infrastructure.  We have statically
allocated type objects that don't have a GC header (and can't easily
be given one) and heap-allocated type objects that do have a GC
header.  Giving these different metatypes would be really ugly: I
tried, and I had to modify pickle.py, cPickle.c, copy.py, add a new
invent a new name for the new metatype and make it a built-in, change
affected tests...  In short, a mess.  So instead, we add a new type
slot tp_is_gc, which is a simple Boolean function that determines
whether a particular instance has GC headers or not.  This slot is
only relevant for types that have the (new) GC flag bit set.  If the
tp_is_gc slot is NULL (by far the most common case), all instances of
the type are deemed to have GC headers.  This slot is called by the
PyObject_IS_GC() macro (which is only used twice, both times in
gcmodule.c).
I also changed the extern declarations for a bunch of GC-related
functions (_PyObject_GC_Del etc.): these always exist but objimpl.h
only declared them when WITH_CYCLE_GC was defined, but I needed to be
able to reference them without #ifdefs.  (When WITH_CYCLE_GC is not
defined, they do the same as their non-GC counterparts anyway.)
											
										 
											2001-10-02 21:24:57 +00:00
										 |  |  | 	if (type->tp_flags & Py_TPFLAGS_HAVE_GC) { | 
					
						
							| 
									
										
										
										
											2002-04-12 03:06:53 +00:00
										 |  |  | 		type->tp_free = PyObject_GC_Del; | 
					
						
							| 
									
										
										
										
											2001-10-05 20:51:39 +00:00
										 |  |  | 		type->tp_traverse = subtype_traverse; | 
					
						
							| 
									
										
										
										
											2002-06-04 19:52:53 +00:00
										 |  |  | 		type->tp_clear = subtype_clear; | 
					
						
							| 
									
										
											  
											
												Add Garbage Collection support to new-style classes (not yet to their
instances).
Also added GC support to various auxiliary types: super, property,
descriptors, wrappers, dictproxy.  (Only type objects have a tp_clear
field; the other types are.)
One change was necessary to the GC infrastructure.  We have statically
allocated type objects that don't have a GC header (and can't easily
be given one) and heap-allocated type objects that do have a GC
header.  Giving these different metatypes would be really ugly: I
tried, and I had to modify pickle.py, cPickle.c, copy.py, add a new
invent a new name for the new metatype and make it a built-in, change
affected tests...  In short, a mess.  So instead, we add a new type
slot tp_is_gc, which is a simple Boolean function that determines
whether a particular instance has GC headers or not.  This slot is
only relevant for types that have the (new) GC flag bit set.  If the
tp_is_gc slot is NULL (by far the most common case), all instances of
the type are deemed to have GC headers.  This slot is called by the
PyObject_IS_GC() macro (which is only used twice, both times in
gcmodule.c).
I also changed the extern declarations for a bunch of GC-related
functions (_PyObject_GC_Del etc.): these always exist but objimpl.h
only declared them when WITH_CYCLE_GC was defined, but I needed to be
able to reference them without #ifdefs.  (When WITH_CYCLE_GC is not
defined, they do the same as their non-GC counterparts anyway.)
											
										 
											2001-10-02 21:24:57 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							| 
									
										
										
										
											2002-04-12 03:06:53 +00:00
										 |  |  | 		type->tp_free = PyObject_Del; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* 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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | 	/* Put the proper slots in place */ | 
					
						
							|  |  |  | 	fixup_slot_dispatchers(type); | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i, n; | 
					
						
							| 
									
										
										
										
											2001-11-14 23:32:33 +00:00
										 |  |  | 	PyObject *mro, *res, *base, *dict; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-15 22:03:32 +00:00
										 |  |  | 	/* Look in tp_dict of types in MRO */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	mro = type->tp_mro; | 
					
						
							| 
									
										
										
										
											2002-06-10 14:30:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* If mro is NULL, the type is either not yet initialized
 | 
					
						
							|  |  |  | 	   by PyType_Ready(), or already cleared by type_clear(). | 
					
						
							|  |  |  | 	   Either way the safest thing to do is to return NULL. */ | 
					
						
							|  |  |  | 	if (mro == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	assert(PyTuple_Check(mro)); | 
					
						
							|  |  |  | 	n = PyTuple_GET_SIZE(mro); | 
					
						
							|  |  |  | 	for (i = 0; i < n; i++) { | 
					
						
							| 
									
										
										
										
											2001-11-14 23:32:33 +00:00
										 |  |  | 		base = PyTuple_GET_ITEM(mro, i); | 
					
						
							|  |  |  | 		if (PyClass_Check(base)) | 
					
						
							|  |  |  | 			dict = ((PyClassObject *)base)->cl_dict; | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			assert(PyType_Check(base)); | 
					
						
							|  |  |  | 			dict = ((PyTypeObject *)base)->tp_dict; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		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; | 
					
						
							| 
									
										
										
										
											2002-04-04 17:50:54 +00:00
										 |  |  | 	PyObject *meta_attribute, *attribute; | 
					
						
							|  |  |  | 	descrgetfunc meta_get; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* 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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-04-04 17:50:54 +00:00
										 |  |  | 	/* No readable descriptor found yet */ | 
					
						
							|  |  |  | 	meta_get = NULL; | 
					
						
							| 
									
										
											  
											
												object.h special-build macro minefield:  renamed all the new lexical
helper macros to something saner, and used them appropriately in other
files too, to reduce #ifdef blocks.
classobject.c, instance_dealloc():  One of my worst Python Memories is
trying to fix this routine a few years ago when COUNT_ALLOCS was defined
but Py_TRACE_REFS wasn't.  The special-build code here is way too
complicated.  Now it's much simpler.  Difference:  in a Py_TRACE_REFS
build, the instance is no longer in the doubly-linked list of live
objects while its __del__ method is executing, and that may be visible
via sys.getobjects() called from a __del__ method.  Tough -- the object
is presumed dead while its __del__ is executing anyway, and not calling
_Py_NewReference() at the start allows enormous code simplification.
typeobject.c, call_finalizer():  The special-build instance_dealloc()
pain apparently spread to here too via cut-'n-paste, and this is much
simpler now too.  In addition, I didn't understand why this routine
was calling _PyObject_GC_TRACK() after a resurrection, since there's no
plausible way _PyObject_GC_UNTRACK() could have been called on the
object by this point.  I suspect it was left over from pasting the
instance_delloc() code.  Instead asserted that the object is still
tracked.  Caution:  I suspect we don't have a test that actually
exercises the subtype_dealloc() __del__-resurrected-me code.
											
										 
											2002-07-11 06:23:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-04-04 17:50:54 +00:00
										 |  |  | 	/* Look for the attribute in the metatype */ | 
					
						
							|  |  |  | 	meta_attribute = _PyType_Lookup(metatype, name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (meta_attribute != NULL) { | 
					
						
							|  |  |  | 		meta_get = meta_attribute->ob_type->tp_descr_get; | 
					
						
							| 
									
										
											  
											
												object.h special-build macro minefield:  renamed all the new lexical
helper macros to something saner, and used them appropriately in other
files too, to reduce #ifdef blocks.
classobject.c, instance_dealloc():  One of my worst Python Memories is
trying to fix this routine a few years ago when COUNT_ALLOCS was defined
but Py_TRACE_REFS wasn't.  The special-build code here is way too
complicated.  Now it's much simpler.  Difference:  in a Py_TRACE_REFS
build, the instance is no longer in the doubly-linked list of live
objects while its __del__ method is executing, and that may be visible
via sys.getobjects() called from a __del__ method.  Tough -- the object
is presumed dead while its __del__ is executing anyway, and not calling
_Py_NewReference() at the start allows enormous code simplification.
typeobject.c, call_finalizer():  The special-build instance_dealloc()
pain apparently spread to here too via cut-'n-paste, and this is much
simpler now too.  In addition, I didn't understand why this routine
was calling _PyObject_GC_TRACK() after a resurrection, since there's no
plausible way _PyObject_GC_UNTRACK() could have been called on the
object by this point.  I suspect it was left over from pasting the
instance_delloc() code.  Instead asserted that the object is still
tracked.  Caution:  I suspect we don't have a test that actually
exercises the subtype_dealloc() __del__-resurrected-me code.
											
										 
											2002-07-11 06:23:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-04-04 17:50:54 +00:00
										 |  |  | 		if (meta_get != NULL && PyDescr_IsData(meta_attribute)) { | 
					
						
							|  |  |  | 			/* Data descriptors implement tp_descr_set to intercept
 | 
					
						
							|  |  |  | 			 * writes. Assume the attribute is not overridden in | 
					
						
							|  |  |  | 			 * type's tp_dict (and bases): call the descriptor now. | 
					
						
							|  |  |  | 			 */ | 
					
						
							|  |  |  | 			return meta_get(meta_attribute, (PyObject *)type, | 
					
						
							|  |  |  | 					(PyObject *)metatype); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2003-08-15 13:07:47 +00:00
										 |  |  | 		Py_INCREF(meta_attribute); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-04-04 17:50:54 +00:00
										 |  |  | 	/* No data descriptor found on metatype. Look in tp_dict of this
 | 
					
						
							|  |  |  | 	 * type and its bases */ | 
					
						
							|  |  |  | 	attribute = _PyType_Lookup(type, name); | 
					
						
							|  |  |  | 	if (attribute != NULL) { | 
					
						
							|  |  |  | 		/* Implement descriptor functionality, if any */ | 
					
						
							|  |  |  | 		descrgetfunc local_get = attribute->ob_type->tp_descr_get; | 
					
						
							| 
									
										
										
										
											2003-08-15 13:07:47 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		Py_XDECREF(meta_attribute); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-04-04 17:50:54 +00:00
										 |  |  | 		if (local_get != NULL) { | 
					
						
							|  |  |  | 			/* NULL 2nd argument indicates the descriptor was
 | 
					
						
							|  |  |  | 			 * found on the target object itself (or a base)  */ | 
					
						
							|  |  |  | 			return local_get(attribute, (PyObject *)NULL, | 
					
						
							|  |  |  | 					 (PyObject *)type); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
											  
											
												object.h special-build macro minefield:  renamed all the new lexical
helper macros to something saner, and used them appropriately in other
files too, to reduce #ifdef blocks.
classobject.c, instance_dealloc():  One of my worst Python Memories is
trying to fix this routine a few years ago when COUNT_ALLOCS was defined
but Py_TRACE_REFS wasn't.  The special-build code here is way too
complicated.  Now it's much simpler.  Difference:  in a Py_TRACE_REFS
build, the instance is no longer in the doubly-linked list of live
objects while its __del__ method is executing, and that may be visible
via sys.getobjects() called from a __del__ method.  Tough -- the object
is presumed dead while its __del__ is executing anyway, and not calling
_Py_NewReference() at the start allows enormous code simplification.
typeobject.c, call_finalizer():  The special-build instance_dealloc()
pain apparently spread to here too via cut-'n-paste, and this is much
simpler now too.  In addition, I didn't understand why this routine
was calling _PyObject_GC_TRACK() after a resurrection, since there's no
plausible way _PyObject_GC_UNTRACK() could have been called on the
object by this point.  I suspect it was left over from pasting the
instance_delloc() code.  Instead asserted that the object is still
tracked.  Caution:  I suspect we don't have a test that actually
exercises the subtype_dealloc() __del__-resurrected-me code.
											
										 
											2002-07-11 06:23:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-04-04 17:50:54 +00:00
										 |  |  | 		Py_INCREF(attribute); | 
					
						
							|  |  |  | 		return attribute; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-04-04 17:50:54 +00:00
										 |  |  | 	/* No attribute found in local __dict__ (or bases): use the
 | 
					
						
							|  |  |  | 	 * descriptor from the metatype, if any */ | 
					
						
							| 
									
										
										
										
											2003-08-15 13:07:47 +00:00
										 |  |  | 	if (meta_get != NULL) { | 
					
						
							|  |  |  | 		PyObject *res; | 
					
						
							|  |  |  | 		res = meta_get(meta_attribute, (PyObject *)type, | 
					
						
							|  |  |  | 			       (PyObject *)metatype); | 
					
						
							|  |  |  | 		Py_DECREF(meta_attribute); | 
					
						
							|  |  |  | 		return res; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-04-04 17:50:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* If an ordinary attribute was found on the metatype, return it now */ | 
					
						
							|  |  |  | 	if (meta_attribute != NULL) { | 
					
						
							|  |  |  | 		return meta_attribute; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Give up */ | 
					
						
							|  |  |  | 	PyErr_Format(PyExc_AttributeError, | 
					
						
							| 
									
										
										
										
											2002-04-04 17:50:54 +00:00
										 |  |  | 			 "type object '%.50s' has no attribute '%.400s'", | 
					
						
							|  |  |  | 			 type->tp_name, PyString_AS_STRING(name)); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | type_setattro(PyTypeObject *type, PyObject *name, PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2001-10-15 21:05:10 +00:00
										 |  |  | 	if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { | 
					
						
							|  |  |  | 		PyErr_Format( | 
					
						
							|  |  |  | 			PyExc_TypeError, | 
					
						
							|  |  |  | 			"can't set attributes of built-in/extension type '%s'", | 
					
						
							|  |  |  | 			type->tp_name); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2003-03-24 23:49:49 +00:00
										 |  |  | 	/* XXX Example of how I expect this to be used...
 | 
					
						
							|  |  |  | 	if (update_subclasses(type, name, invalidate_cache, NULL) < 0) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	*/ | 
					
						
							| 
									
										
										
										
											2001-10-15 21:05:10 +00:00
										 |  |  | 	if (PyObject_GenericSetAttr((PyObject *)type, name, value) < 0) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	return update_slot(type, name); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | type_dealloc(PyTypeObject *type) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  | 	PyHeapTypeObject *et; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Assert this is a heap-allocated type object */ | 
					
						
							|  |  |  | 	assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE); | 
					
						
							| 
									
										
											  
											
												Add Garbage Collection support to new-style classes (not yet to their
instances).
Also added GC support to various auxiliary types: super, property,
descriptors, wrappers, dictproxy.  (Only type objects have a tp_clear
field; the other types are.)
One change was necessary to the GC infrastructure.  We have statically
allocated type objects that don't have a GC header (and can't easily
be given one) and heap-allocated type objects that do have a GC
header.  Giving these different metatypes would be really ugly: I
tried, and I had to modify pickle.py, cPickle.c, copy.py, add a new
invent a new name for the new metatype and make it a built-in, change
affected tests...  In short, a mess.  So instead, we add a new type
slot tp_is_gc, which is a simple Boolean function that determines
whether a particular instance has GC headers or not.  This slot is
only relevant for types that have the (new) GC flag bit set.  If the
tp_is_gc slot is NULL (by far the most common case), all instances of
the type are deemed to have GC headers.  This slot is called by the
PyObject_IS_GC() macro (which is only used twice, both times in
gcmodule.c).
I also changed the extern declarations for a bunch of GC-related
functions (_PyObject_GC_Del etc.): these always exist but objimpl.h
only declared them when WITH_CYCLE_GC was defined, but I needed to be
able to reference them without #ifdefs.  (When WITH_CYCLE_GC is not
defined, they do the same as their non-GC counterparts anyway.)
											
										 
											2001-10-02 21:24:57 +00:00
										 |  |  | 	_PyObject_GC_UNTRACK(type); | 
					
						
							| 
									
										
										
										
											2001-10-08 15:18:27 +00:00
										 |  |  | 	PyObject_ClearWeakRefs((PyObject *)type); | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  | 	et = (PyHeapTypeObject *)type; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	Py_XDECREF(type->tp_base); | 
					
						
							|  |  |  | 	Py_XDECREF(type->tp_dict); | 
					
						
							|  |  |  | 	Py_XDECREF(type->tp_bases); | 
					
						
							|  |  |  | 	Py_XDECREF(type->tp_mro); | 
					
						
							| 
									
										
										
										
											2001-10-15 22:03:32 +00:00
										 |  |  | 	Py_XDECREF(type->tp_cache); | 
					
						
							| 
									
										
										
										
											2001-10-08 15:18:27 +00:00
										 |  |  | 	Py_XDECREF(type->tp_subclasses); | 
					
						
							| 
									
										
										
										
											2005-12-10 18:50:16 +00:00
										 |  |  |         /* A type's tp_doc is heap allocated, unlike the tp_doc slots
 | 
					
						
							|  |  |  |          * of most other objects.  It's okay to cast it to char *. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  | 	PyObject_Free((char *)type->tp_doc); | 
					
						
							| 
									
										
										
										
											2006-02-20 22:27:28 +00:00
										 |  |  | 	Py_XDECREF(et->ht_name); | 
					
						
							|  |  |  | 	Py_XDECREF(et->ht_slots); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	type->ob_type->tp_free((PyObject *)type); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-08 15:18:27 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | type_subclasses(PyTypeObject *type, PyObject *args_ignored) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *list, *raw, *ref; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i, n; | 
					
						
							| 
									
										
										
										
											2001-10-08 15:18:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	list = PyList_New(0); | 
					
						
							|  |  |  | 	if (list == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	raw = type->tp_subclasses; | 
					
						
							|  |  |  | 	if (raw == NULL) | 
					
						
							|  |  |  | 		return list; | 
					
						
							|  |  |  | 	assert(PyList_Check(raw)); | 
					
						
							|  |  |  | 	n = PyList_GET_SIZE(raw); | 
					
						
							|  |  |  | 	for (i = 0; i < n; i++) { | 
					
						
							|  |  |  | 		ref = PyList_GET_ITEM(raw, i); | 
					
						
							| 
									
										
										
										
											2001-10-08 16:49:26 +00:00
										 |  |  | 		assert(PyWeakref_CheckRef(ref)); | 
					
						
							| 
									
										
										
										
											2001-10-08 15:18:27 +00:00
										 |  |  | 		ref = PyWeakref_GET_OBJECT(ref); | 
					
						
							|  |  |  | 		if (ref != Py_None) { | 
					
						
							|  |  |  | 			if (PyList_Append(list, ref) < 0) { | 
					
						
							|  |  |  | 				Py_DECREF(list); | 
					
						
							|  |  |  | 				return NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return list; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static PyMethodDef type_methods[] = { | 
					
						
							| 
									
										
										
										
											2001-08-16 13:15:00 +00:00
										 |  |  | 	{"mro", (PyCFunction)mro_external, METH_NOARGS, | 
					
						
							| 
									
										
										
										
											2002-08-13 22:19:13 +00:00
										 |  |  | 	 PyDoc_STR("mro() -> list\nreturn a type's method resolution order")}, | 
					
						
							| 
									
										
										
										
											2001-10-08 15:18:27 +00:00
										 |  |  | 	{"__subclasses__", (PyCFunction)type_subclasses, METH_NOARGS, | 
					
						
							| 
									
										
										
										
											2002-08-13 22:19:13 +00:00
										 |  |  | 	 PyDoc_STR("__subclasses__() -> list of immediate subclasses")}, | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-13 20:33:02 +00:00
										 |  |  | PyDoc_STRVAR(type_doc, | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | "type(object) -> the object's type\n" | 
					
						
							| 
									
										
										
										
											2002-06-13 20:33:02 +00:00
										 |  |  | "type(name, bases, dict) -> a new type"); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Add Garbage Collection support to new-style classes (not yet to their
instances).
Also added GC support to various auxiliary types: super, property,
descriptors, wrappers, dictproxy.  (Only type objects have a tp_clear
field; the other types are.)
One change was necessary to the GC infrastructure.  We have statically
allocated type objects that don't have a GC header (and can't easily
be given one) and heap-allocated type objects that do have a GC
header.  Giving these different metatypes would be really ugly: I
tried, and I had to modify pickle.py, cPickle.c, copy.py, add a new
invent a new name for the new metatype and make it a built-in, change
affected tests...  In short, a mess.  So instead, we add a new type
slot tp_is_gc, which is a simple Boolean function that determines
whether a particular instance has GC headers or not.  This slot is
only relevant for types that have the (new) GC flag bit set.  If the
tp_is_gc slot is NULL (by far the most common case), all instances of
the type are deemed to have GC headers.  This slot is called by the
PyObject_IS_GC() macro (which is only used twice, both times in
gcmodule.c).
I also changed the extern declarations for a bunch of GC-related
functions (_PyObject_GC_Del etc.): these always exist but objimpl.h
only declared them when WITH_CYCLE_GC was defined, but I needed to be
able to reference them without #ifdefs.  (When WITH_CYCLE_GC is not
defined, they do the same as their non-GC counterparts anyway.)
											
										 
											2001-10-02 21:24:57 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | type_traverse(PyTypeObject *type, visitproc visit, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-06-10 15:24:42 +00:00
										 |  |  | 	/* Because of type_is_gc(), the collector only calls this
 | 
					
						
							|  |  |  | 	   for heaptypes. */ | 
					
						
							|  |  |  | 	assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE); | 
					
						
							| 
									
										
											  
											
												Add Garbage Collection support to new-style classes (not yet to their
instances).
Also added GC support to various auxiliary types: super, property,
descriptors, wrappers, dictproxy.  (Only type objects have a tp_clear
field; the other types are.)
One change was necessary to the GC infrastructure.  We have statically
allocated type objects that don't have a GC header (and can't easily
be given one) and heap-allocated type objects that do have a GC
header.  Giving these different metatypes would be really ugly: I
tried, and I had to modify pickle.py, cPickle.c, copy.py, add a new
invent a new name for the new metatype and make it a built-in, change
affected tests...  In short, a mess.  So instead, we add a new type
slot tp_is_gc, which is a simple Boolean function that determines
whether a particular instance has GC headers or not.  This slot is
only relevant for types that have the (new) GC flag bit set.  If the
tp_is_gc slot is NULL (by far the most common case), all instances of
the type are deemed to have GC headers.  This slot is called by the
PyObject_IS_GC() macro (which is only used twice, both times in
gcmodule.c).
I also changed the extern declarations for a bunch of GC-related
functions (_PyObject_GC_Del etc.): these always exist but objimpl.h
only declared them when WITH_CYCLE_GC was defined, but I needed to be
able to reference them without #ifdefs.  (When WITH_CYCLE_GC is not
defined, they do the same as their non-GC counterparts anyway.)
											
										 
											2001-10-02 21:24:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-15 21:47:09 +00:00
										 |  |  | 	Py_VISIT(type->tp_dict); | 
					
						
							|  |  |  | 	Py_VISIT(type->tp_cache); | 
					
						
							|  |  |  | 	Py_VISIT(type->tp_mro); | 
					
						
							|  |  |  | 	Py_VISIT(type->tp_bases); | 
					
						
							|  |  |  | 	Py_VISIT(type->tp_base); | 
					
						
							| 
									
										
										
										
											2002-06-10 15:24:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* There's no need to visit type->tp_subclasses or
 | 
					
						
							| 
									
										
										
										
											2006-02-20 22:27:28 +00:00
										 |  |  | 	   ((PyHeapTypeObject *)type)->ht_slots, because they can't be involved | 
					
						
							| 
									
										
										
										
											2002-06-10 15:24:42 +00:00
										 |  |  | 	   in cycles; tp_subclasses is a list of weak references, | 
					
						
							|  |  |  | 	   and slots is a tuple of strings. */ | 
					
						
							| 
									
										
											  
											
												Add Garbage Collection support to new-style classes (not yet to their
instances).
Also added GC support to various auxiliary types: super, property,
descriptors, wrappers, dictproxy.  (Only type objects have a tp_clear
field; the other types are.)
One change was necessary to the GC infrastructure.  We have statically
allocated type objects that don't have a GC header (and can't easily
be given one) and heap-allocated type objects that do have a GC
header.  Giving these different metatypes would be really ugly: I
tried, and I had to modify pickle.py, cPickle.c, copy.py, add a new
invent a new name for the new metatype and make it a built-in, change
affected tests...  In short, a mess.  So instead, we add a new type
slot tp_is_gc, which is a simple Boolean function that determines
whether a particular instance has GC headers or not.  This slot is
only relevant for types that have the (new) GC flag bit set.  If the
tp_is_gc slot is NULL (by far the most common case), all instances of
the type are deemed to have GC headers.  This slot is called by the
PyObject_IS_GC() macro (which is only used twice, both times in
gcmodule.c).
I also changed the extern declarations for a bunch of GC-related
functions (_PyObject_GC_Del etc.): these always exist but objimpl.h
only declared them when WITH_CYCLE_GC was defined, but I needed to be
able to reference them without #ifdefs.  (When WITH_CYCLE_GC is not
defined, they do the same as their non-GC counterparts anyway.)
											
										 
											2001-10-02 21:24:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | type_clear(PyTypeObject *type) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-06-10 15:24:42 +00:00
										 |  |  | 	/* Because of type_is_gc(), the collector only calls this
 | 
					
						
							|  |  |  | 	   for heaptypes. */ | 
					
						
							|  |  |  | 	assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE); | 
					
						
							| 
									
										
											  
											
												Add Garbage Collection support to new-style classes (not yet to their
instances).
Also added GC support to various auxiliary types: super, property,
descriptors, wrappers, dictproxy.  (Only type objects have a tp_clear
field; the other types are.)
One change was necessary to the GC infrastructure.  We have statically
allocated type objects that don't have a GC header (and can't easily
be given one) and heap-allocated type objects that do have a GC
header.  Giving these different metatypes would be really ugly: I
tried, and I had to modify pickle.py, cPickle.c, copy.py, add a new
invent a new name for the new metatype and make it a built-in, change
affected tests...  In short, a mess.  So instead, we add a new type
slot tp_is_gc, which is a simple Boolean function that determines
whether a particular instance has GC headers or not.  This slot is
only relevant for types that have the (new) GC flag bit set.  If the
tp_is_gc slot is NULL (by far the most common case), all instances of
the type are deemed to have GC headers.  This slot is called by the
PyObject_IS_GC() macro (which is only used twice, both times in
gcmodule.c).
I also changed the extern declarations for a bunch of GC-related
functions (_PyObject_GC_Del etc.): these always exist but objimpl.h
only declared them when WITH_CYCLE_GC was defined, but I needed to be
able to reference them without #ifdefs.  (When WITH_CYCLE_GC is not
defined, they do the same as their non-GC counterparts anyway.)
											
										 
											2001-10-02 21:24:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-10 15:24:42 +00:00
										 |  |  | 	/* The only field we need to clear is tp_mro, which is part of a
 | 
					
						
							|  |  |  | 	   hard cycle (its first element is the class itself) that won't | 
					
						
							|  |  |  | 	   be broken otherwise (it's a tuple and tuples don't have a | 
					
						
							|  |  |  | 	   tp_clear handler).  None of the other fields need to be | 
					
						
							|  |  |  | 	   cleared, and here's why: | 
					
						
							| 
									
										
											  
											
												Add Garbage Collection support to new-style classes (not yet to their
instances).
Also added GC support to various auxiliary types: super, property,
descriptors, wrappers, dictproxy.  (Only type objects have a tp_clear
field; the other types are.)
One change was necessary to the GC infrastructure.  We have statically
allocated type objects that don't have a GC header (and can't easily
be given one) and heap-allocated type objects that do have a GC
header.  Giving these different metatypes would be really ugly: I
tried, and I had to modify pickle.py, cPickle.c, copy.py, add a new
invent a new name for the new metatype and make it a built-in, change
affected tests...  In short, a mess.  So instead, we add a new type
slot tp_is_gc, which is a simple Boolean function that determines
whether a particular instance has GC headers or not.  This slot is
only relevant for types that have the (new) GC flag bit set.  If the
tp_is_gc slot is NULL (by far the most common case), all instances of
the type are deemed to have GC headers.  This slot is called by the
PyObject_IS_GC() macro (which is only used twice, both times in
gcmodule.c).
I also changed the extern declarations for a bunch of GC-related
functions (_PyObject_GC_Del etc.): these always exist but objimpl.h
only declared them when WITH_CYCLE_GC was defined, but I needed to be
able to reference them without #ifdefs.  (When WITH_CYCLE_GC is not
defined, they do the same as their non-GC counterparts anyway.)
											
										 
											2001-10-02 21:24:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-10 15:24:42 +00:00
										 |  |  | 	   tp_dict: | 
					
						
							|  |  |  | 	       It is a dict, so the collector will call its tp_clear. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	   tp_cache: | 
					
						
							|  |  |  | 	       Not used; if it were, it would be a dict. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	   tp_bases, tp_base: | 
					
						
							|  |  |  | 	       If these are involved in a cycle, there must be at least | 
					
						
							|  |  |  | 	       one other, mutable object in the cycle, e.g. a base | 
					
						
							|  |  |  | 	       class's dict; the cycle will be broken that way. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	   tp_subclasses: | 
					
						
							|  |  |  | 	       A list of weak references can't be part of a cycle; and | 
					
						
							|  |  |  | 	       lists have their own tp_clear. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  | 	   slots (in PyHeapTypeObject): | 
					
						
							| 
									
										
										
										
											2002-06-10 15:24:42 +00:00
										 |  |  | 	       A tuple of strings can't be part of a cycle. | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-15 17:28:34 +00:00
										 |  |  | 	Py_CLEAR(type->tp_mro); | 
					
						
							| 
									
										
											  
											
												Add Garbage Collection support to new-style classes (not yet to their
instances).
Also added GC support to various auxiliary types: super, property,
descriptors, wrappers, dictproxy.  (Only type objects have a tp_clear
field; the other types are.)
One change was necessary to the GC infrastructure.  We have statically
allocated type objects that don't have a GC header (and can't easily
be given one) and heap-allocated type objects that do have a GC
header.  Giving these different metatypes would be really ugly: I
tried, and I had to modify pickle.py, cPickle.c, copy.py, add a new
invent a new name for the new metatype and make it a built-in, change
affected tests...  In short, a mess.  So instead, we add a new type
slot tp_is_gc, which is a simple Boolean function that determines
whether a particular instance has GC headers or not.  This slot is
only relevant for types that have the (new) GC flag bit set.  If the
tp_is_gc slot is NULL (by far the most common case), all instances of
the type are deemed to have GC headers.  This slot is called by the
PyObject_IS_GC() macro (which is only used twice, both times in
gcmodule.c).
I also changed the extern declarations for a bunch of GC-related
functions (_PyObject_GC_Del etc.): these always exist but objimpl.h
only declared them when WITH_CYCLE_GC was defined, but I needed to be
able to reference them without #ifdefs.  (When WITH_CYCLE_GC is not
defined, they do the same as their non-GC counterparts anyway.)
											
										 
											2001-10-02 21:24:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | type_is_gc(PyTypeObject *type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return type->tp_flags & Py_TPFLAGS_HEAPTYPE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 */ | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  | 	sizeof(PyHeapTypeObject),		/* tp_basicsize */ | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | 	sizeof(PyMemberDef),			/* tp_itemsize */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	(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 */ | 
					
						
							| 
									
										
											  
											
												Add Garbage Collection support to new-style classes (not yet to their
instances).
Also added GC support to various auxiliary types: super, property,
descriptors, wrappers, dictproxy.  (Only type objects have a tp_clear
field; the other types are.)
One change was necessary to the GC infrastructure.  We have statically
allocated type objects that don't have a GC header (and can't easily
be given one) and heap-allocated type objects that do have a GC
header.  Giving these different metatypes would be really ugly: I
tried, and I had to modify pickle.py, cPickle.c, copy.py, add a new
invent a new name for the new metatype and make it a built-in, change
affected tests...  In short, a mess.  So instead, we add a new type
slot tp_is_gc, which is a simple Boolean function that determines
whether a particular instance has GC headers or not.  This slot is
only relevant for types that have the (new) GC flag bit set.  If the
tp_is_gc slot is NULL (by far the most common case), all instances of
the type are deemed to have GC headers.  This slot is called by the
PyObject_IS_GC() macro (which is only used twice, both times in
gcmodule.c).
I also changed the extern declarations for a bunch of GC-related
functions (_PyObject_GC_Del etc.): these always exist but objimpl.h
only declared them when WITH_CYCLE_GC was defined, but I needed to be
able to reference them without #ifdefs.  (When WITH_CYCLE_GC is not
defined, they do the same as their non-GC counterparts anyway.)
											
										 
											2001-10-02 21:24:57 +00:00
										 |  |  | 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | | 
					
						
							|  |  |  | 		Py_TPFLAGS_BASETYPE,		/* tp_flags */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	type_doc,				/* tp_doc */ | 
					
						
							| 
									
										
											  
											
												Add Garbage Collection support to new-style classes (not yet to their
instances).
Also added GC support to various auxiliary types: super, property,
descriptors, wrappers, dictproxy.  (Only type objects have a tp_clear
field; the other types are.)
One change was necessary to the GC infrastructure.  We have statically
allocated type objects that don't have a GC header (and can't easily
be given one) and heap-allocated type objects that do have a GC
header.  Giving these different metatypes would be really ugly: I
tried, and I had to modify pickle.py, cPickle.c, copy.py, add a new
invent a new name for the new metatype and make it a built-in, change
affected tests...  In short, a mess.  So instead, we add a new type
slot tp_is_gc, which is a simple Boolean function that determines
whether a particular instance has GC headers or not.  This slot is
only relevant for types that have the (new) GC flag bit set.  If the
tp_is_gc slot is NULL (by far the most common case), all instances of
the type are deemed to have GC headers.  This slot is called by the
PyObject_IS_GC() macro (which is only used twice, both times in
gcmodule.c).
I also changed the extern declarations for a bunch of GC-related
functions (_PyObject_GC_Del etc.): these always exist but objimpl.h
only declared them when WITH_CYCLE_GC was defined, but I needed to be
able to reference them without #ifdefs.  (When WITH_CYCLE_GC is not
defined, they do the same as their non-GC counterparts anyway.)
											
										 
											2001-10-02 21:24:57 +00:00
										 |  |  | 	(traverseproc)type_traverse,		/* tp_traverse */ | 
					
						
							|  |  |  | 	(inquiry)type_clear,			/* tp_clear */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	0,					/* tp_richcompare */ | 
					
						
							| 
									
										
										
										
											2001-10-08 15:18:27 +00:00
										 |  |  | 	offsetof(PyTypeObject, tp_weaklist),	/* tp_weaklistoffset */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	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 */ | 
					
						
							| 
									
										
										
										
											2002-04-12 03:06:53 +00:00
										 |  |  | 	PyObject_GC_Del,        		/* tp_free */ | 
					
						
							| 
									
										
											  
											
												Add Garbage Collection support to new-style classes (not yet to their
instances).
Also added GC support to various auxiliary types: super, property,
descriptors, wrappers, dictproxy.  (Only type objects have a tp_clear
field; the other types are.)
One change was necessary to the GC infrastructure.  We have statically
allocated type objects that don't have a GC header (and can't easily
be given one) and heap-allocated type objects that do have a GC
header.  Giving these different metatypes would be really ugly: I
tried, and I had to modify pickle.py, cPickle.c, copy.py, add a new
invent a new name for the new metatype and make it a built-in, change
affected tests...  In short, a mess.  So instead, we add a new type
slot tp_is_gc, which is a simple Boolean function that determines
whether a particular instance has GC headers or not.  This slot is
only relevant for types that have the (new) GC flag bit set.  If the
tp_is_gc slot is NULL (by far the most common case), all instances of
the type are deemed to have GC headers.  This slot is called by the
PyObject_IS_GC() macro (which is only used twice, both times in
gcmodule.c).
I also changed the extern declarations for a bunch of GC-related
functions (_PyObject_GC_Del etc.): these always exist but objimpl.h
only declared them when WITH_CYCLE_GC was defined, but I needed to be
able to reference them without #ifdefs.  (When WITH_CYCLE_GC is not
defined, they do the same as their non-GC counterparts anyway.)
											
										 
											2001-10-02 21:24:57 +00:00
										 |  |  | 	(inquiry)type_is_gc,			/* tp_is_gc */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* The base type of all types (eventually)... except itself. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | object_init(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-02-13 16:30:16 +00:00
										 |  |  | /* If we don't have a tp_new for a new-style class, new will use this one.
 | 
					
						
							|  |  |  |    Therefore this should take no arguments/keywords.  However, this new may | 
					
						
							|  |  |  |    also be inherited by objects that define a tp_init but no tp_new.  These | 
					
						
							|  |  |  |    objects WILL pass argumets to tp_new, because it gets the same args as | 
					
						
							|  |  |  |    tp_init.  So only allow arguments if we aren't using the default init, in | 
					
						
							|  |  |  |    which case we expect init to handle argument parsing. */ | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | object_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (type->tp_init == object_init && (PyTuple_GET_SIZE(args) || | 
					
						
							|  |  |  | 	     (kwds && PyDict_Check(kwds) && PyDict_Size(kwds)))) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  | 				"default __new__ takes no parameters"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return type->tp_alloc(type, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | object_dealloc(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	self->ob_type->tp_free(self); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-12 05:17:56 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | object_repr(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2001-08-16 18:52:43 +00:00
										 |  |  | 	PyTypeObject *type; | 
					
						
							| 
									
										
										
										
											2001-08-24 18:34:26 +00:00
										 |  |  | 	PyObject *mod, *name, *rtn; | 
					
						
							| 
									
										
										
										
											2001-08-12 05:17:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-16 18:52:43 +00:00
										 |  |  | 	type = self->ob_type; | 
					
						
							|  |  |  | 	mod = type_module(type, NULL); | 
					
						
							|  |  |  | 	if (mod == NULL) | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							|  |  |  | 	else if (!PyString_Check(mod)) { | 
					
						
							|  |  |  | 		Py_DECREF(mod); | 
					
						
							|  |  |  | 		mod = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	name = type_name(type, NULL); | 
					
						
							|  |  |  | 	if (name == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	if (mod != NULL && strcmp(PyString_AS_STRING(mod), "__builtin__")) | 
					
						
							| 
									
										
										
										
											2001-09-24 16:03:59 +00:00
										 |  |  | 		rtn = PyString_FromFormat("<%s.%s object at %p>", | 
					
						
							| 
									
										
										
										
											2001-08-24 18:34:26 +00:00
										 |  |  | 					  PyString_AS_STRING(mod), | 
					
						
							|  |  |  | 					  PyString_AS_STRING(name), | 
					
						
							|  |  |  | 					  self); | 
					
						
							| 
									
										
										
										
											2001-08-16 18:52:43 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2001-09-24 16:03:59 +00:00
										 |  |  | 		rtn = PyString_FromFormat("<%s object at %p>", | 
					
						
							| 
									
										
										
										
											2001-08-24 18:34:26 +00:00
										 |  |  | 					  type->tp_name, self); | 
					
						
							| 
									
										
										
										
											2001-08-16 18:52:43 +00:00
										 |  |  | 	Py_XDECREF(mod); | 
					
						
							|  |  |  | 	Py_DECREF(name); | 
					
						
							| 
									
										
										
										
											2001-08-24 18:34:26 +00:00
										 |  |  | 	return rtn; | 
					
						
							| 
									
										
										
										
											2001-08-12 05:17:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | object_str(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unaryfunc f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	f = self->ob_type->tp_repr; | 
					
						
							|  |  |  | 	if (f == NULL) | 
					
						
							|  |  |  | 		f = object_repr; | 
					
						
							|  |  |  | 	return f(self); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-12 05:17:56 +00:00
										 |  |  | static long | 
					
						
							|  |  |  | object_hash(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return _Py_HashPointer(self); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-25 03:43:42 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | object_get_class(PyObject *self, void *closure) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Py_INCREF(self->ob_type); | 
					
						
							|  |  |  | 	return (PyObject *)(self->ob_type); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | equiv_structs(PyTypeObject *a, PyTypeObject *b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return a == b || | 
					
						
							|  |  |  | 	       (a != NULL && | 
					
						
							|  |  |  | 		b != NULL && | 
					
						
							|  |  |  | 		a->tp_basicsize == b->tp_basicsize && | 
					
						
							|  |  |  | 		a->tp_itemsize == b->tp_itemsize && | 
					
						
							|  |  |  | 		a->tp_dictoffset == b->tp_dictoffset && | 
					
						
							|  |  |  | 		a->tp_weaklistoffset == b->tp_weaklistoffset && | 
					
						
							|  |  |  | 		((a->tp_flags & Py_TPFLAGS_HAVE_GC) == | 
					
						
							|  |  |  | 		 (b->tp_flags & Py_TPFLAGS_HAVE_GC))); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | same_slots_added(PyTypeObject *a, PyTypeObject *b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyTypeObject *base = a->tp_base; | 
					
						
							| 
									
										
										
										
											2006-02-16 14:32:27 +00:00
										 |  |  | 	Py_ssize_t size; | 
					
						
							| 
									
										
										
										
											2001-09-25 03:43:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (base != b->tp_base) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	if (equiv_structs(a, base) && equiv_structs(b, base)) | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	size = base->tp_basicsize; | 
					
						
							|  |  |  | 	if (a->tp_dictoffset == size && b->tp_dictoffset == size) | 
					
						
							|  |  |  | 		size += sizeof(PyObject *); | 
					
						
							|  |  |  | 	if (a->tp_weaklistoffset == size && b->tp_weaklistoffset == size) | 
					
						
							|  |  |  | 		size += sizeof(PyObject *); | 
					
						
							|  |  |  | 	return size == a->tp_basicsize && size == b->tp_basicsize; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2006-04-11 07:42:36 +00:00
										 |  |  | compatible_for_assignment(PyTypeObject* oldto, PyTypeObject* newto, char* attr) | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PyTypeObject *newbase, *oldbase; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-11 07:42:36 +00:00
										 |  |  | 	if (newto->tp_dealloc != oldto->tp_dealloc || | 
					
						
							|  |  |  | 	    newto->tp_free != oldto->tp_free) | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "%s assignment: " | 
					
						
							|  |  |  | 			     "'%s' deallocator differs from '%s'", | 
					
						
							|  |  |  | 			     attr, | 
					
						
							| 
									
										
										
										
											2006-04-11 07:42:36 +00:00
										 |  |  | 			     newto->tp_name, | 
					
						
							|  |  |  | 			     oldto->tp_name); | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-04-11 07:42:36 +00:00
										 |  |  | 	newbase = newto; | 
					
						
							|  |  |  | 	oldbase = oldto; | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 	while (equiv_structs(newbase, newbase->tp_base)) | 
					
						
							|  |  |  | 		newbase = newbase->tp_base; | 
					
						
							|  |  |  | 	while (equiv_structs(oldbase, oldbase->tp_base)) | 
					
						
							|  |  |  | 		oldbase = oldbase->tp_base; | 
					
						
							|  |  |  | 	if (newbase != oldbase && | 
					
						
							|  |  |  | 	    (newbase->tp_base != oldbase->tp_base || | 
					
						
							|  |  |  | 	     !same_slots_added(newbase, oldbase))) { | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "%s assignment: " | 
					
						
							|  |  |  | 			     "'%s' object layout differs from '%s'", | 
					
						
							|  |  |  | 			     attr, | 
					
						
							| 
									
										
										
										
											2006-04-11 07:42:36 +00:00
										 |  |  | 			     newto->tp_name, | 
					
						
							|  |  |  | 			     oldto->tp_name); | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-12-07 21:39:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-25 03:43:42 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | object_set_class(PyObject *self, PyObject *value, void *closure) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-04-11 07:42:36 +00:00
										 |  |  | 	PyTypeObject *oldto = self->ob_type; | 
					
						
							|  |  |  | 	PyTypeObject *newto; | 
					
						
							| 
									
										
										
										
											2001-09-25 03:43:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-04-15 01:03:30 +00:00
										 |  |  | 	if (value == NULL) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  | 				"can't delete __class__ attribute"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-09-25 03:43:42 +00:00
										 |  |  | 	if (!PyType_Check(value)) { | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 		  "__class__ must be set to new-style class, not '%s' object", | 
					
						
							|  |  |  | 		  value->ob_type->tp_name); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-04-11 07:42:36 +00:00
										 |  |  | 	newto = (PyTypeObject *)value; | 
					
						
							|  |  |  | 	if (!(newto->tp_flags & Py_TPFLAGS_HEAPTYPE) || | 
					
						
							|  |  |  | 	    !(oldto->tp_flags & Py_TPFLAGS_HEAPTYPE)) | 
					
						
							| 
									
										
										
										
											2002-08-10 05:42:07 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "__class__ assignment: only for heap types"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-04-11 07:42:36 +00:00
										 |  |  | 	if (compatible_for_assignment(newto, oldto, "__class__")) { | 
					
						
							|  |  |  | 		Py_INCREF(newto); | 
					
						
							|  |  |  | 		self->ob_type = newto; | 
					
						
							|  |  |  | 		Py_DECREF(oldto); | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2002-05-24 18:47:47 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2001-09-25 03:43:42 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyGetSetDef object_getsets[] = { | 
					
						
							|  |  |  | 	{"__class__", object_get_class, object_set_class, | 
					
						
							| 
									
										
										
										
											2002-08-13 17:18:45 +00:00
										 |  |  | 	 PyDoc_STR("the object's class")}, | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-02-21 22:02:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Stuff to implement __reduce_ex__ for pickle protocols >= 2.
 | 
					
						
							|  |  |  |    We fall back to helpers in copy_reg for: | 
					
						
							|  |  |  |    - pickle protocols < 2 | 
					
						
							|  |  |  |    - calculating the list of slot names (done only once per class) | 
					
						
							|  |  |  |    - the __newobj__ function (which is used as a token but never called) | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | import_copy_reg(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	static PyObject *copy_reg_str; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!copy_reg_str) { | 
					
						
							|  |  |  | 		copy_reg_str = PyString_InternFromString("copy_reg"); | 
					
						
							|  |  |  | 		if (copy_reg_str == NULL) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return PyImport_Import(copy_reg_str); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | slotnames(PyObject *cls) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *clsdict; | 
					
						
							|  |  |  | 	PyObject *copy_reg; | 
					
						
							|  |  |  | 	PyObject *slotnames; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyType_Check(cls)) { | 
					
						
							|  |  |  | 		Py_INCREF(Py_None); | 
					
						
							|  |  |  | 		return Py_None; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	clsdict = ((PyTypeObject *)cls)->tp_dict; | 
					
						
							|  |  |  | 	slotnames = PyDict_GetItemString(clsdict, "__slotnames__"); | 
					
						
							| 
									
										
										
										
											2005-09-24 22:58:41 +00:00
										 |  |  | 	if (slotnames != NULL && PyList_Check(slotnames)) { | 
					
						
							| 
									
										
										
										
											2003-02-21 22:02:54 +00:00
										 |  |  | 		Py_INCREF(slotnames); | 
					
						
							|  |  |  | 		return slotnames; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	copy_reg = import_copy_reg(); | 
					
						
							|  |  |  | 	if (copy_reg == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	slotnames = PyObject_CallMethod(copy_reg, "_slotnames", "O", cls); | 
					
						
							|  |  |  | 	Py_DECREF(copy_reg); | 
					
						
							|  |  |  | 	if (slotnames != NULL && | 
					
						
							|  |  |  | 	    slotnames != Py_None && | 
					
						
							|  |  |  | 	    !PyList_Check(slotnames)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  | 			"copy_reg._slotnames didn't return a list or None"); | 
					
						
							|  |  |  | 		Py_DECREF(slotnames); | 
					
						
							|  |  |  | 		slotnames = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return slotnames; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | reduce_2(PyObject *obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *cls, *getnewargs; | 
					
						
							|  |  |  | 	PyObject *args = NULL, *args2 = NULL; | 
					
						
							|  |  |  | 	PyObject *getstate = NULL, *state = NULL, *names = NULL; | 
					
						
							|  |  |  | 	PyObject *slots = NULL, *listitems = NULL, *dictitems = NULL; | 
					
						
							|  |  |  | 	PyObject *copy_reg = NULL, *newobj = NULL, *res = NULL; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i, n; | 
					
						
							| 
									
										
										
										
											2003-02-21 22:02:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	cls = PyObject_GetAttrString(obj, "__class__"); | 
					
						
							|  |  |  | 	if (cls == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	getnewargs = PyObject_GetAttrString(obj, "__getnewargs__"); | 
					
						
							|  |  |  | 	if (getnewargs != NULL) { | 
					
						
							|  |  |  | 		args = PyObject_CallObject(getnewargs, NULL); | 
					
						
							|  |  |  | 		Py_DECREF(getnewargs); | 
					
						
							|  |  |  | 		if (args != NULL && !PyTuple_Check(args)) { | 
					
						
							| 
									
										
										
										
											2006-06-18 22:17:29 +00:00
										 |  |  | 			PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 				"__getnewargs__ should return a tuple, " | 
					
						
							|  |  |  | 				"not '%.200s'", args->ob_type->tp_name); | 
					
						
							| 
									
										
										
										
											2003-02-21 22:02:54 +00:00
										 |  |  | 			goto end; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							|  |  |  | 		args = PyTuple_New(0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (args == NULL) | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	getstate = PyObject_GetAttrString(obj, "__getstate__"); | 
					
						
							|  |  |  | 	if (getstate != NULL) { | 
					
						
							|  |  |  | 		state = PyObject_CallObject(getstate, NULL); | 
					
						
							|  |  |  | 		Py_DECREF(getstate); | 
					
						
							| 
									
										
										
										
											2003-06-08 13:19:58 +00:00
										 |  |  | 		if (state == NULL) | 
					
						
							|  |  |  | 			goto end; | 
					
						
							| 
									
										
										
										
											2003-02-21 22:02:54 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2004-02-08 04:21:26 +00:00
										 |  |  | 		PyErr_Clear(); | 
					
						
							| 
									
										
										
										
											2003-02-21 22:02:54 +00:00
										 |  |  | 		state = PyObject_GetAttrString(obj, "__dict__"); | 
					
						
							|  |  |  | 		if (state == NULL) { | 
					
						
							|  |  |  | 			PyErr_Clear(); | 
					
						
							|  |  |  | 			state = Py_None; | 
					
						
							|  |  |  | 			Py_INCREF(state); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		names = slotnames(cls); | 
					
						
							|  |  |  | 		if (names == NULL) | 
					
						
							|  |  |  | 			goto end; | 
					
						
							|  |  |  | 		if (names != Py_None) { | 
					
						
							|  |  |  | 			assert(PyList_Check(names)); | 
					
						
							|  |  |  | 			slots = PyDict_New(); | 
					
						
							|  |  |  | 			if (slots == NULL) | 
					
						
							|  |  |  | 				goto end; | 
					
						
							|  |  |  | 			n = 0; | 
					
						
							|  |  |  | 			/* Can't pre-compute the list size; the list
 | 
					
						
							|  |  |  | 			   is stored on the class so accessible to other | 
					
						
							|  |  |  | 			   threads, which may be run by DECREF */ | 
					
						
							|  |  |  | 			for (i = 0; i < PyList_GET_SIZE(names); i++) { | 
					
						
							|  |  |  | 				PyObject *name, *value; | 
					
						
							|  |  |  | 				name = PyList_GET_ITEM(names, i); | 
					
						
							|  |  |  | 				value = PyObject_GetAttr(obj, name); | 
					
						
							|  |  |  | 				if (value == NULL) | 
					
						
							|  |  |  | 					PyErr_Clear(); | 
					
						
							|  |  |  | 				else { | 
					
						
							|  |  |  | 					int err = PyDict_SetItem(slots, name, | 
					
						
							|  |  |  | 								 value); | 
					
						
							|  |  |  | 					Py_DECREF(value); | 
					
						
							|  |  |  | 					if (err) | 
					
						
							|  |  |  | 						goto end; | 
					
						
							|  |  |  | 					n++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (n) { | 
					
						
							|  |  |  | 				state = Py_BuildValue("(NO)", state, slots); | 
					
						
							|  |  |  | 				if (state == NULL) | 
					
						
							|  |  |  | 					goto end; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyList_Check(obj)) { | 
					
						
							|  |  |  | 		listitems = Py_None; | 
					
						
							|  |  |  | 		Py_INCREF(listitems); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		listitems = PyObject_GetIter(obj); | 
					
						
							|  |  |  | 		if (listitems == NULL) | 
					
						
							|  |  |  | 			goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyDict_Check(obj)) { | 
					
						
							|  |  |  | 		dictitems = Py_None; | 
					
						
							|  |  |  | 		Py_INCREF(dictitems); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		dictitems = PyObject_CallMethod(obj, "iteritems", ""); | 
					
						
							|  |  |  | 		if (dictitems == NULL) | 
					
						
							|  |  |  | 			goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	copy_reg = import_copy_reg(); | 
					
						
							|  |  |  | 	if (copy_reg == NULL) | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	newobj = PyObject_GetAttrString(copy_reg, "__newobj__"); | 
					
						
							|  |  |  | 	if (newobj == NULL) | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	n = PyTuple_GET_SIZE(args); | 
					
						
							|  |  |  | 	args2 = PyTuple_New(n+1); | 
					
						
							|  |  |  | 	if (args2 == NULL) | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	PyTuple_SET_ITEM(args2, 0, cls); | 
					
						
							|  |  |  | 	cls = NULL; | 
					
						
							|  |  |  | 	for (i = 0; i < n; i++) { | 
					
						
							|  |  |  | 		PyObject *v = PyTuple_GET_ITEM(args, i); | 
					
						
							|  |  |  | 		Py_INCREF(v); | 
					
						
							|  |  |  | 		PyTuple_SET_ITEM(args2, i+1, v); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-10-12 19:09:37 +00:00
										 |  |  | 	res = PyTuple_Pack(5, newobj, args2, state, listitems, dictitems); | 
					
						
							| 
									
										
										
										
											2003-02-21 22:02:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   end: | 
					
						
							|  |  |  | 	Py_XDECREF(cls); | 
					
						
							|  |  |  | 	Py_XDECREF(args); | 
					
						
							|  |  |  | 	Py_XDECREF(args2); | 
					
						
							| 
									
										
										
										
											2003-04-09 21:01:42 +00:00
										 |  |  | 	Py_XDECREF(slots); | 
					
						
							| 
									
										
										
										
											2003-02-21 22:02:54 +00:00
										 |  |  | 	Py_XDECREF(state); | 
					
						
							|  |  |  | 	Py_XDECREF(names); | 
					
						
							|  |  |  | 	Py_XDECREF(listitems); | 
					
						
							|  |  |  | 	Py_XDECREF(dictitems); | 
					
						
							|  |  |  | 	Py_XDECREF(copy_reg); | 
					
						
							|  |  |  | 	Py_XDECREF(newobj); | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-25 16:25:58 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2003-02-18 22:05:12 +00:00
										 |  |  | object_reduce_ex(PyObject *self, PyObject *args) | 
					
						
							| 
									
										
										
										
											2001-09-25 16:25:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2003-02-18 22:05:12 +00:00
										 |  |  | 	/* Call copy_reg._reduce_ex(self, proto) */ | 
					
						
							| 
									
										
										
										
											2003-02-21 22:02:54 +00:00
										 |  |  | 	PyObject *reduce, *copy_reg, *res; | 
					
						
							| 
									
										
										
										
											2003-02-18 22:05:12 +00:00
										 |  |  | 	int proto = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyArg_ParseTuple(args, "|i:__reduce_ex__", &proto)) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2001-09-25 16:25:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-02-21 22:02:54 +00:00
										 |  |  | 	reduce = PyObject_GetAttrString(self, "__reduce__"); | 
					
						
							|  |  |  | 	if (reduce == NULL) | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		PyObject *cls, *clsreduce, *objreduce; | 
					
						
							|  |  |  | 		int override; | 
					
						
							|  |  |  | 		cls = PyObject_GetAttrString(self, "__class__"); | 
					
						
							|  |  |  | 		if (cls == NULL) { | 
					
						
							|  |  |  | 			Py_DECREF(reduce); | 
					
						
							| 
									
										
										
										
											2001-09-25 16:25:58 +00:00
										 |  |  | 			return NULL; | 
					
						
							| 
									
										
										
										
											2003-02-21 22:02:54 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		clsreduce = PyObject_GetAttrString(cls, "__reduce__"); | 
					
						
							|  |  |  | 		Py_DECREF(cls); | 
					
						
							|  |  |  | 		if (clsreduce == NULL) { | 
					
						
							|  |  |  | 			Py_DECREF(reduce); | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		objreduce = PyDict_GetItemString(PyBaseObject_Type.tp_dict, | 
					
						
							|  |  |  | 						 "__reduce__"); | 
					
						
							|  |  |  | 		override = (clsreduce != objreduce); | 
					
						
							|  |  |  | 		Py_DECREF(clsreduce); | 
					
						
							|  |  |  | 		if (override) { | 
					
						
							|  |  |  | 			res = PyObject_CallObject(reduce, NULL); | 
					
						
							|  |  |  | 			Py_DECREF(reduce); | 
					
						
							|  |  |  | 			return res; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			Py_DECREF(reduce); | 
					
						
							| 
									
										
										
										
											2001-09-25 16:25:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2003-02-21 22:02:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (proto >= 2) | 
					
						
							|  |  |  | 		return reduce_2(self); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	copy_reg = import_copy_reg(); | 
					
						
							| 
									
										
										
										
											2001-09-25 16:25:58 +00:00
										 |  |  | 	if (!copy_reg) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2003-02-21 22:02:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-02-18 22:05:12 +00:00
										 |  |  | 	res = PyEval_CallMethod(copy_reg, "_reduce_ex", "(Oi)", self, proto); | 
					
						
							| 
									
										
										
										
											2001-09-25 16:25:58 +00:00
										 |  |  | 	Py_DECREF(copy_reg); | 
					
						
							| 
									
										
										
										
											2003-02-21 22:02:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-25 16:25:58 +00:00
										 |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMethodDef object_methods[] = { | 
					
						
							| 
									
										
										
										
											2003-02-18 22:05:12 +00:00
										 |  |  | 	{"__reduce_ex__", object_reduce_ex, METH_VARARGS, | 
					
						
							|  |  |  | 	 PyDoc_STR("helper for pickle")}, | 
					
						
							|  |  |  | 	{"__reduce__", object_reduce_ex, METH_VARARGS, | 
					
						
							| 
									
										
										
										
											2002-08-13 22:19:13 +00:00
										 |  |  | 	 PyDoc_STR("helper for pickle")}, | 
					
						
							| 
									
										
										
										
											2001-09-25 16:25:58 +00:00
										 |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-02-21 22:02:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | PyTypeObject PyBaseObject_Type = { | 
					
						
							|  |  |  | 	PyObject_HEAD_INIT(&PyType_Type) | 
					
						
							|  |  |  |  	0,					/* ob_size */ | 
					
						
							|  |  |  | 	"object",				/* tp_name */ | 
					
						
							|  |  |  | 	sizeof(PyObject),			/* tp_basicsize */ | 
					
						
							|  |  |  | 	0,					/* tp_itemsize */ | 
					
						
							| 
									
										
										
										
											2006-03-30 11:57:00 +00:00
										 |  |  | 	object_dealloc,				/* tp_dealloc */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	0,					/* tp_print */ | 
					
						
							|  |  |  | 	0,			 		/* tp_getattr */ | 
					
						
							|  |  |  | 	0,					/* tp_setattr */ | 
					
						
							|  |  |  | 	0,					/* tp_compare */ | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 	object_repr,				/* tp_repr */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	0,					/* tp_as_number */ | 
					
						
							|  |  |  | 	0,					/* tp_as_sequence */ | 
					
						
							|  |  |  | 	0,					/* tp_as_mapping */ | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 	object_hash,				/* tp_hash */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	0,					/* tp_call */ | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 	object_str,				/* tp_str */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	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 */ | 
					
						
							| 
									
										
										
										
											2002-08-13 22:19:13 +00:00
										 |  |  | 	PyDoc_STR("The most base type"),	/* tp_doc */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	0,					/* tp_traverse */ | 
					
						
							|  |  |  | 	0,					/* tp_clear */ | 
					
						
							|  |  |  | 	0,					/* tp_richcompare */ | 
					
						
							|  |  |  | 	0,					/* tp_weaklistoffset */ | 
					
						
							|  |  |  | 	0,					/* tp_iter */ | 
					
						
							|  |  |  | 	0,					/* tp_iternext */ | 
					
						
							| 
									
										
										
										
											2001-09-25 16:25:58 +00:00
										 |  |  | 	object_methods,				/* tp_methods */ | 
					
						
							| 
									
										
										
										
											2001-09-25 03:43:42 +00:00
										 |  |  | 	0,					/* tp_members */ | 
					
						
							|  |  |  | 	object_getsets,				/* tp_getset */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	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 */ | 
					
						
							| 
									
										
										
										
											2003-02-13 16:30:16 +00:00
										 |  |  | 	object_new,				/* tp_new */ | 
					
						
							| 
									
										
										
										
											2002-04-12 03:06:53 +00:00
										 |  |  | 	PyObject_Del,           		/* 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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2001-10-15 22:03:32 +00:00
										 |  |  | 	PyObject *dict = type->tp_dict; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for (; meth->ml_name != NULL; meth++) { | 
					
						
							|  |  |  | 		PyObject *descr; | 
					
						
							| 
									
										
										
										
											2003-12-13 11:26:12 +00:00
										 |  |  | 		if (PyDict_GetItemString(dict, meth->ml_name) && | 
					
						
							|  |  |  | 			!(meth->ml_flags & METH_COEXIST)) | 
					
						
							|  |  |  | 				continue; | 
					
						
							| 
									
										
										
										
											2002-03-28 05:33:33 +00:00
										 |  |  | 		if (meth->ml_flags & METH_CLASS) { | 
					
						
							|  |  |  | 			if (meth->ml_flags & METH_STATIC) { | 
					
						
							|  |  |  | 				PyErr_SetString(PyExc_ValueError, | 
					
						
							|  |  |  | 				     "method cannot be both class and static"); | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2002-12-09 22:56:13 +00:00
										 |  |  | 			descr = PyDescr_NewClassMethod(type, meth); | 
					
						
							| 
									
										
										
										
											2002-03-28 05:33:33 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else if (meth->ml_flags & METH_STATIC) { | 
					
						
							| 
									
										
										
										
											2003-02-11 17:12:46 +00:00
										 |  |  | 			PyObject *cfunc = PyCFunction_New(meth, NULL); | 
					
						
							|  |  |  | 			if (cfunc == NULL) | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			descr = PyStaticMethod_New(cfunc); | 
					
						
							|  |  |  | 			Py_DECREF(cfunc); | 
					
						
							| 
									
										
										
										
											2002-03-28 05:33:33 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			descr = PyDescr_NewMethod(type, meth); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		if (descr == NULL) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							| 
									
										
										
										
											2002-03-28 05:33:33 +00:00
										 |  |  | 		if (PyDict_SetItemString(dict, meth->ml_name, descr) < 0) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 			return -1; | 
					
						
							|  |  |  | 		Py_DECREF(descr); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | add_members(PyTypeObject *type, PyMemberDef *memb) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2001-10-15 22:03:32 +00:00
										 |  |  | 	PyObject *dict = type->tp_dict; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	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 | 
					
						
							| 
									
										
										
										
											2001-09-20 21:45:26 +00:00
										 |  |  | add_getset(PyTypeObject *type, PyGetSetDef *gsp) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2001-10-15 22:03:32 +00:00
										 |  |  | 	PyObject *dict = type->tp_dict; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-16 14:32:27 +00:00
										 |  |  | 	Py_ssize_t 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 */ | 
					
						
							| 
									
										
										
										
											2001-08-29 23:54:54 +00:00
										 |  |  | 	oldsize = base->tp_basicsize; | 
					
						
							|  |  |  | 	newsize = type->tp_basicsize ? type->tp_basicsize : oldsize; | 
					
						
							|  |  |  | 	if (!(type->tp_flags & Py_TPFLAGS_HAVE_GC) && | 
					
						
							|  |  |  | 	    (base->tp_flags & Py_TPFLAGS_HAVE_GC) && | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 	    (type->tp_flags & Py_TPFLAGS_HAVE_RICHCOMPARE/*GC slots exist*/) && | 
					
						
							|  |  |  | 	    (!type->tp_traverse && !type->tp_clear)) { | 
					
						
							| 
									
										
										
										
											2001-08-29 23:54:54 +00:00
										 |  |  | 		type->tp_flags |= Py_TPFLAGS_HAVE_GC; | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 		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) { | 
					
						
							| 
									
										
										
										
											2001-12-17 17:14:22 +00:00
										 |  |  | 		/* The condition below could use some explanation.
 | 
					
						
							|  |  |  | 		   It appears that tp_new is not inherited for static types | 
					
						
							|  |  |  | 		   whose base class is 'object'; this seems to be a precaution | 
					
						
							|  |  |  | 		   so that old extension types don't suddenly become | 
					
						
							|  |  |  | 		   callable (object.__new__ wouldn't insure the invariants | 
					
						
							|  |  |  | 		   that the extension type's own factory function ensures). | 
					
						
							|  |  |  | 		   Heap types, of course, are under our control, so they do | 
					
						
							|  |  |  | 		   inherit tp_new; static extension types that specify some | 
					
						
							|  |  |  | 		   other built-in type as the default are considered | 
					
						
							|  |  |  | 		   new-style-aware so they also inherit object.__new__. */ | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 		if (base != &PyBaseObject_Type || | 
					
						
							|  |  |  | 		    (type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { | 
					
						
							|  |  |  | 			if (type->tp_new == NULL) | 
					
						
							|  |  |  | 				type->tp_new = base->tp_new; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-29 23:54:54 +00:00
										 |  |  | 	type->tp_basicsize = newsize; | 
					
						
							| 
									
										
										
										
											2001-08-14 20:04:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Copy other non-function slots */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef COPYVAL
 | 
					
						
							|  |  |  | #define COPYVAL(SLOT) \
 | 
					
						
							|  |  |  | 	if (type->SLOT == 0) type->SLOT = base->SLOT | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	COPYVAL(tp_itemsize); | 
					
						
							|  |  |  | 	if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_WEAKREFS) { | 
					
						
							|  |  |  | 		COPYVAL(tp_weaklistoffset); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_CLASS) { | 
					
						
							|  |  |  | 		COPYVAL(tp_dictoffset); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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-10-12 14:13:21 +00:00
										 |  |  | #undef COPYBUF
 | 
					
						
							| 
									
										
										
										
											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-10-12 02:38:24 +00:00
										 |  |  | #define COPYBUF(SLOT) COPYSLOT(tp_as_buffer->SLOT)
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-03-07 18:50:55 +00:00
										 |  |  | 		if (base->tp_flags & Py_TPFLAGS_HAVE_INDEX) { | 
					
						
							|  |  |  | 			COPYNUM(nb_index); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											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-10-12 02:38:24 +00:00
										 |  |  | 	if (type->tp_as_buffer != NULL && base->tp_as_buffer != NULL) { | 
					
						
							|  |  |  | 		basebase = base->tp_base; | 
					
						
							|  |  |  | 		if (basebase->tp_as_buffer == NULL) | 
					
						
							|  |  |  | 			basebase = NULL; | 
					
						
							|  |  |  | 		COPYBUF(bf_getreadbuffer); | 
					
						
							|  |  |  | 		COPYBUF(bf_getwritebuffer); | 
					
						
							|  |  |  | 		COPYBUF(bf_getsegcount); | 
					
						
							|  |  |  | 		COPYBUF(bf_getcharbuffer); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 	basebase = base->tp_base; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	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); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 	/* tp_hash see tp_richcompare */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	COPYSLOT(tp_call); | 
					
						
							|  |  |  | 	COPYSLOT(tp_str); | 
					
						
							|  |  |  | 	if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_RICHCOMPARE) { | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 		if (type->tp_compare == NULL && | 
					
						
							|  |  |  | 		    type->tp_richcompare == NULL && | 
					
						
							|  |  |  | 		    type->tp_hash == NULL) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 			type->tp_compare = base->tp_compare; | 
					
						
							|  |  |  | 			type->tp_richcompare = base->tp_richcompare; | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 			type->tp_hash = base->tp_hash; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		COPYSLOT(tp_compare); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2002-04-05 17:10:16 +00:00
										 |  |  | 		COPYSLOT(tp_is_gc); | 
					
						
							| 
									
										
										
										
											2003-05-21 21:29:48 +00:00
										 |  |  | 		if ((type->tp_flags & Py_TPFLAGS_HAVE_GC) == | 
					
						
							|  |  |  | 		    (base->tp_flags & Py_TPFLAGS_HAVE_GC)) { | 
					
						
							|  |  |  | 			/* They agree about gc. */ | 
					
						
							|  |  |  | 			COPYSLOT(tp_free); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if ((type->tp_flags & Py_TPFLAGS_HAVE_GC) && | 
					
						
							|  |  |  | 			 type->tp_free == NULL && | 
					
						
							|  |  |  | 			 base->tp_free == _PyObject_Del) { | 
					
						
							|  |  |  | 			/* A bit of magic to plug in the correct default
 | 
					
						
							|  |  |  | 			 * tp_free function when a derived class adds gc, | 
					
						
							|  |  |  | 			 * didn't define tp_free, and the base uses the | 
					
						
							|  |  |  | 			 * default non-gc tp_free. | 
					
						
							|  |  |  | 			 */ | 
					
						
							|  |  |  | 			type->tp_free = PyObject_GC_Del; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		/* else they didn't agree about gc, and there isn't something
 | 
					
						
							|  |  |  | 		 * obvious to be done -- the type is on its own. | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 16:30:39 +00:00
										 |  |  | static int add_operators(PyTypeObject *); | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2001-10-15 21:05:10 +00:00
										 |  |  | 	PyObject *dict, *bases; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	PyTypeObject *base; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i, n; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-10 15:29:03 +00:00
										 |  |  | 	if (type->tp_flags & Py_TPFLAGS_READY) { | 
					
						
							|  |  |  | 		assert(type->tp_dict != NULL); | 
					
						
							| 
									
										
										
										
											2001-08-10 17:39:49 +00:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2002-06-10 15:29:03 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-10 17:39:49 +00:00
										 |  |  | 	assert((type->tp_flags & Py_TPFLAGS_READYING) == 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	type->tp_flags |= Py_TPFLAGS_READYING; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-23 03:33:13 +00:00
										 |  |  | #ifdef Py_TRACE_REFS
 | 
					
						
							|  |  |  | 	/* PyType_Ready is the closest thing we have to a choke point
 | 
					
						
							|  |  |  | 	 * for type objects, so is the best place I can think of to try | 
					
						
							|  |  |  | 	 * to get type objects into the doubly-linked list of all objects. | 
					
						
							|  |  |  | 	 * Still, not all type objects go thru PyType_Ready. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2003-03-23 17:52:28 +00:00
										 |  |  | 	_Py_AddToAllObjects((PyObject *)type, 0); | 
					
						
							| 
									
										
										
										
											2003-03-23 03:33:13 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	/* Initialize tp_base (defaults to BaseObject unless that's us) */ | 
					
						
							|  |  |  | 	base = type->tp_base; | 
					
						
							| 
									
										
										
										
											2004-08-18 13:16:54 +00:00
										 |  |  | 	if (base == NULL && type != &PyBaseObject_Type) { | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		base = type->tp_base = &PyBaseObject_Type; | 
					
						
							| 
									
										
										
										
											2004-08-18 13:16:54 +00:00
										 |  |  | 		Py_INCREF(base); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-10 02:04:28 +00:00
										 |  |  |         /* Now the only way base can still be NULL is if type is
 | 
					
						
							|  |  |  |          * &PyBaseObject_Type. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-08-14 17:26:30 +00:00
										 |  |  | 	/* Initialize the base class */ | 
					
						
							|  |  |  | 	if (base && base->tp_dict == NULL) { | 
					
						
							|  |  |  | 		if (PyType_Ready(base) < 0) | 
					
						
							|  |  |  | 			goto error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-04-08 01:38:42 +00:00
										 |  |  | 	/* Initialize ob_type if NULL.  This means extensions that want to be
 | 
					
						
							|  |  |  | 	   compilable separately on Windows can call PyType_Ready() instead of | 
					
						
							|  |  |  | 	   initializing the ob_type field of their type objects. */ | 
					
						
							| 
									
										
										
										
											2006-03-10 02:04:28 +00:00
										 |  |  |         /* The test for base != NULL is really unnecessary, since base is only
 | 
					
						
							|  |  |  |            NULL when type is &PyBaseObject_Type, and we know its ob_type is | 
					
						
							|  |  |  |            not NULL (it's initialized to &PyType_Type).  But coverity doesn't | 
					
						
							|  |  |  |            know that. */ | 
					
						
							|  |  |  | 	if (type->ob_type == NULL && base != NULL) | 
					
						
							| 
									
										
										
										
											2002-04-08 01:38:42 +00:00
										 |  |  | 		type->ob_type = base->ob_type; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	/* Initialize tp_bases */ | 
					
						
							|  |  |  | 	bases = type->tp_bases; | 
					
						
							|  |  |  | 	if (bases == NULL) { | 
					
						
							|  |  |  | 		if (base == NULL) | 
					
						
							|  |  |  | 			bases = PyTuple_New(0); | 
					
						
							|  |  |  | 		else | 
					
						
							| 
									
										
										
										
											2003-10-12 19:09:37 +00:00
										 |  |  | 			bases = PyTuple_Pack(1, base); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-15 22:03:32 +00:00
										 |  |  | 	/* Initialize tp_dict */ | 
					
						
							|  |  |  | 	dict = type->tp_dict; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	if (dict == NULL) { | 
					
						
							|  |  |  | 		dict = PyDict_New(); | 
					
						
							|  |  |  | 		if (dict == NULL) | 
					
						
							| 
									
										
										
										
											2001-08-10 17:39:49 +00:00
										 |  |  | 			goto error; | 
					
						
							| 
									
										
										
										
											2001-10-15 22:03:32 +00:00
										 |  |  | 		type->tp_dict = dict; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-15 22:03:32 +00:00
										 |  |  | 	/* Add type-specific descriptors to tp_dict */ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	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
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* 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 */ | 
					
						
							| 
									
										
										
										
											2001-10-15 21:05:10 +00:00
										 |  |  | 	bases = type->tp_mro; | 
					
						
							|  |  |  | 	assert(bases != NULL); | 
					
						
							|  |  |  | 	assert(PyTuple_Check(bases)); | 
					
						
							|  |  |  | 	n = PyTuple_GET_SIZE(bases); | 
					
						
							|  |  |  | 	for (i = 1; i < n; i++) { | 
					
						
							| 
									
										
										
										
											2001-11-14 23:32:33 +00:00
										 |  |  | 		PyObject *b = PyTuple_GET_ITEM(bases, i); | 
					
						
							|  |  |  | 		if (PyType_Check(b)) | 
					
						
							|  |  |  | 			inherit_slots(type, (PyTypeObject *)b); | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-05-21 21:29:48 +00:00
										 |  |  | 	/* Sanity check for tp_free. */ | 
					
						
							|  |  |  | 	if (PyType_IS_GC(type) && (type->tp_flags & Py_TPFLAGS_BASETYPE) && | 
					
						
							|  |  |  | 	    (type->tp_free == NULL || type->tp_free == PyObject_Del)) { | 
					
						
							|  |  |  | 	    	/* This base class needs to call tp_free, but doesn't have
 | 
					
						
							|  |  |  | 	    	 * one, or its tp_free is for non-gc'ed objects. | 
					
						
							|  |  |  | 	    	 */ | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_TypeError, "type '%.100s' participates in " | 
					
						
							|  |  |  | 			     "gc and is a base type but has inappropriate " | 
					
						
							|  |  |  | 			     "tp_free slot", | 
					
						
							|  |  |  | 			     type->tp_name); | 
					
						
							|  |  |  | 		goto error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-02-18 17:46:48 +00:00
										 |  |  | 	/* if the type dictionary doesn't contain a __doc__, set it from
 | 
					
						
							|  |  |  | 	   the tp_doc slot. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if (PyDict_GetItemString(type->tp_dict, "__doc__") == NULL) { | 
					
						
							|  |  |  | 		if (type->tp_doc != NULL) { | 
					
						
							|  |  |  | 			PyObject *doc = PyString_FromString(type->tp_doc); | 
					
						
							| 
									
										
										
										
											2006-07-21 05:32:28 +00:00
										 |  |  | 			if (doc == NULL) | 
					
						
							|  |  |  | 				goto error; | 
					
						
							| 
									
										
										
										
											2002-02-18 17:46:48 +00:00
										 |  |  | 			PyDict_SetItemString(type->tp_dict, "__doc__", doc); | 
					
						
							|  |  |  | 			Py_DECREF(doc); | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2002-04-03 02:13:37 +00:00
										 |  |  | 			PyDict_SetItemString(type->tp_dict, | 
					
						
							|  |  |  | 					     "__doc__", Py_None); | 
					
						
							| 
									
										
										
										
											2002-02-18 17:46:48 +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; | 
					
						
							| 
									
										
										
										
											2003-02-11 20:39:59 +00:00
										 |  |  | 		if (type->tp_as_buffer == NULL) | 
					
						
							|  |  |  | 			type->tp_as_buffer = base->tp_as_buffer; | 
					
						
							| 
									
										
										
										
											2001-08-10 21:24:08 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-08 15:18:27 +00:00
										 |  |  | 	/* Link into each base class's list of subclasses */ | 
					
						
							|  |  |  | 	bases = type->tp_bases; | 
					
						
							|  |  |  | 	n = PyTuple_GET_SIZE(bases); | 
					
						
							|  |  |  | 	for (i = 0; i < n; i++) { | 
					
						
							| 
									
										
										
										
											2001-11-14 23:32:33 +00:00
										 |  |  | 		PyObject *b = PyTuple_GET_ITEM(bases, i); | 
					
						
							|  |  |  | 		if (PyType_Check(b) && | 
					
						
							|  |  |  | 		    add_subclass((PyTypeObject *)b, type) < 0) | 
					
						
							| 
									
										
										
										
											2001-10-08 15:18:27 +00:00
										 |  |  | 			goto error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-08 15:18:27 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | add_subclass(PyTypeObject *base, PyTypeObject *type) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-16 14:32:27 +00:00
										 |  |  | 	Py_ssize_t i; | 
					
						
							|  |  |  | 	int result; | 
					
						
							| 
									
										
										
										
											2006-04-11 07:42:36 +00:00
										 |  |  | 	PyObject *list, *ref, *newobj; | 
					
						
							| 
									
										
										
										
											2001-10-08 15:18:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	list = base->tp_subclasses; | 
					
						
							|  |  |  | 	if (list == NULL) { | 
					
						
							|  |  |  | 		base->tp_subclasses = list = PyList_New(0); | 
					
						
							|  |  |  | 		if (list == NULL) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	assert(PyList_Check(list)); | 
					
						
							| 
									
										
										
										
											2006-04-11 07:42:36 +00:00
										 |  |  | 	newobj = PyWeakref_NewRef((PyObject *)type, NULL); | 
					
						
							| 
									
										
										
										
											2001-10-08 15:18:27 +00:00
										 |  |  | 	i = PyList_GET_SIZE(list); | 
					
						
							|  |  |  | 	while (--i >= 0) { | 
					
						
							|  |  |  | 		ref = PyList_GET_ITEM(list, i); | 
					
						
							|  |  |  | 		assert(PyWeakref_CheckRef(ref)); | 
					
						
							| 
									
										
										
										
											2002-10-18 13:51:49 +00:00
										 |  |  | 		if (PyWeakref_GET_OBJECT(ref) == Py_None) | 
					
						
							| 
									
										
										
										
											2006-04-11 07:42:36 +00:00
										 |  |  | 			return PyList_SetItem(list, i, newobj); | 
					
						
							| 
									
										
										
										
											2001-10-08 15:18:27 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-04-11 07:42:36 +00:00
										 |  |  | 	result = PyList_Append(list, newobj); | 
					
						
							|  |  |  | 	Py_DECREF(newobj); | 
					
						
							| 
									
										
										
										
											2006-02-16 14:32:27 +00:00
										 |  |  | 	return result; | 
					
						
							| 
									
										
										
										
											2001-10-08 15:18:27 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | remove_subclass(PyTypeObject *base, PyTypeObject *type) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i; | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | 	PyObject *list, *ref; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	list = base->tp_subclasses; | 
					
						
							|  |  |  | 	if (list == NULL) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	assert(PyList_Check(list)); | 
					
						
							|  |  |  | 	i = PyList_GET_SIZE(list); | 
					
						
							|  |  |  | 	while (--i >= 0) { | 
					
						
							|  |  |  | 		ref = PyList_GET_ITEM(list, i); | 
					
						
							|  |  |  | 		assert(PyWeakref_CheckRef(ref)); | 
					
						
							|  |  |  | 		if (PyWeakref_GET_OBJECT(ref) == (PyObject*)type) { | 
					
						
							|  |  |  | 			/* this can't fail, right? */ | 
					
						
							|  |  |  | 			PySequence_DelItem(list, i); | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | check_num_args(PyObject *ob, int n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!PyTuple_CheckExact(ob)) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_SystemError, | 
					
						
							|  |  |  | 		    "PyArg_UnpackTuple() argument list is not a tuple"); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (n == PyTuple_GET_SIZE(ob)) | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	PyErr_Format( | 
					
						
							|  |  |  | 	    PyExc_TypeError,  | 
					
						
							| 
									
										
										
										
											2006-02-16 06:54:25 +00:00
										 |  |  | 	    "expected %d arguments, got %zd", n, PyTuple_GET_SIZE(ob)); | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 * | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | wrap_lenfunc(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	lenfunc func = (lenfunc)wrapped; | 
					
						
							|  |  |  | 	Py_ssize_t res; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	if (!check_num_args(args, 0)) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	res = (*func)(self); | 
					
						
							|  |  |  | 	if (res == -1 && PyErr_Occurred()) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	return PyInt_FromLong((long)res); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-10-11 17:29:04 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_inquirypred(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	inquiry func = (inquiry)wrapped; | 
					
						
							|  |  |  | 	int res; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	if (!check_num_args(args, 0)) | 
					
						
							| 
									
										
										
										
											2003-10-11 17:29:04 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	res = (*func)(self); | 
					
						
							|  |  |  | 	if (res == -1 && PyErr_Occurred()) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	return PyBool_FromLong((long)res); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_binaryfunc(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	binaryfunc func = (binaryfunc)wrapped; | 
					
						
							|  |  |  | 	PyObject *other; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	if (!check_num_args(args, 1)) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	other = PyTuple_GET_ITEM(args, 0); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	return (*func)(self, other); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-09 11:07:24 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_binaryfunc_l(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	binaryfunc func = (binaryfunc)wrapped; | 
					
						
							|  |  |  | 	PyObject *other; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	if (!check_num_args(args, 1)) | 
					
						
							| 
									
										
										
										
											2001-10-09 11:07:24 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	other = PyTuple_GET_ITEM(args, 0); | 
					
						
							| 
									
										
										
										
											2001-10-09 11:07:24 +00:00
										 |  |  | 	if (!(self->ob_type->tp_flags & Py_TPFLAGS_CHECKTYPES) && | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | 	    !PyType_IsSubtype(other->ob_type, self->ob_type)) { | 
					
						
							| 
									
										
										
										
											2001-10-09 11:07:24 +00:00
										 |  |  | 		Py_INCREF(Py_NotImplemented); | 
					
						
							|  |  |  | 		return Py_NotImplemented; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return (*func)(self, other); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_binaryfunc_r(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	binaryfunc func = (binaryfunc)wrapped; | 
					
						
							|  |  |  | 	PyObject *other; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	if (!check_num_args(args, 1)) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	other = PyTuple_GET_ITEM(args, 0); | 
					
						
							| 
									
										
										
										
											2001-10-09 11:07:24 +00:00
										 |  |  | 	if (!(self->ob_type->tp_flags & Py_TPFLAGS_CHECKTYPES) && | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | 	    !PyType_IsSubtype(other->ob_type, self->ob_type)) { | 
					
						
							| 
									
										
										
										
											2001-10-09 11:07:24 +00:00
										 |  |  | 		Py_INCREF(Py_NotImplemented); | 
					
						
							|  |  |  | 		return Py_NotImplemented; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	return (*func)(other, self); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-27 20:30:07 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_coercefunc(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	coercion func = (coercion)wrapped; | 
					
						
							|  |  |  | 	PyObject *other, *res; | 
					
						
							|  |  |  | 	int ok; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	if (!check_num_args(args, 1)) | 
					
						
							| 
									
										
										
										
											2001-09-27 20:30:07 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	other = PyTuple_GET_ITEM(args, 0); | 
					
						
							| 
									
										
										
										
											2001-09-27 20:30:07 +00:00
										 |  |  | 	ok = func(&self, &other); | 
					
						
							|  |  |  | 	if (ok < 0) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	if (ok > 0) { | 
					
						
							|  |  |  | 		Py_INCREF(Py_NotImplemented); | 
					
						
							|  |  |  | 		return Py_NotImplemented; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	res = PyTuple_New(2); | 
					
						
							|  |  |  | 	if (res == NULL) { | 
					
						
							|  |  |  | 		Py_DECREF(self); | 
					
						
							|  |  |  | 		Py_DECREF(other); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	PyTuple_SET_ITEM(res, 0, self); | 
					
						
							|  |  |  | 	PyTuple_SET_ITEM(res, 1, other); | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 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__() */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-10-11 19:32:18 +00:00
										 |  |  | 	if (!PyArg_UnpackTuple(args, "", 1, 2, &other, &third)) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	return (*func)(self, other, third); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-28 22:58:52 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_ternaryfunc_r(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ternaryfunc func = (ternaryfunc)wrapped; | 
					
						
							|  |  |  | 	PyObject *other; | 
					
						
							|  |  |  | 	PyObject *third = Py_None; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Note: This wrapper only works for __pow__() */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-10-11 19:32:18 +00:00
										 |  |  | 	if (!PyArg_UnpackTuple(args, "", 1, 2, &other, &third)) | 
					
						
							| 
									
										
										
										
											2001-09-28 22:58:52 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	return (*func)(other, self, third); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_unaryfunc(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unaryfunc func = (unaryfunc)wrapped; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	if (!check_num_args(args, 0)) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	return (*func)(self); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2006-03-30 14:04:02 +00:00
										 |  |  | wrap_indexargfunc(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	ssizeargfunc func = (ssizeargfunc)wrapped; | 
					
						
							| 
									
										
										
										
											2006-03-30 14:04:02 +00:00
										 |  |  | 	PyObject* o; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-30 14:04:02 +00:00
										 |  |  | 	if (!PyArg_UnpackTuple(args, "", 1, 1, &o)) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2006-08-12 17:03:09 +00:00
										 |  |  | 	i = PyNumber_AsSsize_t(o, PyExc_OverflowError); | 
					
						
							| 
									
										
										
										
											2006-03-30 14:04:02 +00:00
										 |  |  | 	if (i == -1 && PyErr_Occurred()) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	return (*func)(self, i); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | static Py_ssize_t | 
					
						
							| 
									
										
										
										
											2001-08-17 21:57:47 +00:00
										 |  |  | getindex(PyObject *self, PyObject *arg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i; | 
					
						
							| 
									
										
										
										
											2001-08-17 21:57:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-12 17:03:09 +00:00
										 |  |  | 	i = PyNumber_AsSsize_t(arg, PyExc_OverflowError); | 
					
						
							| 
									
										
										
										
											2001-08-17 21:57:47 +00:00
										 |  |  | 	if (i == -1 && PyErr_Occurred()) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	if (i < 0) { | 
					
						
							|  |  |  | 		PySequenceMethods *sq = self->ob_type->tp_as_sequence; | 
					
						
							|  |  |  | 		if (sq && sq->sq_length) { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 			Py_ssize_t n = (*sq->sq_length)(self); | 
					
						
							| 
									
										
										
										
											2001-08-17 21:57:47 +00:00
										 |  |  | 			if (n < 0) | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			i += n; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return i; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_sq_item(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	ssizeargfunc func = (ssizeargfunc)wrapped; | 
					
						
							| 
									
										
										
										
											2001-08-17 21:57:47 +00:00
										 |  |  | 	PyObject *arg; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i; | 
					
						
							| 
									
										
										
										
											2001-08-17 21:57:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-03 12:09:30 +00:00
										 |  |  | 	if (PyTuple_GET_SIZE(args) == 1) { | 
					
						
							|  |  |  | 		arg = PyTuple_GET_ITEM(args, 0); | 
					
						
							|  |  |  | 		i = getindex(self, arg); | 
					
						
							|  |  |  | 		if (i == -1 && PyErr_Occurred()) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		return (*func)(self, i); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	check_num_args(args, 1); | 
					
						
							| 
									
										
										
										
											2001-10-03 12:09:30 +00:00
										 |  |  | 	assert(PyErr_Occurred()); | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							| 
									
										
										
										
											2001-08-17 21:57:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | wrap_ssizessizeargfunc(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	ssizessizeargfunc func = (ssizessizeargfunc)wrapped; | 
					
						
							|  |  |  | 	Py_ssize_t i, j; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	if (!PyArg_ParseTuple(args, "nn", &i, &j)) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	return (*func)(self, i, j); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2001-08-17 21:57:47 +00:00
										 |  |  | wrap_sq_setitem(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	ssizeobjargproc func = (ssizeobjargproc)wrapped; | 
					
						
							|  |  |  | 	Py_ssize_t i; | 
					
						
							|  |  |  | 	int res; | 
					
						
							| 
									
										
										
										
											2001-08-17 21:57:47 +00:00
										 |  |  | 	PyObject *arg, *value; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-10-11 19:32:18 +00:00
										 |  |  | 	if (!PyArg_UnpackTuple(args, "", 2, 2, &arg, &value)) | 
					
						
							| 
									
										
										
										
											2001-08-17 21:57:47 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	i = getindex(self, arg); | 
					
						
							|  |  |  | 	if (i == -1 && PyErr_Occurred()) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		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 * | 
					
						
							| 
									
										
										
										
											2001-08-17 21:57:47 +00:00
										 |  |  | wrap_sq_delitem(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							| 
									
										
										
										
											2001-08-02 15:31:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	ssizeobjargproc func = (ssizeobjargproc)wrapped; | 
					
						
							|  |  |  | 	Py_ssize_t i; | 
					
						
							|  |  |  | 	int res; | 
					
						
							| 
									
										
										
										
											2001-08-17 21:57:47 +00:00
										 |  |  | 	PyObject *arg; | 
					
						
							| 
									
										
										
										
											2001-08-02 15:31:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	if (!check_num_args(args, 1)) | 
					
						
							| 
									
										
										
										
											2001-08-17 21:57:47 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	arg = PyTuple_GET_ITEM(args, 0); | 
					
						
							| 
									
										
										
										
											2001-08-17 21:57:47 +00:00
										 |  |  | 	i = getindex(self, arg); | 
					
						
							|  |  |  | 	if (i == -1 && PyErr_Occurred()) | 
					
						
							| 
									
										
										
										
											2001-08-02 15:31:58 +00:00
										 |  |  | 		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 PyObject * | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | wrap_ssizessizeobjargproc(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	ssizessizeobjargproc func = (ssizessizeobjargproc)wrapped; | 
					
						
							|  |  |  | 	Py_ssize_t i, j; | 
					
						
							|  |  |  | 	int res; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	PyObject *value; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	if (!PyArg_ParseTuple(args, "nnO", &i, &j, &value)) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	res = (*func)(self, i, j, value); | 
					
						
							|  |  |  | 	if (res == -1 && PyErr_Occurred()) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	Py_INCREF(Py_None); | 
					
						
							|  |  |  | 	return Py_None; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_delslice(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	ssizessizeobjargproc func = (ssizessizeobjargproc)wrapped; | 
					
						
							|  |  |  | 	Py_ssize_t i, j; | 
					
						
							|  |  |  | 	int res; | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	if (!PyArg_ParseTuple(args, "nn", &i, &j)) | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	res = (*func)(self, i, j, NULL); | 
					
						
							|  |  |  | 	if (res == -1 && PyErr_Occurred()) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	Py_INCREF(Py_None); | 
					
						
							|  |  |  | 	return Py_None; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | /* XXX objobjproc is a misnomer; should be objargpred */ | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_objobjproc(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	objobjproc func = (objobjproc)wrapped; | 
					
						
							|  |  |  | 	int res; | 
					
						
							| 
									
										
										
										
											2003-10-09 03:46:35 +00:00
										 |  |  | 	PyObject *value; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	if (!check_num_args(args, 1)) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	value = PyTuple_GET_ITEM(args, 0); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	res = (*func)(self, value); | 
					
						
							|  |  |  | 	if (res == -1 && PyErr_Occurred()) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2003-10-09 03:46:35 +00:00
										 |  |  | 	else | 
					
						
							|  |  |  | 		return PyBool_FromLong(res); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_objobjargproc(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	objobjargproc func = (objobjargproc)wrapped; | 
					
						
							|  |  |  | 	int res; | 
					
						
							|  |  |  | 	PyObject *key, *value; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-10-11 19:32:18 +00:00
										 |  |  | 	if (!PyArg_UnpackTuple(args, "", 2, 2, &key, &value)) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	if (!check_num_args(args, 1)) | 
					
						
							| 
									
										
										
										
											2001-08-02 15:31:58 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	key = PyTuple_GET_ITEM(args, 0); | 
					
						
							| 
									
										
										
										
											2001-08-02 15:31:58 +00:00
										 |  |  | 	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 PyObject * | 
					
						
							|  |  |  | wrap_cmpfunc(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	cmpfunc func = (cmpfunc)wrapped; | 
					
						
							|  |  |  | 	int res; | 
					
						
							|  |  |  | 	PyObject *other; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	if (!check_num_args(args, 1)) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	other = PyTuple_GET_ITEM(args, 0); | 
					
						
							| 
									
										
										
										
											2001-09-24 18:47:40 +00:00
										 |  |  | 	if (other->ob_type->tp_compare != func && | 
					
						
							|  |  |  | 	    !PyType_IsSubtype(other->ob_type, self->ob_type)) { | 
					
						
							| 
									
										
										
										
											2001-09-18 20:03:57 +00:00
										 |  |  | 		PyErr_Format( | 
					
						
							|  |  |  | 			PyExc_TypeError, | 
					
						
							|  |  |  | 			"%s.__cmp__(x,y) requires y to be a '%s', not a '%s'", | 
					
						
							|  |  |  | 			self->ob_type->tp_name, | 
					
						
							|  |  |  | 			self->ob_type->tp_name, | 
					
						
							|  |  |  | 			other->ob_type->tp_name); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	res = (*func)(self, other); | 
					
						
							|  |  |  | 	if (PyErr_Occurred()) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	return PyInt_FromLong((long)res); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-14 21:46:03 +00:00
										 |  |  | /* Helper to check for object.__setattr__ or __delattr__ applied to a type.
 | 
					
						
							| 
									
										
										
										
											2003-04-15 20:05:10 +00:00
										 |  |  |    This is called the Carlo Verre hack after its discoverer. */ | 
					
						
							| 
									
										
										
										
											2003-04-14 21:46:03 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | hackcheck(PyObject *self, setattrofunc func, char *what) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyTypeObject *type = self->ob_type; | 
					
						
							|  |  |  | 	while (type && type->tp_flags & Py_TPFLAGS_HEAPTYPE) | 
					
						
							|  |  |  | 		type = type->tp_base; | 
					
						
							| 
									
										
										
										
											2006-03-10 02:04:28 +00:00
										 |  |  |         /* If type is NULL now, this is a really weird type.
 | 
					
						
							| 
									
										
										
										
											2006-10-09 18:05:19 +00:00
										 |  |  |            In the spirit of backwards compatibility (?), just shut up. */ | 
					
						
							| 
									
										
										
										
											2006-03-10 02:04:28 +00:00
										 |  |  | 	if (type && type->tp_setattro != func) { | 
					
						
							| 
									
										
										
										
											2003-04-14 21:46:03 +00:00
										 |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "can't apply this %s to %s object", | 
					
						
							|  |  |  | 			     what, | 
					
						
							|  |  |  | 			     type->tp_name); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_setattr(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	setattrofunc func = (setattrofunc)wrapped; | 
					
						
							|  |  |  | 	int res; | 
					
						
							|  |  |  | 	PyObject *name, *value; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-10-11 19:32:18 +00:00
										 |  |  | 	if (!PyArg_UnpackTuple(args, "", 2, 2, &name, &value)) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2003-04-14 21:46:03 +00:00
										 |  |  | 	if (!hackcheck(self, func, "__setattr__")) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	if (!check_num_args(args, 1)) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	name = PyTuple_GET_ITEM(args, 0); | 
					
						
							| 
									
										
										
										
											2003-04-14 21:46:03 +00:00
										 |  |  | 	if (!hackcheck(self, func, "__delattr__")) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	res = (*func)(self, name, NULL); | 
					
						
							|  |  |  | 	if (res < 0) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	Py_INCREF(Py_None); | 
					
						
							|  |  |  | 	return Py_None; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_hashfunc(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hashfunc func = (hashfunc)wrapped; | 
					
						
							|  |  |  | 	long res; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	if (!check_num_args(args, 0)) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	res = (*func)(self); | 
					
						
							|  |  |  | 	if (res == -1 && PyErr_Occurred()) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	return PyInt_FromLong(res); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2001-10-22 00:43:43 +00:00
										 |  |  | wrap_call(PyObject *self, PyObject *args, void *wrapped, PyObject *kwds) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	ternaryfunc func = (ternaryfunc)wrapped; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-22 00:43:43 +00:00
										 |  |  | 	return (*func)(self, args, kwds); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_richcmpfunc(PyObject *self, PyObject *args, void *wrapped, int op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	richcmpfunc func = (richcmpfunc)wrapped; | 
					
						
							|  |  |  | 	PyObject *other; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	if (!check_num_args(args, 1)) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	other = PyTuple_GET_ITEM(args, 0); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	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
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_next(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unaryfunc func = (unaryfunc)wrapped; | 
					
						
							|  |  |  | 	PyObject *res; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	if (!check_num_args(args, 0)) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	res = (*func)(self); | 
					
						
							|  |  |  | 	if (res == NULL && !PyErr_Occurred()) | 
					
						
							|  |  |  | 		PyErr_SetNone(PyExc_StopIteration); | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_descr_get(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	descrgetfunc func = (descrgetfunc)wrapped; | 
					
						
							|  |  |  | 	PyObject *obj; | 
					
						
							|  |  |  | 	PyObject *type = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-10-11 19:32:18 +00:00
										 |  |  | 	if (!PyArg_UnpackTuple(args, "", 1, 2, &obj, &type)) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2003-02-11 16:25:43 +00:00
										 |  |  | 	if (obj == Py_None) | 
					
						
							|  |  |  | 		obj = NULL; | 
					
						
							|  |  |  | 	if (type == Py_None) | 
					
						
							|  |  |  | 		type = NULL; | 
					
						
							|  |  |  | 	if (type == NULL &&obj == NULL) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  | 				"__get__(None, None) is invalid"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	return (*func)(self, obj, type); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | wrap_descr_set(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	descrsetfunc func = (descrsetfunc)wrapped; | 
					
						
							|  |  |  | 	PyObject *obj, *value; | 
					
						
							|  |  |  | 	int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-10-11 19:32:18 +00:00
										 |  |  | 	if (!PyArg_UnpackTuple(args, "", 2, 2, &obj, &value)) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	ret = (*func)(self, obj, value); | 
					
						
							|  |  |  | 	if (ret < 0) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	Py_INCREF(Py_None); | 
					
						
							|  |  |  | 	return Py_None; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2002-08-06 21:41:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-08-01 14:39:25 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | wrap_descr_delete(PyObject *self, PyObject *args, void *wrapped) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	descrsetfunc func = (descrsetfunc)wrapped; | 
					
						
							|  |  |  | 	PyObject *obj; | 
					
						
							|  |  |  | 	int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	if (!check_num_args(args, 1)) | 
					
						
							| 
									
										
										
										
											2002-08-01 14:39:25 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2003-12-13 15:21:55 +00:00
										 |  |  | 	obj = PyTuple_GET_ITEM(args, 0); | 
					
						
							| 
									
										
										
										
											2002-08-01 14:39:25 +00:00
										 |  |  | 	ret = (*func)(self, obj, NULL); | 
					
						
							|  |  |  | 	if (ret < 0) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	Py_INCREF(Py_None); | 
					
						
							|  |  |  | 	return Py_None; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2001-10-22 00:43:43 +00:00
										 |  |  | wrap_init(PyObject *self, PyObject *args, void *wrapped, PyObject *kwds) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	initproc func = (initproc)wrapped; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-22 00:43:43 +00:00
										 |  |  | 	if (func(self, args, kwds) < 0) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	Py_INCREF(Py_None); | 
					
						
							|  |  |  | 	return Py_None; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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-22 19:24:42 +00:00
										 |  |  | 	PyTypeObject *type, *subtype, *staticbase; | 
					
						
							| 
									
										
										
										
											2001-08-06 16:50:37 +00:00
										 |  |  | 	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) { | 
					
						
							| 
									
										
										
										
											2001-08-22 19:24:42 +00:00
										 |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "%s.__new__(): not enough arguments", | 
					
						
							|  |  |  | 			     type->tp_name); | 
					
						
							| 
									
										
										
										
											2001-08-06 16:50:37 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	arg0 = PyTuple_GET_ITEM(args, 0); | 
					
						
							|  |  |  | 	if (!PyType_Check(arg0)) { | 
					
						
							| 
									
										
										
										
											2001-08-22 19:24:42 +00:00
										 |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "%s.__new__(X): X is not a type object (%s)", | 
					
						
							|  |  |  | 			     type->tp_name, | 
					
						
							|  |  |  | 			     arg0->ob_type->tp_name); | 
					
						
							| 
									
										
										
										
											2001-08-06 16:50:37 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	subtype = (PyTypeObject *)arg0; | 
					
						
							|  |  |  | 	if (!PyType_IsSubtype(subtype, type)) { | 
					
						
							| 
									
										
										
										
											2001-08-22 19:24:42 +00:00
										 |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "%s.__new__(%s): %s is not a subtype of %s", | 
					
						
							|  |  |  | 			     type->tp_name, | 
					
						
							|  |  |  | 			     subtype->tp_name, | 
					
						
							|  |  |  | 			     subtype->tp_name, | 
					
						
							|  |  |  | 			     type->tp_name); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Check that the use doesn't do something silly and unsafe like
 | 
					
						
							| 
									
										
										
										
											2001-10-29 22:25:45 +00:00
										 |  |  | 	   object.__new__(dict).  To do this, we check that the | 
					
						
							| 
									
										
										
										
											2001-08-22 19:24:42 +00:00
										 |  |  | 	   most derived base that's not a heap type is this type. */ | 
					
						
							|  |  |  | 	staticbase = subtype; | 
					
						
							|  |  |  | 	while (staticbase && (staticbase->tp_flags & Py_TPFLAGS_HEAPTYPE)) | 
					
						
							|  |  |  | 		staticbase = staticbase->tp_base; | 
					
						
							| 
									
										
										
										
											2006-03-10 02:04:28 +00:00
										 |  |  |         /* If staticbase is NULL now, it is a really weird type.
 | 
					
						
							| 
									
										
										
										
											2006-10-09 18:05:19 +00:00
										 |  |  |            In the spirit of backwards compatibility (?), just shut up. */ | 
					
						
							| 
									
										
										
										
											2006-03-10 02:04:28 +00:00
										 |  |  | 	if (staticbase && staticbase->tp_new != type->tp_new) { | 
					
						
							| 
									
										
										
										
											2001-08-22 19:24:42 +00:00
										 |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "%s.__new__(%s) is not safe, use %s.__new__()", | 
					
						
							|  |  |  | 			     type->tp_name, | 
					
						
							|  |  |  | 			     subtype->tp_name, | 
					
						
							|  |  |  | 			     staticbase == NULL ? "?" : staticbase->tp_name); | 
					
						
							| 
									
										
										
										
											2001-08-06 16:50:37 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-22 19:24:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-06 16:50:37 +00:00
										 |  |  | 	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, | 
					
						
							| 
									
										
										
										
											2002-08-13 22:19:13 +00:00
										 |  |  | 	 PyDoc_STR("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-10-15 22:03:32 +00:00
										 |  |  | 	if (PyDict_GetItemString(type->tp_dict, "__new__") != NULL) | 
					
						
							| 
									
										
										
										
											2001-08-07 16:40:56 +00:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	func = PyCFunction_New(tp_new_methoddef, (PyObject *)type); | 
					
						
							| 
									
										
										
										
											2001-08-06 16:50:37 +00:00
										 |  |  | 	if (func == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2004-06-25 22:24:35 +00:00
										 |  |  | 	if (PyDict_SetItemString(type->tp_dict, "__new__", func)) { | 
					
						
							| 
									
										
										
										
											2004-06-25 22:17:39 +00:00
										 |  |  | 		Py_DECREF(func); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	Py_DECREF(func); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2001-08-06 16:50:37 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-28 18:28:21 +00:00
										 |  |  | 	static PyObject *cache_str; \ | 
					
						
							| 
									
										
										
										
											2001-09-14 16:58:08 +00:00
										 |  |  | 	return call_method(self, OPSTR, &cache_str, "()"); \ | 
					
						
							| 
									
										
										
										
											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-28 18:22:14 +00:00
										 |  |  | 	static PyObject *cache_str; \ | 
					
						
							| 
									
										
										
										
											2001-09-14 16:58:08 +00:00
										 |  |  | 	return call_method(self, OPSTR, &cache_str, "(" ARGCODES ")", arg1); \ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-01-06 22:57:47 +00:00
										 |  |  | /* Boolean helper for SLOT1BINFULL().
 | 
					
						
							|  |  |  |    right.__class__ is a nontrivial subclass of left.__class__. */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | method_is_overloaded(PyObject *left, PyObject *right, char *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *a, *b; | 
					
						
							|  |  |  | 	int ok; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	b = PyObject_GetAttrString((PyObject *)(right->ob_type), name); | 
					
						
							|  |  |  | 	if (b == NULL) { | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							|  |  |  | 		/* If right doesn't have it, it's not overloaded */ | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	a = PyObject_GetAttrString((PyObject *)(left->ob_type), name); | 
					
						
							|  |  |  | 	if (a == NULL) { | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							|  |  |  | 		Py_DECREF(b); | 
					
						
							|  |  |  | 		/* If right has it but left doesn't, it's overloaded */ | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ok = PyObject_RichCompareBool(a, b, Py_NE); | 
					
						
							|  |  |  | 	Py_DECREF(a); | 
					
						
							|  |  |  | 	Py_DECREF(b); | 
					
						
							|  |  |  | 	if (ok < 0) { | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ok; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define SLOT1BINFULL(FUNCNAME, TESTFUNC, SLOTNAME, OPSTR, ROPSTR) \
 | 
					
						
							|  |  |  | static PyObject * \ | 
					
						
							|  |  |  | FUNCNAME(PyObject *self, PyObject *other) \ | 
					
						
							|  |  |  | { \ | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 	static PyObject *cache_str, *rcache_str; \ | 
					
						
							| 
									
										
										
										
											2001-10-01 17:18:22 +00:00
										 |  |  | 	int do_other = self->ob_type != other->ob_type && \ | 
					
						
							|  |  |  | 	    other->ob_type->tp_as_number != NULL && \ | 
					
						
							|  |  |  | 	    other->ob_type->tp_as_number->SLOTNAME == TESTFUNC; \ | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | 	if (self->ob_type->tp_as_number != NULL && \ | 
					
						
							|  |  |  | 	    self->ob_type->tp_as_number->SLOTNAME == TESTFUNC) { \ | 
					
						
							|  |  |  | 		PyObject *r; \ | 
					
						
							| 
									
										
										
										
											2001-10-01 17:18:22 +00:00
										 |  |  | 		if (do_other && \ | 
					
						
							| 
									
										
										
										
											2003-01-06 22:57:47 +00:00
										 |  |  | 		    PyType_IsSubtype(other->ob_type, self->ob_type) && \ | 
					
						
							|  |  |  | 		    method_is_overloaded(self, other, ROPSTR)) { \ | 
					
						
							| 
									
										
										
										
											2001-10-01 17:18:22 +00:00
										 |  |  | 			r = call_maybe( \ | 
					
						
							|  |  |  | 				other, ROPSTR, &rcache_str, "(O)", self); \ | 
					
						
							|  |  |  | 			if (r != Py_NotImplemented) \ | 
					
						
							|  |  |  | 				return r; \ | 
					
						
							|  |  |  | 			Py_DECREF(r); \ | 
					
						
							|  |  |  | 			do_other = 0; \ | 
					
						
							|  |  |  | 		} \ | 
					
						
							| 
									
										
										
										
											2001-09-14 17:51:50 +00:00
										 |  |  | 		r = call_maybe( \ | 
					
						
							| 
									
										
										
										
											2001-09-14 16:58:08 +00:00
										 |  |  | 			self, OPSTR, &cache_str, "(O)", other); \ | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | 		if (r != Py_NotImplemented || \ | 
					
						
							|  |  |  | 		    other->ob_type == self->ob_type) \ | 
					
						
							|  |  |  | 			return r; \ | 
					
						
							|  |  |  | 		Py_DECREF(r); \ | 
					
						
							|  |  |  | 	} \ | 
					
						
							| 
									
										
										
										
											2001-10-01 17:18:22 +00:00
										 |  |  | 	if (do_other) { \ | 
					
						
							| 
									
										
										
										
											2001-09-14 17:51:50 +00:00
										 |  |  | 		return call_maybe( \ | 
					
						
							| 
									
										
										
										
											2001-09-14 16:58:08 +00:00
										 |  |  | 			other, ROPSTR, &rcache_str, "(O)", self); \ | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | 	} \ | 
					
						
							|  |  |  | 	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-28 18:22:14 +00:00
										 |  |  | 	static PyObject *cache_str; \ | 
					
						
							| 
									
										
										
										
											2001-09-14 16:58:08 +00:00
										 |  |  | 	return call_method(self, OPSTR, &cache_str, \ | 
					
						
							|  |  |  | 			   "(" ARGCODES ")", arg1, arg2); \ | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | static Py_ssize_t | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | slot_sq_length(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 	static PyObject *len_str; | 
					
						
							| 
									
										
										
										
											2001-09-14 16:58:08 +00:00
										 |  |  | 	PyObject *res = call_method(self, "__len__", &len_str, "()"); | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t len; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (res == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2006-08-12 18:44:06 +00:00
										 |  |  | 	len = PyInt_AsSsize_t(res); | 
					
						
							| 
									
										
										
										
											2001-10-01 16:42:49 +00:00
										 |  |  | 	Py_DECREF(res); | 
					
						
							| 
									
										
										
										
											2002-07-25 16:06:15 +00:00
										 |  |  | 	if (len < 0) { | 
					
						
							| 
									
										
										
										
											2006-10-04 12:17:45 +00:00
										 |  |  | 		if (!PyErr_Occurred()) | 
					
						
							|  |  |  | 			PyErr_SetString(PyExc_ValueError, | 
					
						
							|  |  |  | 					"__len__() should return >= 0"); | 
					
						
							| 
									
										
										
										
											2002-07-25 16:06:15 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-10-01 16:42:49 +00:00
										 |  |  | 	return len; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-03 12:09:30 +00:00
										 |  |  | /* Super-optimized version of slot_sq_item.
 | 
					
						
							|  |  |  |    Other slots could do the same... */ | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | slot_sq_item(PyObject *self, Py_ssize_t i) | 
					
						
							| 
									
										
										
										
											2001-10-03 12:09:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	static PyObject *getitem_str; | 
					
						
							|  |  |  | 	PyObject *func, *args = NULL, *ival = NULL, *retval = NULL; | 
					
						
							|  |  |  | 	descrgetfunc f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (getitem_str == NULL) { | 
					
						
							|  |  |  | 		getitem_str = PyString_InternFromString("__getitem__"); | 
					
						
							|  |  |  | 		if (getitem_str == NULL) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	func = _PyType_Lookup(self->ob_type, getitem_str); | 
					
						
							|  |  |  | 	if (func != NULL) { | 
					
						
							|  |  |  | 		if ((f = func->ob_type->tp_descr_get) == NULL) | 
					
						
							|  |  |  | 			Py_INCREF(func); | 
					
						
							| 
									
										
										
										
											2002-10-18 16:33:13 +00:00
										 |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2001-10-03 12:09:30 +00:00
										 |  |  | 			func = f(func, self, (PyObject *)(self->ob_type)); | 
					
						
							| 
									
										
										
										
											2002-10-18 16:33:13 +00:00
										 |  |  | 			if (func == NULL) { | 
					
						
							|  |  |  | 				return NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-02-16 14:32:27 +00:00
										 |  |  | 		ival = PyInt_FromSsize_t(i); | 
					
						
							| 
									
										
										
										
											2001-10-03 12:09:30 +00:00
										 |  |  | 		if (ival != NULL) { | 
					
						
							|  |  |  | 			args = PyTuple_New(1); | 
					
						
							|  |  |  | 			if (args != NULL) { | 
					
						
							|  |  |  | 				PyTuple_SET_ITEM(args, 0, ival); | 
					
						
							|  |  |  | 				retval = PyObject_Call(func, args, NULL); | 
					
						
							|  |  |  | 				Py_XDECREF(args); | 
					
						
							|  |  |  | 				Py_XDECREF(func); | 
					
						
							|  |  |  | 				return retval; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		PyErr_SetObject(PyExc_AttributeError, getitem_str); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	Py_XDECREF(args); | 
					
						
							|  |  |  | 	Py_XDECREF(ival); | 
					
						
							|  |  |  | 	Py_XDECREF(func); | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | SLOT2(slot_sq_slice, "__getslice__", Py_ssize_t, Py_ssize_t, "nn") | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | slot_sq_ass_item(PyObject *self, Py_ssize_t index, PyObject *value) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PyObject *res; | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 	static PyObject *delitem_str, *setitem_str; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (value == NULL) | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 		res = call_method(self, "__delitem__", &delitem_str, | 
					
						
							| 
									
										
										
										
											2006-04-21 11:26:56 +00:00
										 |  |  | 				  "(n)", index); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 		res = call_method(self, "__setitem__", &setitem_str, | 
					
						
							| 
									
										
										
										
											2006-04-21 11:26:56 +00:00
										 |  |  | 				  "(nO)", index, value); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	if (res == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	Py_DECREF(res); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | slot_sq_ass_slice(PyObject *self, Py_ssize_t i, Py_ssize_t j, PyObject *value) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PyObject *res; | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 	static PyObject *delslice_str, *setslice_str; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (value == NULL) | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 		res = call_method(self, "__delslice__", &delslice_str, | 
					
						
							| 
									
										
										
										
											2006-04-21 11:26:56 +00:00
										 |  |  | 				  "(nn)", i, j); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 		res = call_method(self, "__setslice__", &setslice_str, | 
					
						
							| 
									
										
										
										
											2006-04-21 11:26:56 +00:00
										 |  |  | 				  "(nnO)", i, j, value); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	if (res == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	Py_DECREF(res); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | slot_sq_contains(PyObject *self, PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 	PyObject *func, *res, *args; | 
					
						
							| 
									
										
										
										
											2003-03-23 05:35:36 +00:00
										 |  |  | 	int result = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 	static PyObject *contains_str; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-01 17:18:22 +00:00
										 |  |  | 	func = lookup_maybe(self, "__contains__", &contains_str); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 	if (func != NULL) { | 
					
						
							| 
									
										
										
										
											2003-10-12 19:09:37 +00:00
										 |  |  | 		args = PyTuple_Pack(1, value); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 		if (args == NULL) | 
					
						
							|  |  |  | 			res = NULL; | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2001-09-14 16:58:08 +00:00
										 |  |  | 			res = PyObject_Call(func, args, NULL); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 			Py_DECREF(args); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		Py_DECREF(func); | 
					
						
							| 
									
										
										
										
											2003-03-23 05:35:36 +00:00
										 |  |  | 		if (res != NULL) { | 
					
						
							|  |  |  | 			result = PyObject_IsTrue(res); | 
					
						
							|  |  |  | 			Py_DECREF(res); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2003-03-23 05:35:36 +00:00
										 |  |  | 	else if (! PyErr_Occurred()) { | 
					
						
							| 
									
										
										
										
											2006-03-07 12:08:51 +00:00
										 |  |  | 		/* Possible results: -1 and 1 */ | 
					
						
							|  |  |  | 		result = (int)_PySequence_IterSearch(self, value, | 
					
						
							| 
									
										
										
										
											2003-03-23 05:35:36 +00:00
										 |  |  | 						 PY_ITERSEARCH_CONTAINS); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2003-03-23 05:35:36 +00:00
										 |  |  | 	return result; | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 	static PyObject *delitem_str, *setitem_str; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (value == NULL) | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 		res = call_method(self, "__delitem__", &delitem_str, | 
					
						
							| 
									
										
										
										
											2001-09-14 16:58:08 +00:00
										 |  |  | 				  "(O)", key); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 		res = call_method(self, "__setitem__", &setitem_str, | 
					
						
							| 
									
										
										
										
											2001-09-14 16:58:08 +00:00
										 |  |  | 				 "(OO)", key, value); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	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__") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 16:30:39 +00:00
										 |  |  | static PyObject *slot_nb_power(PyObject *, PyObject *, PyObject *); | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | SLOT1BINFULL(slot_nb_power_binary, slot_nb_power, | 
					
						
							|  |  |  | 	     nb_power, "__pow__", "__rpow__") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | slot_nb_power(PyObject *self, PyObject *other, PyObject *modulus) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 	static PyObject *pow_str; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | 	if (modulus == Py_None) | 
					
						
							|  |  |  | 		return slot_nb_power_binary(self, other); | 
					
						
							| 
									
										
										
										
											2002-06-10 14:30:43 +00:00
										 |  |  | 	/* Three-arg power doesn't use __rpow__.  But ternary_op
 | 
					
						
							|  |  |  | 	   can call this when the second argument's type uses | 
					
						
							|  |  |  | 	   slot_nb_power, so check before calling self.__pow__. */ | 
					
						
							|  |  |  | 	if (self->ob_type->tp_as_number != NULL && | 
					
						
							|  |  |  | 	    self->ob_type->tp_as_number->nb_power == slot_nb_power) { | 
					
						
							|  |  |  | 		return call_method(self, "__pow__", &pow_str, | 
					
						
							|  |  |  | 				   "(OO)", other, modulus); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	Py_INCREF(Py_NotImplemented); | 
					
						
							|  |  |  | 	return Py_NotImplemented; | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-12-07 21:39:16 +00:00
										 |  |  | 	PyObject *func, *args; | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 	static PyObject *nonzero_str, *len_str; | 
					
						
							| 
									
										
										
										
											2002-12-07 21:39:16 +00:00
										 |  |  | 	int result = -1; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-01 17:18:22 +00:00
										 |  |  | 	func = lookup_maybe(self, "__nonzero__", &nonzero_str); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 	if (func == NULL) { | 
					
						
							| 
									
										
										
										
											2001-10-01 17:18:22 +00:00
										 |  |  | 		if (PyErr_Occurred()) | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 			return -1; | 
					
						
							| 
									
										
										
										
											2001-10-01 17:18:22 +00:00
										 |  |  | 		func = lookup_maybe(self, "__len__", &len_str); | 
					
						
							| 
									
										
										
										
											2002-12-07 21:39:16 +00:00
										 |  |  | 		if (func == NULL) | 
					
						
							|  |  |  | 			return PyErr_Occurred() ? -1 : 1; | 
					
						
							|  |  |  |  	} | 
					
						
							|  |  |  | 	args = PyTuple_New(0); | 
					
						
							| 
									
										
										
										
											2002-08-16 17:01:09 +00:00
										 |  |  | 	if (args != NULL) { | 
					
						
							| 
									
										
										
										
											2002-12-07 21:39:16 +00:00
										 |  |  | 		PyObject *temp = PyObject_Call(func, args, NULL); | 
					
						
							| 
									
										
										
										
											2002-08-16 17:01:09 +00:00
										 |  |  | 		Py_DECREF(args); | 
					
						
							| 
									
										
										
										
											2002-12-07 21:39:16 +00:00
										 |  |  | 		if (temp != NULL) { | 
					
						
							| 
									
										
										
										
											2003-06-27 17:38:27 +00:00
										 |  |  | 			if (PyInt_CheckExact(temp) || PyBool_Check(temp)) | 
					
						
							| 
									
										
										
										
											2003-06-27 16:46:45 +00:00
										 |  |  | 				result = PyObject_IsTrue(temp); | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 					     "__nonzero__ should return " | 
					
						
							|  |  |  | 					     "bool or int, returned %s", | 
					
						
							|  |  |  | 					     temp->ob_type->tp_name); | 
					
						
							| 
									
										
										
										
											2003-06-27 17:38:27 +00:00
										 |  |  | 				result = -1; | 
					
						
							| 
									
										
										
										
											2003-06-27 16:46:45 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2002-12-07 21:39:16 +00:00
										 |  |  | 			Py_DECREF(temp); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2002-08-16 17:01:09 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-10-01 17:18:22 +00:00
										 |  |  | 	Py_DECREF(func); | 
					
						
							| 
									
										
										
										
											2002-12-07 21:39:16 +00:00
										 |  |  | 	return result; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-07 18:50:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-12 17:03:09 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2006-03-07 18:50:55 +00:00
										 |  |  | slot_nb_index(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	static PyObject *index_str; | 
					
						
							| 
									
										
										
										
											2006-08-12 17:03:09 +00:00
										 |  |  | 	return call_method(self, "__index__", &index_str, "()"); | 
					
						
							| 
									
										
										
										
											2006-03-07 18:50:55 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-09-27 20:30:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | slot_nb_coerce(PyObject **a, PyObject **b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	static PyObject *coerce_str; | 
					
						
							|  |  |  | 	PyObject *self = *a, *other = *b; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (self->ob_type->tp_as_number != NULL && | 
					
						
							|  |  |  | 	    self->ob_type->tp_as_number->nb_coerce == slot_nb_coerce) { | 
					
						
							|  |  |  | 		PyObject *r; | 
					
						
							|  |  |  | 		r = call_maybe( | 
					
						
							|  |  |  | 			self, "__coerce__", &coerce_str, "(O)", other); | 
					
						
							|  |  |  | 		if (r == NULL) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		if (r == Py_NotImplemented) { | 
					
						
							|  |  |  | 			Py_DECREF(r); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2001-10-01 17:18:22 +00:00
										 |  |  | 		else { | 
					
						
							|  |  |  | 			if (!PyTuple_Check(r) || PyTuple_GET_SIZE(r) != 2) { | 
					
						
							|  |  |  | 				PyErr_SetString(PyExc_TypeError, | 
					
						
							| 
									
										
										
										
											2001-09-27 20:30:07 +00:00
										 |  |  | 					"__coerce__ didn't return a 2-tuple"); | 
					
						
							| 
									
										
										
										
											2001-10-01 17:18:22 +00:00
										 |  |  | 				Py_DECREF(r); | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			*a = PyTuple_GET_ITEM(r, 0); | 
					
						
							|  |  |  | 			Py_INCREF(*a); | 
					
						
							|  |  |  | 			*b = PyTuple_GET_ITEM(r, 1); | 
					
						
							|  |  |  | 			Py_INCREF(*b); | 
					
						
							| 
									
										
										
										
											2001-09-27 20:30:07 +00:00
										 |  |  | 			Py_DECREF(r); | 
					
						
							| 
									
										
										
										
											2001-10-01 17:18:22 +00:00
										 |  |  | 			return 0; | 
					
						
							| 
									
										
										
										
											2001-09-27 20:30:07 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (other->ob_type->tp_as_number != NULL && | 
					
						
							|  |  |  | 	    other->ob_type->tp_as_number->nb_coerce == slot_nb_coerce) { | 
					
						
							|  |  |  | 		PyObject *r; | 
					
						
							|  |  |  | 		r = call_maybe( | 
					
						
							|  |  |  | 			other, "__coerce__", &coerce_str, "(O)", self); | 
					
						
							|  |  |  | 		if (r == NULL) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		if (r == Py_NotImplemented) { | 
					
						
							|  |  |  | 			Py_DECREF(r); | 
					
						
							|  |  |  | 			return 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (!PyTuple_Check(r) || PyTuple_GET_SIZE(r) != 2) { | 
					
						
							|  |  |  | 			PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  | 					"__coerce__ didn't return a 2-tuple"); | 
					
						
							|  |  |  | 			Py_DECREF(r); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		*a = PyTuple_GET_ITEM(r, 1); | 
					
						
							|  |  |  | 		Py_INCREF(*a); | 
					
						
							|  |  |  | 		*b = PyTuple_GET_ITEM(r, 0); | 
					
						
							|  |  |  | 		Py_INCREF(*b); | 
					
						
							|  |  |  | 		Py_DECREF(r); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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") | 
					
						
							| 
									
										
										
										
											2002-10-15 01:01:53 +00:00
										 |  |  | SLOT1(slot_nb_inplace_power, "__ipow__", PyObject *, "O") | 
					
						
							| 
									
										
										
										
											2001-08-08 22:26:22 +00:00
										 |  |  | 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
										 |  |  | 
 | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | half_compare(PyObject *self, PyObject *other) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *func, *args, *res; | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 	static PyObject *cmp_str; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t c; | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 	func = lookup_method(self, "__cmp__", &cmp_str); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 	if (func == NULL) { | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2003-10-12 19:09:37 +00:00
										 |  |  | 		args = PyTuple_Pack(1, other); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 		if (args == NULL) | 
					
						
							|  |  |  | 			res = NULL; | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2001-09-14 16:58:08 +00:00
										 |  |  | 			res = PyObject_Call(func, args, NULL); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 			Py_DECREF(args); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2002-06-24 13:08:16 +00:00
										 |  |  | 		Py_DECREF(func); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 		if (res != Py_NotImplemented) { | 
					
						
							|  |  |  | 			if (res == NULL) | 
					
						
							|  |  |  | 				return -2; | 
					
						
							|  |  |  | 			c = PyInt_AsLong(res); | 
					
						
							|  |  |  | 			Py_DECREF(res); | 
					
						
							|  |  |  | 			if (c == -1 && PyErr_Occurred()) | 
					
						
							|  |  |  | 				return -2; | 
					
						
							|  |  |  | 			return (c < 0) ? -1 : (c > 0) ? 1 : 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		Py_DECREF(res); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 2; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-18 20:38:53 +00:00
										 |  |  | /* This slot is published for the benefit of try_3way_compare in object.c */ | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | _PyObject_SlotCompare(PyObject *self, PyObject *other) | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 	int c; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-18 20:38:53 +00:00
										 |  |  | 	if (self->ob_type->tp_compare == _PyObject_SlotCompare) { | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 		c = half_compare(self, other); | 
					
						
							|  |  |  | 		if (c <= 1) | 
					
						
							|  |  |  | 			return c; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-09-18 20:38:53 +00:00
										 |  |  | 	if (other->ob_type->tp_compare == _PyObject_SlotCompare) { | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 		c = half_compare(other, self); | 
					
						
							|  |  |  | 		if (c < -1) | 
					
						
							|  |  |  | 			return -2; | 
					
						
							|  |  |  | 		if (c <= 1) | 
					
						
							|  |  |  | 			return -c; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return (void *)self < (void *)other ? -1 : | 
					
						
							|  |  |  | 		(void *)self > (void *)other ? 1 : 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | slot_tp_repr(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *func, *res; | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 	static PyObject *repr_str; | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 	func = lookup_method(self, "__repr__", &repr_str); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 	if (func != NULL) { | 
					
						
							|  |  |  | 		res = PyEval_CallObject(func, NULL); | 
					
						
							|  |  |  | 		Py_DECREF(func); | 
					
						
							|  |  |  | 		return res; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-24 18:34:26 +00:00
										 |  |  | 	PyErr_Clear(); | 
					
						
							|  |  |  | 	return PyString_FromFormat("<%s object at %p>", | 
					
						
							|  |  |  | 				   self->ob_type->tp_name, self); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | slot_tp_str(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *func, *res; | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 	static PyObject *str_str; | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 	func = lookup_method(self, "__str__", &str_str); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 	if (func != NULL) { | 
					
						
							|  |  |  | 		res = PyEval_CallObject(func, NULL); | 
					
						
							|  |  |  | 		Py_DECREF(func); | 
					
						
							|  |  |  | 		return res; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							|  |  |  | 		return slot_tp_repr(self); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static long | 
					
						
							|  |  |  | slot_tp_hash(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-12-06 23:38:02 +00:00
										 |  |  | 	PyObject *func; | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 	static PyObject *hash_str, *eq_str, *cmp_str; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	long h; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 	func = lookup_method(self, "__hash__", &hash_str); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (func != NULL) { | 
					
						
							| 
									
										
										
										
											2002-12-06 23:38:02 +00:00
										 |  |  | 		PyObject *res = PyEval_CallObject(func, NULL); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 		Py_DECREF(func); | 
					
						
							|  |  |  | 		if (res == NULL) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							| 
									
										
										
										
											2006-08-09 07:57:39 +00:00
										 |  |  | 		if (PyLong_Check(res)) | 
					
						
							| 
									
										
										
										
											2006-08-09 14:55:26 +00:00
										 |  |  | 			h = PyLong_Type.tp_hash(res); | 
					
						
							| 
									
										
										
										
											2006-08-09 07:57:39 +00:00
										 |  |  | 		else | 
					
						
							|  |  |  | 			h = PyInt_AsLong(res); | 
					
						
							| 
									
										
										
										
											2002-12-06 23:38:02 +00:00
										 |  |  | 		Py_DECREF(res); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 		func = lookup_method(self, "__eq__", &eq_str); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 		if (func == NULL) { | 
					
						
							|  |  |  | 			PyErr_Clear(); | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 			func = lookup_method(self, "__cmp__", &cmp_str); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if (func != NULL) { | 
					
						
							| 
									
										
										
										
											2006-06-18 22:17:29 +00:00
										 |  |  | 			PyErr_Format(PyExc_TypeError, "unhashable type: '%.200s'", | 
					
						
							|  |  |  | 				     self->ob_type->tp_name); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 			Py_DECREF(func); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							|  |  |  | 		h = _Py_HashPointer((void *)self); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	if (h == -1 && !PyErr_Occurred()) | 
					
						
							|  |  |  | 		h = -2; | 
					
						
							|  |  |  | 	return h; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | slot_tp_call(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 	static PyObject *call_str; | 
					
						
							|  |  |  | 	PyObject *meth = lookup_method(self, "__call__", &call_str); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	PyObject *res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (meth == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2006-06-21 21:58:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* PyObject_Call() will end up calling slot_tp_call() again if
 | 
					
						
							|  |  |  | 	   the object returned for __call__ has __call__ itself defined | 
					
						
							|  |  |  | 	   upon it.  This can be an infinite recursion if you set | 
					
						
							|  |  |  | 	   __call__ in a class to an instance of it. */ | 
					
						
							| 
									
										
										
										
											2006-06-23 03:32:44 +00:00
										 |  |  | 	if (Py_EnterRecursiveCall(" in __call__")) { | 
					
						
							|  |  |  | 		Py_DECREF(meth); | 
					
						
							| 
									
										
										
										
											2006-06-21 21:58:50 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2006-06-23 03:32:44 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	res = PyObject_Call(meth, args, kwds); | 
					
						
							| 
									
										
										
										
											2006-06-21 21:58:50 +00:00
										 |  |  | 	Py_LeaveRecursiveCall(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	Py_DECREF(meth); | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-17 13:59:09 +00:00
										 |  |  | /* There are two slot dispatch functions for tp_getattro.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    - slot_tp_getattro() is used when __getattribute__ is overridden | 
					
						
							|  |  |  |      but no __getattr__ hook is present; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    - slot_tp_getattr_hook() is used when a __getattr__ hook is present. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-04-04 23:44:47 +00:00
										 |  |  |    The code in update_one_slot() always installs slot_tp_getattr_hook(); this | 
					
						
							|  |  |  |    detects the absence of __getattr__ and then installs the simpler slot if | 
					
						
							|  |  |  |    necessary. */ | 
					
						
							| 
									
										
										
										
											2001-10-17 13:59:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | slot_tp_getattro(PyObject *self, PyObject *name) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2001-10-17 13:59:09 +00:00
										 |  |  | 	static PyObject *getattribute_str = NULL; | 
					
						
							|  |  |  | 	return call_method(self, "__getattribute__", &getattribute_str, | 
					
						
							|  |  |  | 			   "(O)", name); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-21 21:24:49 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | slot_tp_getattr_hook(PyObject *self, PyObject *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyTypeObject *tp = self->ob_type; | 
					
						
							|  |  |  | 	PyObject *getattr, *getattribute, *res; | 
					
						
							|  |  |  | 	static PyObject *getattribute_str = NULL; | 
					
						
							|  |  |  | 	static PyObject *getattr_str = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (getattr_str == NULL) { | 
					
						
							|  |  |  | 		getattr_str = PyString_InternFromString("__getattr__"); | 
					
						
							|  |  |  | 		if (getattr_str == NULL) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (getattribute_str == NULL) { | 
					
						
							|  |  |  | 		getattribute_str = | 
					
						
							|  |  |  | 			PyString_InternFromString("__getattribute__"); | 
					
						
							|  |  |  | 		if (getattribute_str == NULL) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	getattr = _PyType_Lookup(tp, getattr_str); | 
					
						
							| 
									
										
										
										
											2001-10-17 13:59:09 +00:00
										 |  |  | 	if (getattr == NULL) { | 
					
						
							| 
									
										
										
										
											2001-10-13 20:02:41 +00:00
										 |  |  | 		/* No __getattr__ hook: use a simpler dispatcher */ | 
					
						
							|  |  |  | 		tp->tp_getattro = slot_tp_getattro; | 
					
						
							|  |  |  | 		return slot_tp_getattro(self, name); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-09-21 21:24:49 +00:00
										 |  |  | 	getattribute = _PyType_Lookup(tp, getattribute_str); | 
					
						
							| 
									
										
										
										
											2001-10-17 13:59:09 +00:00
										 |  |  | 	if (getattribute == NULL || | 
					
						
							|  |  |  | 	    (getattribute->ob_type == &PyWrapperDescr_Type && | 
					
						
							|  |  |  | 	     ((PyWrapperDescrObject *)getattribute)->d_wrapped == | 
					
						
							|  |  |  | 	     (void *)PyObject_GenericGetAttr)) | 
					
						
							| 
									
										
										
										
											2001-09-21 21:24:49 +00:00
										 |  |  | 		res = PyObject_GenericGetAttr(self, name); | 
					
						
							|  |  |  | 	else | 
					
						
							| 
									
										
										
										
											2006-05-25 19:15:31 +00:00
										 |  |  | 		res = PyObject_CallFunctionObjArgs(getattribute, self, name, NULL); | 
					
						
							| 
									
										
										
										
											2001-10-17 13:59:09 +00:00
										 |  |  | 	if (res == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) { | 
					
						
							| 
									
										
										
										
											2001-09-21 21:24:49 +00:00
										 |  |  | 		PyErr_Clear(); | 
					
						
							| 
									
										
										
										
											2006-05-25 19:15:31 +00:00
										 |  |  | 		res = PyObject_CallFunctionObjArgs(getattr, self, name, NULL); | 
					
						
							| 
									
										
										
										
											2001-09-21 21:24:49 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | slot_tp_setattro(PyObject *self, PyObject *name, PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *res; | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 	static PyObject *delattr_str, *setattr_str; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (value == NULL) | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 		res = call_method(self, "__delattr__", &delattr_str, | 
					
						
							| 
									
										
										
										
											2001-09-14 16:58:08 +00:00
										 |  |  | 				  "(O)", name); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 		res = call_method(self, "__setattr__", &setattr_str, | 
					
						
							| 
									
										
										
										
											2001-09-14 16:58:08 +00:00
										 |  |  | 				  "(OO)", name, value); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	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__", | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | half_richcompare(PyObject *self, PyObject *other, int op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *func, *args, *res; | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 	static PyObject *op_str[6]; | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 	func = lookup_method(self, name_op[op], &op_str[op]); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 	if (func == NULL) { | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							|  |  |  | 		Py_INCREF(Py_NotImplemented); | 
					
						
							|  |  |  | 		return Py_NotImplemented; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2003-10-12 19:09:37 +00:00
										 |  |  | 	args = PyTuple_Pack(1, other); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 	if (args == NULL) | 
					
						
							|  |  |  | 		res = NULL; | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2001-09-14 16:58:08 +00:00
										 |  |  | 		res = PyObject_Call(func, args, NULL); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 		Py_DECREF(args); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	Py_DECREF(func); | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | slot_tp_richcompare(PyObject *self, PyObject *other, int op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *res; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 	if (self->ob_type->tp_richcompare == slot_tp_richcompare) { | 
					
						
							|  |  |  | 		res = half_richcompare(self, other, op); | 
					
						
							|  |  |  | 		if (res != Py_NotImplemented) | 
					
						
							|  |  |  | 			return res; | 
					
						
							|  |  |  | 		Py_DECREF(res); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (other->ob_type->tp_richcompare == slot_tp_richcompare) { | 
					
						
							| 
									
										
										
										
											2004-09-23 02:39:37 +00:00
										 |  |  | 		res = half_richcompare(other, self, _Py_SwappedOp[op]); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 		if (res != Py_NotImplemented) { | 
					
						
							|  |  |  | 			return res; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		Py_DECREF(res); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	Py_INCREF(Py_NotImplemented); | 
					
						
							|  |  |  | 	return Py_NotImplemented; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | slot_tp_iter(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *func, *res; | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 	static PyObject *iter_str, *getitem_str; | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 	func = lookup_method(self, "__iter__", &iter_str); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 	if (func != NULL) { | 
					
						
							| 
									
										
										
										
											2002-08-16 17:01:09 +00:00
										 |  |  | 		PyObject *args; | 
					
						
							|  |  |  | 		args = res = PyTuple_New(0); | 
					
						
							|  |  |  | 		if (args != NULL) { | 
					
						
							|  |  |  | 			res = PyObject_Call(func, args, NULL); | 
					
						
							|  |  |  | 			Py_DECREF(args); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		Py_DECREF(func); | 
					
						
							|  |  |  | 		return res; | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	PyErr_Clear(); | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 	func = lookup_method(self, "__getitem__", &getitem_str); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 	if (func == NULL) { | 
					
						
							| 
									
										
										
										
											2006-06-18 22:17:29 +00:00
										 |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "'%.200s' object is not iterable", | 
					
						
							|  |  |  | 			     self->ob_type->tp_name); | 
					
						
							| 
									
										
										
											
												- Another big step in the right direction.  All the overridable
  operators for which a default implementation exist now work, both in
  dynamic classes and in static classes, overridden or not.  This
  affects __repr__, __str__, __hash__, __contains__, __nonzero__,
  __cmp__, and the rich comparisons (__lt__ etc.).  For dynamic
  classes, this meant copying a lot of code from classobject!  (XXX
  There are still some holes, because the comparison code in object.c
  uses PyInstance_Check(), meaning new-style classes don't get the
  same dispensation.  This needs more thinking.)
- Add object.__hash__, object.__repr__, object.__str__.  The __str__
  dispatcher now calls the __repr__ dispatcher, as it should.
- For static classes, the tp_compare, tp_richcompare and tp_hash slots
  are now inherited together, or not at all.  (XXX I fear there are
  still some situations where you can inherit __hash__ when you
  shouldn't, but mostly it's OK now, and I think there's no way we can
  get that 100% right.)
											
										 
											2001-08-15 23:57:02 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	Py_DECREF(func); | 
					
						
							|  |  |  | 	return PySeqIter_New(self); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | slot_tp_iternext(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 	static PyObject *next_str; | 
					
						
							| 
									
										
										
										
											2001-09-14 16:58:08 +00:00
										 |  |  | 	return call_method(self, "next", &next_str, "()"); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-17 16:47:50 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | slot_tp_descr_get(PyObject *self, PyObject *obj, PyObject *type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyTypeObject *tp = self->ob_type; | 
					
						
							|  |  |  | 	PyObject *get; | 
					
						
							|  |  |  | 	static PyObject *get_str = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (get_str == NULL) { | 
					
						
							|  |  |  | 		get_str = PyString_InternFromString("__get__"); | 
					
						
							|  |  |  | 		if (get_str == NULL) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	get = _PyType_Lookup(tp, get_str); | 
					
						
							|  |  |  | 	if (get == NULL) { | 
					
						
							|  |  |  | 		/* Avoid further slowdowns */ | 
					
						
							|  |  |  | 		if (tp->tp_descr_get == slot_tp_descr_get) | 
					
						
							|  |  |  | 			tp->tp_descr_get = NULL; | 
					
						
							|  |  |  | 		Py_INCREF(self); | 
					
						
							|  |  |  | 		return self; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-24 10:13:31 +00:00
										 |  |  | 	if (obj == NULL) | 
					
						
							|  |  |  | 		obj = Py_None; | 
					
						
							|  |  |  | 	if (type == NULL) | 
					
						
							|  |  |  | 		type = Py_None; | 
					
						
							| 
									
										
										
										
											2006-05-25 19:15:31 +00:00
										 |  |  | 	return PyObject_CallFunctionObjArgs(get, self, obj, type, NULL); | 
					
						
							| 
									
										
										
										
											2001-08-17 16:47:50 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | slot_tp_descr_set(PyObject *self, PyObject *target, PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2001-08-24 10:13:31 +00:00
										 |  |  | 	PyObject *res; | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 	static PyObject *del_str, *set_str; | 
					
						
							| 
									
										
										
										
											2001-08-24 10:13:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (value == NULL) | 
					
						
							| 
									
										
										
										
											2001-12-03 00:08:33 +00:00
										 |  |  | 		res = call_method(self, "__delete__", &del_str, | 
					
						
							| 
									
										
										
										
											2001-09-14 16:58:08 +00:00
										 |  |  | 				  "(O)", target); | 
					
						
							| 
									
										
										
										
											2001-08-24 10:13:31 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2001-08-28 18:22:14 +00:00
										 |  |  | 		res = call_method(self, "__set__", &set_str, | 
					
						
							| 
									
										
										
										
											2001-09-14 16:58:08 +00:00
										 |  |  | 				  "(OO)", target, value); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	if (res == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	Py_DECREF(res); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | slot_tp_init(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2001-08-28 17:47:51 +00:00
										 |  |  | 	static PyObject *init_str; | 
					
						
							|  |  |  | 	PyObject *meth = lookup_method(self, "__init__", &init_str); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	PyObject *res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (meth == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	res = PyObject_Call(meth, args, kwds); | 
					
						
							|  |  |  | 	Py_DECREF(meth); | 
					
						
							|  |  |  | 	if (res == NULL) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2005-03-03 16:45:19 +00:00
										 |  |  | 	if (res != Py_None) { | 
					
						
							| 
									
										
										
										
											2006-06-18 22:17:29 +00:00
										 |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			     "__init__() should return None, not '%.200s'", | 
					
						
							|  |  |  | 			     res->ob_type->tp_name); | 
					
						
							| 
									
										
										
										
											2005-03-03 16:45:19 +00:00
										 |  |  | 		Py_DECREF(res); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	Py_DECREF(res); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-08-08 21:57:53 +00:00
										 |  |  | 	static PyObject *new_str; | 
					
						
							|  |  |  | 	PyObject *func; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	PyObject *newargs, *x; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i, n; | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-08-08 21:57:53 +00:00
										 |  |  | 	if (new_str == NULL) { | 
					
						
							|  |  |  | 		new_str = PyString_InternFromString("__new__"); | 
					
						
							|  |  |  | 		if (new_str == NULL) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	func = PyObject_GetAttr((PyObject *)type, new_str); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2001-10-01 15:55:28 +00:00
										 |  |  | 	Py_DECREF(newargs); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | 	Py_DECREF(func); | 
					
						
							|  |  |  | 	return x; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-08-08 20:55:20 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | slot_tp_del(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	static PyObject *del_str = NULL; | 
					
						
							|  |  |  | 	PyObject *del, *res; | 
					
						
							|  |  |  | 	PyObject *error_type, *error_value, *error_traceback; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Temporarily resurrect the object. */ | 
					
						
							|  |  |  | 	assert(self->ob_refcnt == 0); | 
					
						
							|  |  |  | 	self->ob_refcnt = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Save the current exception, if any. */ | 
					
						
							|  |  |  | 	PyErr_Fetch(&error_type, &error_value, &error_traceback); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Execute __del__ method, if any. */ | 
					
						
							|  |  |  | 	del = lookup_maybe(self, "__del__", &del_str); | 
					
						
							|  |  |  | 	if (del != NULL) { | 
					
						
							|  |  |  | 		res = PyEval_CallObject(del, NULL); | 
					
						
							|  |  |  | 		if (res == NULL) | 
					
						
							|  |  |  | 			PyErr_WriteUnraisable(del); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			Py_DECREF(res); | 
					
						
							|  |  |  | 		Py_DECREF(del); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Restore the saved exception. */ | 
					
						
							|  |  |  | 	PyErr_Restore(error_type, error_value, error_traceback); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Undo the temporary resurrection; can't use DECREF here, it would
 | 
					
						
							|  |  |  | 	 * cause a recursive call. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	assert(self->ob_refcnt > 0); | 
					
						
							|  |  |  | 	if (--self->ob_refcnt == 0) | 
					
						
							|  |  |  | 		return;	/* this is the normal path out */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* __del__ resurrected it!  Make it look like the original Py_DECREF
 | 
					
						
							|  |  |  | 	 * never happened. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-03-07 12:08:51 +00:00
										 |  |  | 		Py_ssize_t refcnt = self->ob_refcnt; | 
					
						
							| 
									
										
										
										
											2002-08-08 20:55:20 +00:00
										 |  |  | 		_Py_NewReference(self); | 
					
						
							|  |  |  | 		self->ob_refcnt = refcnt; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	assert(!PyType_IS_GC(self->ob_type) || | 
					
						
							|  |  |  | 	       _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED); | 
					
						
							| 
									
										
										
										
											2004-08-03 10:21:03 +00:00
										 |  |  | 	/* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
 | 
					
						
							|  |  |  | 	 * we need to undo that. */ | 
					
						
							|  |  |  | 	_Py_DEC_REFTOTAL; | 
					
						
							|  |  |  | 	/* If Py_TRACE_REFS, _Py_NewReference re-added self to the object
 | 
					
						
							|  |  |  | 	 * chain, so no more to do there. | 
					
						
							| 
									
										
										
										
											2002-08-08 20:55:20 +00:00
										 |  |  | 	 * If COUNT_ALLOCS, the original decref bumped tp_frees, and | 
					
						
							|  |  |  | 	 * _Py_NewReference bumped tp_allocs:  both of those need to be | 
					
						
							|  |  |  | 	 * undone. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | #ifdef COUNT_ALLOCS
 | 
					
						
							|  |  |  | 	--self->ob_type->tp_frees; | 
					
						
							|  |  |  | 	--self->ob_type->tp_allocs; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-07 16:40:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | /* Table mapping __foo__ names to tp_foo offsets and slot_tp_foo wrapper
 | 
					
						
							| 
									
										
										
										
											2003-03-23 05:35:36 +00:00
										 |  |  |    functions.  The offsets here are relative to the 'PyHeapTypeObject' | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  |    structure, which incorporates the additional structures used for numbers, | 
					
						
							|  |  |  |    sequences and mappings. | 
					
						
							|  |  |  |    Note that multiple names may map to the same slot (e.g. __eq__, | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  |    __ne__ etc. all map to tp_richcompare) and one name may map to multiple | 
					
						
							| 
									
										
										
										
											2002-04-04 23:44:47 +00:00
										 |  |  |    slots (e.g. __str__ affects tp_str as well as tp_repr). The table is | 
					
						
							|  |  |  |    terminated with an all-zero entry.  (This table is further initialized and | 
					
						
							|  |  |  |    sorted in init_slotdefs() below.) */ | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | typedef struct wrapperbase slotdef; | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #undef TPSLOT
 | 
					
						
							| 
									
										
										
										
											2001-10-22 00:43:43 +00:00
										 |  |  | #undef FLSLOT
 | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | #undef ETSLOT
 | 
					
						
							|  |  |  | #undef SQSLOT
 | 
					
						
							|  |  |  | #undef MPSLOT
 | 
					
						
							|  |  |  | #undef NBSLOT
 | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | #undef UNSLOT
 | 
					
						
							|  |  |  | #undef IBSLOT
 | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | #undef BINSLOT
 | 
					
						
							|  |  |  | #undef RBINSLOT
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | #define TPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
 | 
					
						
							| 
									
										
										
										
											2002-08-13 19:01:38 +00:00
										 |  |  | 	{NAME, offsetof(PyTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \ | 
					
						
							|  |  |  | 	 PyDoc_STR(DOC)} | 
					
						
							| 
									
										
										
										
											2001-10-22 00:43:43 +00:00
										 |  |  | #define FLSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC, FLAGS) \
 | 
					
						
							|  |  |  | 	{NAME, offsetof(PyTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \ | 
					
						
							| 
									
										
										
										
											2002-08-13 19:01:38 +00:00
										 |  |  | 	 PyDoc_STR(DOC), FLAGS} | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | #define ETSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
 | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  | 	{NAME, offsetof(PyHeapTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \ | 
					
						
							| 
									
										
										
										
											2002-08-13 19:01:38 +00:00
										 |  |  | 	 PyDoc_STR(DOC)} | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | #define SQSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
 | 
					
						
							|  |  |  | 	ETSLOT(NAME, as_sequence.SLOT, FUNCTION, WRAPPER, DOC) | 
					
						
							|  |  |  | #define MPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
 | 
					
						
							|  |  |  | 	ETSLOT(NAME, as_mapping.SLOT, FUNCTION, WRAPPER, DOC) | 
					
						
							|  |  |  | #define NBSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
 | 
					
						
							|  |  |  | 	ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, DOC) | 
					
						
							|  |  |  | #define UNSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
 | 
					
						
							|  |  |  | 	ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, \ | 
					
						
							|  |  |  | 	       "x." NAME "() <==> " DOC) | 
					
						
							|  |  |  | #define IBSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
 | 
					
						
							|  |  |  | 	ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, \ | 
					
						
							|  |  |  | 	       "x." NAME "(y) <==> x" DOC "y") | 
					
						
							|  |  |  | #define BINSLOT(NAME, SLOT, FUNCTION, DOC) \
 | 
					
						
							|  |  |  | 	ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_l, \ | 
					
						
							|  |  |  | 	       "x." NAME "(y) <==> x" DOC "y") | 
					
						
							|  |  |  | #define RBINSLOT(NAME, SLOT, FUNCTION, DOC) \
 | 
					
						
							|  |  |  | 	ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_r, \ | 
					
						
							|  |  |  | 	       "x." NAME "(y) <==> y" DOC "x") | 
					
						
							| 
									
										
										
										
											2005-06-03 14:12:21 +00:00
										 |  |  | #define BINSLOTNOTINFIX(NAME, SLOT, FUNCTION, DOC) \
 | 
					
						
							|  |  |  | 	ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_l, \ | 
					
						
							|  |  |  | 	       "x." NAME "(y) <==> " DOC) | 
					
						
							|  |  |  | #define RBINSLOTNOTINFIX(NAME, SLOT, FUNCTION, DOC) \
 | 
					
						
							|  |  |  | 	ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_r, \ | 
					
						
							|  |  |  | 	       "x." NAME "(y) <==> " DOC) | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static slotdef slotdefs[] = { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	SQSLOT("__len__", sq_length, slot_sq_length, wrap_lenfunc, | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | 	       "x.__len__() <==> len(x)"), | 
					
						
							| 
									
										
										
										
											2005-12-29 15:59:19 +00:00
										 |  |  | 	/* Heap types defining __add__/__mul__ have sq_concat/sq_repeat == NULL.
 | 
					
						
							|  |  |  | 	   The logic in abstract.c always falls back to nb_add/nb_multiply in | 
					
						
							|  |  |  | 	   this case.  Defining both the nb_* and the sq_* slots to call the | 
					
						
							|  |  |  | 	   user-defined methods has unexpected side-effects, as shown by | 
					
						
							|  |  |  | 	   test_descr.notimplemented() */ | 
					
						
							|  |  |  | 	SQSLOT("__add__", sq_concat, NULL, wrap_binaryfunc, | 
					
						
							|  |  |  |           "x.__add__(y) <==> x+y"), | 
					
						
							| 
									
										
										
										
											2006-03-30 14:04:02 +00:00
										 |  |  | 	SQSLOT("__mul__", sq_repeat, NULL, wrap_indexargfunc, | 
					
						
							| 
									
										
										
										
											2005-12-29 15:59:19 +00:00
										 |  |  |           "x.__mul__(n) <==> x*n"), | 
					
						
							| 
									
										
										
										
											2006-03-30 14:04:02 +00:00
										 |  |  | 	SQSLOT("__rmul__", sq_repeat, NULL, wrap_indexargfunc, | 
					
						
							| 
									
										
										
										
											2005-12-29 15:59:19 +00:00
										 |  |  |           "x.__rmul__(n) <==> n*x"), | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | 	SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item, | 
					
						
							|  |  |  | 	       "x.__getitem__(y) <==> x[y]"), | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	SQSLOT("__getslice__", sq_slice, slot_sq_slice, wrap_ssizessizeargfunc, | 
					
						
							| 
									
										
										
										
											2003-05-20 02:30:04 +00:00
										 |  |  | 	       "x.__getslice__(i, j) <==> x[i:j]\n\
 | 
					
						
							|  |  |  |                \n\ | 
					
						
							|  |  |  |                Use of negative indices is not supported."), | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | 	SQSLOT("__setitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_setitem, | 
					
						
							| 
									
										
										
										
											2003-05-20 02:40:12 +00:00
										 |  |  | 	       "x.__setitem__(i, y) <==> x[i]=y"), | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | 	SQSLOT("__delitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_delitem, | 
					
						
							| 
									
										
										
										
											2003-05-20 02:40:12 +00:00
										 |  |  | 	       "x.__delitem__(y) <==> del x[y]"), | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | 	SQSLOT("__setslice__", sq_ass_slice, slot_sq_ass_slice, | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	       wrap_ssizessizeobjargproc, | 
					
						
							| 
									
										
										
										
											2003-05-20 02:40:12 +00:00
										 |  |  | 	       "x.__setslice__(i, j, y) <==> x[i:j]=y\n\
 | 
					
						
							|  |  |  |                \n\ | 
					
						
							|  |  |  |                Use  of negative indices is not supported."), | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | 	SQSLOT("__delslice__", sq_ass_slice, slot_sq_ass_slice, wrap_delslice, | 
					
						
							| 
									
										
										
										
											2003-05-20 02:40:12 +00:00
										 |  |  | 	       "x.__delslice__(i, j) <==> del x[i:j]\n\
 | 
					
						
							|  |  |  |                \n\ | 
					
						
							|  |  |  |                Use of negative indices is not supported."), | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | 	SQSLOT("__contains__", sq_contains, slot_sq_contains, wrap_objobjproc, | 
					
						
							|  |  |  | 	       "x.__contains__(y) <==> y in x"), | 
					
						
							| 
									
										
										
										
											2005-12-29 15:59:19 +00:00
										 |  |  | 	SQSLOT("__iadd__", sq_inplace_concat, NULL, | 
					
						
							|  |  |  |           wrap_binaryfunc, "x.__iadd__(y) <==> x+=y"), | 
					
						
							|  |  |  | 	SQSLOT("__imul__", sq_inplace_repeat, NULL, | 
					
						
							| 
									
										
										
										
											2006-03-30 14:04:02 +00:00
										 |  |  |           wrap_indexargfunc, "x.__imul__(y) <==> x*=y"), | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	MPSLOT("__len__", mp_length, slot_mp_length, wrap_lenfunc, | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | 	       "x.__len__() <==> len(x)"), | 
					
						
							| 
									
										
										
										
											2001-10-09 20:17:57 +00:00
										 |  |  | 	MPSLOT("__getitem__", mp_subscript, slot_mp_subscript, | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | 	       wrap_binaryfunc, | 
					
						
							|  |  |  | 	       "x.__getitem__(y) <==> x[y]"), | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | 	MPSLOT("__setitem__", mp_ass_subscript, slot_mp_ass_subscript, | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | 	       wrap_objobjargproc, | 
					
						
							|  |  |  | 	       "x.__setitem__(i, y) <==> x[i]=y"), | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | 	MPSLOT("__delitem__", mp_ass_subscript, slot_mp_ass_subscript, | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | 	       wrap_delitem, | 
					
						
							|  |  |  | 	       "x.__delitem__(y) <==> del x[y]"), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BINSLOT("__add__", nb_add, slot_nb_add, | 
					
						
							|  |  |  | 		"+"), | 
					
						
							|  |  |  | 	RBINSLOT("__radd__", nb_add, slot_nb_add, | 
					
						
							|  |  |  | 		 "+"), | 
					
						
							|  |  |  | 	BINSLOT("__sub__", nb_subtract, slot_nb_subtract, | 
					
						
							|  |  |  | 		"-"), | 
					
						
							|  |  |  | 	RBINSLOT("__rsub__", nb_subtract, slot_nb_subtract, | 
					
						
							|  |  |  | 		 "-"), | 
					
						
							|  |  |  | 	BINSLOT("__mul__", nb_multiply, slot_nb_multiply, | 
					
						
							|  |  |  | 		"*"), | 
					
						
							|  |  |  | 	RBINSLOT("__rmul__", nb_multiply, slot_nb_multiply, | 
					
						
							|  |  |  | 		 "*"), | 
					
						
							|  |  |  | 	BINSLOT("__div__", nb_divide, slot_nb_divide, | 
					
						
							|  |  |  | 		"/"), | 
					
						
							|  |  |  | 	RBINSLOT("__rdiv__", nb_divide, slot_nb_divide, | 
					
						
							|  |  |  | 		 "/"), | 
					
						
							|  |  |  | 	BINSLOT("__mod__", nb_remainder, slot_nb_remainder, | 
					
						
							|  |  |  | 		"%"), | 
					
						
							|  |  |  | 	RBINSLOT("__rmod__", nb_remainder, slot_nb_remainder, | 
					
						
							|  |  |  | 		 "%"), | 
					
						
							| 
									
										
										
										
											2005-06-03 14:12:21 +00:00
										 |  |  | 	BINSLOTNOTINFIX("__divmod__", nb_divmod, slot_nb_divmod, | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | 		"divmod(x, y)"), | 
					
						
							| 
									
										
										
										
											2005-06-03 14:12:21 +00:00
										 |  |  | 	RBINSLOTNOTINFIX("__rdivmod__", nb_divmod, slot_nb_divmod, | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | 		 "divmod(y, x)"), | 
					
						
							|  |  |  | 	NBSLOT("__pow__", nb_power, slot_nb_power, wrap_ternaryfunc, | 
					
						
							|  |  |  | 	       "x.__pow__(y[, z]) <==> pow(x, y[, z])"), | 
					
						
							|  |  |  | 	NBSLOT("__rpow__", nb_power, slot_nb_power, wrap_ternaryfunc_r, | 
					
						
							|  |  |  | 	       "y.__rpow__(x[, z]) <==> pow(x, y[, z])"), | 
					
						
							|  |  |  | 	UNSLOT("__neg__", nb_negative, slot_nb_negative, wrap_unaryfunc, "-x"), | 
					
						
							|  |  |  | 	UNSLOT("__pos__", nb_positive, slot_nb_positive, wrap_unaryfunc, "+x"), | 
					
						
							|  |  |  | 	UNSLOT("__abs__", nb_absolute, slot_nb_absolute, wrap_unaryfunc, | 
					
						
							|  |  |  | 	       "abs(x)"), | 
					
						
							| 
									
										
										
										
											2003-10-11 17:29:04 +00:00
										 |  |  | 	UNSLOT("__nonzero__", nb_nonzero, slot_nb_nonzero, wrap_inquirypred, | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | 	       "x != 0"), | 
					
						
							|  |  |  | 	UNSLOT("__invert__", nb_invert, slot_nb_invert, wrap_unaryfunc, "~x"), | 
					
						
							|  |  |  | 	BINSLOT("__lshift__", nb_lshift, slot_nb_lshift, "<<"), | 
					
						
							|  |  |  | 	RBINSLOT("__rlshift__", nb_lshift, slot_nb_lshift, "<<"), | 
					
						
							|  |  |  | 	BINSLOT("__rshift__", nb_rshift, slot_nb_rshift, ">>"), | 
					
						
							|  |  |  | 	RBINSLOT("__rrshift__", nb_rshift, slot_nb_rshift, ">>"), | 
					
						
							|  |  |  | 	BINSLOT("__and__", nb_and, slot_nb_and, "&"), | 
					
						
							|  |  |  | 	RBINSLOT("__rand__", nb_and, slot_nb_and, "&"), | 
					
						
							|  |  |  | 	BINSLOT("__xor__", nb_xor, slot_nb_xor, "^"), | 
					
						
							|  |  |  | 	RBINSLOT("__rxor__", nb_xor, slot_nb_xor, "^"), | 
					
						
							|  |  |  | 	BINSLOT("__or__", nb_or, slot_nb_or, "|"), | 
					
						
							|  |  |  | 	RBINSLOT("__ror__", nb_or, slot_nb_or, "|"), | 
					
						
							|  |  |  | 	NBSLOT("__coerce__", nb_coerce, slot_nb_coerce, wrap_coercefunc, | 
					
						
							|  |  |  | 	       "x.__coerce__(y) <==> coerce(x, y)"), | 
					
						
							|  |  |  | 	UNSLOT("__int__", nb_int, slot_nb_int, wrap_unaryfunc, | 
					
						
							|  |  |  | 	       "int(x)"), | 
					
						
							|  |  |  | 	UNSLOT("__long__", nb_long, slot_nb_long, wrap_unaryfunc, | 
					
						
							|  |  |  | 	       "long(x)"), | 
					
						
							|  |  |  | 	UNSLOT("__float__", nb_float, slot_nb_float, wrap_unaryfunc, | 
					
						
							|  |  |  | 	       "float(x)"), | 
					
						
							|  |  |  | 	UNSLOT("__oct__", nb_oct, slot_nb_oct, wrap_unaryfunc, | 
					
						
							|  |  |  | 	       "oct(x)"), | 
					
						
							|  |  |  | 	UNSLOT("__hex__", nb_hex, slot_nb_hex, wrap_unaryfunc, | 
					
						
							|  |  |  | 	       "hex(x)"), | 
					
						
							| 
									
										
										
										
											2006-08-12 17:03:09 +00:00
										 |  |  | 	NBSLOT("__index__", nb_index, slot_nb_index, wrap_unaryfunc,  | 
					
						
							| 
									
										
										
										
											2006-03-07 18:50:55 +00:00
										 |  |  | 	       "x[y:z] <==> x[y.__index__():z.__index__()]"), | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | 	IBSLOT("__iadd__", nb_inplace_add, slot_nb_inplace_add, | 
					
						
							|  |  |  | 	       wrap_binaryfunc, "+"), | 
					
						
							|  |  |  | 	IBSLOT("__isub__", nb_inplace_subtract, slot_nb_inplace_subtract, | 
					
						
							|  |  |  | 	       wrap_binaryfunc, "-"), | 
					
						
							|  |  |  | 	IBSLOT("__imul__", nb_inplace_multiply, slot_nb_inplace_multiply, | 
					
						
							|  |  |  | 	       wrap_binaryfunc, "*"), | 
					
						
							|  |  |  | 	IBSLOT("__idiv__", nb_inplace_divide, slot_nb_inplace_divide, | 
					
						
							|  |  |  | 	       wrap_binaryfunc, "/"), | 
					
						
							|  |  |  | 	IBSLOT("__imod__", nb_inplace_remainder, slot_nb_inplace_remainder, | 
					
						
							|  |  |  | 	       wrap_binaryfunc, "%"), | 
					
						
							|  |  |  | 	IBSLOT("__ipow__", nb_inplace_power, slot_nb_inplace_power, | 
					
						
							| 
									
										
										
										
											2002-10-15 01:01:53 +00:00
										 |  |  | 	       wrap_binaryfunc, "**"), | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | 	IBSLOT("__ilshift__", nb_inplace_lshift, slot_nb_inplace_lshift, | 
					
						
							|  |  |  | 	       wrap_binaryfunc, "<<"), | 
					
						
							|  |  |  | 	IBSLOT("__irshift__", nb_inplace_rshift, slot_nb_inplace_rshift, | 
					
						
							|  |  |  | 	       wrap_binaryfunc, ">>"), | 
					
						
							|  |  |  | 	IBSLOT("__iand__", nb_inplace_and, slot_nb_inplace_and, | 
					
						
							|  |  |  | 	       wrap_binaryfunc, "&"), | 
					
						
							|  |  |  | 	IBSLOT("__ixor__", nb_inplace_xor, slot_nb_inplace_xor, | 
					
						
							|  |  |  | 	       wrap_binaryfunc, "^"), | 
					
						
							|  |  |  | 	IBSLOT("__ior__", nb_inplace_or, slot_nb_inplace_or, | 
					
						
							|  |  |  | 	       wrap_binaryfunc, "|"), | 
					
						
							|  |  |  | 	BINSLOT("__floordiv__", nb_floor_divide, slot_nb_floor_divide, "//"), | 
					
						
							|  |  |  | 	RBINSLOT("__rfloordiv__", nb_floor_divide, slot_nb_floor_divide, "//"), | 
					
						
							|  |  |  | 	BINSLOT("__truediv__", nb_true_divide, slot_nb_true_divide, "/"), | 
					
						
							|  |  |  | 	RBINSLOT("__rtruediv__", nb_true_divide, slot_nb_true_divide, "/"), | 
					
						
							|  |  |  | 	IBSLOT("__ifloordiv__", nb_inplace_floor_divide, | 
					
						
							|  |  |  | 	       slot_nb_inplace_floor_divide, wrap_binaryfunc, "//"), | 
					
						
							|  |  |  | 	IBSLOT("__itruediv__", nb_inplace_true_divide, | 
					
						
							|  |  |  | 	       slot_nb_inplace_true_divide, wrap_binaryfunc, "/"), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	TPSLOT("__str__", tp_str, slot_tp_str, wrap_unaryfunc, | 
					
						
							|  |  |  | 	       "x.__str__() <==> str(x)"), | 
					
						
							| 
									
										
										
										
											2001-10-29 14:33:44 +00:00
										 |  |  | 	TPSLOT("__str__", tp_print, NULL, NULL, ""), | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | 	TPSLOT("__repr__", tp_repr, slot_tp_repr, wrap_unaryfunc, | 
					
						
							|  |  |  | 	       "x.__repr__() <==> repr(x)"), | 
					
						
							| 
									
										
										
										
											2001-10-29 14:33:44 +00:00
										 |  |  | 	TPSLOT("__repr__", tp_print, NULL, NULL, ""), | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | 	TPSLOT("__cmp__", tp_compare, _PyObject_SlotCompare, wrap_cmpfunc, | 
					
						
							|  |  |  | 	       "x.__cmp__(y) <==> cmp(x,y)"), | 
					
						
							|  |  |  | 	TPSLOT("__hash__", tp_hash, slot_tp_hash, wrap_hashfunc, | 
					
						
							|  |  |  | 	       "x.__hash__() <==> hash(x)"), | 
					
						
							| 
									
										
										
										
											2001-10-22 00:43:43 +00:00
										 |  |  | 	FLSLOT("__call__", tp_call, slot_tp_call, (wrapperfunc)wrap_call, | 
					
						
							|  |  |  | 	       "x.__call__(...) <==> x(...)", PyWrapperFlag_KEYWORDS), | 
					
						
							| 
									
										
										
										
											2001-10-13 20:02:41 +00:00
										 |  |  | 	TPSLOT("__getattribute__", tp_getattro, slot_tp_getattr_hook, | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | 	       wrap_binaryfunc, "x.__getattribute__('name') <==> x.name"), | 
					
						
							|  |  |  | 	TPSLOT("__getattribute__", tp_getattr, NULL, NULL, ""), | 
					
						
							|  |  |  | 	TPSLOT("__getattr__", tp_getattro, slot_tp_getattr_hook, NULL, ""), | 
					
						
							|  |  |  | 	TPSLOT("__getattr__", tp_getattr, NULL, NULL, ""), | 
					
						
							|  |  |  | 	TPSLOT("__setattr__", tp_setattro, slot_tp_setattro, wrap_setattr, | 
					
						
							|  |  |  | 	       "x.__setattr__('name', value) <==> x.name = value"), | 
					
						
							|  |  |  | 	TPSLOT("__setattr__", tp_setattr, NULL, NULL, ""), | 
					
						
							|  |  |  | 	TPSLOT("__delattr__", tp_setattro, slot_tp_setattro, wrap_delattr, | 
					
						
							|  |  |  | 	       "x.__delattr__('name') <==> del x.name"), | 
					
						
							|  |  |  | 	TPSLOT("__delattr__", tp_setattr, NULL, NULL, ""), | 
					
						
							|  |  |  | 	TPSLOT("__lt__", tp_richcompare, slot_tp_richcompare, richcmp_lt, | 
					
						
							|  |  |  | 	       "x.__lt__(y) <==> x<y"), | 
					
						
							|  |  |  | 	TPSLOT("__le__", tp_richcompare, slot_tp_richcompare, richcmp_le, | 
					
						
							|  |  |  | 	       "x.__le__(y) <==> x<=y"), | 
					
						
							|  |  |  | 	TPSLOT("__eq__", tp_richcompare, slot_tp_richcompare, richcmp_eq, | 
					
						
							|  |  |  | 	       "x.__eq__(y) <==> x==y"), | 
					
						
							|  |  |  | 	TPSLOT("__ne__", tp_richcompare, slot_tp_richcompare, richcmp_ne, | 
					
						
							|  |  |  | 	       "x.__ne__(y) <==> x!=y"), | 
					
						
							|  |  |  | 	TPSLOT("__gt__", tp_richcompare, slot_tp_richcompare, richcmp_gt, | 
					
						
							|  |  |  | 	       "x.__gt__(y) <==> x>y"), | 
					
						
							|  |  |  | 	TPSLOT("__ge__", tp_richcompare, slot_tp_richcompare, richcmp_ge, | 
					
						
							|  |  |  | 	       "x.__ge__(y) <==> x>=y"), | 
					
						
							|  |  |  | 	TPSLOT("__iter__", tp_iter, slot_tp_iter, wrap_unaryfunc, | 
					
						
							|  |  |  | 	       "x.__iter__() <==> iter(x)"), | 
					
						
							|  |  |  | 	TPSLOT("next", tp_iternext, slot_tp_iternext, wrap_next, | 
					
						
							|  |  |  | 	       "x.next() -> the next value, or raise StopIteration"), | 
					
						
							|  |  |  | 	TPSLOT("__get__", tp_descr_get, slot_tp_descr_get, wrap_descr_get, | 
					
						
							|  |  |  | 	       "descr.__get__(obj[, type]) -> value"), | 
					
						
							|  |  |  | 	TPSLOT("__set__", tp_descr_set, slot_tp_descr_set, wrap_descr_set, | 
					
						
							|  |  |  | 	       "descr.__set__(obj, value)"), | 
					
						
							| 
									
										
										
										
											2002-08-01 14:39:25 +00:00
										 |  |  | 	TPSLOT("__delete__", tp_descr_set, slot_tp_descr_set, | 
					
						
							|  |  |  | 	       wrap_descr_delete, "descr.__delete__(obj)"), | 
					
						
							| 
									
										
										
										
											2001-10-22 00:43:43 +00:00
										 |  |  | 	FLSLOT("__init__", tp_init, slot_tp_init, (wrapperfunc)wrap_init, | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | 	       "x.__init__(...) initializes x; " | 
					
						
							| 
									
										
										
										
											2001-10-22 00:43:43 +00:00
										 |  |  | 	       "see x.__class__.__doc__ for signature", | 
					
						
							|  |  |  | 	       PyWrapperFlag_KEYWORDS), | 
					
						
							|  |  |  | 	TPSLOT("__new__", tp_new, slot_tp_new, NULL, ""), | 
					
						
							| 
									
										
										
										
											2002-08-08 20:55:20 +00:00
										 |  |  | 	TPSLOT("__del__", tp_del, slot_tp_del, NULL, ""), | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | 	{NULL} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-04-04 23:44:47 +00:00
										 |  |  | /* Given a type pointer and an offset gotten from a slotdef entry, return a
 | 
					
						
							|  |  |  |    pointer to the actual slot.  This is not quite the same as simply adding | 
					
						
							|  |  |  |    the offset to the type pointer, since it takes care to indirect through the | 
					
						
							|  |  |  |    proper indirection pointer (as_buffer, etc.); it returns NULL if the | 
					
						
							|  |  |  |    indirection pointer is NULL. */ | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | static void ** | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | slotptr(PyTypeObject *type, int ioffset) | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	char *ptr; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	long offset = ioffset; | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  | 	/* Note: this depends on the order of the members of PyHeapTypeObject! */ | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | 	assert(offset >= 0); | 
					
						
							| 
									
										
										
										
											2006-04-18 00:35:43 +00:00
										 |  |  | 	assert((size_t)offset < offsetof(PyHeapTypeObject, as_buffer)); | 
					
						
							|  |  |  | 	if ((size_t)offset >= offsetof(PyHeapTypeObject, as_sequence)) { | 
					
						
							| 
									
										
										
										
											2006-04-11 09:08:02 +00:00
										 |  |  | 		ptr = (char *)type->tp_as_sequence; | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  | 		offset -= offsetof(PyHeapTypeObject, as_sequence); | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-04-18 00:35:43 +00:00
										 |  |  | 	else if ((size_t)offset >= offsetof(PyHeapTypeObject, as_mapping)) { | 
					
						
							| 
									
										
										
										
											2006-04-11 09:08:02 +00:00
										 |  |  | 		ptr = (char *)type->tp_as_mapping; | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  | 		offset -= offsetof(PyHeapTypeObject, as_mapping); | 
					
						
							| 
									
										
										
										
											2002-06-13 19:17:46 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-04-18 00:35:43 +00:00
										 |  |  | 	else if ((size_t)offset >= offsetof(PyHeapTypeObject, as_number)) { | 
					
						
							| 
									
										
										
										
											2006-04-11 09:08:02 +00:00
										 |  |  | 		ptr = (char *)type->tp_as_number; | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  | 		offset -= offsetof(PyHeapTypeObject, as_number); | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2006-04-11 09:08:02 +00:00
										 |  |  | 		ptr = (char *)type; | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (ptr != NULL) | 
					
						
							|  |  |  | 		ptr += offset; | 
					
						
							|  |  |  | 	return (void **)ptr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-04-04 23:44:47 +00:00
										 |  |  | /* Length of array of slotdef pointers used to store slots with the
 | 
					
						
							|  |  |  |    same __name__.  There should be at most MAX_EQUIV-1 slotdef entries with | 
					
						
							|  |  |  |    the same __name__, for any __name__. Since that's a static property, it is | 
					
						
							|  |  |  |    appropriate to declare fixed-size arrays for this. */ | 
					
						
							|  |  |  | #define MAX_EQUIV 10
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Return a slot pointer for a given name, but ONLY if the attribute has
 | 
					
						
							|  |  |  |    exactly one slot function.  The name must be an interned string. */ | 
					
						
							|  |  |  | static void ** | 
					
						
							|  |  |  | resolve_slotdups(PyTypeObject *type, PyObject *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* XXX Maybe this could be optimized more -- but is it worth it? */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* pname and ptrs act as a little cache */ | 
					
						
							|  |  |  | 	static PyObject *pname; | 
					
						
							|  |  |  | 	static slotdef *ptrs[MAX_EQUIV]; | 
					
						
							|  |  |  | 	slotdef *p, **pp; | 
					
						
							|  |  |  | 	void **res, **ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (pname != name) { | 
					
						
							|  |  |  | 		/* Collect all slotdefs that match name into ptrs. */ | 
					
						
							|  |  |  | 		pname = name; | 
					
						
							|  |  |  | 		pp = ptrs; | 
					
						
							|  |  |  | 		for (p = slotdefs; p->name_strobj; p++) { | 
					
						
							|  |  |  | 			if (p->name_strobj == name) | 
					
						
							|  |  |  | 				*pp++ = p; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		*pp = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Look in all matching slots of the type; if exactly one of these has
 | 
					
						
							|  |  |  | 	   a filled-in slot, return its value.  Otherwise return NULL. */ | 
					
						
							|  |  |  | 	res = NULL; | 
					
						
							|  |  |  | 	for (pp = ptrs; *pp; pp++) { | 
					
						
							|  |  |  | 		ptr = slotptr(type, (*pp)->offset); | 
					
						
							|  |  |  | 		if (ptr == NULL || *ptr == NULL) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		if (res != NULL) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		res = ptr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-24 23:49:49 +00:00
										 |  |  | /* Common code for update_slots_callback() and fixup_slot_dispatchers().  This
 | 
					
						
							| 
									
										
										
										
											2002-04-04 23:44:47 +00:00
										 |  |  |    does some incredibly complex thinking and then sticks something into the | 
					
						
							|  |  |  |    slot.  (It sees if the adjacent slotdefs for the same slot have conflicting | 
					
						
							|  |  |  |    interests, and then stores a generic wrapper or a specific function into | 
					
						
							|  |  |  |    the slot.)  Return a pointer to the next slotdef with a different offset, | 
					
						
							|  |  |  |    because that's convenient  for fixup_slot_dispatchers(). */ | 
					
						
							|  |  |  | static slotdef * | 
					
						
							|  |  |  | update_one_slot(PyTypeObject *type, slotdef *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *descr; | 
					
						
							|  |  |  | 	PyWrapperDescrObject *d; | 
					
						
							|  |  |  | 	void *generic = NULL, *specific = NULL; | 
					
						
							|  |  |  | 	int use_generic = 0; | 
					
						
							|  |  |  | 	int offset = p->offset; | 
					
						
							|  |  |  | 	void **ptr = slotptr(type, offset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ptr == NULL) { | 
					
						
							|  |  |  | 		do { | 
					
						
							|  |  |  | 			++p; | 
					
						
							|  |  |  | 		} while (p->offset == offset); | 
					
						
							|  |  |  | 		return p; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	do { | 
					
						
							|  |  |  | 		descr = _PyType_Lookup(type, p->name_strobj); | 
					
						
							|  |  |  | 		if (descr == NULL) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		if (descr->ob_type == &PyWrapperDescr_Type) { | 
					
						
							|  |  |  | 			void **tptr = resolve_slotdups(type, p->name_strobj); | 
					
						
							|  |  |  | 			if (tptr == NULL || tptr == ptr) | 
					
						
							|  |  |  | 				generic = p->function; | 
					
						
							|  |  |  | 			d = (PyWrapperDescrObject *)descr; | 
					
						
							|  |  |  | 			if (d->d_base->wrapper == p->wrapper && | 
					
						
							|  |  |  | 			    PyType_IsSubtype(type, d->d_type)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				if (specific == NULL || | 
					
						
							|  |  |  | 				    specific == d->d_wrapped) | 
					
						
							|  |  |  | 					specific = d->d_wrapped; | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					use_generic = 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2002-08-09 02:14:34 +00:00
										 |  |  | 		else if (descr->ob_type == &PyCFunction_Type && | 
					
						
							|  |  |  | 			 PyCFunction_GET_FUNCTION(descr) == | 
					
						
							|  |  |  | 			 (PyCFunction)tp_new_wrapper && | 
					
						
							|  |  |  | 			 strcmp(p->name, "__new__") == 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			/* The __new__ wrapper is not a wrapper descriptor,
 | 
					
						
							|  |  |  | 			   so must be special-cased differently. | 
					
						
							|  |  |  | 			   If we don't do this, creating an instance will | 
					
						
							|  |  |  | 			   always use slot_tp_new which will look up | 
					
						
							|  |  |  | 			   __new__ in the MRO which will call tp_new_wrapper | 
					
						
							|  |  |  | 			   which will look through the base classes looking | 
					
						
							|  |  |  | 			   for a static base and call its tp_new (usually | 
					
						
							|  |  |  | 			   PyType_GenericNew), after performing various | 
					
						
							|  |  |  | 			   sanity checks and constructing a new argument | 
					
						
							|  |  |  | 			   list.  Cut all that nonsense short -- this speeds | 
					
						
							|  |  |  | 			   up instance creation tremendously. */ | 
					
						
							| 
									
										
										
										
											2003-05-10 07:36:56 +00:00
										 |  |  | 			specific = (void *)type->tp_new; | 
					
						
							| 
									
										
										
										
											2002-08-09 02:14:34 +00:00
										 |  |  | 			/* XXX I'm not 100% sure that there isn't a hole
 | 
					
						
							|  |  |  | 			   in this reasoning that requires additional | 
					
						
							|  |  |  | 			   sanity checks.  I'll buy the first person to | 
					
						
							|  |  |  | 			   point out a bug in this reasoning a beer. */ | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2002-04-04 23:44:47 +00:00
										 |  |  | 		else { | 
					
						
							|  |  |  | 			use_generic = 1; | 
					
						
							|  |  |  | 			generic = p->function; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} while ((++p)->offset == offset); | 
					
						
							|  |  |  | 	if (specific && !use_generic) | 
					
						
							|  |  |  | 		*ptr = specific; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		*ptr = generic; | 
					
						
							|  |  |  | 	return p; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-24 23:49:49 +00:00
										 |  |  | /* In the type, update the slots whose slotdefs are gathered in the pp array.
 | 
					
						
							|  |  |  |    This is a callback for update_subclasses(). */ | 
					
						
							| 
									
										
										
										
											2001-10-11 18:33:53 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2003-03-24 23:49:49 +00:00
										 |  |  | update_slots_callback(PyTypeObject *type, void *data) | 
					
						
							| 
									
										
										
										
											2001-10-11 18:33:53 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2003-03-24 23:49:49 +00:00
										 |  |  | 	slotdef **pp = (slotdef **)data; | 
					
						
							| 
									
										
										
										
											2001-10-11 18:33:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-24 23:49:49 +00:00
										 |  |  | 	for (; *pp; pp++) | 
					
						
							| 
									
										
										
										
											2002-04-04 23:44:47 +00:00
										 |  |  | 		update_one_slot(type, *pp); | 
					
						
							| 
									
										
										
										
											2001-10-11 18:33:53 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-04-04 23:44:47 +00:00
										 |  |  | /* Comparison function for qsort() to compare slotdefs by their offset, and
 | 
					
						
							|  |  |  |    for equal offset by their address (to force a stable sort). */ | 
					
						
							| 
									
										
										
										
											2001-10-13 20:02:41 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | slotdef_cmp(const void *aa, const void *bb) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const slotdef *a = (const slotdef *)aa, *b = (const slotdef *)bb; | 
					
						
							|  |  |  | 	int c = a->offset - b->offset; | 
					
						
							|  |  |  | 	if (c != 0) | 
					
						
							|  |  |  | 		return c; | 
					
						
							|  |  |  | 	else | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 		/* Cannot use a-b, as this gives off_t, 
 | 
					
						
							|  |  |  | 		   which may lose precision when converted to int. */ | 
					
						
							|  |  |  | 		return (a > b) ? 1 : (a < b) ? -1 : 0; | 
					
						
							| 
									
										
										
										
											2001-10-13 20:02:41 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-04-04 23:44:47 +00:00
										 |  |  | /* Initialize the slotdefs table by adding interned string objects for the
 | 
					
						
							|  |  |  |    names and sorting the entries. */ | 
					
						
							| 
									
										
										
										
											2001-10-11 18:33:53 +00:00
										 |  |  | static void | 
					
						
							| 
									
										
										
										
											2001-10-13 20:02:41 +00:00
										 |  |  | init_slotdefs(void) | 
					
						
							| 
									
										
										
										
											2001-10-11 18:33:53 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	slotdef *p; | 
					
						
							|  |  |  | 	static int initialized = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (initialized) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	for (p = slotdefs; p->name; p++) { | 
					
						
							|  |  |  | 		p->name_strobj = PyString_InternFromString(p->name); | 
					
						
							|  |  |  | 		if (!p->name_strobj) | 
					
						
							| 
									
										
										
										
											2002-04-04 23:44:47 +00:00
										 |  |  | 			Py_FatalError("Out of memory interning slotdef names"); | 
					
						
							| 
									
										
										
										
											2001-10-11 18:33:53 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-10-16 17:00:48 +00:00
										 |  |  | 	qsort((void *)slotdefs, (size_t)(p-slotdefs), sizeof(slotdef), | 
					
						
							|  |  |  | 	      slotdef_cmp); | 
					
						
							| 
									
										
										
										
											2001-10-11 18:33:53 +00:00
										 |  |  | 	initialized = 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-04-04 23:44:47 +00:00
										 |  |  | /* Update the slots after assignment to a class (type) attribute. */ | 
					
						
							| 
									
										
										
										
											2001-10-11 18:33:53 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | update_slot(PyTypeObject *type, PyObject *name) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-04-04 23:44:47 +00:00
										 |  |  | 	slotdef *ptrs[MAX_EQUIV]; | 
					
						
							| 
									
										
										
										
											2001-10-13 20:02:41 +00:00
										 |  |  | 	slotdef *p; | 
					
						
							|  |  |  | 	slotdef **pp; | 
					
						
							| 
									
										
										
										
											2001-10-16 17:00:48 +00:00
										 |  |  | 	int offset; | 
					
						
							| 
									
										
										
										
											2001-10-13 20:02:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-16 17:00:48 +00:00
										 |  |  | 	init_slotdefs(); | 
					
						
							|  |  |  | 	pp = ptrs; | 
					
						
							|  |  |  | 	for (p = slotdefs; p->name; p++) { | 
					
						
							|  |  |  | 		/* XXX assume name is interned! */ | 
					
						
							|  |  |  | 		if (p->name_strobj == name) | 
					
						
							|  |  |  | 			*pp++ = p; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	*pp = NULL; | 
					
						
							| 
									
										
										
										
											2001-10-13 20:02:41 +00:00
										 |  |  | 	for (pp = ptrs; *pp; pp++) { | 
					
						
							|  |  |  | 		p = *pp; | 
					
						
							| 
									
										
										
										
											2001-10-16 17:00:48 +00:00
										 |  |  | 		offset = p->offset; | 
					
						
							|  |  |  | 		while (p > slotdefs && (p-1)->offset == offset) | 
					
						
							| 
									
										
										
										
											2001-10-13 20:02:41 +00:00
										 |  |  | 			--p; | 
					
						
							| 
									
										
										
										
											2001-10-16 17:00:48 +00:00
										 |  |  | 		*pp = p; | 
					
						
							| 
									
										
										
										
											2001-10-11 18:33:53 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2002-04-04 23:44:47 +00:00
										 |  |  | 	if (ptrs[0] == NULL) | 
					
						
							|  |  |  | 		return 0; /* Not an attribute that affects any slots */ | 
					
						
							| 
									
										
										
										
											2003-03-24 23:49:49 +00:00
										 |  |  | 	return update_subclasses(type, name, | 
					
						
							|  |  |  | 				 update_slots_callback, (void *)ptrs); | 
					
						
							| 
									
										
										
										
											2001-10-11 18:33:53 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-04-04 23:44:47 +00:00
										 |  |  | /* Store the proper functions in the slot dispatches at class (type)
 | 
					
						
							|  |  |  |    definition time, based upon which operations the class overrides in its | 
					
						
							|  |  |  |    dict. */ | 
					
						
							| 
									
										
										
										
											2001-10-09 19:39:46 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | fixup_slot_dispatchers(PyTypeObject *type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	slotdef *p; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-13 20:02:41 +00:00
										 |  |  | 	init_slotdefs(); | 
					
						
							| 
									
										
										
										
											2002-04-04 23:44:47 +00:00
										 |  |  | 	for (p = slotdefs; p->name; ) | 
					
						
							|  |  |  | 		p = update_one_slot(type, p); | 
					
						
							| 
									
										
										
										
											2001-08-02 04:15:00 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-26 14:47:27 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | update_all_slots(PyTypeObject* type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	slotdef *p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	init_slotdefs(); | 
					
						
							|  |  |  | 	for (p = slotdefs; p->name; p++) { | 
					
						
							|  |  |  | 		/* update_slot returns int but can't actually fail */ | 
					
						
							|  |  |  | 		update_slot(type, p->name_strobj); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-24 23:49:49 +00:00
										 |  |  | /* recurse_down_subclasses() and update_subclasses() are mutually
 | 
					
						
							|  |  |  |    recursive functions to call a callback for all subclasses, | 
					
						
							|  |  |  |    but refraining from recursing into subclasses that define 'name'. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | update_subclasses(PyTypeObject *type, PyObject *name, | 
					
						
							|  |  |  | 		  update_callback callback, void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (callback(type, data) < 0) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	return recurse_down_subclasses(type, name, callback, data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | recurse_down_subclasses(PyTypeObject *type, PyObject *name, | 
					
						
							|  |  |  | 			update_callback callback, void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyTypeObject *subclass; | 
					
						
							|  |  |  | 	PyObject *ref, *subclasses, *dict; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	Py_ssize_t i, n; | 
					
						
							| 
									
										
										
										
											2003-03-24 23:49:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	subclasses = type->tp_subclasses; | 
					
						
							|  |  |  | 	if (subclasses == NULL) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	assert(PyList_Check(subclasses)); | 
					
						
							|  |  |  | 	n = PyList_GET_SIZE(subclasses); | 
					
						
							|  |  |  | 	for (i = 0; i < n; i++) { | 
					
						
							|  |  |  | 		ref = PyList_GET_ITEM(subclasses, i); | 
					
						
							|  |  |  | 		assert(PyWeakref_CheckRef(ref)); | 
					
						
							|  |  |  | 		subclass = (PyTypeObject *)PyWeakref_GET_OBJECT(ref); | 
					
						
							|  |  |  | 		assert(subclass != NULL); | 
					
						
							|  |  |  | 		if ((PyObject *)subclass == Py_None) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		assert(PyType_Check(subclass)); | 
					
						
							|  |  |  | 		/* Avoid recursing down into unaffected classes */ | 
					
						
							|  |  |  | 		dict = subclass->tp_dict; | 
					
						
							|  |  |  | 		if (dict != NULL && PyDict_Check(dict) && | 
					
						
							|  |  |  | 		    PyDict_GetItem(dict, name) != NULL) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		if (update_subclasses(subclass, name, callback, data) < 0) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-21 00:44:31 +00:00
										 |  |  | /* This function is called by PyType_Ready() to populate the type's
 | 
					
						
							|  |  |  |    dictionary with method descriptors for function slots.  For each | 
					
						
							| 
									
										
										
										
											2002-06-13 19:17:46 +00:00
										 |  |  |    function slot (like tp_repr) that's defined in the type, one or more | 
					
						
							|  |  |  |    corresponding descriptors are added in the type's tp_dict 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). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    In the latter case, the first slotdef entry encoutered wins.  Since | 
					
						
							| 
									
										
										
										
											2003-03-23 05:35:36 +00:00
										 |  |  |    slotdef entries are sorted by the offset of the slot in the | 
					
						
							| 
									
										
										
										
											2003-03-07 15:13:17 +00:00
										 |  |  |    PyHeapTypeObject, this gives us some control over disambiguating | 
					
						
							| 
									
										
										
										
											2003-03-24 23:49:49 +00:00
										 |  |  |    between competing slots: the members of PyHeapTypeObject are listed | 
					
						
							|  |  |  |    from most general to least general, so the most general slot is | 
					
						
							|  |  |  |    preferred.  In particular, because as_mapping comes before as_sequence, | 
					
						
							|  |  |  |    for a type that defines both mp_subscript and sq_item, mp_subscript | 
					
						
							|  |  |  |    wins. | 
					
						
							| 
									
										
										
										
											2002-06-13 19:17:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    This only adds new descriptors and doesn't overwrite entries in | 
					
						
							|  |  |  |    tp_dict 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-10-21 00:44:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | add_operators(PyTypeObject *type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *dict = type->tp_dict; | 
					
						
							|  |  |  | 	slotdef *p; | 
					
						
							|  |  |  | 	PyObject *descr; | 
					
						
							|  |  |  | 	void **ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	init_slotdefs(); | 
					
						
							|  |  |  | 	for (p = slotdefs; p->name; p++) { | 
					
						
							|  |  |  | 		if (p->wrapper == NULL) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		ptr = slotptr(type, p->offset); | 
					
						
							|  |  |  | 		if (!ptr || !*ptr) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		if (PyDict_GetItem(dict, p->name_strobj)) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		descr = PyDescr_NewWrapper(type, p, *ptr); | 
					
						
							|  |  |  | 		if (descr == NULL) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		if (PyDict_SetItem(dict, p->name_strobj, descr) < 0) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		Py_DECREF(descr); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (type->tp_new != NULL) { | 
					
						
							|  |  |  | 		if (add_tp_new_wrapper(type) < 0) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Cooperative 'super' */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  | 	PyObject_HEAD | 
					
						
							| 
									
										
										
										
											2001-08-29 15:47:06 +00:00
										 |  |  | 	PyTypeObject *type; | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | 	PyObject *obj; | 
					
						
							| 
									
										
										
										
											2003-02-12 03:58:38 +00:00
										 |  |  | 	PyTypeObject *obj_type; | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | } superobject; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-20 20:46:19 +00:00
										 |  |  | static PyMemberDef super_members[] = { | 
					
						
							|  |  |  | 	{"__thisclass__", T_OBJECT, offsetof(superobject, type), READONLY, | 
					
						
							|  |  |  | 	 "the class invoking super()"}, | 
					
						
							|  |  |  | 	{"__self__",  T_OBJECT, offsetof(superobject, obj), READONLY, | 
					
						
							|  |  |  | 	 "the instance invoking super(); may be None"}, | 
					
						
							| 
									
										
										
										
											2003-02-12 03:58:38 +00:00
										 |  |  | 	{"__self_class__", T_OBJECT, offsetof(superobject, obj_type), READONLY, | 
					
						
							| 
									
										
										
										
											2003-10-20 14:01:56 +00:00
										 |  |  | 	 "the type of the instance invoking super(); may be None"}, | 
					
						
							| 
									
										
										
										
											2001-08-30 23:13:11 +00:00
										 |  |  | 	{0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | super_dealloc(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	superobject *su = (superobject *)self; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Add Garbage Collection support to new-style classes (not yet to their
instances).
Also added GC support to various auxiliary types: super, property,
descriptors, wrappers, dictproxy.  (Only type objects have a tp_clear
field; the other types are.)
One change was necessary to the GC infrastructure.  We have statically
allocated type objects that don't have a GC header (and can't easily
be given one) and heap-allocated type objects that do have a GC
header.  Giving these different metatypes would be really ugly: I
tried, and I had to modify pickle.py, cPickle.c, copy.py, add a new
invent a new name for the new metatype and make it a built-in, change
affected tests...  In short, a mess.  So instead, we add a new type
slot tp_is_gc, which is a simple Boolean function that determines
whether a particular instance has GC headers or not.  This slot is
only relevant for types that have the (new) GC flag bit set.  If the
tp_is_gc slot is NULL (by far the most common case), all instances of
the type are deemed to have GC headers.  This slot is called by the
PyObject_IS_GC() macro (which is only used twice, both times in
gcmodule.c).
I also changed the extern declarations for a bunch of GC-related
functions (_PyObject_GC_Del etc.): these always exist but objimpl.h
only declared them when WITH_CYCLE_GC was defined, but I needed to be
able to reference them without #ifdefs.  (When WITH_CYCLE_GC is not
defined, they do the same as their non-GC counterparts anyway.)
											
										 
											2001-10-02 21:24:57 +00:00
										 |  |  | 	_PyObject_GC_UNTRACK(self); | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | 	Py_XDECREF(su->obj); | 
					
						
							|  |  |  | 	Py_XDECREF(su->type); | 
					
						
							| 
									
										
										
										
											2003-02-12 03:58:38 +00:00
										 |  |  | 	Py_XDECREF(su->obj_type); | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | 	self->ob_type->tp_free(self); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-30 23:13:11 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | super_repr(PyObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	superobject *su = (superobject *)self; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-02-12 03:58:38 +00:00
										 |  |  | 	if (su->obj_type) | 
					
						
							| 
									
										
										
										
											2001-08-30 23:13:11 +00:00
										 |  |  | 		return PyString_FromFormat( | 
					
						
							| 
									
										
										
										
											2001-09-25 03:56:29 +00:00
										 |  |  | 			"<super: <class '%s'>, <%s object>>", | 
					
						
							| 
									
										
										
										
											2001-08-30 23:13:11 +00:00
										 |  |  | 			su->type ? su->type->tp_name : "NULL", | 
					
						
							| 
									
										
										
										
											2003-02-12 03:58:38 +00:00
										 |  |  | 			su->obj_type->tp_name); | 
					
						
							| 
									
										
										
										
											2001-08-30 23:13:11 +00:00
										 |  |  | 	else | 
					
						
							|  |  |  | 		return PyString_FromFormat( | 
					
						
							| 
									
										
										
										
											2001-09-25 03:56:29 +00:00
										 |  |  | 			"<super: <class '%s'>, NULL>", | 
					
						
							| 
									
										
										
										
											2001-08-30 23:13:11 +00:00
										 |  |  | 			su->type ? su->type->tp_name : "NULL"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | super_getattro(PyObject *self, PyObject *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	superobject *su = (superobject *)self; | 
					
						
							| 
									
										
										
										
											2003-04-16 19:40:58 +00:00
										 |  |  | 	int skip = su->obj_type == NULL; | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-16 19:40:58 +00:00
										 |  |  | 	if (!skip) { | 
					
						
							|  |  |  | 		/* We want __class__ to return the class of the super object
 | 
					
						
							|  |  |  | 		   (i.e. super, or a subclass), not the class of su->obj. */ | 
					
						
							|  |  |  | 		skip = (PyString_Check(name) && | 
					
						
							|  |  |  | 			PyString_GET_SIZE(name) == 9 && | 
					
						
							|  |  |  | 			strcmp(PyString_AS_STRING(name), "__class__") == 0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!skip) { | 
					
						
							| 
									
										
										
										
											2001-11-14 23:32:33 +00:00
										 |  |  | 		PyObject *mro, *res, *tmp, *dict; | 
					
						
							| 
									
										
										
										
											2002-04-02 17:53:47 +00:00
										 |  |  | 		PyTypeObject *starttype; | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | 		descrgetfunc f; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 		Py_ssize_t i, n; | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-02-12 03:58:38 +00:00
										 |  |  | 		starttype = su->obj_type; | 
					
						
							| 
									
										
										
										
											2002-04-02 17:53:47 +00:00
										 |  |  | 		mro = starttype->tp_mro; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-30 23:13:11 +00:00
										 |  |  | 		if (mro == NULL) | 
					
						
							|  |  |  | 			n = 0; | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			assert(PyTuple_Check(mro)); | 
					
						
							|  |  |  | 			n = PyTuple_GET_SIZE(mro); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | 		for (i = 0; i < n; i++) { | 
					
						
							| 
									
										
										
										
											2001-08-29 15:47:06 +00:00
										 |  |  | 			if ((PyObject *)(su->type) == PyTuple_GET_ITEM(mro, i)) | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		i++; | 
					
						
							|  |  |  | 		res = NULL; | 
					
						
							|  |  |  | 		for (; i < n; i++) { | 
					
						
							|  |  |  | 			tmp = PyTuple_GET_ITEM(mro, i); | 
					
						
							| 
									
										
										
										
											2001-11-14 23:32:33 +00:00
										 |  |  | 			if (PyType_Check(tmp)) | 
					
						
							|  |  |  | 				dict = ((PyTypeObject *)tmp)->tp_dict; | 
					
						
							|  |  |  | 			else if (PyClass_Check(tmp)) | 
					
						
							|  |  |  | 				dict = ((PyClassObject *)tmp)->cl_dict; | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			res = PyDict_GetItem(dict, name); | 
					
						
							| 
									
										
										
										
											2003-04-16 20:01:36 +00:00
										 |  |  | 			if (res != NULL) { | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | 				Py_INCREF(res); | 
					
						
							|  |  |  | 				f = res->ob_type->tp_descr_get; | 
					
						
							|  |  |  | 				if (f != NULL) { | 
					
						
							| 
									
										
										
										
											2004-03-25 02:19:34 +00:00
										 |  |  | 					tmp = f(res, | 
					
						
							|  |  |  | 						/* Only pass 'obj' param if
 | 
					
						
							|  |  |  | 						   this is instance-mode super  | 
					
						
							|  |  |  | 						   (See SF ID #743627) | 
					
						
							|  |  |  | 						*/ | 
					
						
							| 
									
										
										
										
											2004-03-25 16:37:03 +00:00
										 |  |  | 						(su->obj == (PyObject *) | 
					
						
							|  |  |  | 							    su->obj_type  | 
					
						
							| 
									
										
										
										
											2004-03-25 02:19:34 +00:00
										 |  |  | 							? (PyObject *)NULL  | 
					
						
							|  |  |  | 							: su->obj), | 
					
						
							| 
									
										
										
										
											2002-04-03 02:13:37 +00:00
										 |  |  | 						(PyObject *)starttype); | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | 					Py_DECREF(res); | 
					
						
							|  |  |  | 					res = tmp; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return res; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return PyObject_GenericGetAttr(self, name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-02-12 03:58:38 +00:00
										 |  |  | static PyTypeObject * | 
					
						
							| 
									
										
										
										
											2001-12-03 15:38:28 +00:00
										 |  |  | supercheck(PyTypeObject *type, PyObject *obj) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2003-02-12 03:58:38 +00:00
										 |  |  | 	/* Check that a super() call makes sense.  Return a type object.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	   obj can be a new-style class, or an instance of one: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	   - If it is a class, it must be a subclass of 'type'.  This case is | 
					
						
							|  |  |  | 	     used for class methods; the return value is obj. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	   - If it is an instance, it must be an instance of 'type'.  This is | 
					
						
							|  |  |  | 	     the normal case; the return value is obj.__class__. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	   But... when obj is an instance, we want to allow for the case where | 
					
						
							|  |  |  | 	   obj->ob_type is not a subclass of type, but obj.__class__ is! | 
					
						
							|  |  |  | 	   This will allow using super() with a proxy for obj. | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-02-18 19:22:22 +00:00
										 |  |  | 	/* Check for first bullet above (special case) */ | 
					
						
							|  |  |  | 	if (PyType_Check(obj) && PyType_IsSubtype((PyTypeObject *)obj, type)) { | 
					
						
							|  |  |  | 		Py_INCREF(obj); | 
					
						
							|  |  |  | 		return (PyTypeObject *)obj; | 
					
						
							| 
									
										
										
										
											2003-02-12 03:58:38 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2003-02-18 19:22:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Normal case */ | 
					
						
							|  |  |  | 	if (PyType_IsSubtype(obj->ob_type, type)) { | 
					
						
							| 
									
										
										
										
											2003-02-12 03:58:38 +00:00
										 |  |  | 		Py_INCREF(obj->ob_type); | 
					
						
							|  |  |  | 		return obj->ob_type; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		/* Try the slow way */ | 
					
						
							|  |  |  | 		static PyObject *class_str = NULL; | 
					
						
							|  |  |  | 		PyObject *class_attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (class_str == NULL) { | 
					
						
							|  |  |  | 			class_str = PyString_FromString("__class__"); | 
					
						
							|  |  |  | 			if (class_str == NULL) | 
					
						
							|  |  |  | 				return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		class_attr = PyObject_GetAttr(obj, class_str); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (class_attr != NULL && | 
					
						
							|  |  |  | 		    PyType_Check(class_attr) && | 
					
						
							|  |  |  | 		    (PyTypeObject *)class_attr != obj->ob_type) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			int ok = PyType_IsSubtype( | 
					
						
							|  |  |  | 				(PyTypeObject *)class_attr, type); | 
					
						
							|  |  |  | 			if (ok) | 
					
						
							|  |  |  | 				return (PyTypeObject *)class_attr; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (class_attr == NULL) | 
					
						
							|  |  |  | 			PyErr_Clear(); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			Py_DECREF(class_attr); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-02-18 19:32:50 +00:00
										 |  |  |   	PyErr_SetString(PyExc_TypeError, | 
					
						
							| 
									
										
										
										
											2001-12-03 15:38:28 +00:00
										 |  |  | 			"super(type, obj): " | 
					
						
							|  |  |  | 			"obj must be an instance or subtype of type"); | 
					
						
							| 
									
										
										
										
											2003-02-12 03:58:38 +00:00
										 |  |  | 	return NULL; | 
					
						
							| 
									
										
										
										
											2001-12-03 15:38:28 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | super_descr_get(PyObject *self, PyObject *obj, PyObject *type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	superobject *su = (superobject *)self; | 
					
						
							| 
									
										
										
										
											2006-04-11 07:42:36 +00:00
										 |  |  | 	superobject *newobj; | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (obj == NULL || obj == Py_None || su->obj != NULL) { | 
					
						
							|  |  |  | 		/* Not binding to an object, or already bound */ | 
					
						
							|  |  |  | 		Py_INCREF(self); | 
					
						
							|  |  |  | 		return self; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-12-03 15:38:28 +00:00
										 |  |  | 	if (su->ob_type != &PySuper_Type) | 
					
						
							| 
									
										
										
										
											2005-05-15 15:32:08 +00:00
										 |  |  | 		/* If su is an instance of a (strict) subclass of super,
 | 
					
						
							| 
									
										
										
										
											2001-12-03 15:38:28 +00:00
										 |  |  | 		   call its type */ | 
					
						
							| 
									
										
										
										
											2006-05-25 19:15:31 +00:00
										 |  |  | 		return PyObject_CallFunctionObjArgs((PyObject *)su->ob_type, | 
					
						
							|  |  |  | 					            su->type, obj, NULL); | 
					
						
							| 
									
										
										
										
											2001-12-03 15:38:28 +00:00
										 |  |  | 	else { | 
					
						
							|  |  |  | 		/* Inline the common case */ | 
					
						
							| 
									
										
										
										
											2003-02-12 03:58:38 +00:00
										 |  |  | 		PyTypeObject *obj_type = supercheck(su->type, obj); | 
					
						
							|  |  |  | 		if (obj_type == NULL) | 
					
						
							| 
									
										
										
										
											2001-12-03 15:38:28 +00:00
										 |  |  | 			return NULL; | 
					
						
							| 
									
										
										
										
											2006-04-11 07:42:36 +00:00
										 |  |  | 		newobj = (superobject *)PySuper_Type.tp_new(&PySuper_Type, | 
					
						
							| 
									
										
										
										
											2001-12-03 15:38:28 +00:00
										 |  |  | 							 NULL, NULL); | 
					
						
							| 
									
										
										
										
											2006-04-11 07:42:36 +00:00
										 |  |  | 		if (newobj == NULL) | 
					
						
							| 
									
										
										
										
											2001-12-03 15:38:28 +00:00
										 |  |  | 			return NULL; | 
					
						
							|  |  |  | 		Py_INCREF(su->type); | 
					
						
							|  |  |  | 		Py_INCREF(obj); | 
					
						
							| 
									
										
										
										
											2006-04-11 07:42:36 +00:00
										 |  |  | 		newobj->type = su->type; | 
					
						
							|  |  |  | 		newobj->obj = obj; | 
					
						
							|  |  |  | 		newobj->obj_type = obj_type; | 
					
						
							|  |  |  | 		return (PyObject *)newobj; | 
					
						
							| 
									
										
										
										
											2001-12-03 15:38:28 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | super_init(PyObject *self, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	superobject *su = (superobject *)self; | 
					
						
							| 
									
										
										
										
											2001-08-29 15:47:06 +00:00
										 |  |  | 	PyTypeObject *type; | 
					
						
							|  |  |  | 	PyObject *obj = NULL; | 
					
						
							| 
									
										
										
										
											2003-02-12 03:58:38 +00:00
										 |  |  | 	PyTypeObject *obj_type = NULL; | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-30 08:43:30 +00:00
										 |  |  | 	if (!_PyArg_NoKeywords("super", kwds)) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | 	if (!PyArg_ParseTuple(args, "O!|O:super", &PyType_Type, &type, &obj)) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	if (obj == Py_None) | 
					
						
							|  |  |  | 		obj = NULL; | 
					
						
							| 
									
										
										
										
											2003-02-12 03:58:38 +00:00
										 |  |  | 	if (obj != NULL) { | 
					
						
							|  |  |  | 		obj_type = supercheck(type, obj); | 
					
						
							|  |  |  | 		if (obj_type == NULL) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		Py_INCREF(obj); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | 	Py_INCREF(type); | 
					
						
							|  |  |  | 	su->type = type; | 
					
						
							|  |  |  | 	su->obj = obj; | 
					
						
							| 
									
										
										
										
											2003-02-12 03:58:38 +00:00
										 |  |  | 	su->obj_type = obj_type; | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-13 20:33:02 +00:00
										 |  |  | PyDoc_STRVAR(super_doc, | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | "super(type) -> unbound super object\n" | 
					
						
							|  |  |  | "super(type, obj) -> bound super object; requires isinstance(obj, type)\n" | 
					
						
							| 
									
										
										
										
											2001-08-29 15:47:06 +00:00
										 |  |  | "super(type, type2) -> bound super object; requires issubclass(type2, type)\n" | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | "Typical use to call a cooperative superclass method:\n" | 
					
						
							|  |  |  | "class C(B):\n" | 
					
						
							|  |  |  | "    def meth(self, arg):\n" | 
					
						
							| 
									
										
										
										
											2002-06-13 20:33:02 +00:00
										 |  |  | "        super(C, self).meth(arg)"); | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Add Garbage Collection support to new-style classes (not yet to their
instances).
Also added GC support to various auxiliary types: super, property,
descriptors, wrappers, dictproxy.  (Only type objects have a tp_clear
field; the other types are.)
One change was necessary to the GC infrastructure.  We have statically
allocated type objects that don't have a GC header (and can't easily
be given one) and heap-allocated type objects that do have a GC
header.  Giving these different metatypes would be really ugly: I
tried, and I had to modify pickle.py, cPickle.c, copy.py, add a new
invent a new name for the new metatype and make it a built-in, change
affected tests...  In short, a mess.  So instead, we add a new type
slot tp_is_gc, which is a simple Boolean function that determines
whether a particular instance has GC headers or not.  This slot is
only relevant for types that have the (new) GC flag bit set.  If the
tp_is_gc slot is NULL (by far the most common case), all instances of
the type are deemed to have GC headers.  This slot is called by the
PyObject_IS_GC() macro (which is only used twice, both times in
gcmodule.c).
I also changed the extern declarations for a bunch of GC-related
functions (_PyObject_GC_Del etc.): these always exist but objimpl.h
only declared them when WITH_CYCLE_GC was defined, but I needed to be
able to reference them without #ifdefs.  (When WITH_CYCLE_GC is not
defined, they do the same as their non-GC counterparts anyway.)
											
										 
											2001-10-02 21:24:57 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | super_traverse(PyObject *self, visitproc visit, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	superobject *su = (superobject *)self; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-15 21:47:09 +00:00
										 |  |  | 	Py_VISIT(su->obj); | 
					
						
							|  |  |  | 	Py_VISIT(su->type); | 
					
						
							|  |  |  | 	Py_VISIT(su->obj_type); | 
					
						
							| 
									
										
											  
											
												Add Garbage Collection support to new-style classes (not yet to their
instances).
Also added GC support to various auxiliary types: super, property,
descriptors, wrappers, dictproxy.  (Only type objects have a tp_clear
field; the other types are.)
One change was necessary to the GC infrastructure.  We have statically
allocated type objects that don't have a GC header (and can't easily
be given one) and heap-allocated type objects that do have a GC
header.  Giving these different metatypes would be really ugly: I
tried, and I had to modify pickle.py, cPickle.c, copy.py, add a new
invent a new name for the new metatype and make it a built-in, change
affected tests...  In short, a mess.  So instead, we add a new type
slot tp_is_gc, which is a simple Boolean function that determines
whether a particular instance has GC headers or not.  This slot is
only relevant for types that have the (new) GC flag bit set.  If the
tp_is_gc slot is NULL (by far the most common case), all instances of
the type are deemed to have GC headers.  This slot is called by the
PyObject_IS_GC() macro (which is only used twice, both times in
gcmodule.c).
I also changed the extern declarations for a bunch of GC-related
functions (_PyObject_GC_Del etc.): these always exist but objimpl.h
only declared them when WITH_CYCLE_GC was defined, but I needed to be
able to reference them without #ifdefs.  (When WITH_CYCLE_GC is not
defined, they do the same as their non-GC counterparts anyway.)
											
										 
											2001-10-02 21:24:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | PyTypeObject PySuper_Type = { | 
					
						
							|  |  |  | 	PyObject_HEAD_INIT(&PyType_Type) | 
					
						
							|  |  |  | 	0,					/* ob_size */ | 
					
						
							|  |  |  | 	"super",				/* tp_name */ | 
					
						
							|  |  |  | 	sizeof(superobject),			/* tp_basicsize */ | 
					
						
							|  |  |  | 	0,					/* tp_itemsize */ | 
					
						
							|  |  |  | 	/* methods */ | 
					
						
							|  |  |  | 	super_dealloc,		 		/* tp_dealloc */ | 
					
						
							|  |  |  | 	0,					/* tp_print */ | 
					
						
							|  |  |  | 	0,					/* tp_getattr */ | 
					
						
							|  |  |  | 	0,					/* tp_setattr */ | 
					
						
							|  |  |  | 	0,					/* tp_compare */ | 
					
						
							| 
									
										
										
										
											2001-08-30 23:13:11 +00:00
										 |  |  | 	super_repr,				/* tp_repr */ | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | 	0,					/* tp_as_number */ | 
					
						
							|  |  |  | 	0,					/* tp_as_sequence */ | 
					
						
							|  |  |  | 	0,		       			/* tp_as_mapping */ | 
					
						
							|  |  |  | 	0,					/* tp_hash */ | 
					
						
							|  |  |  | 	0,					/* tp_call */ | 
					
						
							|  |  |  | 	0,					/* tp_str */ | 
					
						
							|  |  |  | 	super_getattro,				/* tp_getattro */ | 
					
						
							|  |  |  | 	0,					/* tp_setattro */ | 
					
						
							|  |  |  | 	0,					/* tp_as_buffer */ | 
					
						
							| 
									
										
											  
											
												Add Garbage Collection support to new-style classes (not yet to their
instances).
Also added GC support to various auxiliary types: super, property,
descriptors, wrappers, dictproxy.  (Only type objects have a tp_clear
field; the other types are.)
One change was necessary to the GC infrastructure.  We have statically
allocated type objects that don't have a GC header (and can't easily
be given one) and heap-allocated type objects that do have a GC
header.  Giving these different metatypes would be really ugly: I
tried, and I had to modify pickle.py, cPickle.c, copy.py, add a new
invent a new name for the new metatype and make it a built-in, change
affected tests...  In short, a mess.  So instead, we add a new type
slot tp_is_gc, which is a simple Boolean function that determines
whether a particular instance has GC headers or not.  This slot is
only relevant for types that have the (new) GC flag bit set.  If the
tp_is_gc slot is NULL (by far the most common case), all instances of
the type are deemed to have GC headers.  This slot is called by the
PyObject_IS_GC() macro (which is only used twice, both times in
gcmodule.c).
I also changed the extern declarations for a bunch of GC-related
functions (_PyObject_GC_Del etc.): these always exist but objimpl.h
only declared them when WITH_CYCLE_GC was defined, but I needed to be
able to reference them without #ifdefs.  (When WITH_CYCLE_GC is not
defined, they do the same as their non-GC counterparts anyway.)
											
										 
											2001-10-02 21:24:57 +00:00
										 |  |  | 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | | 
					
						
							|  |  |  | 		Py_TPFLAGS_BASETYPE,		/* tp_flags */ | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  |  	super_doc,				/* tp_doc */ | 
					
						
							| 
									
										
											  
											
												Add Garbage Collection support to new-style classes (not yet to their
instances).
Also added GC support to various auxiliary types: super, property,
descriptors, wrappers, dictproxy.  (Only type objects have a tp_clear
field; the other types are.)
One change was necessary to the GC infrastructure.  We have statically
allocated type objects that don't have a GC header (and can't easily
be given one) and heap-allocated type objects that do have a GC
header.  Giving these different metatypes would be really ugly: I
tried, and I had to modify pickle.py, cPickle.c, copy.py, add a new
invent a new name for the new metatype and make it a built-in, change
affected tests...  In short, a mess.  So instead, we add a new type
slot tp_is_gc, which is a simple Boolean function that determines
whether a particular instance has GC headers or not.  This slot is
only relevant for types that have the (new) GC flag bit set.  If the
tp_is_gc slot is NULL (by far the most common case), all instances of
the type are deemed to have GC headers.  This slot is called by the
PyObject_IS_GC() macro (which is only used twice, both times in
gcmodule.c).
I also changed the extern declarations for a bunch of GC-related
functions (_PyObject_GC_Del etc.): these always exist but objimpl.h
only declared them when WITH_CYCLE_GC was defined, but I needed to be
able to reference them without #ifdefs.  (When WITH_CYCLE_GC is not
defined, they do the same as their non-GC counterparts anyway.)
											
										 
											2001-10-02 21:24:57 +00:00
										 |  |  |  	super_traverse,				/* tp_traverse */ | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  |  	0,					/* tp_clear */ | 
					
						
							|  |  |  | 	0,					/* tp_richcompare */ | 
					
						
							|  |  |  | 	0,					/* tp_weaklistoffset */ | 
					
						
							|  |  |  | 	0,					/* tp_iter */ | 
					
						
							|  |  |  | 	0,					/* tp_iternext */ | 
					
						
							|  |  |  | 	0,					/* tp_methods */ | 
					
						
							| 
									
										
										
										
											2001-08-30 23:13:11 +00:00
										 |  |  | 	super_members,				/* tp_members */ | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | 	0,					/* tp_getset */ | 
					
						
							|  |  |  | 	0,					/* tp_base */ | 
					
						
							|  |  |  | 	0,					/* tp_dict */ | 
					
						
							|  |  |  | 	super_descr_get,			/* tp_descr_get */ | 
					
						
							|  |  |  | 	0,					/* tp_descr_set */ | 
					
						
							|  |  |  | 	0,					/* tp_dictoffset */ | 
					
						
							|  |  |  | 	super_init,				/* tp_init */ | 
					
						
							|  |  |  | 	PyType_GenericAlloc,			/* tp_alloc */ | 
					
						
							|  |  |  | 	PyType_GenericNew,			/* tp_new */ | 
					
						
							| 
									
										
										
										
											2002-04-12 03:06:53 +00:00
										 |  |  | 	PyObject_GC_Del,        		/* tp_free */ | 
					
						
							| 
									
										
										
										
											2001-08-24 16:47:00 +00:00
										 |  |  | }; |