From bbb8ade904ea8c9b26236228e6c7029df279a523 Mon Sep 17 00:00:00 2001 From: Robert Collins Date: Mon, 16 Mar 2015 15:27:16 +1300 Subject: Issue #23631: Fix traceback.format_list when a traceback has been mutated. --- Lib/test/test_traceback.py | 10 +++++++++- Lib/traceback.py | 14 ++++++++++---- Misc/NEWS | 2 ++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index d9b73c1..9c8929f 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -555,6 +555,14 @@ class TestStack(unittest.TestCase): [' File "foo.py", line 1, in fred\n line\n'], s.format()) + def test_from_list_edited_stack(self): + s = traceback.StackSummary.from_list([('foo.py', 1, 'fred', 'line')]) + s[0] = ('foo.py', 2, 'fred', 'line') + s2 = traceback.StackSummary.from_list(s) + self.assertEqual( + [' File "foo.py", line 2, in fred\n line\n'], + s2.format()) + def test_format_smoke(self): # For detailed tests see the format_list tests, which consume the same # code. @@ -585,7 +593,7 @@ class TestStack(unittest.TestCase): traceback.walk_stack(None), capture_locals=True, limit=1) s = some_inner(3, 4) self.assertEqual( - [' File "' + __file__ + '", line 585, ' + [' File "' + __file__ + '", line 593, ' 'in some_inner\n' ' traceback.walk_stack(None), capture_locals=True, limit=1)\n' ' a = 1\n' diff --git a/Lib/traceback.py b/Lib/traceback.py index 0ac1819..f7705cd 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -348,11 +348,17 @@ class StackSummary(list): This method supports the older Python API. Each tuple should be a 4-tuple with (filename, lineno, name, line) elements. """ - if isinstance(a_list, StackSummary): - return StackSummary(a_list) + # While doing a fast-path check for isinstance(a_list, StackSummary) is + # appealing, idlelib.run.cleanup_traceback and other similar code may + # break this by making arbitrary frames plain tuples, so we need to + # check on a frame by frame basis. result = StackSummary() - for filename, lineno, name, line in a_list: - result.append(FrameSummary(filename, lineno, name, line=line)) + for frame in a_list: + if isinstance(frame, FrameSummary): + result.append(frame) + else: + filename, lineno, name, line = frame + result.append(FrameSummary(filename, lineno, name, line=line)) return result def format(self): diff --git a/Misc/NEWS b/Misc/NEWS index f51a74b..13c4b3e 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -18,6 +18,8 @@ Core and Builtins Library ------- +- Issue #23631: Fix traceback.format_list when a traceback has been mutated. + - Issue #23568: Add rdivmod support to MagicMock() objects. Patch by Håkan Lövdahl. -- cgit v0.12