diff options
author | Nick Coghlan <ncoghlan@gmail.com> | 2011-10-23 12:36:42 (GMT) |
---|---|---|
committer | Nick Coghlan <ncoghlan@gmail.com> | 2011-10-23 12:36:42 (GMT) |
commit | 9715d26305f7cf6c4db91f3670f1b7e99f04dd2d (patch) | |
tree | 0bd6a35f21a42e42ac2bdeb09b0c5a3b9eb3188a /Objects | |
parent | a0e0e232993b87fe446f95d6583d947ae01bf517 (diff) | |
parent | de31b191e570d00ed7917c7f9ea28af3e770c16d (diff) | |
download | cpython-9715d26305f7cf6c4db91f3670f1b7e99f04dd2d.zip cpython-9715d26305f7cf6c4db91f3670f1b7e99f04dd2d.tar.gz cpython-9715d26305f7cf6c4db91f3670f1b7e99f04dd2d.tar.bz2 |
Merge issue 1294232 patch from 3.2
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/typeobject.c | 61 |
1 files changed, 41 insertions, 20 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 130e8fe..6b60c8f 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1915,6 +1915,42 @@ PyType_GetFlags(PyTypeObject *type) return type->tp_flags; } +/* Determine the most derived metatype. */ +PyTypeObject * +_PyType_CalculateMetaclass(PyTypeObject *metatype, PyObject *bases) +{ + Py_ssize_t i, nbases; + PyTypeObject *winner; + PyObject *tmp; + PyTypeObject *tmptype; + + /* 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); + winner = metatype; + for (i = 0; i < nbases; i++) { + tmp = PyTuple_GET_ITEM(bases, i); + tmptype = Py_TYPE(tmp); + if (PyType_IsSubtype(winner, tmptype)) + continue; + if (PyType_IsSubtype(tmptype, winner)) { + winner = tmptype; + continue; + } + /* else: */ + PyErr_SetString(PyExc_TypeError, + "metaclass conflict: " + "the metaclass of a derived class " + "must be a (non-strict) subclass " + "of the metaclasses of all its bases"); + return NULL; + } + return winner; +} + static PyObject * type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) { @@ -1958,28 +1994,12 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) &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); - winner = metatype; - for (i = 0; i < nbases; i++) { - tmp = PyTuple_GET_ITEM(bases, i); - tmptype = Py_TYPE(tmp); - if (PyType_IsSubtype(winner, tmptype)) - continue; - if (PyType_IsSubtype(tmptype, winner)) { - winner = tmptype; - continue; - } - PyErr_SetString(PyExc_TypeError, - "metaclass conflict: " - "the metaclass of a derived class " - "must be a (non-strict) subclass " - "of the metaclasses of all its bases"); + /* Determine the proper metatype to deal with this: */ + winner = _PyType_CalculateMetaclass(metatype, bases); + if (winner == NULL) { return NULL; } + if (winner != metatype) { if (winner->tp_new != type_new) /* Pass it to the winner */ return winner->tp_new(winner, args, kwds); @@ -1987,6 +2007,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) } /* Adjust for empty tuple bases */ + nbases = PyTuple_GET_SIZE(bases); if (nbases == 0) { bases = PyTuple_Pack(1, &PyBaseObject_Type); if (bases == NULL) |