From 47ab15470d72367694d7758004067313ae022f0e Mon Sep 17 00:00:00 2001 From: Michael Selik Date: Mon, 30 Apr 2018 20:46:52 -0700 Subject: 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. --- Lib/test/test_trace.py | 41 ++++++++++++++++++++++ Lib/trace.py | 39 +++++++++----------- .../next/Library/2017-10-31.bpo-31908.g4xh8x.rst | 3 ++ 3 files changed, 60 insertions(+), 23 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2017-10-31.bpo-31908.g4xh8x.rst diff --git a/Lib/test/test_trace.py b/Lib/test/test_trace.py index e04ca01..55a8bce 100644 --- a/Lib/test/test_trace.py +++ b/Lib/test/test_trace.py @@ -2,6 +2,7 @@ import os import sys from test.support import TESTFN, rmtree, unlink, captured_stdout from test.support.script_helper import assert_python_ok, assert_python_failure +import textwrap import unittest import trace @@ -365,6 +366,46 @@ class Test_Ignore(unittest.TestCase): # Matched before. self.assertTrue(ignore.names(jn('bar', 'baz.py'), 'baz')) +# Created for Issue 31908 -- CLI utility not writing cover files +class TestCoverageCommandLineOutput(unittest.TestCase): + + codefile = 'tmp.py' + coverfile = 'tmp.cover' + + def setUp(self): + with open(self.codefile, 'w') as f: + f.write(textwrap.dedent('''\ + x = 42 + if []: + print('unreachable') + ''')) + + def tearDown(self): + unlink(self.codefile) + unlink(self.coverfile) + + def test_cover_files_written_no_highlight(self): + argv = '-m trace --count'.split() + [self.codefile] + status, stdout, stderr = assert_python_ok(*argv) + self.assertTrue(os.path.exists(self.coverfile)) + with open(self.coverfile) as f: + self.assertEqual(f.read(), + " 1: x = 42\n" + " 1: if []:\n" + " print('unreachable')\n" + ) + + def test_cover_files_written_with_highlight(self): + argv = '-m trace --count --missing'.split() + [self.codefile] + status, stdout, stderr = assert_python_ok(*argv) + self.assertTrue(os.path.exists(self.coverfile)) + with open(self.coverfile) as f: + self.assertEqual(f.read(), textwrap.dedent('''\ + 1: x = 42 + 1: if []: + >>>>>> print('unreachable') + ''')) + class TestCommandLine(unittest.TestCase): def test_failures(self): diff --git a/Lib/trace.py b/Lib/trace.py index ade7616..16c3494 100755 --- a/Lib/trace.py +++ b/Lib/trace.py @@ -73,9 +73,6 @@ def _unsettrace(): PRAGMA_NOCOVER = "#pragma NO COVER" -# Simple rx to find lines with no code. -rx_blank = re.compile(r'^\s*(#.*)?$') - class _Ignore: def __init__(self, modules=None, dirs=None): self._mods = set() if not modules else set(modules) @@ -278,16 +275,15 @@ class CoverageResults: lnotab = _find_executable_linenos(filename) else: lnotab = {} - if lnotab: - source = linecache.getlines(filename) - coverpath = os.path.join(dir, modulename + ".cover") - with open(filename, 'rb') as fp: - encoding, _ = tokenize.detect_encoding(fp.readline) - n_hits, n_lines = self.write_results_file(coverpath, source, - lnotab, count, encoding) - if summary and n_lines: - percent = int(100 * n_hits / n_lines) - sums[modulename] = n_lines, percent, modulename, filename + source = linecache.getlines(filename) + coverpath = os.path.join(dir, modulename + ".cover") + with open(filename, 'rb') as fp: + encoding, _ = tokenize.detect_encoding(fp.readline) + n_hits, n_lines = self.write_results_file(coverpath, source, + lnotab, count, encoding) + if summary and n_lines: + percent = int(100 * n_hits / n_lines) + sums[modulename] = n_lines, percent, modulename, filename if summary and sums: @@ -306,6 +302,7 @@ class CoverageResults: def write_results_file(self, path, lines, lnotab, lines_hit, encoding=None): """Return a coverage results file in path.""" + # ``lnotab`` is a dict of executable lines, or a line number "table" try: outfile = open(path, "w", encoding=encoding) @@ -324,17 +321,13 @@ class CoverageResults: outfile.write("%5d: " % lines_hit[lineno]) n_hits += 1 n_lines += 1 - elif rx_blank.match(line): - outfile.write(" ") - else: - # lines preceded by no marks weren't hit - # Highlight them if so indicated, unless the line contains + elif lineno in lnotab and not PRAGMA_NOCOVER in line: + # Highlight never-executed lines, unless the line contains # #pragma: NO COVER - if lineno in lnotab and not PRAGMA_NOCOVER in line: - outfile.write(">>>>>> ") - n_lines += 1 - else: - outfile.write(" ") + outfile.write(">>>>>> ") + n_lines += 1 + else: + outfile.write(" ") outfile.write(line.expandtabs(8)) return n_hits, n_lines diff --git a/Misc/NEWS.d/next/Library/2017-10-31.bpo-31908.g4xh8x.rst b/Misc/NEWS.d/next/Library/2017-10-31.bpo-31908.g4xh8x.rst new file mode 100644 index 0000000..700bc69 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-10-31.bpo-31908.g4xh8x.rst @@ -0,0 +1,3 @@ +Fix output of cover files for ``trace`` module command-line tool. +Previously emitted cover files only when ``--missing`` option was used. +Patch by Michael Selik. \ No newline at end of file -- cgit v0.12