diff -r 87dcd948dc74 Objects/typeobject.c --- a/Objects/typeobject.c Wed Feb 29 16:21:25 2012 -0800 +++ b/Objects/typeobject.c Thu Mar 01 13:54:08 2012 +0100 @@ -594,7 +594,13 @@ type_dict(PyTypeObject *type, void *cont Py_INCREF(Py_None); return Py_None; } - return PyDictProxy_New(type->tp_dict); + if (PyFrozenDict_Check(type->tp_dict)) { + Py_INCREF(type->tp_dict); + return type->tp_dict; + } + else { + return PyDictProxy_New(type->tp_dict); + } } static PyObject * @@ -1807,7 +1813,7 @@ subtype_setdict(PyObject *obj, PyObject "This object has no __dict__"); return -1; } - if (value != NULL && !PyDict_Check(value)) { + if (value != NULL && !PyDict_Check(value) && !PyFrozenDict_Check(value)) { PyErr_Format(PyExc_TypeError, "__dict__ must be set to a dictionary, " "not a '%.200s'", Py_TYPE(value)->tp_name); @@ -2349,7 +2355,15 @@ type_new(PyTypeObject *metatype, PyObjec /* Put the proper slots in place */ fixup_slot_dispatchers(type); - Py_DECREF(dict); + Py_CLEAR(dict); + + if (PyDict_GetItemString(type->tp_dict, "__final__")) { + dict = PyFrozenDict_Copy(type->tp_dict); + if (dict == NULL) + goto error; + Py_DECREF(type->tp_dict); + type->tp_dict = dict; + } return (PyObject *)type; error: @@ -2451,7 +2465,7 @@ _PyType_Lookup(PyTypeObject *type, PyObj base = PyTuple_GET_ITEM(mro, i); assert(PyType_Check(base)); dict = ((PyTypeObject *)base)->tp_dict; - assert(dict && PyDict_Check(dict)); + assert(dict && (PyDict_Check(dict) || PyFrozenDict_Check(dict))); res = PyDict_GetItem(dict, name); if (res != NULL) break; @@ -2635,7 +2649,7 @@ merge_class_dict(PyObject *dict, PyObjec PyObject *bases; _Py_IDENTIFIER(__bases__); - assert(PyDict_Check(dict)); + assert(PyDict_Check(dict) || PyFrozenDict_Check(dict)); assert(aclass); /* Merge in the type's dict (if any). */ @@ -3587,7 +3601,7 @@ object_dir(PyObject *self, PyObject *arg PyErr_Clear(); dict = PyDict_New(); } - else if (!PyDict_Check(dict)) { + else if (!PyDict_Check(dict) && !PyFrozenDict_Check(dict)) { Py_DECREF(dict); dict = PyDict_New(); } @@ -6114,7 +6128,7 @@ recurse_down_subclasses(PyTypeObject *ty assert(PyType_Check(subclass)); /* Avoid recursing down into unaffected classes */ dict = subclass->tp_dict; - if (dict != NULL && PyDict_Check(dict) && + if (dict != NULL && (PyDict_Check(dict) || PyFrozenDict_Check(dict)) && PyDict_GetItem(dict, name) != NULL) continue; if (update_subclasses(subclass, name, callback, data) < 0)