diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index cdaae0a..022c45c 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1681,6 +1681,18 @@ order (MRO) for bases """ else: self.fail("non-sequence mro() return not caught") + def test_activemro(self): + class Meta(type): + def mro(self): + self.__dict__["f"]() + return super().mro() + + class A(metaclass=Meta): + def f(): + __class__.myself = __class__ + + self.assertIs(A, A.myself) + def test_overloading(self): # Testing operator overloading... diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 030dc1f..a1ac2dd 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2277,7 +2277,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) { PyObject *name, *bases = NULL, *orig_dict, *dict = NULL; static char *kwlist[] = {"name", "bases", "dict", 0}; - PyObject *qualname, *slots = NULL, *tmp, *newslots; + PyObject *qualname, *slots = NULL, *tmp, *newslots, *cell; PyTypeObject *type = NULL, *base, *tmptype, *winner; PyHeapTypeObject *et; PyMemberDef *mp; @@ -2285,6 +2285,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) int j, may_add_dict, may_add_weak; _Py_IDENTIFIER(__qualname__); _Py_IDENTIFIER(__slots__); + _Py_IDENTIFIER(__cell__); assert(args != NULL && PyTuple_Check(args)); assert(kwds == NULL || PyDict_Check(kwds)); @@ -2660,6 +2661,14 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) else type->tp_free = PyObject_Del; + /* store type in class' cell */ + cell = _PyDict_GetItemId(dict, &PyId___cell__); + if (cell != NULL && PyCell_Check(cell)) { + PyCell_Set(cell, (PyObject *) type); + PyDict_DelItem(dict, PyId___cell__.object); + PyErr_Clear(); + } + /* Initialize the rest */ if (PyType_Ready(type) < 0) goto error; diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 4f61d1e..1513913 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -181,8 +181,6 @@ builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) cls = PyEval_CallObjectWithKeywords(meta, margs, mkw); Py_DECREF(margs); } - if (cls != NULL && PyCell_Check(cell)) - PyCell_Set(cell, cls); Py_DECREF(cell); } Py_DECREF(ns); diff --git a/Python/compile.c b/Python/compile.c index d5009e1..6d3628c 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1791,14 +1791,22 @@ compiler_class(struct compiler *c, stmt_ty s) return 0; } assert(i == 0); - /* Return the cell where to store __class__ */ + + /* store __cell__ into class namespace */ ADDOP_I(c, LOAD_CLOSURE, i); + str = PyUnicode_InternFromString("__cell__"); + if (!str || !compiler_nameop(c, str, Store)) { + Py_XDECREF(str); + compiler_exit_scope(c); + return 0; + } + Py_DECREF(str); } else { assert(PyDict_Size(c->u->u_cellvars) == 0); /* This happens when nobody references the cell. Return None. */ - ADDOP_O(c, LOAD_CONST, Py_None, consts); } + ADDOP_O(c, LOAD_CONST, Py_None, consts); ADDOP_IN_SCOPE(c, RETURN_VALUE); /* create the code object */ co = assemble(c, 1);