diff options
author | Guido van Rossum <guido@python.org> | 2001-09-12 19:19:18 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2001-09-12 19:19:18 (GMT) |
commit | 7851eea5f22012297151644fb598b2131e035037 (patch) | |
tree | cf3018f087f23085f5c7142664c12303910abff6 /Python | |
parent | 2400fa4ad115e8ebe75c61c3bb96bd7cf2364dd4 (diff) | |
download | cpython-7851eea5f22012297151644fb598b2131e035037.zip cpython-7851eea5f22012297151644fb598b2131e035037.tar.gz cpython-7851eea5f22012297151644fb598b2131e035037.tar.bz2 |
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?).
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ceval.c | 35 |
1 files changed, 21 insertions, 14 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 030afe6..f948942 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -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 |