[Treepkg-commits] r412 - in trunk: . contrib contrib/sawmill contrib/sawmill/web contrib/sawmill/web/img contrib/sawmill/web/styles contrib/sawmill/web/templates contrib/sawmill/web/treepkgs contrib/sawmill/web/treepkgs/demo
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Fri Aug 20 18:15:31 CEST 2010
Author: teichmann
Date: 2010-08-20 18:15:29 +0200 (Fri, 20 Aug 2010)
New Revision: 412
Added:
trunk/contrib/
trunk/contrib/sawmill/
trunk/contrib/sawmill/README
trunk/contrib/sawmill/web/
trunk/contrib/sawmill/web/details.py
trunk/contrib/sawmill/web/img/
trunk/contrib/sawmill/web/img/bottomleft-inner.png
trunk/contrib/sawmill/web/img/bottomleft.png
trunk/contrib/sawmill/web/img/bottomright-inner.png
trunk/contrib/sawmill/web/img/bottomright.png
trunk/contrib/sawmill/web/img/clear.png
trunk/contrib/sawmill/web/img/logo.jpg
trunk/contrib/sawmill/web/img/topleft-inner.png
trunk/contrib/sawmill/web/img/topleft.png
trunk/contrib/sawmill/web/img/topright-inner.png
trunk/contrib/sawmill/web/img/topright.png
trunk/contrib/sawmill/web/index.py
trunk/contrib/sawmill/web/styles/
trunk/contrib/sawmill/web/styles/style.css
trunk/contrib/sawmill/web/templates/
trunk/contrib/sawmill/web/templates/details.html
trunk/contrib/sawmill/web/templates/overview.html
trunk/contrib/sawmill/web/treepkgs/
trunk/contrib/sawmill/web/treepkgs/demo/
trunk/contrib/sawmill/web/treepkgs/demo/tracks/
trunk/contrib/sawmill/web/treepkgs/demo/treepkg.xml
Log:
Initial check-in of sawmill a simple mod_python based
web application to render build reports of treepkg.
Added: trunk/contrib/sawmill/README
===================================================================
--- trunk/contrib/sawmill/README 2010-08-13 14:16:50 UTC (rev 411)
+++ trunk/contrib/sawmill/README 2010-08-20 16:15:29 UTC (rev 412)
@@ -0,0 +1,2 @@
+A simple mod_python based web application to render the
+build reports of treepkg.
Added: trunk/contrib/sawmill/web/details.py
===================================================================
--- trunk/contrib/sawmill/web/details.py 2010-08-13 14:16:50 UTC (rev 411)
+++ trunk/contrib/sawmill/web/details.py 2010-08-20 16:15:29 UTC (rev 412)
@@ -0,0 +1,155 @@
+# -*- coding: UTF-8 -*-
+#
+# Copyright (C) 2010 by Intevation GmbH
+# Authors:
+# Sascha L. Teichmann <sascha.teichmann at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+from mod_python import apache, psp, util
+
+import os
+import re
+import datetime
+import time
+
+from lxml import etree
+
+BASE_DIR = "treepkgs"
+
+TREEPKG_DIR = os.path.join(os.path.dirname(__file__), BASE_DIR)
+
+STATUS_LINE = re.compile(r"^([^:]+):(.+)")
+
+UNDER_SCORE = re.compile(r"_+(\w)")
+
+def _create_time(s, format="%Y-%m-%d %H:%M:%S"):
+ return datetime.datetime(*(time.strptime(s, format)[0:6]))
+
+def _pretty_log_name(log):
+ log = log.replace(".txt", "").replace(".gz", "").capitalize()
+ return UNDER_SCORE.sub(lambda x: " %s" % x.group(1).upper(), log)
+
+class TrackItem(object):
+
+ def __init__(self, treepkg, track, revision, status_file):
+ self.treepkg = treepkg
+ self.track = track
+ self.revision = revision
+ self.status_file = status_file
+ self.loaded = False
+ self.status = None
+ self.start = None
+ self.stop = None
+ self.logs = None
+
+ def check_loaded(self):
+ if not self.loaded:
+ f = open(self.status_file)
+ try:
+ for line in f:
+ m = STATUS_LINE.match(line)
+ if not m: continue
+ key, value = [x.strip() for x in m.groups()]
+
+ if key == 'status': self.status = value
+ elif key == 'start': self.start = _create_time(value)
+ elif key == 'stop': self.stop = _create_time(value)
+ finally:
+ f.close()
+ self.loaded = True
+
+ def get_build_status(self):
+ self.check_loaded()
+ return self.status
+
+ def get_build_start(self):
+ self.check_loaded()
+ return self.start
+
+ def get_build_stop(self):
+ self.check_loaded()
+ return self.stop
+
+ def log_path(self, log):
+ return "%s/tracks/%s/pkg/%s/log/%s" % (
+ self.treepkg, self.track, self.revision, log)
+
+ def get_build_logs(self):
+ oj = os.path.join
+ if self.logs is None:
+ log_dir = oj(os.path.dirname(self.status_file), "log")
+ if not os.path.isdir(log_dir):
+ self.logs = []
+ else:
+ self.logs =[(_pretty_log_name(f), self.log_path(f))
+ for f in os.listdir(log_dir)
+ if os.path.isfile(oj(log_dir, f)) and f.find("txt") >= 0]
+ return self.logs
+
+ build_status = property(get_build_status)
+ build_start = property(get_build_start)
+ build_stop = property(get_build_stop)
+ build_logs = property(get_build_logs)
+
+
+def __scan_track_items(treepkg, path):
+ items = []
+
+ tracks_path = os.path.join(path, "tracks")
+ for track in os.listdir(tracks_path):
+ track_path = os.path.join(tracks_path, track)
+ if not os.path.isdir(track_path): continue
+ revisions_path = os.path.join(track_path, "pkg")
+ for revision in os.listdir(revisions_path):
+ revision_path = os.path.join(revisions_path, revision)
+ if not os.path.isdir(revision_path): continue
+ status_file = os.path.join(revision_path, "status")
+ if not os.path.isfile(status_file): continue
+ items.append(TrackItem(treepkg, track, revision, status_file))
+
+ return items
+
+def __description_header(treepkg):
+ treepkg_xml = os.path.join(treepkg, "treepkg.xml")
+ if os.path.isfile(treepkg_xml):
+ xml = None
+ try:
+ xml = open(treepkg_xml, "rb")
+ dom = etree.parse(xml)
+ finally:
+ if xml: xml.close()
+
+ description = ''.join(dom.xpath("//description/text()"))
+ header = ''.join([etree.tostring(x, encoding="UTF-8", method="html")
+ for x in dom.xpath("//header/*")])
+ return description, header
+ return "unknown", ""
+
+def index(req, treepkg=''):
+ if not treepkg: util.redirect(req, "index.py")
+
+ found = None
+ for d in os.listdir(TREEPKG_DIR):
+ dp = os.path.join(TREEPKG_DIR, d)
+ if os.path.isdir(dp) and d == treepkg:
+ found = dp
+ break
+
+ if not found:
+ req.status = apache.HTTP_NOT_FOUND
+ return "requested TreePkg not found"
+
+ description, header = __description_header(found)
+
+ track_items = __scan_track_items(treepkg, found)
+
+ req.content_type = 'text/html;charset=utf-8'
+ template = psp.PSP(req, filename='templates/details.html')
+ template.run({
+ 'base_dir': BASE_DIR,
+ 'description': description,
+ 'header': header,
+ 'track_items': track_items
+ })
Added: trunk/contrib/sawmill/web/img/bottomleft-inner.png
===================================================================
(Binary files differ)
Property changes on: trunk/contrib/sawmill/web/img/bottomleft-inner.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/contrib/sawmill/web/img/bottomleft.png
===================================================================
(Binary files differ)
Property changes on: trunk/contrib/sawmill/web/img/bottomleft.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/contrib/sawmill/web/img/bottomright-inner.png
===================================================================
(Binary files differ)
Property changes on: trunk/contrib/sawmill/web/img/bottomright-inner.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/contrib/sawmill/web/img/bottomright.png
===================================================================
(Binary files differ)
Property changes on: trunk/contrib/sawmill/web/img/bottomright.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/contrib/sawmill/web/img/clear.png
===================================================================
(Binary files differ)
Property changes on: trunk/contrib/sawmill/web/img/clear.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/contrib/sawmill/web/img/logo.jpg
===================================================================
(Binary files differ)
Property changes on: trunk/contrib/sawmill/web/img/logo.jpg
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/contrib/sawmill/web/img/topleft-inner.png
===================================================================
(Binary files differ)
Property changes on: trunk/contrib/sawmill/web/img/topleft-inner.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/contrib/sawmill/web/img/topleft.png
===================================================================
(Binary files differ)
Property changes on: trunk/contrib/sawmill/web/img/topleft.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/contrib/sawmill/web/img/topright-inner.png
===================================================================
(Binary files differ)
Property changes on: trunk/contrib/sawmill/web/img/topright-inner.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/contrib/sawmill/web/img/topright.png
===================================================================
(Binary files differ)
Property changes on: trunk/contrib/sawmill/web/img/topright.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/contrib/sawmill/web/index.py
===================================================================
--- trunk/contrib/sawmill/web/index.py 2010-08-13 14:16:50 UTC (rev 411)
+++ trunk/contrib/sawmill/web/index.py 2010-08-20 16:15:29 UTC (rev 412)
@@ -0,0 +1,40 @@
+# -*- coding: UTF-8 -*-
+#
+# Copyright (C) 2010 by Intevation GmbH
+# Authors:
+# Sascha L. Teichmann <sascha.teichmann at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+from mod_python import psp
+
+import os
+
+from lxml import etree
+
+TREEPKG_DIR = os.path.join(os.path.dirname(__file__), "treepkgs")
+
+def index(req):
+ req.content_type = 'text/html;charset=utf-8'
+ template = psp.PSP(req, filename='templates/overview.html')
+
+ descriptions = []
+
+ for f in os.listdir(TREEPKG_DIR):
+ d = os.path.join(TREEPKG_DIR, f)
+ if not os.path.isdir(d): continue
+ treepkg_xml = os.path.join(d, "treepkg.xml")
+ if not os.path.isfile(treepkg_xml): continue
+ xml = None
+ try:
+ xml = open(treepkg_xml, "rb")
+ dom = etree.parse(xml)
+ finally:
+ if xml: xml.close()
+
+ description = ''.join(dom.xpath("//description/text()"))
+
+ descriptions.append((os.path.basename(d), description))
+
+ template.run({'descriptions': descriptions})
Added: trunk/contrib/sawmill/web/styles/style.css
===================================================================
--- trunk/contrib/sawmill/web/styles/style.css 2010-08-13 14:16:50 UTC (rev 411)
+++ trunk/contrib/sawmill/web/styles/style.css 2010-08-20 16:15:29 UTC (rev 412)
@@ -0,0 +1,54 @@
+body {
+ margin-top: 3;
+ margin-left: 3;
+ margin-right: 3;
+ margin-bottom: 3;
+ background-color:#6190c0;
+}
+
+ol,ul,p,body,td,tr,th,form {
+ font-family: verdana,arial,helvetica,sans-serif;
+ font-size:small;
+ color: #333333;
+}
+
+h1 { font-size: x-large; font-family: verdana,arial,helvetica,sans-serif; }
+h2 { font-size: large; font-family: verdana,arial,helvetica,sans-serif; }
+h3 { font-size: medium; font-family: verdana,arial,helvetica,sans-serif; }
+h4 { font-size: small; font-family: verdana,arial,helvetica,sans-serif; }
+h5 { font-size: x-small; font-family: verdana,arial,helvetica,sans-serif; }
+h6 { font-size: xx-small; font-family: verdana,arial,helvetica,sans-serif; }
+
+pre,tt { font-family: courier,sans-serif }
+
+a:link { text-decoration:none; color: #0000be }
+a:visited { text-decoration:none; color: #0000be }
+a:active { text-decoration:none }
+a:hover { text-decoration:underline; color:red }
+
+.titlebar { color: black; text-decoration: none; font-weight: bold; }
+a.tablink { color: black; text-decoration: none; font-weight: bold; font-size: x-small; }
+a.tablink:visited { color: black; text-decoration: none; font-weight: bold; font-size: x-small; }
+a.tablink:hover { text-decoration: none; color: black; font-weight: bold; font-size: x-small; }
+a.tabsellink { color: #0000be; text-decoration: none; font-weight: bold; font-size: x-small; }
+a.tabsellink:visited { color: #0000be; text-decoration: none; font-weight: bold; font-size: x-small; }
+a.tabsellink:hover { text-decoration: none; color: #0000be; font-weight: bold; font-size: x-small; }
+
+.css_prison {}
+
+.css_prison .statustable { background:#F4F4F4; width:95% }
+.css_prison .statustablestatus { background:#E0E0E0; width:15% }
+.css_prison .statustablepkg { background:#E0E0E0; width:45% }
+.css_prison .statustablenotes { background:#E0E0E0; width:10% }
+.css_prison .statustablehead { background:#E0E0E0; }
+.css_prison .statusheading { font-weight:bold; }
+.css_prison .finished { background:#C0FFC0; }
+.css_prison .inprogress { background:#FFFFC0; }
+.css_prison .error { background:#FFC0C0; }
+.css_prison .date_row {
+ background:#F0F0F0;
+ font-weight:bold; font-size:smaller;
+ text-align:center;
+}
+.css_prison tr { background:#FFFFFF; }
+.css_prison td { padding:5px; }
Added: trunk/contrib/sawmill/web/templates/details.html
===================================================================
--- trunk/contrib/sawmill/web/templates/details.html 2010-08-13 14:16:50 UTC (rev 411)
+++ trunk/contrib/sawmill/web/templates/details.html 2010-08-20 16:15:29 UTC (rev 412)
@@ -0,0 +1,206 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<%
+from cgi import escape
+from xml.sax.saxutils import quoteattr
+
+from datetime import date
+%>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <link rel="stylesheet" href="styles/style.css" type="text/css" media="screen" />
+ <title>Sägewerker - Free Software forestry</title>
+ </head>
+
+ <body>
+ <table border="0" width="100%" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+ <a href="/"><img src="img/logo.jpg" border="0" alt="" width="533" height="94" /></a>
+ </td>
+ </tr>
+ </table>
+ <table border="0" width="100%" cellspacing="0" cellpadding="0">
+
+ <tr>
+ <td align="left" bgcolor="#E0E0E0" width="9">
+ <img src="img/topleft.png" height="9" width="9" alt="" />
+ </td>
+ <td bgcolor="#E0E0E0" width="30">
+ <img src="img/clear.png" width="30" height="1" alt="" />
+ </td>
+ <td bgcolor="#E0E0E0">
+ <img src="img/clear.png" width="1" height="1" alt="" />
+
+ </td>
+ <td bgcolor="#E0E0E0" width="30">
+ <img src="img/clear.png" width="30" height="1" alt="" />
+ </td>
+ <td align="right" bgcolor="#E0E0E0" width="9">
+ <img src="img/topright.png" height="9" width="9" alt="" />
+ </td>
+ </tr>
+
+ <tr>
+ <!-- Outer body row -->
+ <td bgcolor="#E0E0E0">
+ <img src="img/clear.png" width="10" height="1" alt="" />
+ </td>
+ <td valign="top" width="99%" bgcolor="#E0E0E0" colspan="3">
+ <!-- Inner Tabs / Shell -->
+ <table border="0" width="100%" cellspacing="0" cellpadding="0">
+ <tr>
+
+ <td align="left" bgcolor="#ffffff" width="9">
+ <img src="img/topleft-inner.png" height="9" width="9" alt="" />
+ </td>
+ <td bgcolor="#ffffff">
+ <img src="img/clear.png" width="1" height="1" alt="" />
+ </td>
+ <td align="right" bgcolor="#ffffff" width="9">
+ <img src="img/topright-inner.png" height="9" width="9" alt="" />
+ </td>
+
+ </tr>
+ <tr>
+ <td bgcolor="#ffffff">
+ <img src="img/clear.png" width="10" height="1" alt="" />
+ </td>
+ <td valign="top" width="99%" bgcolor="white" class="css_prison">
+ <!-- end main body row -->
+<h1><%= escape(description) %></h1>
+<%= header %>
+<table class="statustable">
+<tr>
+ <th class="statustablehead">Status</th>
+ <th class="statustablehead">Package</th>
+ <th class="statustablehead">Revision</th>
+ <th class="statustablehead">Start</th>
+ <th class="statustablehead">Stop</th>
+ <th class="statustablehead">Notes</th>
+</tr>
+<%
+
+def nn(s, d=""):
+ if not s: return d
+ return escape(s)
+
+def pretty_time(t, format="%Y-%m-%d %H:%M:%S"):
+ if not t: return "<unknown>"
+ return t.strftime(format)
+
+
+def date_from_datetime(x):
+ if not x: return None
+ return date(x.year, x.month, x.day)
+
+def sort_by_start(a, b):
+ a_start = a.build_start
+ b_start = b.build_start
+ if not a_start and not b_start: return 0
+ if not a_start: return 1
+ if not b_start: return -1
+ return cmp(a_start, b_start)
+
+track_items = sorted(track_items, cmp=sort_by_start, reverse=True)
+
+last_date = None
+
+STATUS2CLASS = {
+ 'creating_binary_package': 'inprogress',
+ 'binary_package_created': 'finished'
+}
+
+STATUS2MSG = {
+ 'creating_binary_package': 'building binary packages',
+ 'binary_package_created': 'build successful'
+}
+
+for track_item in track_items:
+ # for all track items
+ curr_date = date_from_datetime(track_item.build_start)
+ if curr_date != last_date:
+ last_date = curr_date
+%>
+<tr class="date_row"><td colspan="6"><%= pretty_time(last_date, "%Y-%m-%d") %></td></tr>
+<%
+ # date changed
+%>
+<tr class="<%= STATUS2CLASS.get(track_item.build_status, 'error') %>">
+ <td><%= STATUS2MSG.get(track_item.build_status, 'error') %></td>
+ <td style="font-weight:bold;"><%= nn(track_item.track) %></td>
+ <td align="right"><%= nn(track_item.revision) %></td>
+ <td><%= pretty_time(track_item.build_start) %></td>
+ <td><%= pretty_time(track_item.build_stop) %></td>
+ <td>
+<%
+ for log_desc, log_path in track_item.build_logs:
+ # for all logs
+%>
+[<a href=<%= quoteattr("%s/%s" % (base_dir, log_path)) %>><%= nn(log_desc) %></a>]
+
+<%
+ # for all logs
+%>
+ </td>
+</tr>
+
+<%
+# for all track itemes
+%>
+
+</table>
+
+
+ <!-- end main body row -->
+ </td>
+ <td width="10" bgcolor="#ffffff">
+ <img src="img/clear.png" width="2" height="1" alt="" />
+ </td>
+ </tr>
+
+ <tr>
+ <td align="left" bgcolor="#E0E0E0" width="9">
+ <img src="img/bottomleft-inner.png" height="11" width="11" alt="" />
+ </td>
+ <td bgcolor="#ffffff">
+ <img src="img/clear.png" width="1" height="1" alt="" />
+ </td>
+ <td align="right" bgcolor="#E0E0E0" width="9">
+ <img src="img/bottomright-inner.png" height="11" width="11" alt="" />
+
+ </td>
+ </tr>
+ </table>
+
+ <!-- end inner body row -->
+
+ </td>
+ <td width="10" bgcolor="#E0E0E0">
+ <img src="img/clear.png" width="2" height="1" alt="" />
+ </td>
+
+ </tr>
+ <tr>
+ <td align="left" bgcolor="#E0E0E0" width="9">
+ <img src="img/bottomleft.png" height="9" width="9" alt="" />
+ </td>
+ <td bgcolor="#E0E0E0" colspan="3">
+ <img src="img/clear.png" width="1" height="1" alt="" />
+ </td>
+ <td align="right" bgcolor="#E0E0E0" width="9">
+
+ <img src="img/bottomright.png" height="9" width="9" alt="" />
+ </td>
+ </tr>
+ </table>
+ <br />
+ <center>
+ <b style="color:white; font-size:13px;">
+ This site is hosted by the <a href="http://www.intevation.de">Intevation GmbH</a>
+ </b>
+ </center>
+
+ </body>
+</html>
Added: trunk/contrib/sawmill/web/templates/overview.html
===================================================================
--- trunk/contrib/sawmill/web/templates/overview.html 2010-08-13 14:16:50 UTC (rev 411)
+++ trunk/contrib/sawmill/web/templates/overview.html 2010-08-20 16:15:29 UTC (rev 412)
@@ -0,0 +1,133 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<%
+from cgi import escape
+from xml.sax.saxutils import quoteattr
+%>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <link rel="stylesheet" href="styles/style.css" type="text/css" media="screen" />
+ <title>Sägewerker - Free Software forestry</title>
+ </head>
+
+ <body>
+ <table border="0" width="100%" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+ <a href="/"><img src="img/logo.jpg" border="0" alt="" width="533" height="94" /></a>
+ </td>
+ </tr>
+ </table>
+ <table border="0" width="100%" cellspacing="0" cellpadding="0">
+
+ <tr>
+ <td align="left" bgcolor="#E0E0E0" width="9">
+ <img src="img/topleft.png" height="9" width="9" alt="" />
+ </td>
+ <td bgcolor="#E0E0E0" width="30">
+ <img src="img/clear.png" width="30" height="1" alt="" />
+ </td>
+ <td bgcolor="#E0E0E0">
+ <img src="img/clear.png" width="1" height="1" alt="" />
+
+ </td>
+ <td bgcolor="#E0E0E0" width="30">
+ <img src="img/clear.png" width="30" height="1" alt="" />
+ </td>
+ <td align="right" bgcolor="#E0E0E0" width="9">
+ <img src="img/topright.png" height="9" width="9" alt="" />
+ </td>
+ </tr>
+
+ <tr>
+ <!-- Outer body row -->
+ <td bgcolor="#E0E0E0">
+ <img src="img/clear.png" width="10" height="1" alt="" />
+ </td>
+ <td valign="top" width="99%" bgcolor="#E0E0E0" colspan="3">
+ <!-- Inner Tabs / Shell -->
+ <table border="0" width="100%" cellspacing="0" cellpadding="0">
+ <tr>
+
+ <td align="left" bgcolor="#ffffff" width="9">
+ <img src="img/topleft-inner.png" height="9" width="9" alt="" />
+ </td>
+ <td bgcolor="#ffffff">
+ <img src="img/clear.png" width="1" height="1" alt="" />
+ </td>
+ <td align="right" bgcolor="#ffffff" width="9">
+ <img src="img/topright-inner.png" height="9" width="9" alt="" />
+ </td>
+
+ </tr>
+ <tr>
+ <td bgcolor="#ffffff">
+ <img src="img/clear.png" width="10" height="1" alt="" />
+ </td>
+ <td valign="top" width="99%" bgcolor="white">
+ <!-- end main body row -->
+ <div style="text-align: right"><a href="http://wald.intevation.de/">...to WALD source code repository</a></div>
+
+<%
+for treepkg, description in descriptions:
+ # for all descriptions
+%>
+<div style="magin:5px;border-bottom:1px solid #DDDDDD;padding:5px;font-weight:bold; font-size: 16pt">
+<a href=<%= quoteattr("details.py?treepkg=%s" % treepkg) %>><%= escape(description) %></a>
+</div>
+<%
+# for all descriptions
+%>
+ <!-- end main body row -->
+ </td>
+ <td width="10" bgcolor="#ffffff">
+ <img src="img/clear.png" width="2" height="1" alt="" />
+ </td>
+ </tr>
+
+ <tr>
+ <td align="left" bgcolor="#E0E0E0" width="9">
+ <img src="img/bottomleft-inner.png" height="11" width="11" alt="" />
+ </td>
+ <td bgcolor="#ffffff">
+ <img src="img/clear.png" width="1" height="1" alt="" />
+ </td>
+ <td align="right" bgcolor="#E0E0E0" width="9">
+ <img src="img/bottomright-inner.png" height="11" width="11" alt="" />
+
+ </td>
+ </tr>
+ </table>
+
+ <!-- end inner body row -->
+
+ </td>
+ <td width="10" bgcolor="#E0E0E0">
+ <img src="img/clear.png" width="2" height="1" alt="" />
+ </td>
+
+ </tr>
+ <tr>
+ <td align="left" bgcolor="#E0E0E0" width="9">
+ <img src="img/bottomleft.png" height="9" width="9" alt="" />
+ </td>
+ <td bgcolor="#E0E0E0" colspan="3">
+ <img src="img/clear.png" width="1" height="1" alt="" />
+ </td>
+ <td align="right" bgcolor="#E0E0E0" width="9">
+
+ <img src="img/bottomright.png" height="9" width="9" alt="" />
+ </td>
+ </tr>
+ </table>
+ <br />
+ <center>
+ <b style="color:white; font-size:13px;">
+ This site is hosted by the <a href="http://www.intevation.de">Intevation GmbH</a>
+
+ </b>
+ </center>
+
+ </body>
+</html>
Added: trunk/contrib/sawmill/web/treepkgs/demo/treepkg.xml
===================================================================
--- trunk/contrib/sawmill/web/treepkgs/demo/treepkg.xml 2010-08-13 14:16:50 UTC (rev 411)
+++ trunk/contrib/sawmill/web/treepkgs/demo/treepkg.xml 2010-08-20 16:15:29 UTC (rev 412)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<treepkg>
+ <description>This is the status of the demo packager</description>
+ <header>
+ <div xmlns="http://www.w3.org/1999/xhtml">
+ <p>
+ Put extra project information here.
+ <strong>Any type of HTML tags are allowed here</strong>
+ </p>
+ </div>
+ </header>
+</treepkg>
More information about the Treepkg-commits
mailing list