[pypy-svn] r75238 - in pypy/trunk/pypy/module/sys: . test

arigo at codespeak.net arigo at codespeak.net
Wed Jun 9 18:24:27 CEST 2010


Author: arigo
Date: Wed Jun  9 18:24:25 2010
New Revision: 75238

Modified:
   pypy/trunk/pypy/module/sys/app.py
   pypy/trunk/pypy/module/sys/test/test_sysmodule.py
Log:
Try to be really careful in sys.excepthook().


Modified: pypy/trunk/pypy/module/sys/app.py
==============================================================================
--- pypy/trunk/pypy/module/sys/app.py	(original)
+++ pypy/trunk/pypy/module/sys/app.py	Wed Jun  9 18:24:25 2010
@@ -7,8 +7,35 @@
 
 def excepthook(exctype, value, traceback):
     """Handle an exception by displaying it with a traceback on sys.stderr."""
-    from traceback import print_exception
-    print_exception(exctype, value, traceback)
+    try:
+        from traceback import print_exception
+        print_exception(exctype, value, traceback)
+    except:
+        if not excepthook_failsafe(exctype, value):
+            raise
+
+def excepthook_failsafe(exctype, value):
+    # This version carefully tries to handle all bad cases (e.g. an
+    # ImportError looking for traceback.py), but may still raise.
+    # If it does, we get "Error calling sys.excepthook" from app_main.py.
+    try:
+        # first try to print the exception's class name
+        stderr = sys.stderr
+        stderr.write(getattr(exctype, '__name__', exctype))
+        # then attempt to get the str() of the exception
+        try:
+            s = str(value)
+        except:
+            s = '<failure of str() on the exception instance>'
+        # then print it, and don't worry too much about the extra space
+        # between the exception class and the ':'
+        if s:
+            stderr.write(': %s\n' % (s,))
+        else:
+            stderr.write('\n')
+        return True     # successfully printed at least the class and value
+    except:
+        return False    # got an exception again... ignore, report the original
 
 def exit(exitcode=0):
     """Exit the interpreter by raising SystemExit(exitcode).

Modified: pypy/trunk/pypy/module/sys/test/test_sysmodule.py
==============================================================================
--- pypy/trunk/pypy/module/sys/test/test_sysmodule.py	(original)
+++ pypy/trunk/pypy/module/sys/test/test_sysmodule.py	Wed Jun  9 18:24:25 2010
@@ -177,6 +177,26 @@
         sys.stderr = savestderr
         assert err.getvalue().endswith("ValueError: 42\n")
 
+    def test_excepthook_failsafe_path(self):
+        import traceback
+        original_print_exception = traceback.print_exception
+        import cStringIO
+        savestderr = sys.stderr
+        err = cStringIO.StringIO()
+        sys.stderr = err
+        try:
+            traceback.print_exception = "foo"
+            eh = sys.__excepthook__
+            try:
+                raise ValueError(42)
+            except ValueError, exc:
+                eh(*sys.exc_info())
+        finally:
+            traceback.print_exception = original_print_exception
+            sys.stderr = savestderr
+
+        assert err.getvalue() == "ValueError: 42\n"
+
     # FIXME: testing the code for a lost or replaced excepthook in
     # Python/pythonrun.c::PyErr_PrintEx() is tricky.
 



More information about the Pypy-commit mailing list