Skip to content

Commit a607f8b

Browse files
bpo-31908: Fix output of cover files for trace module command-line tool. (GH-4205)
Previously emitted cover files only when --missing option was used. (cherry picked from commit 47ab154) Co-authored-by: Michael Selik <mike@selik.org>
1 parent 3d11630 commit a607f8b

File tree

3 files changed

+60
-23
lines changed

3 files changed

+60
-23
lines changed

Lib/test/test_trace.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import sys
33
from test.support import TESTFN, rmtree, unlink, captured_stdout
44
from test.support.script_helper import assert_python_ok, assert_python_failure
5+
import textwrap
56
import unittest
67

78
import trace
@@ -365,6 +366,46 @@ def test_ignored(self):
365366
# Matched before.
366367
self.assertTrue(ignore.names(jn('bar', 'baz.py'), 'baz'))
367368

369+
# Created for Issue 31908 -- CLI utility not writing cover files
370+
class TestCoverageCommandLineOutput(unittest.TestCase):
371+
372+
codefile = 'tmp.py'
373+
coverfile = 'tmp.cover'
374+
375+
def setUp(self):
376+
with open(self.codefile, 'w') as f:
377+
f.write(textwrap.dedent('''\
378+
x = 42
379+
if []:
380+
print('unreachable')
381+
'''))
382+
383+
def tearDown(self):
384+
unlink(self.codefile)
385+
unlink(self.coverfile)
386+
387+
def test_cover_files_written_no_highlight(self):
388+
argv = '-m trace --count'.split() + [self.codefile]
389+
status, stdout, stderr = assert_python_ok(*argv)
390+
self.assertTrue(os.path.exists(self.coverfile))
391+
with open(self.coverfile) as f:
392+
self.assertEqual(f.read(),
393+
" 1: x = 42\n"
394+
" 1: if []:\n"
395+
" print('unreachable')\n"
396+
)
397+
398+
def test_cover_files_written_with_highlight(self):
399+
argv = '-m trace --count --missing'.split() + [self.codefile]
400+
status, stdout, stderr = assert_python_ok(*argv)
401+
self.assertTrue(os.path.exists(self.coverfile))
402+
with open(self.coverfile) as f:
403+
self.assertEqual(f.read(), textwrap.dedent('''\
404+
1: x = 42
405+
1: if []:
406+
>>>>>> print('unreachable')
407+
'''))
408+
368409
class TestCommandLine(unittest.TestCase):
369410

370411
def test_failures(self):

Lib/trace.py

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,6 @@ def _unsettrace():
7979

8080
PRAGMA_NOCOVER = "#pragma NO COVER"
8181

82-
# Simple rx to find lines with no code.
83-
rx_blank = re.compile(r'^\s*(#.*)?$')
84-
8582
class _Ignore:
8683
def __init__(self, modules=None, dirs=None):
8784
self._mods = set() if not modules else set(modules)
@@ -284,16 +281,15 @@ def write_results(self, show_missing=True, summary=False, coverdir=None):
284281
lnotab = _find_executable_linenos(filename)
285282
else:
286283
lnotab = {}
287-
if lnotab:
288-
source = linecache.getlines(filename)
289-
coverpath = os.path.join(dir, modulename + ".cover")
290-
with open(filename, 'rb') as fp:
291-
encoding, _ = tokenize.detect_encoding(fp.readline)
292-
n_hits, n_lines = self.write_results_file(coverpath, source,
293-
lnotab, count, encoding)
294-
if summary and n_lines:
295-
percent = int(100 * n_hits / n_lines)
296-
sums[modulename] = n_lines, percent, modulename, filename
284+
source = linecache.getlines(filename)
285+
coverpath = os.path.join(dir, modulename + ".cover")
286+
with open(filename, 'rb') as fp:
287+
encoding, _ = tokenize.detect_encoding(fp.readline)
288+
n_hits, n_lines = self.write_results_file(coverpath, source,
289+
lnotab, count, encoding)
290+
if summary and n_lines:
291+
percent = int(100 * n_hits / n_lines)
292+
sums[modulename] = n_lines, percent, modulename, filename
297293

298294

299295
if summary and sums:
@@ -312,6 +308,7 @@ def write_results(self, show_missing=True, summary=False, coverdir=None):
312308

313309
def write_results_file(self, path, lines, lnotab, lines_hit, encoding=None):
314310
"""Return a coverage results file in path."""
311+
# ``lnotab`` is a dict of executable lines, or a line number "table"
315312

316313
try:
317314
outfile = open(path, "w", encoding=encoding)
@@ -330,17 +327,13 @@ def write_results_file(self, path, lines, lnotab, lines_hit, encoding=None):
330327
outfile.write("%5d: " % lines_hit[lineno])
331328
n_hits += 1
332329
n_lines += 1
333-
elif rx_blank.match(line):
334-
outfile.write(" ")
335-
else:
336-
# lines preceded by no marks weren't hit
337-
# Highlight them if so indicated, unless the line contains
330+
elif lineno in lnotab and not PRAGMA_NOCOVER in line:
331+
# Highlight never-executed lines, unless the line contains
338332
# #pragma: NO COVER
339-
if lineno in lnotab and not PRAGMA_NOCOVER in line:
340-
outfile.write(">>>>>> ")
341-
n_lines += 1
342-
else:
343-
outfile.write(" ")
333+
outfile.write(">>>>>> ")
334+
n_lines += 1
335+
else:
336+
outfile.write(" ")
344337
outfile.write(line.expandtabs(8))
345338

346339
return n_hits, n_lines
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix output of cover files for ``trace`` module command-line tool.
2+
Previously emitted cover files only when ``--missing`` option was used.
3+
Patch by Michael Selik.

0 commit comments

Comments
 (0)