Author: Amaury Forgeot d'Arc <amaur...@gmail.com>
Branch: py3k
Changeset: r58768:fdfaf9044e48
Date: 2012-11-06 22:07 +0100
http://bitbucket.org/pypy/pypy/changeset/fdfaf9044e48/

Log:    hg merge default

diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py
--- a/pypy/interpreter/error.py
+++ b/pypy/interpreter/error.py
@@ -231,7 +231,8 @@
             raise operationerrfmt(space.w_TypeError, msg, typename)
         return w_type
 
-    def write_unraisable(self, space, where, w_object=None):
+    def write_unraisable(self, space, where, w_object=None,
+                         with_traceback=False):
         if w_object is None:
             objrepr = ''
         else:
@@ -239,10 +240,25 @@
                 objrepr = space.str_w(space.repr(w_object))
             except OperationError:
                 objrepr = '?'
-        msg = 'Exception %s in %s%s ignored\n' % (
-            self.errorstr(space, use_repr=True), where, objrepr)
+        #
         try:
-            space.call_method(space.sys.get('stderr'), 'write', 
space.wrap(msg))
+            if with_traceback:
+                w_t = self.w_type
+                w_v = self.get_w_value(space)
+                w_tb = space.wrap(self.get_traceback())
+                space.appexec([space.wrap(where),
+                               space.wrap(objrepr),
+                               w_t, w_v, w_tb],
+                """(where, objrepr, t, v, tb):
+                    import sys, traceback
+                    sys.stderr.write('From %s%s:\\n' % (where, objrepr))
+                    traceback.print_exception(t, v, tb)
+                """)
+            else:
+                msg = 'Exception %s in %s%s ignored\n' % (
+                    self.errorstr(space, use_repr=True), where, objrepr)
+                space.call_method(space.sys.get('stderr'), 'write',
+                                  space.wrap(msg))
         except OperationError:
             pass   # ignored
 
diff --git a/pypy/module/_cffi_backend/ccallback.py 
b/pypy/module/_cffi_backend/ccallback.py
--- a/pypy/module/_cffi_backend/ccallback.py
+++ b/pypy/module/_cffi_backend/ccallback.py
@@ -92,7 +92,8 @@
 
     def print_error(self, operr):
         space = self.space
-        operr.write_unraisable(space, "cffi callback", self.w_callable)
+        operr.write_unraisable(space, "callback ", self.w_callable,
+                               with_traceback=True)
 
     def write_error_return_value(self, ll_res):
         fresult = self.getfunctype().ctitem
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py 
b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -1020,6 +1020,55 @@
     e = py.test.raises(TypeError, f)
     assert str(e.value) == "'int(*)(int)' expects 1 arguments, got 0"
 
+def test_callback_exception():
+    import cStringIO, linecache
+    def matches(str, pattern):
+        while '$' in pattern:
+            i = pattern.index('$')
+            assert str[:i] == pattern[:i]
+            j = str.find(pattern[i+1], i)
+            assert i + 1 <= j <= str.find('\n', i)
+            str = str[j:]
+            pattern = pattern[i+1:]
+        assert str == pattern
+        return True
+    def check_value(x):
+        if x == 10000:
+            raise ValueError(42)
+    def cb1(x):
+        check_value(x)
+        return x * 3
+    BShort = new_primitive_type("short")
+    BFunc = new_function_type((BShort,), BShort, False)
+    f = callback(BFunc, cb1, -42)
+    orig_stderr = sys.stderr
+    orig_getline = linecache.getline
+    try:
+        linecache.getline = lambda *args: 'LINE'    # hack: speed up PyPy tests
+        sys.stderr = cStringIO.StringIO()
+        assert f(100) == 300
+        assert sys.stderr.getvalue() == ''
+        assert f(10000) == -42
+        assert matches(sys.stderr.getvalue(), """\
+From callback <function cb1 at 0x$>:
+Traceback (most recent call last):
+  File "$", line $, in cb1
+    $
+  File "$", line $, in check_value
+    $
+ValueError: 42
+""")
+        sys.stderr = cStringIO.StringIO()
+        bigvalue = 20000
+        assert f(bigvalue) == -42
+        assert matches(sys.stderr.getvalue(), """\
+From callback <function cb1 at 0x$>:
+OverflowError: integer 60000 does not fit 'short'
+""")
+    finally:
+        sys.stderr = orig_stderr
+        linecache.getline = orig_getline
+
 def test_callback_return_type():
     for rettype in ["signed char", "short", "int", "long", "long long",
                     "unsigned char", "unsigned short", "unsigned int",
diff --git a/pypy/module/_cffi_backend/test/test_c.py 
b/pypy/module/_cffi_backend/test/test_c.py
--- a/pypy/module/_cffi_backend/test/test_c.py
+++ b/pypy/module/_cffi_backend/test/test_c.py
@@ -30,7 +30,7 @@
 class AppTestC(object):
     """Populated below, hack hack hack."""
 
-    spaceconfig = dict(usemodules=('_cffi_backend',))
+    spaceconfig = dict(usemodules=('_cffi_backend', 'cStringIO'))
 
     def setup_class(cls):
         testfuncs_w = []
diff --git a/pypy/tool/pytest/inttest.py b/pypy/tool/pytest/inttest.py
--- a/pypy/tool/pytest/inttest.py
+++ b/pypy/tool/pytest/inttest.py
@@ -3,6 +3,7 @@
 # Most pypy tests are of this kind.
 
 import py
+import sys
 from pypy.interpreter.error import OperationError
 from pypy.conftest import PyPyClassCollector
 
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to