[Xfce4-commits] <xfce-buildbot-scripts:master> Major UI changes
Enrico Tröger
noreply at xfce.org
Sat Oct 10 00:20:02 CEST 2009
Updating branch refs/heads/master
to cedc1802520b88550c8761b91e24196456c2c95d (commit)
from 62de4bbbc0be59b1658d0ad5ba73890c32b64f8a (commit)
commit cedc1802520b88550c8761b91e24196456c2c95d
Author: Enrico Tröger <enrico.troeger at uvena.de>
Date: Fri Oct 9 23:43:55 2009 +0200
Major UI changes
- Implement a very basic HTML generator
- Use the default Xfce website header and CSS files for a more unique layout
xfcebuildstatus.py | 295 +++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 236 insertions(+), 59 deletions(-)
diff --git a/xfcebuildstatus.py b/xfcebuildstatus.py
index a1ef4a6..89ffbce 100644
--- a/xfcebuildstatus.py
+++ b/xfcebuildstatus.py
@@ -40,19 +40,25 @@ template = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
- <title>Xfce Buildbots Status</title>
+ <title>${title}</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<meta name="generator" content="Geany 0.19" />
+ <link rel="stylesheet" media="screen" href="http://www.xfce.org/layout/css/layout.css" type="text/css" />
+ <link rel="stylesheet" media="screen" href="http://www.xfce.org/layout/css/front.css" type="text/css" />
<style type="text/css">
- body, p, pre, td {
- font-size: 12px;
- font-family: sans-serif;
+ ${layout_css}
+ /* link styles */
+ :link, :visited, :link:active, :link:active {
+ color: #154374;
+ text-decoration: underline;
}
- img {
- border: 0px;
+ :link:hover, :visited:hover {
+ color: #000000;
+ text-decoration: underline;
}
- a {
+ .status_link {
color: #000000;
+ text-decoration: none;
}
h1 {
margin-top: 25px;
@@ -68,13 +74,13 @@ template = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
text-align: right;
}
.status_success {
- background-color: #00ff00;
+ background-color: #8cff8c;
}
.status_failed {
- background-color: #ff0000;
+ background-color: #ff7171;
}
.status_unknown {
- background-color: #ffff00;
+ background-color: #ffff84;
}
.item {
font-weight: bold;
@@ -86,14 +92,144 @@ template = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
</style>
</head>
-<body>
-${content}
+<body id="top">
+ <div class="hidden">
+ <a href="#global-contentwrap" title="Skip site navigation" accesskey="1">Skip site navigation</a> (1)
+ <h1>Xfce Desktop Environment</h1>
+ <h4>...and everything goes faster!</h4>
+ <hr />
+ </div>
+ <div id="global-pagewrap">
+ <div id="global-page">
+ <div id="header">
+ <div id="header-logo"></div>
+ <div id="header-right">
+ <div id="header-style">
+ <h2 class="hidden">Website Layout</h2>
+ <p>Layout: <a href="?layout=normal" title="Normal layout (Min: 740px, Max: 1000px)">Normal</a> /
+ <a href="?layout=liquid" title="Fluid Layout (100% Width)">Liquid</a></p>
+ </div>
+ </div>
+ <div id="header-menu">
+ <ul>
+ <li><a href="${url}">Overview</a></li>
+ </ul>
+ </div>
+ <div id="header-white">
+ <div id="header-language">
+ <!-- TODO content? -->
+ </div>
+ </div>
+ </div>
+ <h3>${title}</h3>
+ ${content}
+ </div>
+</div>
</body>
-</html>"""
+</html>
+"""
debug_out = ''
+
+class HtmlGen(object):
+ """Very simple HTML generator"""
+ # TODO add_element is nice, but for nested elements this still needs to be improved
+
+ def __init__(self, url, layout):
+ self.html = ''
+ self.title = ''
+ self.url = url
+ if layout == 'liquid':
+ self.layout = '#global-page { width: 100%; }'
+ else:
+ self.layout = '#global-page { min-width: 760px; max-width: 1000px; width: 100%; }'
+
+ #----------------------------------------------------------------------
+ def __nonzero__(self):
+ return self.html != ''
+
+ #----------------------------------------------------------------------
+ def __str__(self):
+ return Template(template).substitute(
+ url=self.url,
+ layout_css=self.layout,
+ title=self.title,
+ content=self.html)
+
+ #----------------------------------------------------------------------
+ def add_element(self, tagname, cdata=None, attribs={}):
+ """
+ Generic function to generate a complete HTML tag element named tagname with the contents cdata.
+ If cdata is None, a single tag is created (e.g. <br /> or <hr />). If cdata is an empty string,
+ a normal tag is created with no contents (e.g. <td></td>).
+ attribs is a dictionary of tag attributes.
+
+ @param tagname (str)
+ @param cdata (str)
+ @param attribs (dict)
+ """
+ if not tagname:
+ return
+
+ if cdata == None:
+ attribs_str = ''
+ for attr, value in attribs.items():
+ attribs_str += ' %s="%s"' % (attr, value)
+ self.html += '<%s%s />\n' % (tagname, attribs_str)
+ else:
+ self.open_tag(tagname, attribs=attribs)
+ self.add_cdata(cdata)
+ self.close_tag(tagname)
+
+ #----------------------------------------------------------------------
+ def open_tag(self, tagname, attribs={}):
+ """
+ Generic function to generate a HTML tag named tagname.
+ attribs is a dictionary of tag attributes.
+
+ @param tagname (str)
+ @param attribs (dict)
+ """
+ if not tagname:
+ return
+
+ attribs_str = ''
+ for attr, value in attribs.items():
+ attribs_str += ' %s="%s"' % (attr, value)
+ self.html += '<%s%s>' % (tagname, attribs_str)
+
+ #----------------------------------------------------------------------
+ def close_tag(self, tagname):
+ """
+ Close the given tag
+
+ @param tagname (str)
+ """
+ if tagname:
+ self.html += '</%s>' % (tagname)
+
+ #----------------------------------------------------------------------
+ def add_cdata(self, cdata):
+ """
+ Simply add the passed text to the HTML content
+
+ @param cdata (str)
+ """
+ if cdata:
+ self.html += cdata
+
+ #----------------------------------------------------------------------
+ def set_title(self, title):
+ """
+ Set the document title
+
+ @param title (str)
+ """
+ self.title = title
+
+
#----------------------------------------------------------------------
def split_builder_name(input):
"""
@@ -158,33 +294,38 @@ def list_to_str(input):
return steps[0:-2]
#----------------------------------------------------------------------
-def get_build_status_html(url, input):
+def get_build_status_html(html, url, input):
"""
Create HTML code from the given input.
+ @param html (HtmlGen)
@param url (str)
@param input (dict)
- @return html code (str)
"""
- result = '<table><tr>\n<td class="modules"></td>\n'
+ html.set_title('Xfce Buildbot Status')
+ html.open_tag('table')
+ html.open_tag('tr')
+ html.add_element('td', 'Module')
for name in PLATFORM_NAMES.values():
- result += '<td>%s</td>\n' % name
- result += '</tr>\n'
+ html.add_element('td', name)
+ html.close_tag('tr')
sorted_builders = []
for x in input.items():
sorted_builders.append(x)
sorted_builders.sort(cmp=lambda x,y: cmp(x[0], y[0]))
- # TODO rewrite this code to be clean
for module_name, status in sorted_builders:
- result += '<tr>\n<td class="modules">%s</td>\n' % module_name
+ html.open_tag('tr')
+ html.add_element('td', module_name)
for name in PLATFORM_NAMES:
try:
if status[name][0] == 'success':
- result += '''<td class="status_success"><a href="%s/detail/s/%s/%d"
- title="Built revision %s on %s">%s</a></td>\n''' % \
- (url, status[name][6], status[name][3], status[name][2][:7], status[name][1], status[name][0])
+ link_url = '%s/detail/s/%s/%d' % (url, status[name][6], status[name][3])
+ title = 'Built revision %s on %s' % (status[name][2][:7], status[name][1])
+ html.open_tag('td', attribs={'class': 'status_success'})
+ html.add_element('a', status[name][0], attribs={'href':link_url, 'title':title, 'class': 'status_link'})
+ html.close_tag('td')
elif status[name][0] == 'failure':
steps = list_to_str(status[name][4])
reasons = list_to_str(status[name][5])
@@ -192,16 +333,19 @@ def get_build_status_html(url, input):
(module_name, steps, status[name][1], reasons)
if status[name][2]:
desc += ' Revision %s' % (status[name][2][:7])
- result += '<td class="status_failed"><a href="%s/detail/f/%s/%d" title="%s">%s</a></td>\n' % \
- (url, status[name][6], status[name][3], desc, status[name][0])
+ link_url = '%s/detail/f/%s/%d' % (url, status[name][6], status[name][3])
+
+ html.open_tag('td', {'class': 'status_failed'})
+ html.add_element('a', status[name][0], attribs={'href':link_url, 'title':desc, 'class': 'status_link'})
+ html.close_tag('td')
else:
- result += '<td class="status_unknown">unknown</td>\n'
+ # trigger the exception handler below
+ raise KeyError
except KeyError:
- result += '<td class="status_unknown">unknown</td>\n'
- result += '</tr>\n'
- result += '</table>\n'
+ html.add_element('td', 'unknown', attribs={'class': 'status_unknown'})
- return Template(template).substitute(content=result)
+ html.close_tag('tr')
+ html.close_tag('table')
#----------------------------------------------------------------------
def get_detail_status(url, args):
@@ -213,8 +357,8 @@ def get_detail_status(url, args):
@return status per module (dict)
"""
global debug_out
- server = ServerProxy(url)
+ server = ServerProxy(url)
try:
if args[1] == 's':
builder = server.getBuild(args[2], int(args[3]))
@@ -264,13 +408,13 @@ def format_time(duration):
return ", ".join(eta_parts)
#----------------------------------------------------------------------
-def get_detail_status_html(url, input):
+def get_detail_status_html(html, url, input):
"""
Create HTML code from the given input.
+ @param html (HtmlGen)
@param url (str)
@param input (dict)
- @return html code (str)
"""
result = ''
if input:
@@ -286,15 +430,37 @@ def get_detail_status_html(url, input):
status_class = 'status_success' if status == 'successful' else 'status_failed'
# output
- result += '<h1>Build status for "%s"</h1>\n' % module_name
- result += '<p><span class="item">Build result:</span> <span class="%s">%s</span></p>\n' % (status_class, status)
- result += '<p><span class="item">Build started:</span> %s</p>\n' % start
- result += '<p><span class="item">Build finished:</span> %s</p>\n' % end
- result += '<p><span class="item">Build duration:</span> %s</p>\n' % duration
- result += '<p><span class="item">Build reason:</span> %s</p>\n' % input['reason']
- result += '<p><span class="item">Built revision:</span> %s</p>\n' % input['revision']
- result += '<p><span class="item">Build steps:</span></p>'
- result += '<p>\n'
+ html.set_title('Build Status for "%s"' % module_name)
+
+ html.add_element('p', ' ')
+ html.open_tag('p')
+ html.add_element('span', 'Build result:', attribs={'class':'item'})
+ html.add_cdata(' ')
+ html.add_element('span', status, attribs={'class':status_class})
+ html.close_tag('p')
+ html.open_tag('p')
+ html.add_element('span', 'Build started:', attribs={'class':'item'})
+ html.add_cdata(' %s' % start)
+ html.close_tag('p')
+ html.open_tag('p')
+ html.add_element('span', 'Build finished:', attribs={'class':'item'})
+ html.add_cdata(' %s' % end)
+ html.close_tag('p')
+ html.open_tag('p')
+ html.add_element('span', 'Build duration:', attribs={'class':'item'})
+ html.add_cdata(' %s' % duration)
+ html.close_tag('p')
+ html.open_tag('p')
+ html.add_element('span', 'Build reason:', attribs={'class':'item'})
+ html.add_cdata(' %s' % input['reason'])
+ html.close_tag('p')
+ html.open_tag('p')
+ html.add_element('span', 'Build revision:', attribs={'class':'item'})
+ html.add_cdata(' %s' % input['revision'])
+ html.close_tag('p')
+ html.add_element('p', 'Build steps:', attribs={'class':'item'})
+
+ html.open_tag('p')
for step in input['steps']:
# make Samuel happy :)
if step['name'].startswith('chmod '):
@@ -302,19 +468,27 @@ def get_detail_status_html(url, input):
log_suffix = find_log(input['logs'], step['name'])
log_url = ''
if log_suffix:
- log_url = ', <a href="%s/steps/%s/logs/%s">Logs</a>' % (input['url'], log_suffix[0], log_suffix[1])
- result += '<span class="step"><span class="item">%s: %s</span> (%s%s)</span><br/>\n' % \
- (step['name'], ' '.join(step['text']), format_time(step['end'] - step['start']), log_url)
- result += '</p>\n'
- result += '<p> </p>'
- result += '<p><span class="item">More details:</span> <a href="%s">%s</a></p>\n' % (input['url'], input['url'])
+ log_url = '%s/steps/%s/logs/%s' % (input['url'], log_suffix[0], log_suffix[1])
+ html.open_tag('span', attribs={'class':'step'})
+ html.add_element('span', '%s: %s' % (step['name'], ' '.join(step['text'])), attribs={'class':'item'})
+ html.add_cdata(' (%s ' % format_time(step['end'] - step['start']))
+ html.add_element('a', 'Logs', attribs={'href':log_url})
+ html.add_cdata(')')
+ html.close_tag('span')
+ html.add_element('br')
+
+ html.close_tag('p')
+ html.add_element('p', ' ')
+ html.open_tag('p')
+ html.add_element('span', 'More details:', attribs={'class':'item'})
+ html.add_cdata(' ')
+ html.add_element('a', input['url'], attribs={'href':input['url']})
+ html.close_tag('p')
else:
# TODO do something here
- result = 'Currently no information for failed builds can be retrieved :('
- pass
-
- return Template(template).substitute(content=result)
+ html.set_title('Xfce Build Status error')
+ html.add_element('p', 'Currently no information can be retrieved for failed builds :(')
#----------------------------------------------------------------------
def parse_url():
@@ -335,14 +509,17 @@ def parse_url():
me = ''
args = uri.split('/')
if not args[0]:
- del args[0]
+ del args[0]
return (me, args)
except:
return ('', '')
#----------------------------------------------------------------------
def main():
- debug = cgi.FieldStorage(keep_blank_values=True).has_key('debug')
+ # parse query string
+ fs = cgi.FieldStorage(keep_blank_values=True)
+ layout = fs['layout'].value if fs.has_key('layout') else 'normal'
+ debug = fs.has_key('debug')
if debug:
import cgitb
cgitb.enable(display=1)
@@ -350,18 +527,18 @@ def main():
# handle arguments
url, args = parse_url()
- output = ''
headers = []
+ html = HtmlGen(url, layout)
if args:
args_len = len(args)
if args[0] == 'detail' and args_len == 4:
status = get_detail_status(XMLRPC_URL, args)
- output = get_detail_status_html(url, status)
+ get_detail_status_html(html, url, status)
# fallback to overview page
- if not output:
+ if not html:
status = get_build_status(XMLRPC_URL)
- output = get_build_status_html(url, status)
+ get_build_status_html(html, url, status)
if not headers:
print 'Content-type: text/html'
@@ -370,7 +547,7 @@ def main():
print h
print # final blank line to end HTTP headers
- print output
+ print str(html)
if debug:
print debug_out
print cgi.print_environ()
More information about the Xfce4-commits
mailing list