summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2001-08-17 11:18:38 (GMT)
committerGuido van Rossum <guido@python.org>2001-08-17 11:18:38 (GMT)
commit8d32c8b59f9b5f4315f42a48b73a52adea3e10a2 (patch)
tree08128b39b33e961359cf962ae4ef0b5c9becc459 /Objects
parent4b046c252e637a482e162f7057294c95933614f2 (diff)
downloadcpython-8d32c8b59f9b5f4315f42a48b73a52adea3e10a2.zip
cpython-8d32c8b59f9b5f4315f42a48b73a52adea3e10a2.tar.gz
cpython-8d32c8b59f9b5f4315f42a48b73a52adea3e10a2.tar.bz2
type_new(): only defer to the winning metatype if it's different from
the metatype passed in as an argument. This prevents infinite recursion when a metatype written in Python calls type.__new__() as a "super" call. Also tweaked some comments.
Diffstat (limited to 'Objects')
-rw-r--r--Objects/typeobject.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index c38340e..474ff3e 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -497,21 +497,21 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
PyObject *name, *bases, *dict;
static char *kwlist[] = {"name", "bases", "dict", 0};
PyObject *slots, *tmp;
- PyTypeObject *type, *base, *tmptype;
+ PyTypeObject *type, *base, *tmptype, *winner;
etype *et;
struct memberlist *mp;
int i, nbases, nslots, slotoffset, dynamic;
+ /* Special case: type(x) should return x->ob_type */
if (metatype == &PyType_Type &&
PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 &&
(kwds == NULL || (PyDict_Check(kwds) && PyDict_Size(kwds) == 0))) {
- /* type(x) -> x.__class__ */
PyObject *x = PyTuple_GET_ITEM(args, 0);
Py_INCREF(x->ob_type);
return (PyObject *) x->ob_type;
}
- /* Check arguments */
+ /* Check arguments: (name, bases, dict) */
if (!PyArg_ParseTupleAndKeywords(args, kwds, "SO!O!:type", kwlist,
&name,
&PyTuple_Type, &bases,
@@ -523,21 +523,25 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
Note that if some other metatype wins to contract,
it's possible that its instances are not types. */
nbases = PyTuple_GET_SIZE(bases);
+ winner = metatype;
for (i = 0; i < nbases; i++) {
tmp = PyTuple_GET_ITEM(bases, i);
tmptype = tmp->ob_type;
- if (PyType_IsSubtype(metatype, tmptype))
+ if (PyType_IsSubtype(winner, tmptype))
continue;
- if (PyType_IsSubtype(tmptype, metatype)) {
- metatype = tmptype;
+ if (PyType_IsSubtype(tmptype, winner)) {
+ winner = tmptype;
continue;
}
PyErr_SetString(PyExc_TypeError,
"metatype conflict among bases");
return NULL;
}
- if (metatype->tp_new != type_new) /* Pass it to the winner */
- return metatype->tp_new(metatype, args, kwds);
+ if (winner != metatype) {
+ if (winner->tp_new != type_new) /* Pass it to the winner */
+ return winner->tp_new(winner, args, kwds);
+ metatype = winner;
+ }
/* Adjust for empty tuple bases */
if (nbases == 0) {