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