diff --git a/Makefile b/Makefile
index 2c32b3b9b..5f0d49278 100644
--- a/Makefile
+++ b/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
diff --git a/misc/figleaf2html b/misc/figleaf2html
new file mode 100644
index 000000000..9157f8131
--- /dev/null
+++ b/misc/figleaf2html
@@ -0,0 +1,3 @@
+#! /usr/bin/env python
+from allmydata.util import figleaf_htmlizer
+figleaf_htmlizer.main()
diff --git a/src/allmydata/util/figleaf_htmlizer.py b/src/allmydata/util/figleaf_htmlizer.py
new file mode 100644
index 000000000..63a7960db
--- /dev/null
+++ b/src/allmydata/util/figleaf_htmlizer.py
@@ -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('%4d. %s' % (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: %s
\n' % (k,))
+ html_outfp.write('file stats: %d lines, %d executed: %.1f%% covered\n' % (n_lines, n_covered, pcnt))
+
+ html_outfp.write('
\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('figleaf code coverage report \n') + index_fp.write('Summary
%d files total: %d files > 90%%, %d files > 75%%, %d files > 50%%' % (len(pcnts), len(pcnt_90), len(pcnt_75), len(pcnt_50))) + index_fp.write('
Filename | # lines | # covered | % covered |
---|---|---|---|
totals: | %d | %d | %.1f%% |
%s | %d | %d | %.1f |