[pypy-commit] pypy py3.5: test and fix

arigo pypy.commits at gmail.com
Sat Dec 3 03:47:49 EST 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5
Changeset: r88839:5ff985c7735b
Date: 2016-12-03 09:47 +0100
http://bitbucket.org/pypy/pypy/changeset/5ff985c7735b/

Log:	test and fix

diff --git a/pypy/objspace/std/test/test_typeobject.py b/pypy/objspace/std/test/test_typeobject.py
--- a/pypy/objspace/std/test/test_typeobject.py
+++ b/pypy/objspace/std/test/test_typeobject.py
@@ -270,6 +270,37 @@
             assert 0, "exception not propagated"
             """
 
+    def test_mutable_bases_with_failing_mro_2(self): """
+        class E(Exception):
+            pass
+        class M(type):
+            def mro(cls):
+                if cls.__name__ == 'Sub' and A.__bases__ == (Base1,):
+                    A.__bases__ = (Base2,)
+                    raise E
+                return type.mro(cls)
+
+        class Base0:
+            pass
+        class Base1:
+            pass
+        class Base2:
+            pass
+        class A(Base0, metaclass=M):
+            pass
+        class Sub(A):
+            pass
+
+        try:
+            A.__bases__ = (Base1,)
+        except E:
+            assert A.__bases__ == (Base2,)
+            assert A.__mro__ == (A, Base2, object)
+            assert Sub.__mro__ == (Sub, A, Base2, object)
+        else:
+            assert 0
+        """
+
     def test_mutable_bases_catch_mro_conflict(self):
         class A(object):
             pass
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -802,8 +802,9 @@
     return space.newtuple(w_type.bases_w)
 
 def mro_subclasses(space, w_type, temp):
-    temp.append((w_type, w_type.mro_w))
+    old_mro_w = w_type.mro_w
     compute_mro(w_type)
+    temp.append((w_type, old_mro_w, w_type.mro_w))
     for w_sc in w_type.get_subclasses():
         assert isinstance(w_sc, W_TypeObject)
         mro_subclasses(space, w_sc, temp)
@@ -856,9 +857,11 @@
         # try to recompute all MROs
         mro_subclasses(space, w_type, temp)
     except:
-        for cls, old_mro in temp:
-            cls.mro_w = old_mro
-        w_type.bases_w = saved_bases_w
+        for cls, old_mro, new_mro in temp:
+            if cls.mro_w is new_mro:      # don't revert if it changed again
+                cls.mro_w = old_mro
+        if w_type.bases_w is newbases_w:  # don't revert if it changed again
+            w_type.bases_w = saved_bases_w
         raise
     if (w_type.version_tag() is not None and
         not is_mro_purely_of_types(w_type.mro_w)):


More information about the pypy-commit mailing list