aboutsummaryrefslogtreecommitdiff
path: root/rcynic/rcynic.py
diff options
context:
space:
mode:
Diffstat (limited to 'rcynic/rcynic.py')
-rw-r--r--rcynic/rcynic.py253
1 files changed, 123 insertions, 130 deletions
diff --git a/rcynic/rcynic.py b/rcynic/rcynic.py
index e371edcf..2bd02bcd 100644
--- a/rcynic/rcynic.py
+++ b/rcynic/rcynic.py
@@ -1,6 +1,8 @@
"""
Python translation of rcynic.xsl, which has gotten too slow and complex.
+$Id$
+
Copyright (C) 2010-2011 Internet Systems Consortium, Inc. ("ISC")
Permission to use, copy, modify, and/or distribute this software for any
@@ -18,7 +20,7 @@ PERFORMANCE OF THIS SOFTWARE.
import sys, urlparse, os
-from xml.etree.cElementTree import (ElementTree, Element, SubElement, Comment)
+from xml.etree.ElementTree import (ElementTree, Element, SubElement, Comment)
refresh = 1800
suppress_zero_columns = True
@@ -28,184 +30,175 @@ show_detailed_status = True
show_problems = False
show_summary = True
-#input = ElementTree(file = sys.stdin)
-input = ElementTree(file = "rcynic.xml")
+class Label(object):
+
+ def __init__(self, elt):
+ self.code = elt.tag
+ self.mood = elt.get("kind")
+ self.text = elt.text.strip()
+ self.sum = 0
+
+class Validation_Status(object):
+
+ def __init__(self, elt, map):
+ self.uri = elt.text.strip()
+ self.timestamp = elt.get("timestamp")
+ self.generation = elt.get("generation")
+ self.hostname = urlparse.urlparse(self.uri).hostname or None
+ self.fn2 = os.path.splitext(self.uri)[1] or None if self.generation else None
+ self.label = map[elt.get("status")]
+ self.label.sum += 1
+
+ @property
+ def code(self):
+ return self.label.code
+
+ @property
+ def mood(self):
+ return self.label.mood
+
+input = ElementTree(file = sys.stdin)
+labels = [Label(elt) for elt in input.find("labels")]
+label_map = dict((l.code, l) for l in labels)
+validation_status = [Validation_Status(elt, label_map) for elt in input.findall("validation_status")]
+del label_map
+if suppress_zero_columns:
+ labels = [l for l in labels if l.sum > 0]
html = Element("html")
-html.append(Comment(" Generators:\n " +
- input.getroot().get("rcynic-version") +
- "\n $Id$\n"))
+html.append(Comment(" Generators:\n" +
+ " " + input.getroot().get("rcynic-version") + "\n" +
+ " $Id$\n"))
head = SubElement(html, "head")
body = SubElement(html, "body")
title = "rcynic summary %s" % input.getroot().get("date")
SubElement(head, "title").text = title
SubElement(body, "h1").text = title
+del title
if refresh:
SubElement(head, "meta", { "http-equiv" : "Refresh", "content" : str(refresh) })
-css = '''
- td { text-align: center; padding: 4px }
+SubElement(head, "style", type = "text/css").text = '''
+ th, td { text-align: center; padding: 4px }
td.uri { text-align: left }
- td.host { text-align: left }
+ thead tr th,
+ tfoot tr td { font-weight: bold }
'''
+table_css = { "rules" : "all", "border" : "1"}
+uri_css = { "class" : "uri" }
+
if use_colors:
- css += '''\
- tr.good,td.good { background-color: #77ff77 }
- tr.warn,td.warn { background-color: yellow }
- tr.bad,td.bad { background-color: #ff5500 }
+ SubElement(head, "style", type = "text/css").text = '''
+ .good { background-color: #77ff77 }
+ .warn { background-color: yellow }
+ .bad { background-color: #ff5500 }
'''
-SubElement(head, "style", type = "text/css").text = css
-
-class Label(object):
-
- def __init__(self, elt):
- self.tag = elt.tag
- self.kind = elt.get("kind")
- self.text = elt.text.strip()
-
-class Host_Datum(object):
-
- def __init__(self, elt):
- self.uri = elt.text.strip()
- self.status = elt.get("status")
- self.timestamp = elt.get("timestamp")
- self.generation = elt.get("generation")
- self.hostname = urlparse.urlparse(self.uri).hostname
- self.label = label_map[self.status]
- self.mood = self.label.kind
- self.fn2 = os.path.splitext(self.uri)[1] or None
- if not self.generation:
- self.fn2 = None
-
- def __cmp__(self, other):
- return cmp(self.uri, other.uri) or cmp(self.generation, other.generation)
-
-class Total(object):
-
- # This probably should merge into the Label class, right now I'm
- # just trying to do straight translation to keep from getting too
- # confused by all the different attribute names.
-
- def __init__(self, label, host_data):
- self.label = label
- self.name = label.tag
- self.mood = label.kind
- self.text = label.text
- self.sum = sum(int(h.status == self.name) for h in host_data)
- self.show = self.sum > 0 or not suppress_zero_columns
-
-labels = [Label(elt) for elt in input.find("labels")]
-label_map = dict((label.tag, label) for label in labels)
-
if show_summary:
- host_data = [Host_Datum(elt) for elt in input.findall("validation_status")]
- #host_data.sort()
-
- unique_hostnames = set(h.hostname for h in host_data)
- unique_fn2s = set(h.fn2 for h in host_data)
- unique_generations = set(h.generation for h in host_data)
-
- totals = [Total(label, host_data) for label in labels]
- columns = sum(total.sum for total in totals)
+ unique_hostnames = sorted(set(v.hostname for v in validation_status))
+ unique_fn2s = sorted(set(v.fn2 for v in validation_status))
+ unique_generations = sorted(set(v.generation for v in validation_status))
if show_summary:
SubElement(body, "br")
SubElement(body, "h2").text = "Grand Totals"
- table = SubElement(body, "table", { "class" : "summary", "rules" : "all", "border" : "1"})
+ table = SubElement(body, "table", table_css)
thead = SubElement(table, "thead")
- tr = SubElement(thead, "tr")
- SubElement(tr, "td")
- for t in totals:
- if t.show:
- elt = SubElement(tr, "td")
- elt = SubElement(elt, "b")
- elt.text = t.text
+ tfoot = SubElement(table, "tfoot")
tbody = SubElement(table, "tbody")
- tr = SubElement(tbody, "tr")
- elt = SubElement(tr, "td")
- elt = SubElement(elt, "b")
- elt.text = "Total"
- for t in totals:
- if t.show:
- SubElement(tr, "td", { "class" : t.mood }).text = str(t.sum)
+ tr = SubElement(thead, "tr")
+ SubElement(tr, "th")
+ for l in labels:
+ SubElement(tr, "th").text = l.text
+ for fn2 in unique_fn2s:
+ for generation in unique_generations:
+ if any(v.fn2 == fn2 and v.generation == generation for v in validation_status):
+ tr = SubElement(tbody, "tr")
+ SubElement(tr, "td").text = ((generation or "") + " " + (fn2 or "")).strip()
+ for l in labels:
+ value = sum(int(v.fn2 == fn2 and v.generation == generation and v.code == l.code) for v in validation_status)
+ td = SubElement(tr, "td")
+ if value > 0:
+ td.set("class", l.mood)
+ td.text = str(value)
+
+ tr = SubElement(tfoot, "tr")
+ SubElement(tr, "td").text = "Total"
+ for l in labels:
+ SubElement(tr, "td", { "class" : l.mood }).text = str(l.sum)
SubElement(body, "br")
SubElement(body, "h2").text = "Summaries by Repository Host"
-
- for hostname in sorted(unique_hostnames):
+ for hostname in unique_hostnames:
SubElement(body, "br")
SubElement(body, "h3").text = hostname
- table = SubElement(body, "table", { "class" : "summary", "rules" : "all", "border" : "1"})
+ table = SubElement(body, "table", table_css)
thead = SubElement(table, "thead")
- tr = SubElement(thead, "tr")
- SubElement(tr, "td")
- for t in totals:
- if t.show:
- elt = SubElement(tr, "td")
- elt = SubElement(elt, "b")
- elt.text = t.text
+ tfoot = SubElement(table, "tfoot")
tbody = SubElement(table, "tbody")
- for fn2 in sorted(unique_fn2s):
- for generation in sorted(unique_generations):
- if any(h.hostname == hostname and h.fn2 == fn2 and h.generation == generation for h in host_data):
+ tr = SubElement(thead, "tr")
+ SubElement(tr, "th")
+ for l in labels:
+ SubElement(tr, "th").text = l.text
+ for fn2 in unique_fn2s:
+ for generation in unique_generations:
+ if any(v.hostname == hostname and v.fn2 == fn2 and v.generation == generation for v in validation_status):
tr = SubElement(tbody, "tr")
- SubElement(tr, "td").text = (generation or "") + " " + (fn2 or "")
- for t in totals:
- if t.show:
- value = sum(int(h.hostname == hostname and h.fn2 == fn2 and h.generation == generation and h.status == t.name) for h in host_data)
- elt = SubElement(tr, "td")
- if value > 0:
- elt.set("class", t.mood)
- elt.text = str(value)
- tr = SubElement(tbody, "tr")
+ SubElement(tr, "td").text = ((generation or "") + " " + (fn2 or "")).strip()
+ for l in labels:
+ value = sum(int(v.hostname == hostname and v.fn2 == fn2 and v.generation == generation and v.code == l.code) for v in validation_status)
+ td = SubElement(tr, "td")
+ if value > 0:
+ td.set("class", l.mood)
+ td.text = str(value)
+
+ tr = SubElement(tfoot, "tr")
SubElement(tr, "td").text = "Total"
- for t in totals:
- if t.show:
- value = sum(int(h.hostname == hostname and h.status == t.name) for h in host_data)
- elt = SubElement(tr, "td")
- if value > 0:
- elt.set("class", t.mood)
- elt.text = str(value)
+ for l in labels:
+ value = sum(int(v.hostname == hostname and v.code == l.code) for v in validation_status)
+ td = SubElement(tr, "td")
+ if value > 0:
+ td.set("class", l.mood)
+ td.text = str(value)
if show_problems:
SubElement(body, "br")
SubElement(body, "h2").text = "Problems"
- table = SubElement(body, "table", { "class" : "problems", "rules" : "all", "border" : "1"})
+ table = SubElement(body, "table", table_css)
thead = SubElement(table, "thead")
- tr = SubElement(thead, "tr")
- for c in ("Status", "URI"):
- elt = SubElement(tr, "td", { "class" : c.lower() })
- SubElement(elt, "b").text = c
tbody = SubElement(table, "tbody")
- for h in host_data:
- if h.mood != "good":
- tr = SubElement(tbody, "tr", { "class" : h.mood })
- SubElement(tr, "td", { "class" : "status" }).text = h.label.text
- SubElement(tr, "td", { "class" : "uri" }).text = h.uri
+ tr = SubElement(thead, "tr")
+ SubElement(tr, "th").text = "Status"
+ SubElement(tr, "th").text = "URI"
+ for v in validation_status:
+ if v.mood != "good":
+ tr = SubElement(tbody, "tr", { "class" : v.mood })
+ SubElement(tr, "td").text = v.label.text
+ SubElement(tr, "td", uri_css).text = v.uri
if show_detailed_status:
SubElement(body, "br")
SubElement(body, "h2").text = "Validation Status"
- table = SubElement(body, "table", { "class" : "details", "rules" : "all", "border" : "1"})
+ table = SubElement(body, "table", table_css)
thead = SubElement(table, "thead")
- tr = SubElement(thead, "tr")
- for c in ("Timestamp", "Generation", "Status", "URI"):
- elt = SubElement(tr, "td", { "class" : c.lower() })
- SubElement(elt, "b").text = c
tbody = SubElement(table, "tbody")
- for h in host_data:
- tr = SubElement(tbody, "tr", { "class" : h.mood })
- SubElement(tr, "td", { "class" : "timestamp" }).text = h.timestamp
- SubElement(tr, "td", { "class" : "generation" }).text = h.generation
- SubElement(tr, "td", { "class" : "status" }).text = h.label.text
- SubElement(tr, "td", { "class" : "uri" }).text = h.uri
+ tr = SubElement(thead, "tr")
+ SubElement(tr, "th").text = "Timestamp"
+ SubElement(tr, "th").text = "Generation"
+ SubElement(tr, "th").text = "Status"
+ SubElement(tr, "th").text = "URI"
+ for v in validation_status:
+ tr = SubElement(tbody, "tr", { "class" : v.mood })
+ SubElement(tr, "td").text = v.timestamp
+ SubElement(tr, "td").text = v.generation
+ SubElement(tr, "td").text = v.label.text
+ SubElement(tr, "td", uri_css).text = v.uri
ElementTree(element = html).write(sys.stdout)