mirror of
https://github.com/python/cpython.git
synced 2025-07-19 09:15:34 +00:00
Merge issue 1294232 patch from 3.2
This commit is contained in:
commit
9715d26305
5 changed files with 244 additions and 23 deletions
|
@ -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)) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue