summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.txt2
-rw-r--r--coverage/annotate.py7
-rw-r--r--coverage/control.py7
-rw-r--r--coverage/misc.py2
-rw-r--r--coverage/parser.py23
-rw-r--r--coverage/results.py2
-rw-r--r--coverage/xmlreport.py2
-rw-r--r--tests/coveragetest.py7
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(""):