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 &gt; '
-                   '90%%, %d files &gt; 75%%, %d files &gt; 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("&", "&amp;")
-    s = s.replace("<", "&lt;")
-    s = s.replace(">", "&gt;")
-    s = s.replace('"', "&quot;")
-    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 &gt; '
+                       '90%%, %d files &gt; 75%%, %d files &gt; 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("&", "&amp;")
+        s = s.replace("<", "&lt;")
+        s = s.replace(">", "&gt;")
+        s = s.replace('"', "&quot;")
+        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