diff options
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/linecache.py | 7 | ||||
-rw-r--r-- | Lib/test/test_cmd_line_script.py | 2 | ||||
-rw-r--r-- | Lib/test/test_repl.py | 62 | ||||
-rw-r--r-- | Lib/traceback.py | 10 |
4 files changed, 78 insertions, 3 deletions
diff --git a/Lib/linecache.py b/Lib/linecache.py index 97644a8..c1c988d 100644 --- a/Lib/linecache.py +++ b/Lib/linecache.py @@ -180,3 +180,10 @@ def lazycache(filename, module_globals): cache[filename] = (get_lines,) return True return False + +def _register_code(code, string, name): + cache[code] = ( + len(string), + None, + [line + '\n' for line in string.splitlines()], + name) diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py index 1b58882..614c6b3 100644 --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -203,6 +203,8 @@ class CmdLineTest(unittest.TestCase): stderr = p.stderr if separate_stderr else p.stdout self.assertIn(b'Traceback ', stderr.readline()) self.assertIn(b'File "<stdin>"', stderr.readline()) + self.assertIn(b'1/0', stderr.readline()) + self.assertIn(b' ~^~', stderr.readline()) self.assertIn(b'ZeroDivisionError', stderr.readline()) def test_repl_stdout_flush(self): diff --git a/Lib/test/test_repl.py b/Lib/test/test_repl.py index 58392f2..2ee5117 100644 --- a/Lib/test/test_repl.py +++ b/Lib/test/test_repl.py @@ -131,6 +131,68 @@ class TestInteractiveInterpreter(unittest.TestCase): self.assertEqual(process.returncode, 0) self.assertIn('before close', output) + def test_interactive_traceback_reporting(self): + user_input = "1 / 0 / 3 / 4" + p = spawn_repl() + p.stdin.write(user_input) + output = kill_python(p) + self.assertEqual(p.returncode, 0) + + traceback_lines = output.splitlines()[-6:-1] + expected_lines = [ + "Traceback (most recent call last):", + " File \"<stdin>\", line 1, in <module>", + " 1 / 0 / 3 / 4", + " ~~^~~", + "ZeroDivisionError: division by zero", + ] + self.assertEqual(traceback_lines, expected_lines) + + def test_interactive_traceback_reporting_multiple_input(self): + user_input1 = dedent(""" + def foo(x): + 1 / x + + """) + p = spawn_repl() + p.stdin.write(user_input1) + user_input2 = "foo(0)" + p.stdin.write(user_input2) + output = kill_python(p) + self.assertEqual(p.returncode, 0) + + traceback_lines = output.splitlines()[-7:-1] + expected_lines = [ + ' File "<stdin>", line 1, in <module>', + ' foo(0)', + ' File "<stdin>", line 2, in foo', + ' 1 / x', + ' ~~^~~', + 'ZeroDivisionError: division by zero' + ] + self.assertEqual(traceback_lines, expected_lines) + + def test_interactive_source_is_in_linecache(self): + user_input = dedent(""" + def foo(x): + return x + 1 + + def bar(x): + return foo(x) + 2 + """) + p = spawn_repl() + p.stdin.write(user_input) + user_input2 = dedent(""" + import linecache + print(linecache.cache['<python-input-1>']) + """) + p.stdin.write(user_input2) + output = kill_python(p) + self.assertEqual(p.returncode, 0) + expected = "(30, None, [\'def foo(x):\\n\', \' return x + 1\\n\', \'\\n\'], \'<stdin>\')" + self.assertIn(expected, output, expected) + + class TestInteractiveModeSyntaxErrors(unittest.TestCase): diff --git a/Lib/traceback.py b/Lib/traceback.py index 12fcdad..7cc84b9 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -434,7 +434,6 @@ class StackSummary(list): co = f.f_code filename = co.co_filename name = co.co_name - fnames.add(filename) linecache.lazycache(filename, f.f_globals) # Must defer line lookups until we have called checkcache. @@ -447,6 +446,7 @@ class StackSummary(list): end_lineno=end_lineno, colno=colno, end_colno=end_colno)) for filename in fnames: linecache.checkcache(filename) + # If immediate lookup was desired, trigger lookups now. if lookup_lines: for f in result: @@ -479,8 +479,12 @@ class StackSummary(list): gets called for every frame to be printed in the stack summary. """ row = [] - row.append(' File "{}", line {}, in {}\n'.format( - frame_summary.filename, frame_summary.lineno, frame_summary.name)) + if frame_summary.filename.startswith("<python-input"): + row.append(' File "<stdin>", line {}, in {}\n'.format( + frame_summary.lineno, frame_summary.name)) + else: + row.append(' File "{}", line {}, in {}\n'.format( + frame_summary.filename, frame_summary.lineno, frame_summary.name)) if frame_summary.line: stripped_line = frame_summary.line.strip() row.append(' {}\n'.format(stripped_line)) |