Skip to content

Commit a57ed8a

Browse files
author
Richard Jones
committed
fixes to the new template parser
1 parent 3ae3c51 commit a57ed8a

File tree

2 files changed

+137
-17
lines changed

2 files changed

+137
-17
lines changed

roundup/template_parser.py

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,36 @@ def append(self, data):
1717
self.current.append(data)
1818
def elseMode(self):
1919
self.current = self.fail
20+
def __repr__(self):
21+
return '<Require %r ok:%r fail:%r>'%(self.attributes, self.ok,
22+
self.fail)
2023

2124
class Display:
2225
''' Encapsulates a parsed <display attributes>
2326
'''
2427
def __init__(self, attributes):
2528
self.attributes = attributes
29+
def __repr__(self):
30+
return '<Display %r>'%self.attributes
2631

2732
class Property:
2833
''' Encapsulates a parsed <property attributes>
2934
'''
3035
def __init__(self, attributes):
3136
self.attributes = attributes
37+
self.current = self.structure = []
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)
3248

33-
class RoundupTemplateParser(htmllib.HTMLParser):
49+
class RoundupTemplate(htmllib.HTMLParser):
3450
''' Parse Roundup's HTML template structure into a list of components:
3551
3652
'string': this is just plain data to be displayed
@@ -68,7 +84,7 @@ def handle_starttag(self, tag, method, attributes):
6884
self.unknown_starttag(tag, attributes)
6985

7086
def unknown_endtag(self, tag):
71-
if tag == 'require':
87+
if tag in ('require','property'):
7288
self.current = self.stack.pop()
7389
else:
7490
self.append_data('</%s>'%tag)
@@ -83,7 +99,10 @@ def do_display(self, attributes):
8399
self.current.append(Display(attributes))
84100

85101
def do_property(self, attributes):
86-
self.current.append(Property(attributes))
102+
p = Property(attributes)
103+
self.current.append(p)
104+
self.stack.append(self.current)
105+
self.current = p
87106

88107
def do_require(self, attributes):
89108
r = Require(attributes)
@@ -94,30 +113,33 @@ def do_require(self, attributes):
94113
def do_else(self, attributes):
95114
self.current.elseMode()
96115

116+
def __repr__(self):
117+
return '<RoundupTemplate %r>'%self.structure
118+
97119
def display(structure, indent=''):
98120
''' Pretty-print the parsed structure for debugging
99121
'''
122+
l = []
100123
for entry in structure:
101124
if isinstance(entry, type('')):
102-
print "%s%r"%(indent, entry[:50])
125+
l.append("%s%s"%(indent, entry))
103126
elif isinstance(entry, Require):
104-
print '%sTEST: %r'%(indent, entry.attributes)
105-
print '%sOK...'%indent
106-
display(entry.ok, indent+' ')
127+
l.append('%sTEST: %r\n'%(indent, entry.attributes))
128+
l.append('%sOK...'%indent)
129+
l.append(display(entry.ok, indent+' '))
107130
if entry.fail:
108-
print '%sFAIL...'%indent
109-
display(entry.fail, indent+' ')
131+
l.append('%sFAIL...'%indent)
132+
l.append(display(entry.fail, indent+' '))
110133
elif isinstance(entry, Display):
111-
print '%sDISPLAY: %r'%(indent, entry.attributes)
134+
l.append('%sDISPLAY: %r'%(indent, entry.attributes))
135+
elif isinstance(entry, Property):
136+
l.append('%sPROPERTY: %r'%(indent, entry.attributes))
137+
l.append(display(entry.structure, indent+' '))
138+
return ''.join(l)
112139

113140
if __name__ == '__main__':
114141
import sys
115-
parser = RoundupTemplateParser()
142+
parser = RoundupTemplate()
116143
parser.feed(open(sys.argv[1], 'r').read())
117-
display(parser.structure)
118-
119-
#
120-
# $Log: not supported by cvs2svn $
121-
#
122-
# vim: set filetype=python ts=4 sw=4 et si
144+
print display(parser.structure)
123145

test/test_template_parser.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# $Id: test_template_parser.py,v 1.1 2002-08-02 23:45:41 richard Exp $
2+
3+
import unittest
4+
from roundup import template_parser
5+
6+
class TemplateParserTestCase(unittest.TestCase):
7+
def testParser(self):
8+
parser = template_parser.RoundupTemplate()
9+
s = '''
10+
<table border=0 cellspacing=5 cellpadding=0>
11+
<tr>
12+
<td bgcolor="ffffea">
13+
<property name="prop1">
14+
<require permission="perm1">
15+
<display call="field('prop1')">
16+
<else>
17+
<display call="plain('prop1')">
18+
</require>
19+
</property>
20+
</td>
21+
</tr>
22+
</table>
23+
24+
<table border=0 cellspacing=5 cellpadding=0>
25+
<property name="prop2">
26+
<tr>
27+
<td class="form-label">Prop2:</td>
28+
<td class="form-text">
29+
<require permission="perm2">
30+
<display call="field('prop2')">
31+
<else>
32+
<display call="plain('prop2')">
33+
</require>
34+
</td>
35+
</tr>
36+
</property>
37+
</table>'''
38+
parser.feed(s)
39+
self.assertEqual(template_parser.display(parser.structure),
40+
'\n<table border="0" cellspacing="5" cellpadding="0">\n <tr>\n <td bgcolor="ffffea">\n PROPERTY: [(\'name\', \'prop1\')] \n TEST: [(\'permission\', \'perm1\')]\n OK... \n DISPLAY: [(\'call\', "field(\'prop1\')")] \n FAIL... \n DISPLAY: [(\'call\', "plain(\'prop1\')")] \n \n \n </td>\n </tr>\n</table>\n\n<table border="0" cellspacing="5" cellpadding="0">\n PROPERTY: [(\'name\', \'prop2\')] \n <tr>\n <td class="form-label">Prop2:</td>\n <td class="form-text">\n TEST: [(\'permission\', \'perm2\')]\n OK... \n DISPLAY: [(\'call\', "field(\'prop2\')")] \n FAIL... \n DISPLAY: [(\'call\', "plain(\'prop2\')")] \n \n </td>\n </tr>\n \n</table>')
41+
42+
def suite():
43+
return unittest.makeSuite(TemplateParserTestCase, 'test')
44+
45+
46+
#
47+
# $Log: not supported by cvs2svn $
48+
# Revision 1.12 2002/07/14 06:05:50 richard
49+
# . fixed the date module so that Date(". - 2d") works
50+
#
51+
# Revision 1.11 2002/02/21 23:34:52 richard
52+
# Oops, there's 24 hours in a day, and subtraction of intervals now works
53+
# properly.
54+
#
55+
# Revision 1.10 2002/02/21 23:11:45 richard
56+
# . fixed some problems in date calculations (calendar.py doesn't handle over-
57+
# and under-flow). Also, hour/minute/second intervals may now be more than
58+
# 99 each.
59+
#
60+
# Revision 1.9 2002/02/21 06:57:39 richard
61+
# . Added popup help for classes using the classhelp html template function.
62+
# - add <display call="classhelp('priority', 'id,name,description')">
63+
# to an item page, and it generates a link to a popup window which displays
64+
# the id, name and description for the priority class. The description
65+
# field won't exist in most installations, but it will be added to the
66+
# default templates.
67+
#
68+
# Revision 1.8 2002/01/16 07:02:57 richard
69+
# . lots of date/interval related changes:
70+
# - more relaxed date format for input
71+
#
72+
# Revision 1.7 2001/08/13 23:01:53 richard
73+
# fixed a 2.1-ism
74+
#
75+
# Revision 1.6 2001/08/07 00:24:43 richard
76+
# stupid typo
77+
#
78+
# Revision 1.5 2001/08/07 00:15:51 richard
79+
# Added the copyright/license notice to (nearly) all files at request of
80+
# Bizar Software.
81+
#
82+
# Revision 1.4 2001/07/29 23:32:13 richard
83+
# Fixed bug in unit test ;)
84+
#
85+
# Revision 1.3 2001/07/29 07:01:39 richard
86+
# Added vim command to all source so that we don't get no steenkin' tabs :)
87+
#
88+
# Revision 1.2 2001/07/29 06:42:20 richard
89+
# Added Interval tests.
90+
#
91+
# Revision 1.1 2001/07/27 06:55:07 richard
92+
# moving tests -> test
93+
#
94+
# Revision 1.2 2001/07/25 04:34:31 richard
95+
# Added id and log to tests files...
96+
#
97+
#
98+
# vim: set filetype=python ts=4 sw=4 et si

0 commit comments

Comments
 (0)