"""HTML reporting for coverage.py"""
import os, shutil
from coverage import __version__ # pylint: disable-msg=W0611
from coverage.report import Reporter
from coverage.templite import Templite
def data_filename(fname):
"""Return the path to a data file of ours."""
return os.path.join(os.path.split(__file__)[0], fname)
def data(fname):
"""Return the contents of a data file of ours."""
return open(data_filename(fname)).read()
class HtmlReporter(Reporter):
"""HTML reporting.
"""
def __init__(self, coverage, ignore_errors=False):
super(HtmlReporter, self).__init__(coverage, ignore_errors)
self.directory = None
self.source_tmpl = Templite(data("htmlfiles/pyfile.html"), globals())
def report(self, morfs, directory=None, omit_prefixes=None):
assert directory, "must provide a directory for html reporting"
# Create the output directory if needed.
if not os.path.exists(directory):
os.makedirs(directory)
# Create the once-per-directory files.
shutil.copyfile(
data_filename("htmlfiles/style.css"),
os.path.join(directory, "style.css")
)
shutil.copyfile(
data_filename("htmlfiles/jquery-1.3.2.min.js"),
os.path.join(directory, "jquery-1.3.2.min.js")
)
# Process all the files.
self.report_files(self.html_file, morfs, directory, omit_prefixes)
def html_file(self, cu, statements, excluded, missing):
"""Generate an HTML file for one source file."""
source = cu.source_file()
source_lines = source.readlines()
n_lin = len(source_lines)
n_stm = len(statements)
n_exc = len(excluded)
n_mis = len(missing)
n_run = n_stm - n_mis
if n_stm > 0:
pc_cov = 100.0 * float(n_run) / n_stm
else:
pc_cov = 100.0
lines = []
for lineno, line in enumerate(source_lines):
lineno += 1 # enum is 0-based, lines are 1-based.
css_class = ""
if lineno in statements:
css_class += " stm"
if lineno not in missing and lineno not in excluded:
css_class += " run hide"
if lineno in excluded:
css_class += " exc"
if lineno in missing:
css_class += " mis"
lineinfo = {
'text': line,
'number': lineno,
'class': css_class.strip() or "pln"
}
lines.append(lineinfo)
html_filename = os.path.join(self.directory, cu.flat_rootname())
html_filename += ".html"
fhtml = open(html_filename, 'w')
fhtml.write(self.source_tmpl.render(locals()))
fhtml.close()
# Helpers for templates
def escape(t):
"""HTML-escape the text in t."""
return (t
.replace("&", "&").replace("<", "<").replace(">", ">")
.replace("'", "'").replace('"', """)
.replace(" ", " ")
)
def not_empty(t):
"""Make sure HTML content is not completely empty."""
return t or " "
def format_pct(p):
return "%.0f" % p