Mercurial > treepkg
diff contrib/sawmill/web/details.py @ 452:333232953771
Initial check-in of sawmill a simple mod_python based
web application to render build reports of treepkg.
author | Sascha Teichmann <teichmann@intevation.de> |
---|---|
date | Fri, 20 Aug 2010 16:15:29 +0000 |
parents | |
children | 52f841330c16 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/sawmill/web/details.py Fri Aug 20 16:15:29 2010 +0000 @@ -0,0 +1,155 @@ +# -*- coding: UTF-8 -*- +# +# Copyright (C) 2010 by Intevation GmbH +# Authors: +# Sascha L. Teichmann <sascha.teichmann@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 + })