[pypy-svn] r30391 - pypy/dist/pypy/rpython

arigo at codespeak.net arigo at codespeak.net
Sun Jul 23 12:56:50 CEST 2006


Author: arigo
Date: Sun Jul 23 12:56:48 2006
New Revision: 30391

Modified:
   pypy/dist/pypy/rpython/llinterp.py
Log:
Fix for test_llinterp, which fails in 2.5 although the bug was really always there:
find_exception() could accidentally return a subclass of the expected class
(depending on exceptions.__dict__ enumeration order).



Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Sun Jul 23 12:56:48 2006
@@ -129,19 +129,17 @@
 
     def find_exception(self, exc):
         assert isinstance(exc, LLException)
-        import exceptions
         klass, inst = exc.args[0], exc.args[1]
         exdata = self.typer.getexceptiondata()
         frame = self.frame_class(None, [], self)
         old_active_frame = self.active_frame
         try:
-            for cls in exceptions.__dict__.values():
-                if type(cls) is type(Exception):
-                    evalue = frame.op_direct_call(exdata.fn_pyexcclass2exc,
-                            lltype.pyobjectptr(cls))
-                    etype = frame.op_direct_call(exdata.fn_type_of_exc_inst, evalue)
-                    if etype == klass:
-                        return cls
+            for cls in enumerate_exceptions_top_down():
+                evalue = frame.op_direct_call(exdata.fn_pyexcclass2exc,
+                        lltype.pyobjectptr(cls))
+                etype = frame.op_direct_call(exdata.fn_type_of_exc_inst, evalue)
+                if etype == klass:
+                    return cls
         finally:
             self.active_frame = old_active_frame
         raise ValueError, "couldn't match exception"
@@ -955,6 +953,22 @@
     return graph.name, interp_func
 
 
+def enumerate_exceptions_top_down():
+    import exceptions
+    result = []
+    seen = {}
+    def addcls(cls):
+        if type(cls) is type(Exception) and issubclass(cls, Exception):
+            if cls in seen:
+                return
+            for base in cls.__bases__:   # bases first
+                addcls(base)
+            result.append(cls)
+            seen[cls] = True
+    for cls in exceptions.__dict__.values():
+        addcls(cls)
+    return result
+
 # by default we route all logging messages to nothingness
 # e.g. tests can then switch on logging to get more help
 # for failing tests



More information about the Pypy-commit mailing list