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 /Python/bltinmodule.c | |
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 'Python/bltinmodule.c')
-rw-r--r-- | Python/bltinmodule.c | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index e68f025..fd242b7 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -38,9 +38,10 @@ _Py_IDENTIFIER(flush); static PyObject * builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) { - PyObject *func, *name, *bases, *mkw, *meta, *prep, *ns, *cell; + PyObject *func, *name, *bases, *mkw, *meta, *winner, *prep, *ns, *cell; PyObject *cls = NULL; - Py_ssize_t nargs; + Py_ssize_t nargs, nbases; + int isclass; _Py_IDENTIFIER(__prepare__); assert(args != NULL); @@ -85,17 +86,43 @@ builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) Py_DECREF(bases); return NULL; } + /* metaclass is explicitly given, check if it's indeed a class */ + isclass = PyType_Check(meta); } } if (meta == NULL) { - if (PyTuple_GET_SIZE(bases) == 0) + /* if there are no bases, use type: */ + if (PyTuple_GET_SIZE(bases) == 0) { meta = (PyObject *) (&PyType_Type); + } + /* else get the type of the first base */ else { PyObject *base0 = PyTuple_GET_ITEM(bases, 0); meta = (PyObject *) (base0->ob_type); } Py_INCREF(meta); + isclass = 1; /* meta is really a class */ + } + + if (isclass) { + /* meta is really a class, so check for a more derived + metaclass, or possible metaclass conflicts: */ + winner = (PyObject *)_PyType_CalculateMetaclass((PyTypeObject *)meta, + bases); + if (winner == NULL) { + Py_DECREF(meta); + Py_XDECREF(mkw); + Py_DECREF(bases); + return NULL; + } + if (winner != meta) { + Py_DECREF(meta); + meta = winner; + Py_INCREF(meta); + } } + /* else: meta is not a class, so we cannot do the metaclass + calculation, so we will use the explicitly given object as it is */ prep = _PyObject_GetAttrId(meta, &PyId___prepare__); if (prep == NULL) { if (PyErr_ExceptionMatches(PyExc_AttributeError)) { |