Mercurial > cpython-lru_cache-weakref
diff Python/ceval.c @ 5911:6986781a07ef legacy-trunk
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!
| author | Guido van Rossum <guido@python.org> |
|---|---|
| date | Thu, 31 Jul 1997 03:54:02 +0000 |
| parents | 9841bce37c4d |
| children | 8d2194e22e67 |
line wrap: on
line diff
--- a/Python/ceval.c Wed Jul 30 22:05:07 1997 +0000 +++ b/Python/ceval.c Thu Jul 31 03:54:02 1997 +0000 @@ -2689,22 +2689,39 @@ 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");
