Author: Armin Rigo <ar...@tunes.org>
Branch: 
Changeset: r98507:11a00b95fd59
Date: 2020-01-10 12:59 +0100
http://bitbucket.org/pypy/pypy/changeset/11a00b95fd59/

Log:    Issue #3149

        Fix the exception-matching logic to fall back to the general
        issubclass() logic. This is what CPython 2.x does.

diff --git a/pypy/module/__builtin__/abstractinst.py 
b/pypy/module/__builtin__/abstractinst.py
--- a/pypy/module/__builtin__/abstractinst.py
+++ b/pypy/module/__builtin__/abstractinst.py
@@ -219,13 +219,15 @@
     return BaseObjSpace.exception_getclass(space, w_obj)
 
 def exception_issubclass_w(space, w_cls1, w_cls2):
-    if isinstance(w_cls1, W_ClassObject):
-        if isinstance(w_cls2, W_ClassObject):
-            return w_cls1.is_subclass_of(w_cls2)
-        return False
-    if isinstance(w_cls2, W_ClassObject):
-        return False
-    return BaseObjSpace.exception_issubclass_w(space, w_cls1, w_cls2)
+    if (space.type(w_cls1) is space.w_type and
+        space.type(w_cls2) is space.w_type):
+        return BaseObjSpace.exception_issubclass_w(space, w_cls1, w_cls2)
+    #
+    # The rest is the rare slow case.  Use the general logic of issubclass()
+    # (issue #3149).  CPython 3.x doesn't do that, but there is a many-years
+    # issue report: https://bugs.python.org/issue12029.  In PyPy3 we try to
+    # fix the issue with the same code, as long as no CPython3 test fails.
+    return abstract_issubclass_w(space, w_cls1, w_cls2, True)
 
 # ____________________________________________________________
 # App-level interface
diff --git a/pypy/module/__builtin__/test/test_abstractinst.py 
b/pypy/module/__builtin__/test/test_abstractinst.py
--- a/pypy/module/__builtin__/test/test_abstractinst.py
+++ b/pypy/module/__builtin__/test/test_abstractinst.py
@@ -239,3 +239,23 @@
                 return False
 
         assert issubclass(42, M()) is False
+
+    def test_exception_match_calls_subclasscheck(self):
+        class Special(Exception):
+            class __metaclass__(type):
+                def __subclasscheck__(cls1, cls2):
+                    return True
+        try:
+            raise ValueError
+        except Special:
+            pass
+
+    def test_exception_raising_calls_subclasscheck(self):
+        class Special(Exception):
+            class __metaclass__(type):
+                def __subclasscheck__(cls1, cls2):
+                    return True
+        try:
+            raise Special, ValueError()
+        except ValueError:
+            pass
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to