Kaydet (Commit) 55b9ab5b authored tarafından Guido van Rossum's avatar Guido van Rossum

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!
üst fd16ca45
...@@ -2689,22 +2689,39 @@ build_class(methods, bases, name) ...@@ -2689,22 +2689,39 @@ build_class(methods, bases, name)
return NULL; return NULL;
} }
for (i = PyTuple_Size(bases); --i >= 0; ) { 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); PyObject *base = PyTuple_GET_ITEM(bases, i);
if (!PyClass_Check(base)) { if (!PyClass_Check(base)) {
/* Call the base's *type*, if it is callable. /* Call the base's *type*, if it is callable.
This code is a hook for Donald Beaudry's This code is a hook for Donald Beaudry's
and Jim Fulton's type extensions. In and Jim Fulton's type extensions. In
unexended Python it will never be triggered unexended Python it will never be triggered
since its types are not callable. */ since its types are not callable.
if (base->ob_type->ob_type->tp_call) { Ditto: call the bases's *class*, if it has
PyObject *args; one. This makes the same thing possible
PyObject *class; without writing C code. A true meta-object
args = Py_BuildValue("(OOO)", protocol! */
name, bases, methods); PyObject *basetype = (PyObject *)base->ob_type;
class = PyEval_CallObject( PyObject *callable = NULL;
(PyObject *)base->ob_type, args); if (PyCallable_Check(basetype))
Py_DECREF(args); callable = basetype;
return class; 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, PyErr_SetString(PyExc_TypeError,
"base is not a class object"); "base is not a class object");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment