diff options
-rw-r--r-- | CHANGES.txt | 2 | ||||
-rw-r--r-- | coverage/annotate.py | 7 | ||||
-rw-r--r-- | coverage/control.py | 7 | ||||
-rw-r--r-- | coverage/misc.py | 2 | ||||
-rw-r--r-- | coverage/parser.py | 23 | ||||
-rw-r--r-- | coverage/results.py | 2 | ||||
-rw-r--r-- | coverage/xmlreport.py | 2 | ||||
-rw-r--r-- | tests/coveragetest.py | 7 |
8 files changed, 33 insertions, 19 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index ddb0e47..6de9512 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -8,6 +8,8 @@ Change history for Coverage.py - Fixed the mechanism for finding OS-installed static files for the HTML report so that it will actually find OS-installed static files. +- Improved the speed of HTML report generation by about 10%. + 3.7 --- 6 October 2013 ---------------------- diff --git a/coverage/annotate.py b/coverage/annotate.py index b7f32c1..5c39678 100644 --- a/coverage/annotate.py +++ b/coverage/annotate.py @@ -2,6 +2,7 @@ import os, re +from coverage.backward import sorted # pylint: disable=W0622 from coverage.report import Reporter class AnnotateReporter(Reporter): @@ -59,9 +60,9 @@ class AnnotateReporter(Reporter): dest_file = filename + ",cover" dest = open(dest_file, 'w') - statements = analysis.statements - missing = analysis.missing - excluded = analysis.excluded + statements = sorted(analysis.statements) + missing = sorted(analysis.missing) + excluded = sorted(analysis.excluded) lineno = 0 i = 0 diff --git a/coverage/control.py b/coverage/control.py index 4b76121..f75a3dd 100644 --- a/coverage/control.py +++ b/coverage/control.py @@ -572,8 +572,11 @@ class coverage(object): """ analysis = self._analyze(morf) return ( - analysis.filename, analysis.statements, analysis.excluded, - analysis.missing, analysis.missing_formatted() + analysis.filename, + sorted(analysis.statements), + sorted(analysis.excluded), + sorted(analysis.missing), + analysis.missing_formatted(), ) def _analyze(self, it): diff --git a/coverage/misc.py b/coverage/misc.py index 2d2662d..40fe8f7 100644 --- a/coverage/misc.py +++ b/coverage/misc.py @@ -38,6 +38,8 @@ def format_lines(statements, lines): i = 0 j = 0 start = None + statements = sorted(statements) + lines = sorted(lines) while i < len(statements) and j < len(lines): if statements[i] == lines[j]: if start == None: diff --git a/coverage/parser.py b/coverage/parser.py index 581c851..7459eef 100644 --- a/coverage/parser.py +++ b/coverage/parser.py @@ -175,16 +175,18 @@ class CodeParser(object): first_line = line return first_line - def first_lines(self, lines, ignore=None): + def first_lines(self, lines, *ignores): """Map the line numbers in `lines` to the correct first line of the statement. - Skip any line mentioned in `ignore`. + Skip any line mentioned in any of the sequences in `ignores`. - Returns a sorted list of the first lines. + Returns a set of the first lines. """ - ignore = ignore or [] + ignore = set() + for ign in ignores: + ignore.update(ign) lset = set() for l in lines: if l in ignore: @@ -192,13 +194,13 @@ class CodeParser(object): new_l = self.first_line(l) if new_l not in ignore: lset.add(new_l) - return sorted(lset) + return lset def parse_source(self): """Parse source text to find executable lines, excluded lines, etc. - Return values are 1) a sorted list of executable line numbers, and - 2) a sorted list of excluded line numbers. + Return values are 1) a set of executable line numbers, and 2) a set of + excluded line numbers. Reported line numbers are normalized to the first line of multi-line statements. @@ -215,8 +217,11 @@ class CodeParser(object): ) excluded_lines = self.first_lines(self.excluded) - ignore = excluded_lines + list(self.docstrings) - lines = self.first_lines(self.statement_starts, ignore) + lines = self.first_lines( + self.statement_starts, + excluded_lines, + self.docstrings + ) return lines, excluded_lines diff --git a/coverage/results.py b/coverage/results.py index 2d13e81..db6df0d 100644 --- a/coverage/results.py +++ b/coverage/results.py @@ -26,7 +26,7 @@ class Analysis(object): # Identify missing statements. executed = self.coverage.data.executed_lines(self.filename) exec1 = self.parser.first_lines(executed) - self.missing = sorted(set(self.statements) - set(exec1)) + self.missing = self.statements - exec1 if self.coverage.data.has_arcs(): self.no_branch = self.parser.lines_matching( diff --git a/coverage/xmlreport.py b/coverage/xmlreport.py index 7837524..26ac02a 100644 --- a/coverage/xmlreport.py +++ b/coverage/xmlreport.py @@ -117,7 +117,7 @@ class XmlReporter(Reporter): branch_stats = analysis.branch_stats() # For each statement, create an XML 'line' element. - for line in analysis.statements: + for line in sorted(analysis.statements): xline = self.xml_out.createElement("line") xline.setAttribute("number", str(line)) diff --git a/tests/coveragetest.py b/tests/coveragetest.py index 9f7c79c..f6680cc 100644 --- a/tests/coveragetest.py +++ b/tests/coveragetest.py @@ -355,20 +355,21 @@ class CoverageTest(TestCase): # Get the analysis results, and check that they are right. analysis = cov._analyze(mod) + statements = sorted(analysis.statements) if lines is not None: if type(lines[0]) == type(1): # lines is just a list of numbers, it must match the statements # found in the code. - self.assertEqual(analysis.statements, lines) + self.assertEqual(statements, lines) else: # lines is a list of possible line number lists, one of them # must match. for line_list in lines: - if analysis.statements == line_list: + if statements == line_list: break else: self.fail("None of the lines choices matched %r" % - analysis.statements + statements ) if type(missing) == type(""): |