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

Guido van Rossum gvanrossum@users.sourceforge.net
2001年7月05日 14:39:54 -0700


Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv25858
Modified Files:
 Tag: descr-branch
	typeobject.c 
Log Message:
Make method resolution a method defined on the metatype, mro(), which
can be overridden.
PyType_InitDict(): change the initialization order a little bit again,
so that mro() can be called on a type that isn't quite entirely
type_members[]: make this a static array, which it should have been
all the time.
conservative_merge(): add full error checking.
method_resolution(): refactored into mro_external(), mro_internal(),
and mro_implementation(); add full error checking.
PyType_Type: add type_methods[], the array or methods. Currently
there's one type method, "mro".
Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.16.8.61
retrieving revision 2.16.8.62
diff -C2 -r2.16.8.61 -r2.16.8.62
*** typeobject.c	2001年07月05日 21:26:00	2.16.8.61
--- typeobject.c	2001年07月05日 21:39:52	2.16.8.62
***************
*** 7,11 ****
 staticforward int add_members(PyTypeObject *, struct memberlist *);
 
! struct memberlist type_members[] = {
 	{"__name__", T_STRING, offsetof(PyTypeObject, tp_name), READONLY},
 	{"__basicsize__", T_INT, offsetof(PyTypeObject,tp_basicsize),READONLY},
--- 7,11 ----
 staticforward int add_members(PyTypeObject *, struct memberlist *);
 
! static struct memberlist type_members[] = {
 	{"__name__", T_STRING, offsetof(PyTypeObject, tp_name), READONLY},
 	{"__basicsize__", T_INT, offsetof(PyTypeObject,tp_basicsize),READONLY},
***************
*** 225,232 ****
 	int left_size;
 	int right_size;
! 	int i, j, r;
 	PyObject *temp, *rr;
 
! 	/* XXX add error checking */
 
 again:
--- 225,233 ----
 	int left_size;
 	int right_size;
! 	int i, j, r, ok;
 	PyObject *temp, *rr;
 
! 	assert(PyList_Check(left));
! 	assert(PyList_Check(right));
 
 again:
***************
*** 239,250 ****
 				/* found a merge point */
 				temp = PyList_New(0);
 				for (r = 0; r < j; r++) {
 					rr = PyList_GET_ITEM(right, r);
! 					if (!PySequence_Contains(left, rr))
! 						PyList_Append(temp, rr);
 				}
! 				PyList_SetSlice(left, i, i, temp);
 				Py_DECREF(temp);
! 				PyList_SetSlice(right, 0, j+1, NULL);
 				goto again;
 			}
--- 240,267 ----
 				/* found a merge point */
 				temp = PyList_New(0);
+ 				if (temp == NULL)
+ 					return -1;
 				for (r = 0; r < j; r++) {
 					rr = PyList_GET_ITEM(right, r);
! 					ok = PySequence_Contains(left, rr);
! 					if (ok < 0) {
! 						Py_DECREF(temp);
! 						return -1;
! 					}
! 					if (!ok) {
! 						ok = PyList_Append(temp, rr);
! 						if (ok < 0) {
! 							Py_DECREF(temp);
! 							return -1;
! 						}
! 					}
 				}
! 				ok = PyList_SetSlice(left, i, i, temp);
 				Py_DECREF(temp);
! 				if (ok < 0)
! 					return -1;
! 				ok = PyList_SetSlice(right, 0, j+1, NULL);
! 				if (ok < 0)
! 					return -1;
 				goto again;
 			}
***************
*** 261,284 ****
 
 static PyObject *
! method_resolution_order(PyTypeObject *type)
 {
! 	int i, n;
! 	PyObject *bases;
! 	PyObject *result;
! 
! 	/* XXX add error checking */
! 
! 	if (type->tp_mro != NULL)
! 		return PySequence_List(type->tp_mro);
 
 	bases = type->tp_bases;
- 	if (bases == NULL || !PyTuple_Check(bases))
- 		return NULL;
 	n = PyTuple_GET_SIZE(bases);
! 	result = Py_BuildValue("[O]", type);
 	for (i = 0; i < n; i++) {
! 		PyTypeObject *base = (PyTypeObject *)
! 			PyTuple_GET_ITEM(bases, i);
! 		PyObject *parentMRO = method_resolution_order(base);
 		if (parentMRO == NULL) {
 			Py_DECREF(result);
--- 278,295 ----
 
 static PyObject *
! mro_implementation(PyTypeObject *type)
 {
! 	int i, n, ok;
! 	PyObject *bases, *result;
 
 	bases = type->tp_bases;
 	n = PyTuple_GET_SIZE(bases);
! 	result = Py_BuildValue("[O]", (PyObject *)type);
! 	if (result == NULL)
! 		return NULL;
 	for (i = 0; i < n; i++) {
! 		PyTypeObject *base =
! 			(PyTypeObject *) PyTuple_GET_ITEM(bases, i);
! 		PyObject *parentMRO = PySequence_List(base->tp_mro);
 		if (parentMRO == NULL) {
 			Py_DECREF(result);
***************
*** 289,300 ****
 			return NULL;
 		}
! 		conservative_merge(result, parentMRO);
 		Py_DECREF(parentMRO);
 	}
- 	if (result != NULL && type->tp_mro == NULL)
- 		type->tp_mro = PySequence_Tuple(result);
 	return result;
 }
 
 /* Calculate the best base amongst multiple base classes.
 This is the first one that's on the path to the "solid base". */
--- 300,347 ----
 			return NULL;
 		}
! 		ok = conservative_merge(result, parentMRO);
 		Py_DECREF(parentMRO);
+ 		if (ok < 0) {
+ 			Py_DECREF(result);
+ 			return NULL;
+ 		}
 	}
 	return result;
 }
 
+ static PyObject *
+ mro_external(PyObject *self, PyObject *args)
+ {
+ 	PyTypeObject *type = (PyTypeObject *)self;
+ 
+ 	if (!PyArg_ParseTuple(args, ""))
+ 		return NULL;
+ 	return mro_implementation(type);
+ }
+ 
+ static int
+ mro_internal(PyTypeObject *type)
+ {
+ 	PyObject *mro, *result, *tuple;
+ 
+ 	if (type->ob_type == &PyType_Type) {
+ 		result = mro_implementation(type);
+ 	}
+ 	else {
+ 		mro = PyObject_GetAttrString((PyObject *)type, "mro");
+ 		if (mro == NULL)
+ 			return -1;
+ 		result = PyObject_CallObject(mro, NULL);
+ 		Py_DECREF(mro);
+ 	}
+ 	if (result == NULL)
+ 		return -1;
+ 	tuple = PySequence_Tuple(result);
+ 	Py_DECREF(result);
+ 	type->tp_mro = tuple;
+ 	return 0;
+ }
+ 
+ 
 /* Calculate the best base amongst multiple base classes.
 This is the first one that's on the path to the "solid base". */
***************
*** 707,710 ****
--- 754,763 ----
 }
 
+ static PyMethodDef type_methods[] = {
+ 	{"mro", mro_external, METH_VARARGS,
+ 	 "mro() -> list\nreturn a type's method resolution order"},
+ 	{0}
+ };
+ 
 static char type_doc[] =
 "type(object) -> the object's type\n"
***************
*** 740,744 ****
 	0,					/* tp_iter */
 	0,					/* tp_iternext */
! 	0,					/* tp_methods */
 	type_members,				/* tp_members */
 	type_getsets,				/* tp_getset */
--- 793,797 ----
 	0,					/* tp_iter */
 	0,					/* tp_iternext */
! 	type_methods,				/* tp_methods */
 	type_members,				/* tp_members */
 	type_getsets,				/* tp_getset */
***************
*** 1152,1177 ****
 	}
 
 	/* Calculate method resolution order */
! 	x = method_resolution_order(type);
! 	if (x == NULL) {
! 		if (!PyErr_Occurred())
! 			PyErr_SetString(PyExc_TypeError,
! 					"method resolution order failed");
 		return -1;
 	}
- 	Py_DECREF(x);
 
! 	/* Initialize tp_dict */
! 	if (type->tp_flags & Py_TPFLAGS_DYNAMICTYPE) {
! 		/* For a dynamic type. tp_dict *is* tp_defined */
! 		Py_INCREF(type->tp_defined);
! 		type->tp_dict = type->tp_defined;
! 	}
! 	else {
 		/* For a static type, tp_dict is the consolidation
 		 of the tp_defined of its bases in MRO. Earlier
 		 bases override later bases; since d.update() works
 		 the other way, we walk the MRO sequence backwards. */
! 
 		type->tp_dict = PyDict_New();
 		if (type->tp_dict == NULL)
--- 1205,1226 ----
 	}
 
+ 	/* Temporarily make tp_dict the same object as tp_defined.
+ 	 (This is needed to call mro(), and can stay this way for
+ 	 dynamic types). */
+ 	Py_INCREF(type->tp_defined);
+ 	type->tp_dict = type->tp_defined;
+ 
 	/* Calculate method resolution order */
! 	if (mro_internal(type) < 0) {
 		return -1;
 	}
 
! 	/* Initialize tp_dict properly */
! 	if (!PyType_HasFeature(type, Py_TPFLAGS_DYNAMICTYPE)) {
 		/* For a static type, tp_dict is the consolidation
 		 of the tp_defined of its bases in MRO. Earlier
 		 bases override later bases; since d.update() works
 		 the other way, we walk the MRO sequence backwards. */
! 		Py_DECREF(type->tp_dict);
 		type->tp_dict = PyDict_New();
 		if (type->tp_dict == NULL)

AltStyle によって変換されたページ (->オリジナル) /