summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2019-06-18 17:42:12 -0400
committerNed Batchelder <ned@nedbatchelder.com>2019-06-19 08:54:22 -0400
commite126d4720a4abad33a772734e0a0b40403b974d2 (patch)
tree098224fea6d35158f275b1053fd1debfa889a968
parent8c767f2888a931e7eaad942e875e127a776e9456 (diff)
downloadpython-coveragepy-git-e126d4720a4abad33a772734e0a0b40403b974d2.tar.gz
Split HtmlReporter to get at data
-rw-r--r--coverage/html.py154
-rw-r--r--coverage/htmlfiles/pyfile.html8
2 files changed, 87 insertions, 75 deletions
diff --git a/coverage/html.py b/coverage/html.py
index 0ad56063..78c982a2 100644
--- a/coverage/html.py
+++ b/coverage/html.py
@@ -74,6 +74,72 @@ def write_html(fname, html):
fout.write(html.encode('ascii', 'xmlcharrefreplace'))
+class HtmlDataGeneration(object):
+ """Generate structured data to be turned into HTML reports."""
+
+ def __init__(self, cov):
+ self.coverage = cov
+ self.config = self.coverage.config
+ self.has_arcs = self.coverage.get_data().has_arcs()
+
+ def data_for_file(self, fr, analysis):
+ """Produce the data needed for one file's report."""
+ if self.has_arcs:
+ missing_branch_arcs = analysis.missing_branch_arcs()
+ arcs_executed = analysis.arcs_executed()
+
+ contexts_by_lineno = collections.defaultdict(list)
+ if self.config.show_contexts:
+ # Lookup line number contexts.
+ contexts_by_lineno = analysis.data.contexts_by_lineno(fr.filename)
+
+ lines = []
+
+ for lineno, tokens in enumerate(fr.source_token_lines(), start=1):
+ # Figure out how to mark this line.
+ category = None
+ short_annotations = []
+ long_annotations = []
+
+ if lineno in analysis.excluded:
+ category = 'exc'
+ elif lineno in analysis.missing:
+ category = 'mis'
+ elif self.has_arcs and lineno in missing_branch_arcs:
+ category = 'par'
+ for b in missing_branch_arcs[lineno]:
+ if b < 0:
+ short_annotations.append("exit")
+ else:
+ short_annotations.append(b)
+ long_annotations.append(fr.missing_arc_description(lineno, b, arcs_executed))
+ elif lineno in analysis.statements:
+ category = 'run'
+
+ if self.config.show_contexts:
+ contexts = sorted(filter(None, contexts_by_lineno[lineno]))
+ else:
+ contexts = None
+
+ lines.append(SimpleNamespace(
+ tokens=tokens,
+ number=lineno,
+ category=category,
+ statement=(lineno in analysis.statements),
+ contexts=contexts,
+ short_annotations=short_annotations,
+ long_annotations=long_annotations,
+ ))
+
+ file_data = SimpleNamespace(
+ relative_filename=fr.relative_filename(),
+ nums=analysis.numbers,
+ lines=lines,
+ )
+
+ return file_data
+
+
class HtmlReporter(object):
"""HTML reporting."""
@@ -91,12 +157,6 @@ class HtmlReporter(object):
("keybd_open.png", ""),
]
- # These classes determine which lines are highlighted by default.
- c_run = "run hide_run"
- c_exc = "exc"
- c_mis = "mis"
- c_par = "par run hide_run"
-
def __init__(self, cov):
self.coverage = cov
self.config = self.coverage.config
@@ -116,28 +176,32 @@ class HtmlReporter(object):
self.file_summaries = []
self.all_files_nums = []
self.incr = IncrementalChecker(self.directory)
+ self.datagen = HtmlDataGeneration(self.coverage)
self.totals = Numbers()
self.template_globals = {
# Functions available in the templates.
'escape': escape,
'pair': pair,
- 'title': title,
'len': len,
# Constants for this report.
'__url__': coverage.__url__,
'__version__': coverage.__version__,
+ 'title': title,
'time_stamp': datetime.datetime.now().strftime('%Y-%m-%d %H:%M'),
'extra_css': self.extra_css,
'has_arcs': self.has_arcs,
'show_contexts': self.config.show_contexts,
# Constants for all reports.
- 'c_exc': self.c_exc,
- 'c_mis': self.c_mis,
- 'c_par': self.c_par,
- 'c_run': self.c_run,
+ # These css classes determine which lines are highlighted by default.
+ 'category': {
+ 'exc': 'exc',
+ 'mis': 'mis',
+ 'par': 'par run hide_run',
+ 'run': 'run hide_run',
+ }
}
self.pyfile_html_source = read_data("pyfile.html")
self.source_tmpl = Templite(self.pyfile_html_source, self.template_globals)
@@ -211,7 +275,7 @@ class HtmlReporter(object):
return
# Write the HTML page for this file.
- file_data = self.data_for_file(fr, analysis)
+ file_data = self.datagen.data_for_file(fr, analysis)
for ldata in file_data.lines:
# Build the HTML for the line.
html = []
@@ -250,6 +314,13 @@ class HtmlReporter(object):
else:
ldata.annotate_long = None
+ css_classes = []
+ if ldata.statement:
+ css_classes.append("stm")
+ if ldata.category:
+ css_classes.append(self.template_globals['category'][ldata.category])
+ ldata.css_class = ' '.join(css_classes) or "pln"
+
html = self.source_tmpl.render(file_data.__dict__)
write_html(html_path, html)
@@ -262,65 +333,6 @@ class HtmlReporter(object):
self.file_summaries.append(index_info)
self.incr.set_index_info(rootname, index_info)
- def data_for_file(self, fr, analysis):
- """Produce the data needed for one file's report."""
- if self.has_arcs:
- missing_branch_arcs = analysis.missing_branch_arcs()
- arcs_executed = analysis.arcs_executed()
-
- contexts_by_lineno = collections.defaultdict(list)
- if self.config.show_contexts:
- # Lookup line number contexts.
- contexts_by_lineno = analysis.data.contexts_by_lineno(fr.filename)
-
- lines = []
-
- for lineno, tokens in enumerate(fr.source_token_lines(), start=1):
- # Figure out how to mark this line.
- css_classes = []
- short_annotations = []
- long_annotations = []
-
- if lineno in analysis.statements:
- css_classes.append("stm")
-
- if lineno in analysis.excluded:
- css_classes.append(self.c_exc)
- elif lineno in analysis.missing:
- css_classes.append(self.c_mis)
- elif self.has_arcs and lineno in missing_branch_arcs:
- css_classes.append(self.c_par)
- for b in missing_branch_arcs[lineno]:
- if b < 0:
- short_annotations.append("exit")
- else:
- short_annotations.append(b)
- long_annotations.append(fr.missing_arc_description(lineno, b, arcs_executed))
- elif lineno in analysis.statements:
- css_classes.append(self.c_run)
-
- if self.config.show_contexts:
- contexts = sorted(filter(None, contexts_by_lineno[lineno]))
- else:
- contexts = None
-
- lines.append(SimpleNamespace(
- tokens=tokens,
- number=lineno,
- css_class=' '.join(css_classes) or "pln",
- contexts=contexts,
- short_annotations=short_annotations,
- long_annotations=long_annotations,
- ))
-
- file_data = SimpleNamespace(
- relative_filename=fr.relative_filename(),
- nums=analysis.numbers,
- lines=lines,
- )
-
- return file_data
-
def index_file(self):
"""Write the index.html file for this report."""
index_tmpl = Templite(read_data("index.html"), self.template_globals)
diff --git a/coverage/htmlfiles/pyfile.html b/coverage/htmlfiles/pyfile.html
index 72cf77c9..d4a86ff3 100644
--- a/coverage/htmlfiles/pyfile.html
+++ b/coverage/htmlfiles/pyfile.html
@@ -33,12 +33,12 @@
<h2 class="stats">
{{nums.n_statements}} statements &nbsp;
- <span class="{{c_run}} shortkey_r button_toggle_run">{{nums.n_executed}} run</span>
- <span class="{{c_mis}} shortkey_m button_toggle_mis">{{nums.n_missing}} missing</span>
- <span class="{{c_exc}} shortkey_x button_toggle_exc">{{nums.n_excluded}} excluded</span>
+ <span class="{{category.run}} shortkey_r button_toggle_run">{{nums.n_executed}} run</span>
+ <span class="{{category.mis}} shortkey_m button_toggle_mis">{{nums.n_missing}} missing</span>
+ <span class="{{category.exc}} shortkey_x button_toggle_exc">{{nums.n_excluded}} excluded</span>
{% if has_arcs %}
- <span class="{{c_par}} shortkey_p button_toggle_par">{{nums.n_partial_branches}} partial</span>
+ <span class="{{category.par}} shortkey_p button_toggle_par">{{nums.n_partial_branches}} partial</span>
{% endif %}
</h2>
</div>