diff options
author | Guido van Rossum <guido@python.org> | 2001-08-17 11:18:38 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2001-08-17 11:18:38 (GMT) |
commit | 8d32c8b59f9b5f4315f42a48b73a52adea3e10a2 (patch) | |
tree | 08128b39b33e961359cf962ae4ef0b5c9becc459 /Objects | |
parent | 4b046c252e637a482e162f7057294c95933614f2 (diff) | |
download | cpython-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.c | 20 |
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) { |