[pypy-svn] r69173 - in pypy/branch/faster-raise/pypy: interpreter interpreter/test module/__builtin__

fijal at codespeak.net fijal at codespeak.net
Wed Nov 11 15:39:36 CET 2009


Author: fijal
Date: Wed Nov 11 15:39:36 2009
New Revision: 69173

Modified:
   pypy/branch/faster-raise/pypy/interpreter/baseobjspace.py
   pypy/branch/faster-raise/pypy/interpreter/error.py
   pypy/branch/faster-raise/pypy/interpreter/test/test_raise.py
   pypy/branch/faster-raise/pypy/module/__builtin__/__init__.py
   pypy/branch/faster-raise/pypy/module/__builtin__/abstractinst.py
Log:
(arigo, fijal)
Implement helpers for checking types valid for exeptions.
Change a world a bit.


Modified: pypy/branch/faster-raise/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/branch/faster-raise/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/branch/faster-raise/pypy/interpreter/baseobjspace.py	Wed Nov 11 15:39:36 2009
@@ -802,34 +802,44 @@
         w_objtype = self.type(w_obj)
         return self.issubtype(w_objtype, w_type)
 
+    # The code below only works
+    # for the simple case (new-style instance).
+    # These methods are patched with the full logic by the __builtin__
+    # module when it is loaded
+
     def abstract_issubclass_w(self, w_cls1, w_cls2):
-        # Equivalent to 'issubclass(cls1, cls2)'.  The code below only works
-        # for the simple case (new-style class, new-style class).
-        # This method is patched with the full logic by the __builtin__
-        # module when it is loaded.
+        # Equivalent to 'issubclass(cls1, cls2)'.
         return self.is_true(self.issubtype(w_cls1, w_cls2))
 
     def abstract_isinstance_w(self, w_obj, w_cls):
-        # Equivalent to 'isinstance(obj, cls)'.  The code below only works
-        # for the simple case (new-style instance, new-style class).
-        # This method is patched with the full logic by the __builtin__
-        # module when it is loaded.
+        # Equivalent to 'isinstance(obj, cls)'.
         return self.is_true(self.isinstance(w_obj, w_cls))
 
     def abstract_isclass_w(self, w_obj):
-        # Equivalent to 'isinstance(obj, type)'.  The code below only works
-        # for the simple case (new-style instance without special stuff).
-        # This method is patched with the full logic by the __builtin__
-        # module when it is loaded.
+        # Equivalent to 'isinstance(obj, type)'.
         return self.is_true(self.isinstance(w_obj, self.w_type))
 
     def abstract_getclass(self, w_obj):
-        # Equivalent to 'obj.__class__'.  The code below only works
-        # for the simple case (new-style instance without special stuff).
-        # This method is patched with the full logic by the __builtin__
-        # module when it is loaded.
+        # Equivalent to 'obj.__class__'.
+        return self.type(w_obj)
+
+    # CPython rules allows old style classes or subclasses
+    # of BaseExceptions to be exceptions.
+    # This is slightly less general than the case above, so we prefix
+    # it with exception_
+
+    def exception_is_valid_class_w(self, w_obj):
+        return (self.is_true(self.isinstance(w_obj, self.w_type)) and
+                self.is_true(self.issubtype(w_obj, self.w_BaseException)))
+
+    def exception_getclass(self, w_obj):
         return self.type(w_obj)
 
+    def exception_issubclass_w(self, w_cls1, w_cls2):
+        return self.is_true(self.issubtype(w_cls1, w_cls2))
+
+    # end of special support code
+
     def eval(self, expression, w_globals, w_locals, hidden_applevel=False):
         "NOT_RPYTHON: For internal debugging."
         import types

Modified: pypy/branch/faster-raise/pypy/interpreter/error.py
==============================================================================
--- pypy/branch/faster-raise/pypy/interpreter/error.py	(original)
+++ pypy/branch/faster-raise/pypy/interpreter/error.py	Wed Nov 11 15:39:36 2009
@@ -177,16 +177,15 @@
             while space.is_true(space.isinstance(w_type, space.w_tuple)):
                 w_type = space.getitem(w_type, space.wrap(0))
 
-        if (space.abstract_isclass_w(w_type) and
-            is_valid_exception_class(space, w_type)):
+        if space.exception_is_valid_class_w(w_type):
             # this is for all cases of the form (Class, something)
             if space.is_w(w_value, space.w_None):
                 # raise Type: we assume we have to instantiate Type
                 w_value = space.call_function(w_type)
-                w_type = space.abstract_getclass(w_value)
+                w_type = space.exception_getclass(w_value)
             else:
-                w_valuetype = space.abstract_getclass(w_value)
-                if space.abstract_issubclass_w(w_valuetype, w_type):
+                w_valuetype = space.exception_getclass(w_value)
+                if space.exception_issubclass_w(w_valuetype, w_type):
                     # raise Type, Instance: let etype be the exact type of value
                     w_type = w_valuetype
                 else:
@@ -198,7 +197,7 @@
                     else:
                         # raise Type, X: assume X is the constructor argument
                         w_value = space.call_function(w_type, w_value)
-                    w_type = space.abstract_getclass(w_value)
+                    w_type = space.exception_getclass(w_value)
 
         elif space.full_exceptions and space.is_w(space.type(w_type),
                                                   space.w_str):
@@ -208,8 +207,8 @@
         else:
             # the only case left here is (inst, None), from a 'raise inst'.
             w_inst = w_type
-            w_instclass = space.abstract_getclass(w_inst)
-            if not is_valid_exception_class(space, w_instclass):
+            w_instclass = space.exception_getclass(w_inst)
+            if not space.exception_is_valid_class_w(w_instclass):
                 instclassname = w_instclass.getname(space, '?')
                 msg = ("exceptions must be classes, or instances,"
                        "or strings (deprecated) not %s" % (instclassname,))
@@ -240,23 +239,6 @@
         except OperationError:
             pass   # ignored
 
-
-def is_valid_exception_class(space, w_type):
-    """Assuming that 'w_type' is a new-style or old-style class, is it
-    correct to use it as the class of an exception?  The answer is no
-    if it is a new-style class that doesn't inherit from BaseException.
-    """
-    if not space.full_exceptions:
-        return True         # always, for the flow space
-    try:
-        return space.is_true(
-            space.issubtype(w_type, space.w_BaseException))
-    except OperationError, e:
-        if not e.match(space, space.w_TypeError):
-            raise
-        return True         # assuming w_type is an old-style class
-
-
 # Utilities
 from pypy.tool.ansi_print import ansi_print
 

Modified: pypy/branch/faster-raise/pypy/interpreter/test/test_raise.py
==============================================================================
--- pypy/branch/faster-raise/pypy/interpreter/test/test_raise.py	(original)
+++ pypy/branch/faster-raise/pypy/interpreter/test/test_raise.py	Wed Nov 11 15:39:36 2009
@@ -244,3 +244,14 @@
             assert 0
         except KeyError:
             pass
+
+    def test_obscure_bases(self):
+        # this test checks bug-to-bug cpython compatibility
+        e = ValueError()
+        e.__bases__ = (5,)
+        try:
+            raise e
+        except ValueError:
+            pass
+
+            

Modified: pypy/branch/faster-raise/pypy/module/__builtin__/__init__.py
==============================================================================
--- pypy/branch/faster-raise/pypy/module/__builtin__/__init__.py	(original)
+++ pypy/branch/faster-raise/pypy/module/__builtin__/__init__.py	Wed Nov 11 15:39:36 2009
@@ -148,6 +148,9 @@
         space.abstract_issubclass_w = ab.abstract_issubclass_w.__get__(space)
         space.abstract_isclass_w = ab.abstract_isclass_w.__get__(space)
         space.abstract_getclass = ab.abstract_getclass.__get__(space)
+        space.exception_is_valid_class_w = ab.exception_is_valid_class_w.__get__(space)
+        space.exception_getclass = ab.exception_getclass.__get__(space)
+        space.exception_issubclass_w = ab.exception_issubclass_w.__get__(space)
 
     def startup(self, space):
         # install zipimport hook if --withmod-zipimport is used

Modified: pypy/branch/faster-raise/pypy/module/__builtin__/abstractinst.py
==============================================================================
--- pypy/branch/faster-raise/pypy/module/__builtin__/abstractinst.py	(original)
+++ pypy/branch/faster-raise/pypy/module/__builtin__/abstractinst.py	Wed Nov 11 15:39:36 2009
@@ -11,6 +11,7 @@
 from pypy.interpreter.error import OperationError
 from pypy.module.__builtin__.interp_classobj import W_ClassObject
 from pypy.module.__builtin__.interp_classobj import W_InstanceObject
+from pypy.interpreter.baseobjspace import ObjSpace as BaseObjSpace
 
 def _get_bases(space, w_cls):
     """Returns 'cls.__bases__'.  Returns None if there is
@@ -152,6 +153,31 @@
                 " or tuple of classes and types")
     return _issubclass_recurse(space, w_derived, w_klass_or_tuple)
 
+# ------------------------------------------------------------
+# Exception helpers
+
+def exception_is_valid_class_w(space, w_obj):
+    obj = space.interpclass_w(w_obj)
+    if isinstance(obj, W_ClassObject):
+        return True
+    return BaseObjSpace.exception_is_valid_class_w(space, w_obj)
+
+def exception_getclass(space, w_obj):
+    obj = space.interpclass_w(w_obj)
+    if isinstance(obj, W_InstanceObject):
+        return obj.w_class
+    return BaseObjSpace.exception_getclass(space, w_obj)
+
+def exception_issubclass_w(space, w_cls1, w_cls2):
+    cls1 = space.interpclass_w(w_cls1)
+    cls2 = space.interpclass_w(w_cls2)
+    if isinstance(cls1, W_ClassObject):
+        if isinstance(cls2, W_ClassObject):
+            return cls1.is_subclass_of(cls2)
+        return False
+    if isinstance(cls2, W_ClassObject):
+        return False
+    return BaseObjSpace.exception_issubclass_w(space, w_cls1, w_cls2)
 
 # ____________________________________________________________
 # App-level interface



More information about the Pypy-commit mailing list