Implement PEP 3115 -- new metaclass syntax and semantics.

The compiler package hasn't been updated yet; test_compiler.py fails.
Otherwise all tests seem to be passing now.  There are no occurrences
of __metaclass__ left in the standard library.
Docs have not been updated.
This commit is contained in:
Guido van Rossum 2007-03-18 15:41:51 +00:00
parent ef17c16b36
commit 52cc1d838f
25 changed files with 604 additions and 237 deletions

View file

@ -117,7 +117,6 @@ static int assign_slice(PyObject *, PyObject *,
static PyObject * cmp_outcome(int, PyObject *, PyObject *);
static PyObject * import_from(PyObject *, PyObject *);
static int import_all_from(PyObject *, PyObject *);
static PyObject * build_class(PyObject *, PyObject *, PyObject *);
static void set_exc_info(PyThreadState *, PyObject *, PyObject *, PyObject *);
static void reset_exc_info(PyThreadState *);
static void format_exc_check_arg(PyObject *, char *, PyObject *);
@ -1532,14 +1531,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
}
break;
case LOAD_LOCALS:
if ((x = f->f_locals) != NULL) {
Py_INCREF(x);
PUSH(x);
continue;
}
PyErr_SetString(PyExc_SystemError, "no locals");
break;
case STORE_LOCALS:
x = POP();
v = f->f_locals;
Py_XDECREF(v);
f->f_locals = x;
continue;
case RETURN_VALUE:
retval = POP();
@ -1586,16 +1583,16 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_DECREF(v);
break;
case BUILD_CLASS:
u = TOP();
v = SECOND();
w = THIRD();
STACKADJ(-2);
x = build_class(u, v, w);
SET_TOP(x);
Py_DECREF(u);
Py_DECREF(v);
Py_DECREF(w);
case LOAD_BUILD_CLASS:
x = PyDict_GetItemString(f->f_builtins,
"__build_class__");
if (x == NULL) {
PyErr_SetString(PyExc_ImportError,
"__build_class__ not found");
break;
}
Py_INCREF(x);
PUSH(x);
break;
case STORE_NAME:
@ -4023,60 +4020,6 @@ import_all_from(PyObject *locals, PyObject *v)
return err;
}
static PyObject *
build_class(PyObject *methods, PyObject *bases, PyObject *name)
{
PyObject *metaclass = NULL, *result, *base;
if (PyDict_Check(methods))
metaclass = PyDict_GetItemString(methods, "__metaclass__");
if (metaclass != NULL)
Py_INCREF(metaclass);
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);
}
}
else {
PyObject *g = PyEval_GetGlobals();
if (g != NULL && PyDict_Check(g))
metaclass = PyDict_GetItemString(g, "__metaclass__");
if (metaclass == NULL)
metaclass = (PyObject *) &PyType_Type;
Py_INCREF(metaclass);
}
result = PyObject_CallFunctionObjArgs(metaclass, name, bases, methods,
NULL);
Py_DECREF(metaclass);
if (result == NULL && PyErr_ExceptionMatches(PyExc_TypeError)) {
/* A type error here likely means that the user passed
in a base that was not a class (such the random module
instead of the random.random type). Help them out with
by augmenting the error message with more information.*/
PyObject *ptype, *pvalue, *ptraceback;
PyErr_Fetch(&ptype, &pvalue, &ptraceback);
if (PyString_Check(pvalue)) {
PyObject *newmsg;
newmsg = PyString_FromFormat(
"Error when calling the metaclass bases\n"
" %s",
PyString_AS_STRING(pvalue));
if (newmsg != NULL) {
Py_DECREF(pvalue);
pvalue = newmsg;
}
}
PyErr_Restore(ptype, pvalue, ptraceback);
}
return result;
}
static void
format_exc_check_arg(PyObject *exc, char *format_str, PyObject *obj)
{