mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-02-04 02:00:59 +00:00
move figleaf2html and figleaf_htmlizer.py into our tree, for easier customization
This commit is contained in:
parent
f97eec893e
commit
e8ee3365ef
3
Makefile
3
Makefile
@ -36,7 +36,8 @@ test-figleaf:
|
||||
$(PP) trial --reporter=bwverbose-figleaf $(TEST)
|
||||
|
||||
figleaf-output:
|
||||
figleaf2html -d coverage-html -x src/allmydata/test/figleaf.excludes
|
||||
$(PP) python misc/figleaf2html -d coverage-html -x src/allmydata/test/figleaf.excludes
|
||||
@echo "now point your browser at coverage-html/index.html"
|
||||
# after doing test-figleaf and figleaf-output, point your browser at
|
||||
# coverage-html/index.html
|
||||
|
||||
|
3
misc/figleaf2html
Normal file
3
misc/figleaf2html
Normal file
@ -0,0 +1,3 @@
|
||||
#! /usr/bin/env python
|
||||
from allmydata.util import figleaf_htmlizer
|
||||
figleaf_htmlizer.main()
|
211
src/allmydata/util/figleaf_htmlizer.py
Normal file
211
src/allmydata/util/figleaf_htmlizer.py
Normal file
@ -0,0 +1,211 @@
|
||||
#! /usr/bin/env python
|
||||
import sys
|
||||
import figleaf
|
||||
from cPickle import load
|
||||
import os
|
||||
import re
|
||||
|
||||
from optparse import OptionParser
|
||||
|
||||
import logging
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
logger = logging.getLogger('figleaf.htmlizer')
|
||||
|
||||
def read_exclude_patterns(f):
|
||||
if not f:
|
||||
return []
|
||||
exclude_patterns = []
|
||||
|
||||
fp = open(f)
|
||||
for line in fp:
|
||||
line = line.rstrip()
|
||||
if line and not line.startswith('#'):
|
||||
pattern = re.compile(line)
|
||||
exclude_patterns.append(pattern)
|
||||
|
||||
return exclude_patterns
|
||||
|
||||
def report_as_html(coverage, directory, exclude_patterns=[], ):
|
||||
### now, output.
|
||||
|
||||
keys = coverage.keys()
|
||||
info_dict = {}
|
||||
for k in keys:
|
||||
skip = False
|
||||
for pattern in exclude_patterns:
|
||||
if pattern.search(k):
|
||||
logger.debug('SKIPPING %s -- matches exclusion pattern' % k)
|
||||
skip = True
|
||||
break
|
||||
|
||||
if skip:
|
||||
continue
|
||||
|
||||
if k.endswith('figleaf.py'):
|
||||
continue
|
||||
|
||||
if not k.startswith("/"):
|
||||
continue
|
||||
|
||||
try:
|
||||
pyfile = open(k)
|
||||
# print 'opened', k
|
||||
except IOError:
|
||||
logger.warning('CANNOT OPEN: %s' % k)
|
||||
continue
|
||||
|
||||
try:
|
||||
lines = figleaf.get_lines(pyfile)
|
||||
except KeyboardInterrupt:
|
||||
raise
|
||||
except Exception, e:
|
||||
pyfile.close()
|
||||
logger.warning('ERROR: %s %s' % (k, str(e)))
|
||||
continue
|
||||
|
||||
# ok, got all the info. now annotate file ==> html.
|
||||
|
||||
covered = coverage[k]
|
||||
n_covered = n_lines = 0
|
||||
|
||||
pyfile = open(k)
|
||||
output = []
|
||||
for i, line in enumerate(pyfile):
|
||||
is_covered = False
|
||||
is_line = False
|
||||
|
||||
i += 1
|
||||
|
||||
if i in covered:
|
||||
is_covered = True
|
||||
|
||||
n_covered += 1
|
||||
n_lines += 1
|
||||
elif i in lines:
|
||||
is_line = True
|
||||
|
||||
n_lines += 1
|
||||
|
||||
color = 'black'
|
||||
if is_covered:
|
||||
color = 'green'
|
||||
elif is_line:
|
||||
color = 'red'
|
||||
|
||||
line = escape_html(line.rstrip())
|
||||
output.append('<font color="%s">%4d. %s</font>' % (color, i, line.rstrip()))
|
||||
|
||||
try:
|
||||
pcnt = n_covered * 100. / n_lines
|
||||
except ZeroDivisionError:
|
||||
pcnt = 100
|
||||
info_dict[k] = (n_lines, n_covered, pcnt)
|
||||
|
||||
html_outfile = make_html_filename(os.path.basename(k))
|
||||
html_outfp = open(os.path.join(directory, html_outfile), 'w')
|
||||
html_outfp.write('source file: <b>%s</b><br>\n' % (k,))
|
||||
html_outfp.write('file stats: <b>%d lines, %d executed: %.1f%% covered</b>\n' % (n_lines, n_covered, pcnt))
|
||||
|
||||
html_outfp.write('<pre>\n')
|
||||
html_outfp.write("\n".join(output))
|
||||
html_outfp.close()
|
||||
|
||||
### print a summary, too.
|
||||
|
||||
info_dict_items = info_dict.items()
|
||||
|
||||
def sort_by_pcnt(a, b):
|
||||
a = a[1][2]
|
||||
b = b[1][2]
|
||||
|
||||
return -cmp(a,b)
|
||||
info_dict_items.sort(sort_by_pcnt)
|
||||
|
||||
summary_lines = sum([ v[0] for (k, v) in info_dict_items])
|
||||
summary_cover = sum([ v[1] for (k, v) in info_dict_items])
|
||||
|
||||
summary_pcnt = 100
|
||||
if summary_lines:
|
||||
summary_pcnt = float(summary_cover) * 100. / float(summary_lines)
|
||||
|
||||
|
||||
pcnts = [ float(v[1]) * 100. / float(v[0]) for (k, v) in info_dict_items if v[0] ]
|
||||
pcnt_90 = [ x for x in pcnts if x >= 90 ]
|
||||
pcnt_75 = [ x for x in pcnts if x >= 75 ]
|
||||
pcnt_50 = [ x for x in pcnts if x >= 50 ]
|
||||
|
||||
index_fp = open('%s/index.html' % (directory,), 'w')
|
||||
index_fp.write('<title>figleaf code coverage report</title>\n')
|
||||
index_fp.write('<h2>Summary</h2> %d files total: %d files > 90%%, %d files > 75%%, %d files > 50%%<p>' % (len(pcnts), len(pcnt_90), len(pcnt_75), len(pcnt_50)))
|
||||
index_fp.write('<table border=1><tr><th>Filename</th><th># lines</th><th># covered</th><th>% covered</th></tr>\n')
|
||||
index_fp.write('<tr><td><b>totals:</b></td><td><b>%d</b></td><td><b>%d</b></td><td><b>%.1f%%</b></td></tr><tr></tr>\n' % (summary_lines, summary_cover, summary_pcnt,))
|
||||
|
||||
for filename, (n_lines, n_covered, percent_covered,) in info_dict_items:
|
||||
html_outfile = make_html_filename(os.path.basename(filename))
|
||||
|
||||
index_fp.write('<tr><td><a href="./%s">%s</a></td><td>%d</td><td>%d</td><td>%.1f</td></tr>\n' % (html_outfile, filename, n_lines, n_covered, percent_covered,))
|
||||
|
||||
index_fp.write('</table>\n')
|
||||
index_fp.close()
|
||||
|
||||
logger.info('reported on %d file(s) total\n' % len(info_dict))
|
||||
return len(info_dict)
|
||||
|
||||
def prepare_reportdir(dirname='html'):
|
||||
try:
|
||||
os.mkdir(dirname)
|
||||
except OSError: # already exists
|
||||
pass
|
||||
|
||||
def make_html_filename(orig):
|
||||
orig = os.path.splitdrive(orig)[1].replace('_', '__')
|
||||
return orig.replace(os.path.sep, '_') + '.html'
|
||||
|
||||
def escape_html(s):
|
||||
s = s.replace("&", "&")
|
||||
s = s.replace("<", "<")
|
||||
s = s.replace(">", ">")
|
||||
s = s.replace('"', """)
|
||||
return s
|
||||
|
||||
def main():
|
||||
###
|
||||
|
||||
option_parser = OptionParser()
|
||||
|
||||
option_parser.add_option('-x', '--exclude-patterns', action="store",
|
||||
dest="exclude_patterns_file",
|
||||
help="file containing regexp patterns to exclude")
|
||||
|
||||
option_parser.add_option('-d', '--output-directory', action='store',
|
||||
dest="output_dir",
|
||||
default = "html",
|
||||
help="directory for HTML output")
|
||||
|
||||
option_parser.add_option('-q', '--quiet', action='store_true', dest='quiet', help='Suppress all but error messages')
|
||||
|
||||
(options, args) = option_parser.parse_args()
|
||||
|
||||
if options.quiet:
|
||||
logging.disable(logging.DEBUG)
|
||||
|
||||
### load
|
||||
|
||||
if not args:
|
||||
args = ['.figleaf']
|
||||
|
||||
coverage = {}
|
||||
for filename in args:
|
||||
logger.debug("loading coverage info from '%s'\n" % (filename,))
|
||||
d = figleaf.read_coverage(filename)
|
||||
coverage = figleaf.combine_coverage(coverage, d)
|
||||
|
||||
if not coverage:
|
||||
logger.warning('EXITING -- no coverage info!\n')
|
||||
sys.exit(-1)
|
||||
|
||||
### make directory
|
||||
prepare_reportdir(options.output_dir)
|
||||
report_as_html(coverage, options.output_dir, read_exclude_patterns(options.exclude_patterns_file))
|
||||
|
Loading…
x
Reference in New Issue
Block a user