Author: Armin Rigo <[email protected]>
Branch: py3.5
Changeset: r89403:671ae80283ca
Date: 2017-01-06 17:35 +0100
http://bitbucket.org/pypy/pypy/changeset/671ae80283ca/

Log:    Update the unraisable-exception output to include a full traceback

diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py
--- a/pypy/interpreter/error.py
+++ b/pypy/interpreter/error.py
@@ -248,6 +248,10 @@
 
     def write_unraisable(self, space, where, w_object=None,
                          with_traceback=False, extra_line=''):
+        # Note: since Python 3.5, unraisable exceptions are always
+        # printed with a traceback.  Setting 'with_traceback=False'
+        # only asks for a different format, starting with the message
+        # "Exception Xxx ignored".
         if w_object is None:
             objrepr = ''
         else:
@@ -257,31 +261,32 @@
                 objrepr = "<object repr() failed>"
         #
         try:
-            if with_traceback:
-                try:
-                    self.normalize_exception(space)
-                except OperationError:
-                    pass
-                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),
-                               space.wrap(extra_line),
-                               w_t, w_v, w_tb],
-                """(where, objrepr, extra_line, t, v, tb):
-                    import sys, traceback
-                    if where or objrepr:
-                        sys.stderr.write('From %s%s:\\n' % (where, objrepr))
-                    if extra_line:
-                        sys.stderr.write(extra_line)
-                    traceback.print_exception(t, v, tb)
-                """)
+            try:
+                self.normalize_exception(space)
+            except OperationError:
+                pass
+            w_t = self.w_type
+            w_v = self.get_w_value(space)
+            w_tb = space.wrap(self.get_traceback())
+            if where or objrepr:
+                if with_traceback:
+                    first_line = 'From %s%s:\n' % (where, objrepr)
+                else:
+                    first_line = 'Exception ignored in: %s%s\n' % (
+                        where, objrepr)
             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))
+                first_line = ''
+            space.appexec([space.wrap(first_line),
+                           space.wrap(extra_line),
+                           w_t, w_v, w_tb],
+            """(first_line, extra_line, t, v, tb):
+                import sys
+                sys.stderr.write(first_line)
+                if extra_line:
+                    sys.stderr.write(extra_line)
+                import traceback
+                traceback.print_exception(t, v, tb)
+            """)
         except OperationError:
             pass   # ignored
 
diff --git a/pypy/interpreter/executioncontext.py 
b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -574,9 +574,13 @@
             if self.gc_disabled(w_obj):
                 return
             try:
-                space.get_and_call_function(w_del, w_obj)
+                w_impl = space.get(w_del, w_obj)
             except Exception as e:
                 report_error(space, e, "method __del__ of ", w_obj)
+            try:
+                space.call_function(w_impl)
+            except Exception as e:
+                report_error(space, e, '', w_impl)
 
         # Call the RPython-level _finalize_() method.
         try:
diff --git a/pypy/objspace/std/test/test_userobject.py 
b/pypy/objspace/std/test/test_userobject.py
--- a/pypy/objspace/std/test/test_userobject.py
+++ b/pypy/objspace/std/test/test_userobject.py
@@ -163,29 +163,38 @@
         from io import StringIO
         class A(object):
             def __del__(self):
-                yaddadlaouti
+                raise ValueError('foo bar')
         prev = sys.stderr
         try:
             sys.stderr = StringIO()
             A()
             gc.collect()
             res = sys.stderr.getvalue()
+            sys.stderr = StringIO()
             A()
             gc.collect()
             res2 = sys.stderr.getvalue()
+            A.__del__ = lambda a, b, c: None  # will get "not enough arguments"
+            sys.stderr = StringIO()
+            A()
+            gc.collect()
+            res3 = sys.stderr.getvalue()
         finally:
             sys.stderr = prev
-        assert res.startswith('Exception')
-        assert 'NameError' in res
-        assert 'yaddadlaouti' in res
-        assert 'ignored' in res
-        assert res.count('\n') == 1    # a single line
-        assert res2.count('\n') == 2   # two lines
-        line2 = res2.split('\n')[1]
-        assert line2.startswith('Exception')
-        assert 'NameError' in line2
-        assert 'yaddadlaouti' in line2
-        assert 'ignored' in line2
+        def check_tb(x, traceback=True):
+            print('----\n%s----\n' % (x,))
+            assert x.startswith('Exception ignored in: <bound method ')
+            if traceback:
+                assert '>\nTraceback (most recent call last):\n  File "' in x
+                assert " in __del__\n" in x
+                assert x.endswith("\nValueError: foo bar\n")
+            else:
+                assert 'Traceback' not in x
+                assert '  File' not in x
+                assert '>\nTypeError: <lambda>() missing 2 required pos' in x
+        check_tb(res)
+        check_tb(res2)
+        check_tb(res3, traceback=False)
 
     def test_instance_overrides_meth(self):
         class C(object):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to