Skip to content

Commit

Permalink
pythongh-103956: Fix trace output in case of missing source line (p…
Browse files Browse the repository at this point in the history
…ythonGH-103958)

Print only filename with lineno if linecache.getline() returns an empty string.
(cherry picked from commit 7c87ce7)

Co-authored-by: Radislav Chugunov <52372310+chgnrdv@users.noreply.github.com>
  • Loading branch information
chgnrdv authored and miss-islington committed May 9, 2024
1 parent d86b494 commit 46dd2a7
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 4 deletions.
25 changes: 25 additions & 0 deletions Lib/test/test_trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from test.support.script_helper import assert_python_ok, assert_python_failure
import textwrap
import unittest
from types import FunctionType

import trace
from trace import Trace
Expand Down Expand Up @@ -559,5 +560,29 @@ def test_run_as_module(self):
assert_python_failure('-m', 'trace', '-l', '--module', 'not_a_module_zzz')


class TestTrace(unittest.TestCase):
def setUp(self):
self.addCleanup(sys.settrace, sys.gettrace())
self.tracer = Trace(count=0, trace=1)
self.filemod = my_file_and_modname()

def test_no_source_file(self):
filename = "<unknown>"
co = traced_func_linear.__code__
co = co.replace(co_filename=filename)
f = FunctionType(co, globals())

with captured_stdout() as out:
self.tracer.runfunc(f, 2, 3)

out = out.getvalue().splitlines()
firstlineno = get_firstlineno(f)
self.assertIn(f" --- modulename: {self.filemod[1]}, funcname: {f.__code__.co_name}", out[0])
self.assertIn(f"{filename}({firstlineno + 1})", out[1])
self.assertIn(f"{filename}({firstlineno + 2})", out[2])
self.assertIn(f"{filename}({firstlineno + 3})", out[3])
self.assertIn(f"{filename}({firstlineno + 4})", out[4])


if __name__ == '__main__':
unittest.main()
16 changes: 12 additions & 4 deletions Lib/trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -565,8 +565,12 @@ def localtrace_trace_and_count(self, frame, why, arg):
if self.start_time:
print('%.2f' % (_time() - self.start_time), end=' ')
bname = os.path.basename(filename)
print("%s(%d): %s" % (bname, lineno,
linecache.getline(filename, lineno)), end='')
line = linecache.getline(filename, lineno)
print("%s(%d)" % (bname, lineno), end='')
if line:
print(": ", line, end='')
else:
print()
return self.localtrace

def localtrace_trace(self, frame, why, arg):
Expand All @@ -578,8 +582,12 @@ def localtrace_trace(self, frame, why, arg):
if self.start_time:
print('%.2f' % (_time() - self.start_time), end=' ')
bname = os.path.basename(filename)
print("%s(%d): %s" % (bname, lineno,
linecache.getline(filename, lineno)), end='')
line = linecache.getline(filename, lineno)
print("%s(%d)" % (bname, lineno), end='')
if line:
print(": ", line, end='')
else:
print()
return self.localtrace

def localtrace_count(self, frame, why, arg):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix lack of newline characters in :mod:`trace` module output when line tracing is enabled but source code line for current frame is not available.

0 comments on commit 46dd2a7

Please sign in to comment.