diff options
author | Guido van Rossum <guido@python.org> | 1997-07-31 03:54:02 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1997-07-31 03:54:02 (GMT) |
commit | 55b9ab5bdb0ef3b00339d751a8db5e23aa936cf0 (patch) | |
tree | ca863911a7ea4619c2a97c58c524a1882a040f23 /Python | |
parent | fd16ca4542b418e5fa1f70782f65f905540da711 (diff) | |
download | cpython-55b9ab5bdb0ef3b00339d751a8db5e23aa936cf0.zip cpython-55b9ab5bdb0ef3b00339d751a8db5e23aa936cf0.tar.gz cpython-55b9ab5bdb0ef3b00339d751a8db5e23aa936cf0.tar.bz2 |
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!
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ceval.c | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index ec2e419..205d8d4 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"); |