#!/usr/bin/python import xmllib; import sys; import string import re def html_subst(s): if s.group(1) != None: return s.group(0) elif s.group(2) != None: return '' + s.group(0) + '' elif s.group(3) != None: return '' + s.group(0) + '' def htmlify(str): return re.sub ("(<[^>]*>)|(http://[~.:/\w-]+)|([\w._!-]+@[\w_-]+).[\w_-]+", html_subst, str) def bug_subst(s): if s.group(1) != None: return s.group(0) else: n = s.group(2) return '#%s' % (n[0:2], n, n) def bugify(str): str = re.sub ("(<[^>]*>)|#(\d+)", bug_subst, str) return htmlify(str) def make_id(str): return re.sub ("[^a-z]","-", string.lower(str)) class ParseError (Exception): pass class Entry: def __init__(self): self.description = None self.title = None self.url = None self.contact = None self.bugs = None def set_size(self, size): size = string.lower(size) if size == "small": self.size = "Small" elif size == "medium": self.size = "Medium" elif size == "big": self.size = "Big" else: raise ParseError, 'size must be "small", "medium", or "big"' def output(self): if self.size == "Big": bgcolor = "#88bb88" elif self.size == "Medium": bgcolor = "#b4d4b4" else: bgcolor = "#d0e0d0" print '''
%s Size: %s Status: %s Target Version: %s
%s ''' % (bgcolor, self.title, self.size, self.status, self.target, htmlify(self.description)) if self.url != None: print '''''' % htmlify (self.url) if self.bugs != None: print '''''' % bugify (self.bugs) if self.contact != None: print '''''' % htmlify (self.contact) print '''
More Info: %s
Bug Reports: %s
Contact: %s
''' class Section: def __init__(self): self.title = None self.entries = [] def output(self): print '

%s

' % (make_id(self.title), self.title) first = 1 for entry in self.entries: if not first: print "
" first = 0 entry.output() class TodoParser (xmllib.XMLParser): def __init__(self): xmllib.XMLParser.__init__(self) self.in_todo = 0 self.in_data = 0 self.data = "" self.section = None self.entry = None self.logourl = None self.title = None self.sections = [] self.entitydefs = {} def start_todo(self,attributes): if self.in_todo: raise ParseError, " tags may not be nested" if attributes.has_key ("logourl"): self.logourl = attributes["logourl"] self.in_todo = 1 def end_todo(self): self.in_todo = 0 def start_section(self,attributes): if self.section: raise ParseError, "
tags may not be nested" self.section = Section() def end_section(self): if self.section.title == None: raise ParseError, "
requires " self.sections.append(self.section) self.section = None def start_title(self,attributes): if not self.in_todo: raise ParseError, "<title> tag must be in <todo>, <section> or <entry>" if self.in_data: raise ParseError, "Unexpected <title> tag in content" self.in_data = 1 def end_title(self): self.in_data = 0 if self.entry: self.entry.title = self.data elif self.section: self.section.title = self.data else: self.title = self.data self.data = "" def start_description(self,attributes): if not self.entry: raise ParseError, "<description> tag must be in <entry>" if self.in_data: raise ParseError, "Unexpected <description> tag in content" self.in_data = 1 def end_description(self): self.in_data = 0 self.entry.description = self.data self.data = "" def start_url(self,attributes): if not self.entry: raise ParseError, "<url> tag must be in <entry>" if self.in_data: raise ParseError, "Unexpected <url> tag in content" self.in_data = 1 def end_url(self): self.in_data = 0 self.entry.url = self.data self.data = "" def start_contact(self,attributes): if not self.entry: raise ParseError, "<contact> tag must be in <entry>" if self.in_data: raise ParseError, "Unexpected <contact> tag in content" self.in_data = 1 def end_contact(self): self.in_data = 0 self.entry.contact = self.data self.data = "" def start_bugs(self,attributes): if not self.entry: raise ParseError, "<bugs> tag must be in <bugs>" if self.in_data: raise ParseError, "Unexpected <bugs> tag in content" self.in_data = 1 def end_bugs(self): self.in_data = 0 self.entry.bugs = self.data self.data = "" def start_entry(self,attributes): if not self.section: raise ParseError, "<entry> tag must be in <section>" if self.entry: raise ParseError, "<entry> tags may not be nested" self.entry = Entry() if not attributes.has_key("size"): raise ParseError, '"size" attribute required for entry' self.entry.set_size(attributes["size"]) if not attributes.has_key("status"): raise ParseError, '"status" attribute (completion percentage) required for entry' self.entry.status=attributes["status"] if not attributes.has_key("target"): raise ParseError, '"target" attribute (target version) required for entry' self.entry.target=attributes["target"] def end_entry(self): if self.entry.title == None: raise ParseError, "<entry> requires <title>" if self.entry.description == None: raise ParseError, "<entry> requires <description>" self.section.entries.append(self.entry) self.entry = None def handle_data(self,data): if self.in_data: self.data = self.data + data def unknown_starttag(self,tag,attributes): if not self.in_data: raise ParseError, "Unexpected start tag: " + tag else: self.data = self.data + "<" + tag for (key,val) in attributes.items(): self.data = self.data + ' %s="%s"' % (key,val) self.data = self.data + ">" def unknown_endtag(self,tag): if not self.in_data: raise ParseError, "Unexpected end tag: " + tag else: self.data = self.data + "</%s>" % tag def syntax_error(self, err): if re.match("reference to unknown entity", err): pass else: xmllib.XMLParser.syntax_error (self, err) def unknown_entityref(self,ref): if not self.in_data: raise ParseError, "Unknown entity &" + ref + ";" else: self.data = self.data + "&" + ref + ";" file = open(sys.argv[1]) parser = TodoParser() lineno = 1 while 1: line = file.readline() if line == "": break try: parser.feed(line) except ParseError, err: sys.stderr.write("Parse error at line " + `lineno` + ": " + err.__str__() + "\n") sys.exit(1) except RuntimeError, err: sys.stderr.write(err.__str__() + "\n") sys.exit(1) lineno = lineno + 1 parser.close() if parser.title == None: sys.stderr.write ("<todo> Document must have a <title>\n") sys.exit (1) print '''<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"> <html> <head> <title>%s ''' if parser.logourl != None: print ''' ''' % parser.logourl print '''

%s

''' % (parser.title, parser.title) for section in parser.sections: ntasks = len(section.entries) id = make_id (section.title) if ntasks == 1: print '%s (1 item)
' % (id,section.title) else: print '%s (%d items)
' % (id,section.title,ntasks) print '''
Logo
''' first = 1 for section in parser.sections: if not first: print "

" first = 0 section.output() print ''' '''