2000-02-25 Jonathan Blandford <jrb@redhat.com> * docs/make-todo (lineno): let title and logo be configurable so that GNOME can use this script too. * TODO.xml: added logourl and a title
		
			
				
	
	
		
			351 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			351 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
#!/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 '<a href="' + s.group(0) + '">' + s.group(0) + '</a>'
 | 
						|
    elif s.group(3) != None:
 | 
						|
        return '<a href="mailto:' + s.group(0) + '">' + s.group(0) + '</a>'
 | 
						|
        
 | 
						|
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 '<a href="http://bugs.gnome.org/db/%s/%s.html">#%s</a>' % (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 '''<table cellspacing="0" cellpadding="2" width="97%%" border="0" bgcolor="#000000">
 | 
						|
        <tbody><tr><td colspan=2>
 | 
						|
        <table cellspacing="0" cellpadding="5" width="100%%" border="0" bgcolor="#ffffff">
 | 
						|
        <tbody>
 | 
						|
   	  <tr bgcolor="%s">
 | 
						|
	     <td align="left"><font size="+1">%s</font></font></td>
 | 
						|
	     <td align="left" width="20%%"><b>Size</b>: %s</td>
 | 
						|
	     <td align="center" width="20%%"><b>Status</b>: %s</td>
 | 
						|
	     <td align="right" width="20%%"><b>Target Version</b>: %s</td>
 | 
						|
	  </tr>
 | 
						|
	  <tr>
 | 
						|
  	     <td colspan=4>
 | 
						|
             %s
 | 
						|
             <table cellspacing="0" cellpadding="0">
 | 
						|
               <tbody>''' % (bgcolor, self.title, self.size, self.status, self.target, htmlify(self.description))
 | 
						|
 | 
						|
        if self.url != None:
 | 
						|
            print '''<tr><td width="0"><b>More Info</b>:</td>
 | 
						|
		     <td>%s</td>
 | 
						|
                     </tr>''' % htmlify (self.url)
 | 
						|
 | 
						|
        if self.bugs != None:
 | 
						|
            print '''<tr><td width="0"><b>Bug Reports</b>:</td>
 | 
						|
		     <td>%s</td>
 | 
						|
                     </tr>''' % bugify (self.bugs)
 | 
						|
 | 
						|
        if self.contact != None:
 | 
						|
            print '''<tr><td width="0"><b>Contact</b>:</td>
 | 
						|
		     <td>%s</td>
 | 
						|
                     </tr>''' % htmlify (self.contact)
 | 
						|
 | 
						|
        print '''</tbody>
 | 
						|
             </table>
 | 
						|
	     </td>
 | 
						|
	 </tr>
 | 
						|
	</tbody></table>
 | 
						|
        </td></tr></tbody></table>
 | 
						|
'''
 | 
						|
 | 
						|
class Section:
 | 
						|
    def __init__(self):
 | 
						|
        self.title = None
 | 
						|
        self.entries = []
 | 
						|
 | 
						|
    def output(self):
 | 
						|
 | 
						|
        print '<h2><a name="%s">%s</a></h2>' % (make_id(self.title), self.title)
 | 
						|
        
 | 
						|
        first = 1
 | 
						|
        for entry in self.entries:
 | 
						|
            if not first:
 | 
						|
                print "<br>"
 | 
						|
            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, "<todo> 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, "<section> tags may not be nested"
 | 
						|
        
 | 
						|
        self.section = Section()
 | 
						|
 | 
						|
    def end_section(self):
 | 
						|
        if self.section.title == None:
 | 
						|
            raise ParseError, "<section> requires <title>"
 | 
						|
            
 | 
						|
        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 <contact>"
 | 
						|
        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</title>
 | 
						|
</head>
 | 
						|
<body bgcolor="#ffffff">
 | 
						|
<table width="100%%" cellspacing="0" cellpadding="0" border="0">
 | 
						|
  <tbody>
 | 
						|
    <tr valign="top">
 | 
						|
      <td>
 | 
						|
        <h1>%s</h1>''' % (parser.title, parser.title)
 | 
						|
 | 
						|
 | 
						|
for section in parser.sections:
 | 
						|
    ntasks = len(section.entries)
 | 
						|
    id = make_id (section.title)
 | 
						|
    if ntasks == 1:
 | 
						|
        print '<a href="#%s">%s</a> (1 item)<br>' % (id,section.title)
 | 
						|
    else:
 | 
						|
        print '<a href="#%s">%s</a> (%d items)<br>' % (id,section.title,ntasks)
 | 
						|
 | 
						|
print '''
 | 
						|
      </td>'''
 | 
						|
if parser.logourl != None:
 | 
						|
    print '''      <td align="right">
 | 
						|
       <img src="%s" alt="Logo"></img>
 | 
						|
      </td>''' % parser.logourl
 | 
						|
print '''
 | 
						|
    </tr>
 | 
						|
  </tbody>
 | 
						|
</table>
 | 
						|
''' 
 | 
						|
 | 
						|
first = 1
 | 
						|
for section in parser.sections:
 | 
						|
    if not first:
 | 
						|
        print "<br><br>"
 | 
						|
    first = 0
 | 
						|
    section.output()
 | 
						|
 | 
						|
print '''</body>
 | 
						|
</html>'''
 | 
						|
    
 | 
						|
 |