[pypy-commit] pypy py3k: have the code module display chained exceptions since our repl uses it
pjenvey
noreply at buildbot.pypy.org
Wed Apr 10 01:46:28 CEST 2013
Author: Philip Jenvey <pjenvey at underboss.org>
Branch: py3k
Changeset: r63184:1341a432e134
Date: 2013-04-09 16:45 -0700
http://bitbucket.org/pypy/pypy/changeset/1341a432e134/
Log: have the code module display chained exceptions since our repl uses
it
diff --git a/lib-python/3/code.py b/lib-python/3/code.py
--- a/lib-python/3/code.py
+++ b/lib-python/3/code.py
@@ -130,19 +130,29 @@
The output is written by self.write(), below.
"""
+ sys.last_type, sys.last_value, last_tb = ei = sys.exc_info()
+ sys.last_traceback = last_tb
try:
- type, value, tb = sys.exc_info()
- sys.last_type = type
- sys.last_value = value
- sys.last_traceback = tb
- tblist = traceback.extract_tb(tb)
- del tblist[:1]
- lines = traceback.format_list(tblist)
- if lines:
- lines.insert(0, "Traceback (most recent call last):\n")
- lines.extend(traceback.format_exception_only(type, value))
+ lines = []
+ for value, tb in traceback._iter_chain(*ei[1:]):
+ if isinstance(value, str):
+ lines.append(value)
+ lines.append('\n')
+ continue
+ if tb:
+ tblist = traceback.extract_tb(tb)
+ if tb is last_tb:
+ # The last traceback includes the frame we
+ # exec'd in
+ del tblist[:1]
+ tblines = traceback.format_list(tblist)
+ if tblines:
+ lines.append("Traceback (most recent call last):\n")
+ lines.extend(tblines)
+ lines.extend(traceback.format_exception_only(type(value),
+ value))
finally:
- tblist = tb = None
+ tblist = last_tb = ei = None
self.write(''.join(lines))
def write(self, data):
diff --git a/pypy/module/test_lib_pypy/test_code_module.py b/pypy/module/test_lib_pypy/test_code_module.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/test_lib_pypy/test_code_module.py
@@ -0,0 +1,42 @@
+class AppTestCodeModule:
+
+ def w_get_interp(self):
+ import code
+ import io
+ class MockedInterpreter(code.InteractiveInterpreter):
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.out = io.StringIO()
+
+ def write(self, data):
+ self.out.write(data)
+ return MockedInterpreter()
+
+ def test_cause_tb(self):
+ interp = self.get_interp()
+ interp.runsource('raise IOError from OSError')
+ result = interp.out.getvalue()
+ expected_header = """OSError
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+"""
+ assert expected_header in result
+ assert result.endswith("IOError\n")
+
+ def test_context_tb(self):
+ interp = self.get_interp()
+ interp.runsource("""\
+try: zzzeek
+except: _diana_
+""")
+ result = interp.out.getvalue()
+ expected_header = """NameError: name 'zzzeek' is not defined
+
+During handling of the above exception, another exception occurred:
+
+Traceback (most recent call last):
+"""
+ assert expected_header in result
+ assert result.endswith("NameError: name '_diana_' is not defined\n")
More information about the pypy-commit
mailing list