diff --git a/Lib/test/test_metaclass.py b/Lib/test/test_metaclass.py index 9126cf6524c..abb33303285 100644 --- a/Lib/test/test_metaclass.py +++ b/Lib/test/test_metaclass.py @@ -207,6 +207,29 @@ And again, with a __prepare__ attribute. kw: [('other', 'booh')] >>> +The default metaclass must define a __prepare__() method. + + >>> type.__prepare__() + {} + >>> + +Make sure it works with subclassing. + + >>> class M(type): + ... @classmethod + ... def __prepare__(cls, *args, **kwds): + ... d = super().__prepare__(*args, **kwds) + ... d["hello"] = 42 + ... return d + ... + >>> class C(metaclass=M): + ... print(hello) + ... + 42 + >>> print(C.hello) + 42 + >>> + """ __test__ = {'doctests' : doctests} diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 3ad5efcfc14..8cf28fca7fd 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2200,11 +2200,21 @@ type_subclasses(PyTypeObject *type, PyObject *args_ignored) return list; } +static PyObject * +type_prepare(PyObject *self, PyObject *args, PyObject *kwds) +{ + return PyDict_New(); +} + static PyMethodDef type_methods[] = { {"mro", (PyCFunction)mro_external, METH_NOARGS, PyDoc_STR("mro() -> list\nreturn a type's method resolution order")}, {"__subclasses__", (PyCFunction)type_subclasses, METH_NOARGS, PyDoc_STR("__subclasses__() -> list of immediate subclasses")}, + {"__prepare__", (PyCFunction)type_prepare, + METH_VARARGS | METH_KEYWORDS | METH_CLASS, + PyDoc_STR("__prepare__() -> dict\n" + "used to create the namespace for the class statement")}, {0} };