From 55b9ab5bdb0ef3b00339d751a8db5e23aa936cf0 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Thu, 31 Jul 1997 03:54:02 +0000 Subject: [PATCH] Extend the "Don Beaudry hack" with "Guido's corollary" -- if the base class has a __class__ attribute, call that to create the new class. This allows us to write metaclasses purely in C! --- Python/ceval.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index ec2e419e24f..205d8d42e06 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2689,22 +2689,39 @@ build_class(methods, bases, name) return NULL; } for (i = PyTuple_Size(bases); --i >= 0; ) { + /* XXX Is it intentional that the *last* base gets a + chance at this first? */ PyObject *base = PyTuple_GET_ITEM(bases, i); if (!PyClass_Check(base)) { /* Call the base's *type*, if it is callable. This code is a hook for Donald Beaudry's and Jim Fulton's type extensions. In unexended Python it will never be triggered - since its types are not callable. */ - if (base->ob_type->ob_type->tp_call) { - PyObject *args; - PyObject *class; - args = Py_BuildValue("(OOO)", - name, bases, methods); - class = PyEval_CallObject( - (PyObject *)base->ob_type, args); - Py_DECREF(args); - return class; + since its types are not callable. + Ditto: call the bases's *class*, if it has + one. This makes the same thing possible + without writing C code. A true meta-object + protocol! */ + PyObject *basetype = (PyObject *)base->ob_type; + PyObject *callable = NULL; + if (PyCallable_Check(basetype)) + callable = basetype; + else + callable = PyObject_GetAttrString( + base, "__class__"); + if (callable) { + PyObject *args; + PyObject *newclass = NULL; + args = Py_BuildValue( + "(OOO)", name, bases, methods); + if (args != NULL) { + newclass = PyEval_CallObject( + callable, args); + Py_DECREF(args); + } + if (callable != basetype) + Py_DECREF(callable); + return newclass; } PyErr_SetString(PyExc_TypeError, "base is not a class object");