summaryrefslogtreecommitdiffstats
path: root/Python/bltinmodule.c
diff options
context:
space:
mode:
authorNick Coghlan <ncoghlan@gmail.com>2011-10-23 12:36:42 (GMT)
committerNick Coghlan <ncoghlan@gmail.com>2011-10-23 12:36:42 (GMT)
commit9715d26305f7cf6c4db91f3670f1b7e99f04dd2d (patch)
tree0bd6a35f21a42e42ac2bdeb09b0c5a3b9eb3188a /Python/bltinmodule.c
parenta0e0e232993b87fe446f95d6583d947ae01bf517 (diff)
parentde31b191e570d00ed7917c7f9ea28af3e770c16d (diff)
downloadcpython-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.c33
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)) {