1 import htmllib, formatter
3 class Require:
4 ''' Encapsulates a parsed <require attributes>...[<else>...]</require>
5 '''
6 def __init__(self, attributes):
7 self.attributes = attributes
8 self.current = self.ok = []
9 self.fail = []
10 def __len__(self):
11 return len(self.current)
12 def __getitem__(self, n):
13 return self.current[n]
14 def __setitem__(self, n, data):
15 self.current[n] = data
16 def append(self, data):
17 self.current.append(data)
18 def elseMode(self):
19 self.current = self.fail
20 def __repr__(self):
21 return '<Require %r ok:%r fail:%r>'%(self.attributes, self.ok,
22 self.fail)
24 class Display:
25 ''' Encapsulates a parsed <display attributes>
26 '''
27 def __init__(self, attributes):
28 self.attributes = attributes
29 def __repr__(self):
30 return '<Display %r>'%self.attributes
32 class Property:
33 ''' Encapsulates a parsed <property attributes>
34 '''
35 def __init__(self, attributes):
36 self.attributes = attributes
37 self.current = self.ok = []
38 def __len__(self):
39 return len(self.current)
40 def __getitem__(self, n):
41 return self.current[n]
42 def __setitem__(self, n, data):
43 self.current[n] = data
44 def append(self, data):
45 self.current.append(data)
46 def __repr__(self):
47 return '<Property %r %r>'%(self.attributes, self.structure)
49 class RoundupTemplate(htmllib.HTMLParser):
50 ''' Parse Roundup's HTML template structure into a list of components:
52 'string': this is just plain data to be displayed
53 Display : instances indicate that display functions are to be called
54 Require : if/else style check using the conditions in the attributes,
55 displaying the "ok" list of components or "fail" list
57 '''
58 def __init__(self):
59 htmllib.HTMLParser.__init__(self, formatter.NullFormatter())
60 self.current = self.structure = []
61 self.stack = []
63 def handle_data(self, data):
64 self.append_data(data)
66 def append_data(self, data):
67 if self.current and isinstance(self.current[-1], type('')):
68 self.current[-1] = self.current[-1] + data
69 else:
70 self.current.append(data)
72 def unknown_starttag(self, tag, attributes):
73 self.append_data('<%s' % tag)
74 closeit = 1
75 for name, value in attributes:
76 pos = value.find('<')
77 if pos > -1:
78 self.append_data(' %s="%s' % (name, value[:pos]))
79 closeit = 0
80 else:
81 self.append_data(' %s="%s"' % (name, value))
82 if closeit:
83 self.append_data('>')
85 def handle_starttag(self, tag, method, attributes):
86 if tag in ('require', 'else', 'display', 'property'):
87 method(attributes)
88 else:
89 self.unknown_starttag(tag, attributes)
91 def unknown_endtag(self, tag):
92 if tag in ('require','property'):
93 self.current = self.stack.pop()
94 else:
95 self.append_data('</%s>'%tag)
97 def handle_endtag(self, tag, method):
98 self.unknown_endtag(tag)
100 def close(self):
101 htmllib.HTMLParser.close(self)
103 def do_display(self, attributes):
104 self.current.append(Display(attributes))
106 def do_property(self, attributes):
107 p = Property(attributes)
108 self.current.append(p)
109 self.stack.append(self.current)
110 self.current = p
112 def do_require(self, attributes):
113 r = Require(attributes)
114 self.current.append(r)
115 self.stack.append(self.current)
116 self.current = r
118 def do_else(self, attributes):
119 self.current.elseMode()
121 def __repr__(self):
122 return '<RoundupTemplate %r>'%self.structure
124 def display(structure, indent=''):
125 ''' Pretty-print the parsed structure for debugging
126 '''
127 l = []
128 for entry in structure:
129 if isinstance(entry, type('')):
130 l.append("%s%s"%(indent, entry))
131 elif isinstance(entry, Require):
132 l.append('%sTEST: %r\n'%(indent, entry.attributes))
133 l.append('%sOK...'%indent)
134 l.append(display(entry.ok, indent+' '))
135 if entry.fail:
136 l.append('%sFAIL...'%indent)
137 l.append(display(entry.fail, indent+' '))
138 elif isinstance(entry, Display):
139 l.append('%sDISPLAY: %r'%(indent, entry.attributes))
140 elif isinstance(entry, Property):
141 l.append('%sPROPERTY: %r'%(indent, entry.attributes))
142 l.append(display(entry.ok, indent+' '))
143 return ''.join(l)
145 if __name__ == '__main__':
146 import sys
147 parser = RoundupTemplate()
148 parser.feed(open(sys.argv[1], 'r').read())
149 print display(parser.structure)