[Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.61,2.16.8.62
Guido van Rossum
gvanrossum@users.sourceforge.net
Thu, 05 Jul 2001 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)