mirror of https://github.com/python/cpython
build_class(): one more (hopefully the last) step on the way to
backwards compatibility. When using the class of the first base as the metaclass, use its __class__ attribute in preference over its ob_type slot. This ensures that we can still use classic classes as metaclasse, as shown in the original "Metaclasses" essay. This also makes all the examples in Demo/metaclasses/ work again (maybe these should be turned into a test suite?).
This commit is contained in:
parent
2400fa4ad1
commit
7851eea5f2
|
@ -3500,25 +3500,32 @@ import_all_from(PyObject *locals, PyObject *v)
|
|||
static PyObject *
|
||||
build_class(PyObject *methods, PyObject *bases, PyObject *name)
|
||||
{
|
||||
PyObject *metaclass = NULL;
|
||||
PyObject *metaclass = NULL, *result, *base;
|
||||
|
||||
if (PyDict_Check(methods))
|
||||
metaclass = PyDict_GetItemString(methods, "__metaclass__");
|
||||
|
||||
if (metaclass == NULL) {
|
||||
if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0)
|
||||
metaclass = (PyObject *)
|
||||
PyTuple_GET_ITEM(bases, 0)->ob_type;
|
||||
else {
|
||||
PyObject *g = PyEval_GetGlobals();
|
||||
if (g != NULL && PyDict_Check(g))
|
||||
metaclass = PyDict_GetItemString(
|
||||
g, "__metaclass__");
|
||||
if (metaclass == NULL)
|
||||
metaclass = (PyObject *) &PyClass_Type;
|
||||
if (metaclass != NULL)
|
||||
Py_INCREF(methods);
|
||||
else if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0) {
|
||||
base = PyTuple_GET_ITEM(bases, 0);
|
||||
metaclass = PyObject_GetAttrString(base, "__class__");
|
||||
if (metaclass == NULL) {
|
||||
PyErr_Clear();
|
||||
metaclass = (PyObject *)base->ob_type;
|
||||
Py_INCREF(metaclass);
|
||||
}
|
||||
}
|
||||
return PyObject_CallFunction(metaclass, "OOO", name, bases, methods);
|
||||
else {
|
||||
PyObject *g = PyEval_GetGlobals();
|
||||
if (g != NULL && PyDict_Check(g))
|
||||
metaclass = PyDict_GetItemString(g, "__metaclass__");
|
||||
if (metaclass == NULL)
|
||||
metaclass = (PyObject *) &PyClass_Type;
|
||||
Py_INCREF(metaclass);
|
||||
}
|
||||
result = PyObject_CallFunction(metaclass, "OOO", name, bases, methods);
|
||||
Py_DECREF(metaclass);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
Loading…
Reference in New Issue