aboutsummaryrefslogtreecommitdiffstats
path: root/becommands/html.py
diff options
context:
space:
mode:
authorGianluca Montecchi <gian@grys.it>2009-10-02 23:46:24 +0200
committerGianluca Montecchi <gian@grys.it>2009-10-02 23:46:24 +0200
commitb0b3c9473e3a4b728ea72a2876e39fe41284a9ed (patch)
tree533a389e877b4b1a9c4099bb419eb221b2f12ada /becommands/html.py
parent071fef7c351c4fc23696aa6db693411b78da2edb (diff)
downloadbugseverywhere-b0b3c9473e3a4b728ea72a2876e39fe41284a9ed.tar.gz
Merged with Trevor's -rr branch
Diffstat (limited to 'becommands/html.py')
-rw-r--r--becommands/html.py214
1 files changed, 113 insertions, 101 deletions
diff --git a/becommands/html.py b/becommands/html.py
index 4835227..908c714 100644
--- a/becommands/html.py
+++ b/becommands/html.py
@@ -1,40 +1,47 @@
-# Copyright (C) 2005-2009 Aaron Bentley and Panometrics, Inc.
-# Marien Zwart <marienz@gentoo.org>
-# Thomas Gerigk <tgerigk@gmx.de>
-# W. Trevor King <wking@drexel.edu>
-# <abentley@panoramicfeedback.com>
+# Copyright (C) 2009 Gianluca Montecchi <gian@grys.it>
+# W. Trevor King <wking@drexel.edu>
#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-"""Re-open a bug"""
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 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 os, re, time, string
+import codecs, os, re, string, time
+import xml.sax.saxutils, htmlentitydefs
__desc__ = __doc__
-def execute(args, test=False):
+def execute(args, manipulate_encodings=True):
"""
>>> import os
- >>> bd = bugdir.simple_bug_dir()
+ >>> bd = bugdir.SimpleBugDir()
>>> os.chdir(bd.root)
- >>> print bd.bug_from_shortname("b").status
- closed
- >>> execute(["b"], test=True)
- >>> bd._clear_bugs()
- >>> print bd.bug_from_shortname("b").status
- open
+ >>> execute([], manipulate_encodings=False)
+ Creating the html output in html_export
+ >>> os.path.exists("./html_export")
+ True
+ >>> os.path.exists("./html_export/index.html")
+ True
+ >>> os.path.exists("./html_export/index_inactive.html")
+ True
+ >>> os.path.exists("./html_export/bugs")
+ True
+ >>> os.path.exists("./html_export/bugs/a.html")
+ True
+ >>> os.path.exists("./html_export/bugs/b.html")
+ True
+ >>> bd.cleanup()
"""
parser = get_parser()
options, args = parser.parse_args(args)
@@ -50,7 +57,8 @@ def execute(args, test=False):
if len(args) > 0:
raise cmdutil.UsageError, "Too many arguments."
- bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
+ bd = bugdir.BugDir(from_disk=True,
+ manipulate_encodings=manipulate_encodings)
bd.load_all_bugs()
status_list = bug.status_values
severity_list = bug.severity_values
@@ -61,9 +69,9 @@ def execute(args, test=False):
bugs_inactive = []
for s in status_list:
st[s] = 0
- for b in bd:
+ for b in sorted(bd, reverse=True):
stime[b.uuid] = b.time
- if b.status in ["open", "test", "unconfirmed", "assigned"]:
+ if b.active == True:
bugs_active.append(b)
else:
bugs_inactive.append(b)
@@ -73,8 +81,8 @@ def execute(args, test=False):
#open_bug_list = sorted([(value,key) for (key,value) in bugs.items()])
html_gen = BEHTMLGen(bd)
- html_gen.create_index_file(out_dir, st, bugs_active, ordered_bug_list, "active")
- html_gen.create_index_file(out_dir, st, bugs_inactive, ordered_bug_list, "inactive")
+ 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)
def get_parser():
parser = cmdutil.CmdOptionParser("be open OUTPUT_DIR")
@@ -83,7 +91,8 @@ def get_parser():
return parser
longhelp="""
-Generate a set of html pages.
+Generate a set of html pages representing the current state of the bug
+directory.
"""
def help():
@@ -94,7 +103,18 @@ def complete(options, args, parser):
if "--complete" in args:
raise cmdutil.GetCompletions() # no positional arguments for list
-
+
+def escape(string):
+ if string == None:
+ return ""
+ chars = []
+ for char in xml.sax.saxutils.escape(string):
+ codepoint = ord(char)
+ if codepoint in htmlentitydefs.codepoint2name:
+ char = "&%s;" % htmlentitydefs.codepoint2name[codepoint]
+ chars.append(char)
+ return "".join(chars)
+
class BEHTMLGen():
def __init__(self, bd):
self.index_value = ""
@@ -353,10 +373,12 @@ class BEHTMLGen():
"""
self.index_first = """
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<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=utf-8" />
+ <meta http-equiv="Content-Type" content="text/html; charset=%s" />
<link rel="stylesheet" href="style.css" type="text/css" />
</head>
<body>
@@ -368,17 +390,17 @@ 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="%%s"><a href="index.html">Active Bugs</a></td>
+ <td class="%%s"><a href="index_inactive.html">Inactive Bugs</a></td>
</tr>
</table>
- <table class=table_bug>
+ <table class="table_bug">
<tbody>
- """
+ """ % self.bd.encoding
self.bug_line ="""
- <tr class=%s-row cellspacing=1>
+ <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>
@@ -388,10 +410,12 @@ class BEHTMLGen():
"""
self.detail_first = """
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<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=utf-8" />
+ <meta http-equiv="Content-Type" content="text/html; charset=%s" />
<link rel="stylesheet" href="../style.css" type="text/css" />
</head>
<body>
@@ -399,11 +423,11 @@ class BEHTMLGen():
<div class="main">
<h1>BugsEverywhere Bug List</h1>
- <h5><a href="%s">Back to Index</a></h5>
+ <h5><a href="%%s">Back to Index</a></h5>
<h2>Bug: _bug_id_</h2>
<table >
<tbody>
- """
+ """ % self.bd.encoding
@@ -430,7 +454,7 @@ class BEHTMLGen():
self.begin_comment_section ="""
<tr>
- <td align=right>Comments:
+ <td align="right">Comments:
</td>
<td>
"""
@@ -452,7 +476,7 @@ class BEHTMLGen():
"""
- def create_index_file(self, out_dir_path, summary, bugs, ordered_bug, fileid):
+ def create_index_file(self, out_dir_path, summary, bugs, ordered_bug, fileid, encoding):
try:
os.stat(out_dir_path)
except:
@@ -461,7 +485,7 @@ class BEHTMLGen():
except:
raise cmdutil.UsageError, "Cannot create output directory."
try:
- FO = open(out_dir_path+"/style.css", "w")
+ FO = codecs.open(out_dir_path+"/style.css", "w", encoding)
FO.write(self.css_file)
FO.close()
except:
@@ -474,10 +498,10 @@ class BEHTMLGen():
try:
if fileid == "active":
- FO = open(out_dir_path+"/index.html", "w")
+ FO = codecs.open(out_dir_path+"/index.html", "w", encoding)
FO.write(self.index_first%('td_sel','td_nsel'))
if fileid == "inactive":
- FO = open(out_dir_path+"/index_inactive.html", "w")
+ FO = codecs.open(out_dir_path+"/index_inactive.html", "w", encoding)
FO.write(self.index_first%('td_nsel','td_sel'))
except:
raise cmdutil.UsageError, "Cannot create the index.html file."
@@ -485,25 +509,25 @@ class BEHTMLGen():
c = 0
t = len(bugs) - 1
for l in range(t, -1, -1):
- line = self.bug_line%(bugs[l].severity,
- bugs[l].uuid, bugs[l].uuid[0:3],
- bugs[l].uuid, bugs[l].status,
- bugs[l].uuid, bugs[l].severity,
- bugs[l].uuid, bugs[l].summary,
- bugs[l].uuid, bugs[l].time_string
- )
+ 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)
+ )
FO.write(line)
c += 1
- self.create_detail_file(bugs[l], out_dir_path, fileid)
+ self.create_detail_file(bugs[l], out_dir_path, fileid, encoding)
when = time.ctime()
FO.write(self.index_last%when)
- def create_detail_file(self, bug, out_dir_path, fileid):
+ def create_detail_file(self, bug, out_dir_path, fileid, encoding):
f = "%s.html"%bug.uuid
p = out_dir_path+"/bugs/"+f
try:
- FD = open(p, "w")
+ FD = codecs.open(p, "w", encoding)
except:
raise cmdutil.UsageError, "Cannot create the detail html file."
@@ -519,53 +543,41 @@ class BEHTMLGen():
bug_.load_comments(load_full=True)
FD.write(self.detail_line%("ID : ", bug.uuid))
- FD.write(self.detail_line%("Short name : ", bug.uuid[0:3]))
- FD.write(self.detail_line%("Severity : ", bug.severity))
- FD.write(self.detail_line%("Status : ", bug.status))
- FD.write(self.detail_line%("Assigned : ", bug.assigned))
- FD.write(self.detail_line%("Target : ", bug.target))
- FD.write(self.detail_line%("Reporter : ", bug.reporter))
- FD.write(self.detail_line%("Creator : ", bug.creator))
- FD.write(self.detail_line%("Created : ", bug.time_string))
- FD.write(self.detail_line%("Summary : ", bug.summary))
- FD.write("<tr><td colspan=2><hr></td></tr>")
+ FD.write(self.detail_line%("Short name : ", escape(bug.uuid[0:3])))
+ FD.write(self.detail_line%("Severity : ", escape(bug.severity)))
+ FD.write(self.detail_line%("Status : ", escape(bug.status)))
+ FD.write(self.detail_line%("Assigned : ", escape(bug.assigned)))
+ FD.write(self.detail_line%("Target : ", escape(bug.target)))
+ FD.write(self.detail_line%("Reporter : ", escape(bug.reporter)))
+ FD.write(self.detail_line%("Creator : ", escape(bug.creator)))
+ FD.write(self.detail_line%("Created : ", escape(bug.time_string)))
+ FD.write(self.detail_line%("Summary : ", escape(bug.summary)))
+ FD.write("<tr><td colspan=\"2\"><hr /></td></tr>")
FD.write(self.begin_comment_section)
tr = []
b = ''
level = 0
- for i in bug_.comments():
- if not isinstance(i.in_reply_to,str):
- first = True
- a = i.string_thread(flatten=False)
- d = re.split('\n',a)
- for x in range(0,len(d)):
- hr = ""
- if re.match(" *--------- Comment ---------",d[x]):
- com = """
- %s<br>
- %s<br>
- %s<br>
- %s<br>
- %s<br>
- """%(d[x+1],d[x+2],d[x+3],d[x+4],d[x+5])
- l = re.sub("--------- Comment ---------", "", d[x])
- ll = l.split(" ")
- la = l
- ba = ""
- if len(la) > level:
- FD.write("<div class='comment'>")
- if len(la) < level:
- FD.write("</div>")
- if len(la) == 0:
- if not first :
- FD.write("</div>")
- first = False
- FD.write("<div class='commentF'>")
- level = len(la)
- x += 5
- FD.write("--------- Comment ---------<p />")
- FD.write(com)
- FD.write("</div>")
+ stack = []
+ for depth,comment in bug_.comment_root.thread(flatten=False):
+ while len(stack) > depth:
+ stack.pop(-1) # pop non-parents off the stack
+ FD.write("</div>\n") # close non-parent <div class="comment...
+ assert len(stack) == depth
+ stack.append(comment)
+ lines = ["--------- Comment ---------",
+ "Name: %s" % comment.uuid,
+ "From: %s" % escape(comment.author),
+ "Date: %s" % escape(comment.date),
+ ""]
+ lines.extend(escape(comment.body).splitlines())
+ if depth == 0:
+ FD.write('<div class="commentF">')
+ else:
+ FD.write('<div class="comment">')
+ FD.write("<br />\n".join(lines)+"<br />\n")
+ while len(stack) > 0:
+ stack.pop(-1)
+ FD.write("</div>\n") # close every remaining <div class="comment...
FD.write(self.end_comment_section)
if fileid == "active":
FD.write(self.detail_last%"../index.html")
@@ -573,4 +585,4 @@ class BEHTMLGen():
FD.write(self.detail_last%"../index_inactive.html")
FD.close()
- \ No newline at end of file
+