From 7e7c00db0cc8621d6020f2552a6dba86b4d08d6f Mon Sep 17 00:00:00 2001 From: "Michael W. Hudson" Date: Wed, 27 Nov 2002 15:40:09 +0000 Subject: [PATCH] I don't know why staring at the email to python-checkins made me see problems with my code that I didn't see before the checkin, but: When a subtype .mro() fails, we need to reset the type whose __bases__ are being changed, too. Fix + test. --- Lib/test/test_descr.py | 2 ++ Objects/typeobject.c | 23 ++++++++++++++--------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 19a0ae49241..99eecd3f9e0 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -3566,11 +3566,13 @@ def test_mutable_bases_with_failing_mro(): # check here that E's gets restored. E_mro_before = E.__mro__ + D_mro_before = D.__mro__ try: D.__bases__ = (C2,) except RuntimeError: vereq(E.__mro__, E_mro_before) + vereq(D.__mro__, D_mro_before) else: raise TestFailed, "exception not propagated" diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 949cef58eee..d83ff8cab58 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -242,17 +242,12 @@ type_set_bases(PyTypeObject *type, PyObject *value, void *context) type->tp_base = new_base; if (mro_internal(type) < 0) { - type->tp_bases = old_bases; - type->tp_base = old_base; - type->tp_mro = old_mro; - - Py_DECREF(value); - Py_DECREF(new_base); - - return -1; + goto bail; } temp = PyList_New(0); + if (!temp) + goto bail; r = mro_subclasses(type, temp); @@ -267,7 +262,7 @@ type_set_bases(PyTypeObject *type, PyObject *value, void *context) Py_INCREF(cls->tp_mro); } Py_DECREF(temp); - return r; + goto bail; } Py_DECREF(temp); @@ -303,6 +298,16 @@ type_set_bases(PyTypeObject *type, PyObject *value, void *context) Py_DECREF(old_mro); return r; + + bail: + type->tp_bases = old_bases; + type->tp_base = old_base; + type->tp_mro = old_mro; + + Py_DECREF(value); + Py_DECREF(new_base); + + return -1; } static PyObject *