General cleanup of becommands/html.py
authorW. Trevor King <wking@drexel.edu>
Tue, 20 Oct 2009 01:36:25 +0000 (21:36 -0400)
committerW. Trevor King <wking@drexel.edu>
Tue, 20 Oct 2009 01:36:25 +0000 (21:36 -0400)
becommands/html.py

index e965724a6530d54d0bfdf9cea335225f7e6bcf85..d94411911d74789245df2af00d01deac0b821e0c 100644 (file)
@@ -16,8 +16,7 @@
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 """Generate a static HTML dump of the current repository status"""
 from libbe import cmdutil, bugdir, bug
-#from html_data import *
-import codecs, os, re, string, time
+import codecs, os, os.path, re, string, time
 import xml.sax.saxutils, htmlentitydefs
 
 __desc__ = __doc__
@@ -28,7 +27,6 @@ def execute(args, manipulate_encodings=True):
     >>> bd = bugdir.SimpleBugDir()
     >>> os.chdir(bd.root)
     >>> execute([], manipulate_encodings=False)
-    Creating the html output in html_export
     >>> os.path.exists("./html_export")
     True
     >>> os.path.exists("./html_export/index.html")
@@ -46,8 +44,7 @@ def execute(args, manipulate_encodings=True):
     parser = get_parser()
     options, args = parser.parse_args(args)
     complete(options, args, parser)
-    cmdutil.default_complete(options, args, parser,
-                             bugid_args={0: lambda bug : bug.active==False})
+    cmdutil.default_complete(options, args, parser)
 
     if len(args) == 0:
         out_dir = options.outdir
@@ -58,37 +55,30 @@ def execute(args, manipulate_encodings=True):
             _css_file = template
         if options.verbose == True:
             print "Creating the html output in %s using %s template"%(out_dir, _css_file)
-    else:
-        out_dir = args[0]
     if len(args) > 0:
         raise cmdutil.UsageError, "Too many arguments."
 
     bd = bugdir.BugDir(from_disk=True,
                        manipulate_encodings=manipulate_encodings)
     bd.load_all_bugs()
-    status_list = bug.status_values
-    severity_list = bug.severity_values
-    st = {}
-    se = {}
-    stime = {}
     bugs_active = []
     bugs_inactive = []
-    for s in status_list:
-        st[s] = 0
-    for b in sorted(bd, reverse=True):
-        stime[b.uuid]  = b.time
-        if b.active == True:
-            bugs_active.append(b)
+    bugs = [b for b in bd]
+    bugs.sort()
+    bugs_active = [b for b in bugs if b.active == True]
+    bugs_inactive = [b for b in bugs if b.active != True]
+
+    html_gen = BEHTMLGen(bd, template, options.verbose, bd.encoding)
+    html_gen.create_output_directories(out_dir)
+    html_gen.write_css_file()
+    for b in bugs:
+        if b.active:
+            up_link = "../index.html"
         else:
-            bugs_inactive.append(b)
-        st[b.status] += 1
-    ordered_bug_list = sorted([(value,key) for (key,value) in stime.items()])
-    ordered_bug_list_in = sorted([(value,key) for (key,value) in stime.items()])
-    #open_bug_list = sorted([(value,key) for (key,value) in bugs.items()])
-
-    html_gen = BEHTMLGen(bd, template, options.verbose)
-    html_gen.create_index_file(out_dir,  st, bugs_active, ordered_bug_list, "active", bd.encoding)
-    html_gen.create_index_file(out_dir,  st, bugs_inactive, ordered_bug_list, "inactive", bd.encoding)
+            up_link = "../index_inactive.html"
+        html_gen.write_detail_file(b, up_link)
+    html_gen.write_index_file(bugs_active, "active")
+    html_gen.write_index_file(bugs_inactive, "inactive")
 
 def get_parser():
     parser = cmdutil.CmdOptionParser("be html [options]")
@@ -126,14 +116,15 @@ def escape(string):
     return "".join(chars)
 
 class BEHTMLGen():
-    def __init__(self, bd, template, verbose):
+    def __init__(self, bd, template, verbose, encoding):
         self.index_value = ""
         self.bd = bd
         self.verbose = verbose
+        self.encoding = encoding
         if template == None:
             self.template = "default"
         else:
-            self.template = template
+            self.template = os.path.abspath(os.path.expanduser(template))
 
         self.css_file = """
             body {
@@ -392,7 +383,7 @@ class BEHTMLGen():
             <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
             <head>
             <title>BugsEverywhere Issue Tracker</title>
-            <meta http-equiv="Content-Type" content="text/html; charset=%s" />
+            <meta http-equiv="Content-Type" content="text/html; charset=%(charset)s" />
             <link rel="stylesheet" href="style.css" type="text/css" />
             </head>
             <body>
@@ -404,34 +395,37 @@ class BEHTMLGen():
             <table>
 
             <tr>
-            <td class="%s"><a href="index.html">Active Bugs</a></td>
-            <td class="%s"><a href="index_inactive.html">Inactive Bugs</a></td>
+            <td class="%(active_class)s"><a href="index.html">Active Bugs</a></td>
+            <td class="%(inactive_class)s"><a href="index_inactive.html">Inactive Bugs</a></td>
             </tr>
 
             </table>
             <table class="table_bug">
             <tbody>
 
-            %s
+            %(bug_table)s
 
             </tbody>
             </table>
 
             </div>
 
-            <div class="footer">Generated by <a href="http://www.bugseverywhere.org/">BugsEverywhere</a> on %s</div>
+            <div class="footer">
+            <p>Generated by <a href="http://www.bugseverywhere.org/">
+            BugsEverywhere</a> on %(generation_time)s</p>
+            </div>
 
             </body>
             </html>
         """
 
         self.bug_line ="""
-        <tr class="%s-row">
-        <td ><a href="bugs/%s.html">%s</a></td>
-        <td ><a href="bugs/%s.html">%s</a></td>
-        <td><a href="bugs/%s.html">%s</a></td>
-        <td><a href="bugs/%s.html">%s</a></td>
-        <td><a href="bugs/%s.html">%s</a></td>
+        <tr class="%(severity)s-row">
+        <td ><a href="bugs/%(uuid)s.html">%(shortname)s</a></td>
+        <td ><a href="bugs/%(uuid)s.html">%(status)s</a></td>
+        <td><a href="bugs/%(uuid)s.html">%(severity)s</a></td>
+        <td><a href="bugs/%(uuid)s.html">%(summary)s</a></td>
+        <td><a href="bugs/%(uuid)s.html">%(time_string)s</a></td>
         </tr>
         """
 
@@ -441,7 +435,7 @@ class BEHTMLGen():
         <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
         <head>
         <title>BugsEverywhere Issue Tracker</title>
-        <meta http-equiv="Content-Type" content="text/html; charset=%s" />
+        <meta http-equiv="Content-Type" content="text/html; charset=%(charset)s" />
         <link rel="stylesheet" href="../style.css" type="text/css" />
         </head>
         <body>
@@ -449,18 +443,18 @@ class BEHTMLGen():
 
         <div class="main">
         <h1>BugsEverywhere Bug List</h1>
-        <h5><a href="%%s">Back to Index</a></h5>
-        <h2>Bug: _bug_id_</h2>
+        <h5><a href="%(up_link)s">Back to Index</a></h5>
+        <h2>Bug: %(shortname)s</h2>
         <table >
         <tbody>
 
-        %s
+        %(bug_lines)s
 
-        %s
+        %(comment_lines)s
         </tbody>
         </table>
         </div>
-        <h5><a href="%s">Back to Index</a></h5>
+        <h5><a href="%(up_link)s">Back to Index</a></h5>
         <div class="footer">Generated by <a href="http://www.bugseverywhere.org/">BugsEverywhere</a>.</div>
         </body>
         </html>
@@ -469,7 +463,7 @@ class BEHTMLGen():
 
         self.detail_line ="""
         <tr>
-        <td align="right">%s</td><td>%s</td>
+        <td align="right">%(label)s :</td><td>%(value)s</td>
         </tr>
         """
 
@@ -479,137 +473,72 @@ class BEHTMLGen():
         <td align="right">Comments:
         </td>
         <td>
-        %s
+        %(comment)s
         </td>
         </tr>
         """
 
         if template != None:
+            for filename,attr in [('style.css','css_file'),
+                                  ('index_file.tpl','index_file'),
+                                  ('detail_file.tpl','detail_file'),
+                                  ('comment_section.tpl','comment_section')]:
+                fullpath = os.path.join(self.template, filename)
+                if os.path.exists(fullpath):
+                    f = codecs.open(fullpath, "r", self.encoding)
+                    setattr(self, attr, f.read())
+                    f.close()
+
+    def create_output_directories(self, out_dir):
+        if self.verbose:
+            print "Creating output directories"
+        self.out_dir = os.path.abspath(os.path.expanduser(out_dir))
+        if not os.path.exists(self.out_dir):
             try:
-                FI = open("%s/style.css"%self.template)
-                self.css_file = FI.read()
-                FI.close()
-            except:
-                pass
-            try:
-                FI = open("%s/index_file.tpl"%self.template)
-                self.index_first = FI.read()
-                FI.close()
-            except:
-                pass
-
-            try:
-                FI.open("%s/detail_file.tpl"%self.template)
-                self.detail_first = FI.read()
-                FI.close()
-            except:
-                pass
-            try:
-                FI.open("%s/comment_section.tpl"%self.template)
-                self.comment_section = FI.read()
-                FI.close()
-            except:
-                pass
-
-    def create_index_file(self, out_dir_path,  summary,  bugs, ordered_bug, fileid, encoding):
-
-        try:
-            os.stat(out_dir_path)
-        except:
-            try:
-                os.mkdir(out_dir_path)
+                os.mkdir(self.out_dir)
             except:
-                raise  cmdutil.UsageError, "Cannot create output directory."
-        try:
-            FO = codecs.open(out_dir_path+"/style.css", "w", encoding)
-            FO.write(self.css_file)
-            FO.close()
-        except:
-            raise  cmdutil.UsageError, "Cannot create the style.css file."
-
-        try:
-            os.mkdir(out_dir_path+"/bugs")
-        except:
-            pass
-
-        try:
-            if fileid == "active":
-                if self.verbose:
-                    print "Creating active bug index..."
-                FO = codecs.open(out_dir_path+"/index.html", "w", encoding)
-            if fileid == "inactive":
-                if self.verbose:
-                    print "Creating inactive bug index..."
-                FO = codecs.open(out_dir_path+"/index_inactive.html", "w", encoding)
-        except:
-            raise  cmdutil.UsageError, "Cannot create the index.html file."
-
-        c = 0
-        t = len(bugs) - 1
-        line = ""
-        for l in range(t,  -1,  -1):
-            if self.verbose:
-                print "Creating bug entry: %s"%escape(bugs[l].uuid[0:3])
-            line += self.bug_line%(escape(bugs[l].severity),
-                                  escape(bugs[l].uuid), escape(bugs[l].uuid[0:3]),
-                                  escape(bugs[l].uuid), escape(bugs[l].status),
-                                  escape(bugs[l].uuid), escape(bugs[l].severity),
-                                  escape(bugs[l].uuid), escape(bugs[l].summary),
-                                  escape(bugs[l].uuid), escape(bugs[l].time_string)
-                                  )
-            c += 1
-            if self.verbose:
-                print "\tCreating detail entry for bug: %s"%escape(bugs[l].uuid[0:3])
-            self.create_detail_file(bugs[l], out_dir_path, fileid, encoding)
-        when = time.ctime()
-
-        try:
-            if fileid == "active":
-                if self.verbose:
-                    print "Writing active bug index..."
-                FO.write(self.index_file%(encoding, 'td_sel','td_nsel', line, when))
-            if fileid == "inactive":
-                if self.verbose:
-                    print "Writing inactive bug index..."
-                FO.write(self.index_file%(encoding,'td_nsel','td_sel', line, when))
-        except:
-            raise  cmdutil.UsageError, "Cannot create the index.html file."
-
-
-    def create_detail_file(self, bug, out_dir_path, fileid, encoding):
-        f = "%s.html"%bug.uuid
-        p = out_dir_path+"/bugs/"+f
-        try:
-            FD = codecs.open(p, "w", encoding)
-        except:
-            raise  cmdutil.UsageError, "Cannot create the detail html file."
-
+                raise cmdutil.UsageError, "Cannot create output directory '%s'." % self.out_dir
+        self.out_dir_bugs = os.path.join(self.out_dir, "bugs")
+        if not os.path.exists(self.out_dir_bugs):
+            os.mkdir(self.out_dir_bugs)
+
+    def write_css_file(self):
+        if self.verbose:
+            print "Writing css file"
+        assert hasattr(self, "out_dir"), "Must run after ._create_output_directories()"
+        f = codecs.open(os.path.join(self.out_dir,"style.css"), "w", self.encoding)
+        f.write(self.css_file)
+        f.close()
+
+    def write_detail_file(self, bug, up_link):
+        if self.verbose:
+            print "\tCreating detail entry for bug: %s" % escape(self.bd.bug_shortname(bug))
+        assert hasattr(self, "out_dir_bugs"), "Must run after ._create_output_directories()"
         detail_file_ = re.sub('_bug_id_', bug.uuid[0:3], self.detail_file)
 
         bug_ = self.bd.bug_from_shortname(bug.uuid)
         bug_.load_comments(load_full=True)
-        det_line = ""
-        det_line += self.detail_line%("ID : ", bug.uuid)
-        det_line += self.detail_line%("Short name : ", escape(bug.uuid[0:3]))
-        det_line += self.detail_line%("Severity : ", escape(bug.severity))
-        det_line += self.detail_line%("Status : ", escape(bug.status))
-        det_line += self.detail_line%("Assigned : ", escape(bug.assigned))
-        det_line += self.detail_line%("Target : ", escape(bug.target))
-        det_line += self.detail_line%("Reporter : ", escape(bug.reporter))
-        det_line += self.detail_line%("Creator : ", escape(bug.creator))
-        det_line += self.detail_line%("Created : ", escape(bug.time_string))
-        det_line += self.detail_line%("Summary : ", escape(bug.summary))
-        det_line += """<tr><td colspan="2"><hr /></td></tr>"""
-
-        tr = []
-        b = ''
-        level = 0
+        detail_lines = []
+        for label,value in [('ID', bug.uuid),
+                            ('Short name', escape(self.bd.bug_shortname(bug))),
+                            ('Severity', escape(bug.severity)),
+                            ('Status', escape(bug.status)),
+                            ('Assigned', escape(bug.assigned)),
+                            ('Target', escape(bug.target)),
+                            ('Reporter', escape(bug.reporter)),
+                            ('Creator', escape(bug.creator)),
+                            ('Created', escape(bug.time_string)),
+                            ('Summary', escape(bug.summary)),
+                            ]:
+            detail_lines.append(self.detail_line % {'label':label, 'value':value})
+        detail_lines.append('<tr><td colspan="2"><hr /></td></tr>')
+
         stack = []
-        com = ""
+        comment_lines = []
         for depth,comment in bug_.comment_root.thread(flatten=False):
             while len(stack) > depth:
                 stack.pop(-1)      # pop non-parents off the stack
-                com += "</div>\n" # close non-parent <div class="comment...
+                comment_lines.append("</div>\n") # close non-parent <div class="comment...
             assert len(stack) == depth
             stack.append(comment)
             lines = ["--------- Comment ---------",
@@ -619,18 +548,58 @@ class BEHTMLGen():
                      ""]
             lines.extend(escape(comment.body).splitlines())
             if depth == 0:
-                com += '<div class="commentF">'
+                comment_lines.append('<div class="commentF">')
             else:
-                com += '<div class="comment">'
-            #FD.write("<br />\n".join(lines)+"<br />\n")
-            com += "<br />\n".join(lines)+"<br />\n"
+                comment_lines.append('<div class="comment">')
+            comment_lines.append("<br />\n".join(lines)+"<br />\n")
         while len(stack) > 0:
             stack.pop(-1)
-            com += "</div>\n" # close every remaining <div class="comment...
-        comments = self.comment_section%com
+            comment_lines.append("</div>\n") # close every remaining <div class="comment...
+        comments = self.comment_section % {'comment':'\n'.join(comment_lines)}
+
+        filename = "%s.html" % bug.uuid
+        fullpath = os.path.join(self.out_dir_bugs, filename)
+        template_info = {'charset':self.encoding,
+                         'shortname':self.bd.bug_shortname(bug),
+                         'up_link':up_link,
+                         'bug_lines':'\n'.join(detail_lines),
+                         'comment_lines':comments}
+        f = codecs.open(fullpath, "w", self.encoding)
+        f.write(detail_file_ % template_info)
+        f.close()
+
+    def write_index_file(self, bugs, fileid):
+        if self.verbose:
+            print "Writing %s index file for %d bugs" % (fileid, len(bugs))
+        assert hasattr(self, "out_dir"), "Must run after ._create_output_directories()"
+
+        bug_lines = []
+        for b in bugs:
+            if self.verbose:
+                print "Creating bug entry: %s" % escape(self.bd.bug_shortname(b))
+            template_info = {'uuid':b.uuid,
+                             'shortname':self.bd.bug_shortname(b),
+                             'status':b.status,
+                             'severity':b.severity,
+                             'summary':b.summary,
+                             'time_string':b.time_string}
+            bug_lines.append(self.bug_line % template_info)
 
         if fileid == "active":
-            FD.write(detail_file_%(encoding, "../index.html", det_line, comments, "../index.html"))
+            filename = "index.html"
+        elif fileid == "inactive":
+            filename = "index_inactive.html"
+        else:
+            raise Exception, "Unrecognized fileid: '%s'" % fileid
+        template_info = {'charset':self.encoding,
+                         'active_class':'td_sel',
+                         'inactive_class':'td_nsel',
+                         'bug_table':'\n'.join(bug_lines),
+                         'generation_time':time.ctime()}
         if fileid == "inactive":
-            FD.write(detail_file_%(encoding, "../index_inactive.html", det_line, comments, "../index_inactive.html"))
-        FD.close()
+            template_info['active_class'] = 'td_nsel'
+            template_info['inactive_class'] = 'td_sel'
+
+        f = codecs.open(os.path.join(self.out_dir, filename), "w", self.encoding)
+        f.write(self.index_file % template_info)
+        f.close()