From 6bde1b0345293862af857edb101f864565109a8f Mon Sep 17 00:00:00 2001 From: Brian Warner <warner@allmydata.com> Date: Wed, 11 Feb 2009 19:40:50 -0700 Subject: [PATCH] figleaf_htmlizer: rewrite in class form, behavior should be the same as before --- src/allmydata/util/figleaf_htmlizer.py | 432 ++++++++++++------------- 1 file changed, 216 insertions(+), 216 deletions(-) diff --git a/src/allmydata/util/figleaf_htmlizer.py b/src/allmydata/util/figleaf_htmlizer.py index 1709b45c..cf65963a 100644 --- a/src/allmydata/util/figleaf_htmlizer.py +++ b/src/allmydata/util/figleaf_htmlizer.py @@ -23,234 +23,234 @@ class RenderOptions(usage.Options): if filenames: self.filenames = list(filenames) -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=[], root=None): - ### now, output. - - keys = coverage.keys() - info_dict = {} - for k in keys: - skip = False - for pattern in exclude_patterns: - if pattern.search(k): - skip = True - break - - if skip: - continue - - if k.endswith('figleaf.py'): - continue - - display_filename = k - if root: - if not k.startswith(root): - continue - display_filename = k[len(root):] - assert not display_filename.startswith("/") - assert display_filename.endswith(".py") - display_filename = display_filename[:-3] # trim .py - display_filename = display_filename.replace("/", ".") +class Renderer: - if not k.startswith("/"): - continue + def run(self): + opts = RenderOptions() + opts.parseOptions() - try: - pyfile = open(k) - #print 'opened', k - except IOError: - continue - - try: - lines = figleaf.get_lines(pyfile) - except KeyboardInterrupt: - raise - except Exception, e: - pyfile.close() - continue + ### load - # ok, got all the info. now annotate file ==> html. + coverage = {} + for filename in opts.filenames: + d = figleaf.read_coverage(filename) + coverage = figleaf.combine_coverage(coverage, d) - covered = coverage[k] - n_covered = n_lines = 0 + if not coverage: + sys.exit(-1) - pyfile = open(k) - output = [] - for i, line in enumerate(pyfile): - is_covered = False - is_line = False + self.load_exclude_patterns(opts["exclude-patterns"]) + ### make directory + self.prepare_reportdir(opts["output-directory"]) + self.report_as_html(coverage, opts["output-directory"], opts["root"]) - i += 1 + def load_exclude_patterns(self, f): + self.exclude_patterns = [] + if not f: + return + for line in open(f, "r").readlines(): + line = line.rstrip() + if line and not line.startswith('#'): + self.exclude_patterns.append(re.compile(line)) - if i in covered: - is_covered = True - - n_covered += 1 - n_lines += 1 - elif i in lines: - is_line = True - - n_lines += 1 + def prepare_reportdir(self, dirname='html'): + try: + os.mkdir(dirname) + except OSError: # already exists + pass + + def report_as_html(self, coverage, directory, root=None): + ### now, output. + + keys = coverage.keys() + info_dict = {} + for k in keys: + skip = False + for pattern in self.exclude_patterns: + if pattern.search(k): + skip = True + break + + if skip: + continue - color = 'black' - if is_covered: - color = 'green' - elif is_line: - color = 'red' + if k.endswith('figleaf.py'): + continue - line = escape_html(line.rstrip()) - output.append('<font color="%s">%4d. %s</font>' % (color, i, line.rstrip())) + display_filename = k + if root: + if not k.startswith(root): + continue + display_filename = k[len(root):] + assert not display_filename.startswith("/") + assert display_filename.endswith(".py") + display_filename = display_filename[:-3] # trim .py + display_filename = display_filename.replace("/", ".") + + if not k.startswith("/"): + continue - try: - pcnt = n_covered * 100. / n_lines - except ZeroDivisionError: - pcnt = 0 - info_dict[k] = (n_lines, n_covered, pcnt, display_filename) - - html_outfile = make_html_filename(display_filename) - 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) - - def sort_by_uncovered(a, b): - a_uncovered = a[1][0] - a[1][1] - b_uncovered = b[1][0] - b[1][1] - return -cmp(a_uncovered, b_uncovered) - - info_dict_items.sort(sort_by_uncovered) - - 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 = 0 - 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 ] - - stats_fp = open('%s/stats.out' % (directory,), 'w') - stats_fp.write("total files: %d\n" % len(pcnts)) - stats_fp.write("total source lines: %d\n" % summary_lines) - stats_fp.write("total covered lines: %d\n" % summary_cover) - stats_fp.write("total uncovered lines: %d\n" % - (summary_lines - summary_cover)) - stats_fp.write("total coverage percentage: %.1f\n" % summary_pcnt) - stats_fp.close() - - ## index.html - index_fp = open('%s/index.html' % (directory,), 'w') - # summary info - 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))) - - def emit_table(items, show_totals): - index_fp.write('<table border=1><tr><th>Filename</th>' - '<th># lines</th><th># covered</th>' - '<th># uncovered</th>' - '<th>% covered</th></tr>\n') - if show_totals: - index_fp.write('<tr><td><b>totals:</b></td>' - '<td><b>%d</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_lines - summary_cover), - summary_pcnt,)) - - for filename, stuff in items: - (n_lines, n_covered, percent_covered, display_filename) = stuff - html_outfile = make_html_filename(display_filename) - - index_fp.write('<tr><td><a href="./%s">%s</a></td>' - '<td>%d</td><td>%d</td><td>%d</td><td>%.1f</td>' - '</tr>\n' - % (html_outfile, display_filename, n_lines, - n_covered, (n_lines - n_covered), - percent_covered,)) - - index_fp.write('</table>\n') - - # sorted by number of lines that aren't covered - index_fp.write('<h3>Sorted by Lines Uncovered</h3>\n') - emit_table(info_dict_items, True) - - # sorted by module name - index_fp.write('<h3>Sorted by Module Name (alphabetical)</h3>\n') - info_dict_items.sort() - emit_table(info_dict_items, False) - - index_fp.close() - - return len(info_dict) - -def prepare_reportdir(dirname='html'): - try: - os.mkdir(dirname) - except OSError: # already exists - pass - -def make_html_filename(orig): - return orig + ".html" - -def escape_html(s): - s = s.replace("&", "&") - s = s.replace("<", "<") - s = s.replace(">", ">") - s = s.replace('"', """) - return s + try: + pyfile = open(k) + #print 'opened', k + except IOError: + continue -def main(): - opts = RenderOptions() - opts.parseOptions() + try: + lines = figleaf.get_lines(pyfile) + except KeyboardInterrupt: + raise + except Exception, e: + pyfile.close() + continue - ### load + # ok, got all the info. now annotate file ==> html. - coverage = {} - for filename in opts.filenames: - d = figleaf.read_coverage(filename) - coverage = figleaf.combine_coverage(coverage, d) + covered = coverage[k] + n_covered = n_lines = 0 - if not coverage: - sys.exit(-1) + 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 = self.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 = 0 + info_dict[k] = (n_lines, n_covered, pcnt, display_filename) + + html_outfile = self.make_html_filename(display_filename) + 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) + + def sort_by_uncovered(a, b): + a_uncovered = a[1][0] - a[1][1] + b_uncovered = b[1][0] - b[1][1] + return -cmp(a_uncovered, b_uncovered) + + info_dict_items.sort(sort_by_uncovered) + + 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 = 0 + 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 ] + + stats_fp = open('%s/stats.out' % (directory,), 'w') + stats_fp.write("total files: %d\n" % len(pcnts)) + stats_fp.write("total source lines: %d\n" % summary_lines) + stats_fp.write("total covered lines: %d\n" % summary_cover) + stats_fp.write("total uncovered lines: %d\n" % + (summary_lines - summary_cover)) + stats_fp.write("total coverage percentage: %.1f\n" % summary_pcnt) + stats_fp.close() + + ## index.html + index_fp = open('%s/index.html' % (directory,), 'w') + # summary info + 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))) + + def emit_table(items, show_totals): + index_fp.write('<table border=1><tr><th>Filename</th>' + '<th># lines</th><th># covered</th>' + '<th># uncovered</th>' + '<th>% covered</th></tr>\n') + if show_totals: + index_fp.write('<tr><td><b>totals:</b></td>' + '<td><b>%d</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_lines - summary_cover), + summary_pcnt,)) + + for filename, stuff in items: + (n_lines, n_covered, percent_covered, display_filename) = stuff + html_outfile = self.make_html_filename(display_filename) + + index_fp.write('<tr><td><a href="./%s">%s</a></td>' + '<td>%d</td><td>%d</td><td>%d</td><td>%.1f</td>' + '</tr>\n' + % (html_outfile, display_filename, n_lines, + n_covered, (n_lines - n_covered), + percent_covered,)) + + index_fp.write('</table>\n') + + # sorted by number of lines that aren't covered + index_fp.write('<h3>Sorted by Lines Uncovered</h3>\n') + emit_table(info_dict_items, True) + + # sorted by module name + index_fp.write('<h3>Sorted by Module Name (alphabetical)</h3>\n') + info_dict_items.sort() + emit_table(info_dict_items, False) + + index_fp.close() + + return len(info_dict) + + def make_html_filename(self, orig): + return orig + ".html" + + def escape_html(self, s): + s = s.replace("&", "&") + s = s.replace("<", "<") + s = s.replace(">", ">") + s = s.replace('"', """) + return s - ### make directory - prepare_reportdir(opts["output-directory"]) - report_as_html(coverage, opts["output-directory"], - read_exclude_patterns(opts["exclude-patterns"]), - opts["root"]) +def main(): + r = Renderer() + r.run() -- 2.45.2