diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -1,15 +1,15 @@ """Test cases for traceback module""" from io import StringIO import sys import unittest import re -from test.support import run_unittest, Error, captured_output +from test.support import Error, captured_output, captured_stdout from test.support import TESTFN, unlink, cpython_only from test.script_helper import assert_python_ok import textwrap import traceback class SyntaxTracebackCases(unittest.TestCase): @@ -471,14 +471,24 @@ class MiscTracebackCases(unittest.TestCa self.assertEqual(len(inner_frame.f_locals), 1) # Clear traceback frames traceback.clear_frames(tb) # Local variable dict should now be empty. self.assertEqual(len(inner_frame.f_locals), 0) - -def test_main(): - run_unittest(__name__) + def test_constructors(self): + output = StringIO() + traceback.print_exc(file=output) + self.assertEqual(output.getvalue(), 'NoneType\n') + output = StringIO() + traceback.print_exception(None, None, None, file=output) + self.assertEqual(output.getvalue(), 'NoneType\n') + with captured_stdout() as output: + print(traceback.format_exc()) + self.assertEqual(output.getvalue(), 'NoneType\n\n') + with captured_stdout() as output: + print(traceback.format_exception(None, None, None)) + self.assertEqual(output.getvalue(), "['NoneType\\n']\n") if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/traceback.py b/Lib/traceback.py --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -117,27 +117,27 @@ def extract_tb(tb, limit=None): "\nDuring handling of the above exception, " "another exception occurred:\n") def _iter_chain(exc, custom_tb=None, seen=None): if seen is None: seen = set() seen.add(exc) its = [] - context = exc.__context__ - cause = exc.__cause__ + context = getattr(exc, '__context__', None) + cause = getattr(exc, '__cause__', None) if cause is not None and cause not in seen: its.append(_iter_chain(cause, False, seen)) its.append([(_cause_message, None)]) elif (context is not None and - not exc.__suppress_context__ and + not getattr(exc, '__suppress_context__', None) and context not in seen): its.append(_iter_chain(context, None, seen)) its.append([(_context_message, None)]) - its.append([(exc, custom_tb or exc.__traceback__)]) + its.append([(exc, custom_tb or getattr(exc, '__traceback__', None))]) # itertools.chain is in an extension module and may be unavailable for it in its: yield from it def _format_exception_iter(etype, value, tb, limit, chain): if chain: values = _iter_chain(value, tb) else: