summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2001-09-12 19:19:18 (GMT)
committerGuido van Rossum <guido@python.org>2001-09-12 19:19:18 (GMT)
commit7851eea5f22012297151644fb598b2131e035037 (patch)
treecf3018f087f23085f5c7142664c12303910abff6 /Python
parent2400fa4ad115e8ebe75c61c3bb96bd7cf2364dd4 (diff)
downloadcpython-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.c35
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