view contrib/sawmill/bin/generate-rss.py @ 492:93d66243bce7

sawmill: Added RSS feed generator.
author Sascha Teichmann <teichmann@intevation.de>
date Thu, 30 Sep 2010 22:51:45 +0000
parents
children
line wrap: on
line source
#!/usr/bin/env python
# -*- 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.

import sys
import os
import re
import traceback

from datetime import datetime

from lxml import etree

import PyRSS2Gen as RSS2

BASE_URL = "http://saegewerk2.wald.intevation.org/buildlogs"
LINK_URL = "%s/details.py?treepkg=%%s" % BASE_URL
ITEM_URL = "%s/details.py?treepkg=%%s#%%s" % BASE_URL

TITLE       = "Saegewerk - %s"
DESCRIPTION = "Build errors of '%s'"
MESSAGE     = "%s: error building %s rev. %s"
TTL         = 7

START = re.compile(
    r"start:\s+(\d{4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d{2})")
STATUS = re.compile(r"status:\s+(.+)")

INVALID_LABEL = re.compile(r"[^a-zA-Z0-9_]")

def make_valid_label(l):
    return INVALID_LABEL.sub("_", l)

def to_datetime(m):
    m = map(int, m.groups())
    return datetime(
        year=m[0], month=m[1], day=m[2], 
        hour=m[3], minute=m[4], second=m[5])

def usage(msg, code=1):
    print >> sys.stderr, "%s <treepkgs directory>" % sys.argv[0]
    print >> sys.stderr, "%s" % msg
    sys.exit(code)

def main():
    if len(sys.argv) < 2:
        usage("missing treepkgs directory")

    treepkgs_dir = sys.argv[1]
    if not os.path.isdir(treepkgs_dir):
        usage("'%s' is not a directory" % treepkgs_dir)

    for treepkg in os.listdir(treepkgs_dir):
        treepkg_dir = os.path.join(treepkgs_dir, treepkg)
        if not os.path.isdir(treepkg_dir): continue
        treepkg_xml = os.path.join(treepkg_dir, "treepkg.xml")
        if not os.path.isfile(treepkg_xml): continue
        try:
            f = open(treepkg_xml, "rb")
            try:     treepkg_dom = etree.parse(f)
            finally: f.close()
        except:
            traceback.print_exc(file=sys.stderr)
            continue
        description = ''.join(
            treepkg_dom.xpath('/treepkg/description/text()'))

        tracks_dir = os.path.join(treepkg_dir, "tracks")
        if not os.path.isdir(tracks_dir): continue

        items = []

        for track in os.listdir(tracks_dir):
            track_dir = os.path.join(tracks_dir, track, "pkg")
            if not os.path.isdir(track_dir): continue

            track_label = make_valid_label(track)

            for revision in os.listdir(track_dir):
                revision_dir = os.path.join(track_dir, revision)
                if not os.path.isdir(revision_dir): continue
                status_file = os.path.join(revision_dir, "status")
                if not os.path.isfile(status_file): continue
                start, status = None, None
                try:
                    f = open(status_file, "r")
                    try:
                        while True:
                            line = f.readline()
                            if not line: break
                            m = STATUS.match(line)
                            if m: status = m.group(1); continue
                            m = START.match(line)
                            if m: start = to_datetime(m)
                    finally:
                        f.close()
                except:
                    traceback.print_exc(file=sys.stderr)
                    continue
                if status != "error" or not start: continue

                label = ''.join([
                    track_label,
                    make_valid_label(revision),
                    start.strftime("%Y%m%d%H%M%S")])

                link = ITEM_URL % (treepkg, label)
                msg  = MESSAGE  % (description, track, revision)
                item = RSS2.RSSItem(
                    title       = msg,
                    link        = link,
                    description = msg,
                    guid        = RSS2.Guid(link, isPermaLink=0),
                    pubDate     = start
                )
                items.append(item)

        items.sort(key=lambda x: x.pubDate)

        rss = RSS2.RSS2(
            title       = TITLE % description,
            link        = LINK_URL % treepkg,
            description = DESCRIPTION % description,
            pubDate     = datetime.utcnow(),
            ttl         = TTL,
            items       = items)

        pid, idx = os.getpid(), 0
        while True:
            tmp_f = os.path.join(
                treepkg_dir, "rss.xml.tmp%d-%d" % (pid, idx))
            if not os.path.exists(tmp_f): break
            idx += 1

        try:
            f = open(tmp_f, "wb")
            try: rss.write_xml(f, encoding="UTF-8")
            finally: f.close()

            rss_xml = os.path.join(treepkg_dir, "rss.xml")

            os.rename(tmp_f, rss_xml)
        except:
            traceback.print_exc(file=sys.stderr)
            if os.path.exists(tmp_f):
                try: os.remove(tmp_f)
                except: pass

if __name__ == '__main__':
    main()
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)