Skip to content

Commit

Permalink
IBox HTML -> jinja macro (fixes buildbot#652) + use path_to_build(er)…
Browse files Browse the repository at this point in the history
… in grid
  • Loading branch information
marcus-sonestedt committed Dec 25, 2009
1 parent 5e8de8e commit 70a6bb6
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 76 deletions.
32 changes: 3 additions & 29 deletions buildbot/status/web/base.py
Expand Up @@ -59,33 +59,6 @@ def getAndCheckProperties(req):
return None
properties.setProperty(pname, pvalue, "Force Build Form")
return properties
def td(text="", parms={}, **props):
data = ""
data += " "
#if not props.has_key("border"):
# props["border"] = 1
props.update(parms)
comment = props.get("comment", None)
if comment:
data += "<!-- %s -->" % comment
data += "<td"
class_ = props.get('class_', None)
if class_:
props["class"] = class_
for prop in ("align", "colspan", "rowspan", "border",
"valign", "halign", "class"):
p = props.get(prop, None)
if p != None:
data += " %s=\"%s\"" % (prop, p)
data += ">"
if not text:
text = "&nbsp;"
if isinstance(text, list):
data += "<br />".join(text)
else:
data += text
data += "</td>\n"
return data

def build_get_class(b):
"""
Expand Down Expand Up @@ -168,8 +141,9 @@ def td(self, **props):
text = self.text
if not text and self.show_idle:
text = ["[idle]"]
return td(text, props, class_=self.class_)

props['class'] = self.class_
props['text'] = text;
return props

class HtmlResource(resource.Resource):
# this is a cheap sort of template thingy
Expand Down
9 changes: 3 additions & 6 deletions buildbot/status/web/grid.py
Expand Up @@ -8,9 +8,7 @@
from buildbot import util
from buildbot import version
from buildbot.status.web.base import HtmlResource
#from buildbot.status.web.base import Box, HtmlResource, IBox, ICurrentBox, \
# ITopBox, td, build_get_class, path_to_build, path_to_step, map_branches
from buildbot.status.web.base import build_get_class
from buildbot.status.web.base import build_get_class, path_to_builder, path_to_build

# set grid_css to the full pathname of the css file
if hasattr(sys, "frozen"):
Expand Down Expand Up @@ -69,11 +67,10 @@ def build_cxt(self, request, build):
text = [ 'building' ]

name = build.getBuilder().getName()
number = build.getNumber()

cxt = {}
cxt['name'] = name
cxt['url'] = "builders/%s/builds/%d" % (name, number)
cxt['url'] = path_to_build(request, build)
cxt['text'] = text
cxt['class'] = build_get_class(build)
return cxt
Expand All @@ -99,7 +96,7 @@ def builder_cxt(self, request, builder):
# instead. The only times it should show up in "current activity" is
# when the builder is otherwise idle.

cxt = { 'url': urllib.quote(builder.getName(), safe=''),
cxt = { 'url': path_to_builder(request, builder),
'name': builder.getName(),
'state': state,
'n_pending': len(builder.getPendingBuilds()) }
Expand Down
12 changes: 12 additions & 0 deletions buildbot/status/web/templates/box_macros.html
@@ -0,0 +1,12 @@
{% macro box(text=[], comment=None) -%}

{%- if comment -%}<!-- {{ comment }} -->{%- endif -%}
<td class="{{ kwargs.class or kwargs.class_ or "" }}"
{%- for prop in ("align", "colspan", "rowspan", "border", "valign", "halign") -%}
{%- if prop in kwargs -%}
{{ prop }}="{{ kwargs[prop] }}"
{%- endif -%}
{%- endfor -%}>
{{- text|join("<br/>") -}}
</td>
{% endmacro %}
6 changes: 4 additions & 2 deletions buildbot/status/web/templates/buildstatus.html
@@ -1,11 +1,13 @@
{% extends "layout.html" %}
{% from "box_macros.html" import box %}


{% block content %}
<table>
{% for r in rows %}
<tr>{{ r }}</tr>
<tr>{{ box(r) }}</tr>
{% endfor %}

<tr>{{ build }}</tr>
<tr>{{ box(build) }}</tr>
</table>
{% endblock %}
3 changes: 2 additions & 1 deletion buildbot/status/web/templates/oneboxperbuilder.html
@@ -1,4 +1,5 @@
{% import 'forms.html' as forms %}
{% from "box_macros.html" import box %}

<h1>Latest builds: {{ branches|join(', ')|e }}</h1>

Expand All @@ -14,7 +15,7 @@ <h1>Latest builds: {{ branches|join(', ')|e }}</h1>
{% else %}
<td class="LastBuild box">no build</td>
{% endif %}
{{ b.current_box }}
{{ box(**b.current_box) }}
{% endfor %}
</table>

Expand Down
13 changes: 12 additions & 1 deletion buildbot/status/web/templates/waterfall.html
@@ -1,4 +1,6 @@
{% extends "layout.html" %}
{% from "box_macros.html" import box %}

{% block head %}
{{ super() }}
<meta http-equiv="refresh" content="{{refresh}}"/>
Expand Down Expand Up @@ -44,7 +46,16 @@
{% endfor %}
</tr>

{{ waterfall }}
{# waterfall contents goes here #}
{% for i in range(gridlen) -%}
<tr>
{% for strip in grid -%}
{%- if strip[i] -%}{{ box(**strip[i]) }}
{%- elif no_bubble -%}{{ box() }}
{%- endif -%}
{%- endfor -%}
</tr>
{% endfor %}

</table>

Expand Down
34 changes: 13 additions & 21 deletions buildbot/status/web/waterfall.py
Expand Up @@ -13,7 +13,7 @@
from buildbot.status import builder

from buildbot.status.web.base import Box, HtmlResource, IBox, ICurrentBox, \
ITopBox, td, build_get_class, path_to_build, path_to_step, map_branches
ITopBox, build_get_class, path_to_build, path_to_step, map_branches



Expand Down Expand Up @@ -268,7 +268,7 @@ def content(self, request, cxt):
times.insert(0, (current_reload_time, current_reload_time) )

cxt['times'] = times
cxt['current_reload_time'] = current_reload_time
cxt['current_reload_time'] = current_reload_time

template = request.site.buildbot_service.templates.get_template("waterfallhelp.html")
return template.render(**cxt)
Expand Down Expand Up @@ -388,8 +388,8 @@ def content(self, request, ctx):
'status_class': current_box.class_,
})

ctx['waterfall'] = self.phase2(request, changeNames + builderNames, timestamps, eventGrid,
sourceEvents)
ctx.update(self.phase2(request, changeNames + builderNames, timestamps, eventGrid,
sourceEvents))

def with_args(req, remove_args=[], new_args=[], new_path=None):
# sigh, nevow makes this sort of manipulation easier
Expand Down Expand Up @@ -579,9 +579,10 @@ def get_event_from(g):

def phase2(self, request, sourceNames, timestamps, eventGrid,
sourceEvents):
data = ""

if not timestamps:
return data
return dict(grid=[], gridlen=0)

# first pass: figure out the height of the chunks, populate grid
grid = []
for i in range(1+len(sourceNames)):
Expand Down Expand Up @@ -692,21 +693,12 @@ def phase2(self, request, sourceNames, timestamps, eventGrid,
strip[-i+1] = None
else:
strip[-i].parms['rowspan'] = 1
# third pass: render the HTML table

# convert to dicts
for i in range(gridlen):
data += " <tr>\n";
for strip in grid:
b = strip[i]
if b:
# convert data to a unicode string, whacking any non-ASCII characters it might contain
s = b.td()
if isinstance(s, unicode):
s = s.encode("utf-8", "replace")
data += s
else:
if noBubble:
data += td([])
# Nones are left empty, rowspan should make it all fit
data += " </tr>\n"
return data
if strip[i]:
strip[i] = strip[i].td()

return dict(grid=grid, gridlen=gridlen, no_bubble=noBubble)

24 changes: 8 additions & 16 deletions buildbot/test/test_web.py
Expand Up @@ -226,17 +226,17 @@ def test_waterfall(self):
config1 = base_config + """
from buildbot.changes import mail
c['change_source'] = mail.SyncmailMaildirSource('my-maildir')
c['status'] = [html.Waterfall(http_port=0, robots_txt=%s)]
""" % repr(self.robots_txt)
c['status'] = [html.WebStatus(http_port=0)]
"""

self.master = m = ConfiguredMaster("test_web4", config1)
m.startService()
port = self.find_waterfall(m).getPortnum()
port = self.find_webstatus(m).getPortnum()
self.port = port
# insert an event
m.change_svc.addChange(Change("user", ["foo.c"], "comments"))

d = client.getPage("http://localhost:%d/" % port)
d = client.getPage("http://localhost:%d/waterfall" % port)

def _check1(page):
self.failUnless(page)
Expand All @@ -245,8 +245,7 @@ def _check1(page):
TZ = time.tzname[time.localtime()[-1]]
self.failUnlessIn("(%s)" % TZ, page)

# phase=0 is really for debugging the waterfall layout
return client.getPage("http://localhost:%d/?phase=0" % self.port)
return client.getPage("http://localhost:%d/waterfall" % self.port)
d.addCallback(_check1)

def _check2(page):
Expand All @@ -260,15 +259,8 @@ def _check3(changes):
self.failUnlessIn("<li>Syncmail mailing list in maildir " +
"my-maildir</li>", changes)

return client.getPage("http://localhost:%d/robots.txt" % self.port)
d.addCallback(_check3)

def _check4(robotstxt):
# needed on win32
robotstxt = robotstxt.replace('\r\n', '\n')
self.failUnless(robotstxt == self.robots_txt_contents)
d.addCallback(_check4)

return d

test_waterfall.timeout = 10
Expand Down Expand Up @@ -298,11 +290,11 @@ def childLink(self, name):
return name
req = FakeRequest()
box = waterfall.IBox(s).getBox(req)
td = box.td()
text = "\n".join(box.td()['text'])
e1 = '[<a href="http://coverage.example.org/target" class="BuildStep external">coverage</a>]'
self.failUnlessSubstring(e1, td)
self.failUnlessSubstring(e1, text)
e2 = '[<a href="http://coverage.example.org/icon.png" class="BuildStep external">icon</a>]'
self.failUnlessSubstring(e2, td)
self.failUnlessSubstring(e2, text)



Expand Down

0 comments on commit 70a6bb6

Please sign in to comment.