Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | # Copyright (C) 2004 Python Software Foundation |
2 | # Author: barry@python.org (Barry Warsaw) | |
3 | # License: http://www.opensource.org/licenses/PythonSoftFoundation.php | |
4 | ||
5 | import unittest | |
6 | from string import Template | |
7 | ||
8 | ||
9 | class Bag: | |
10 | pass | |
11 | ||
12 | class Mapping: | |
13 | def __getitem__(self, name): | |
14 | obj = self | |
15 | for part in name.split('.'): | |
16 | try: | |
17 | obj = getattr(obj, part) | |
18 | except AttributeError: | |
19 | raise KeyError(name) | |
20 | return obj | |
21 | ||
22 | ||
23 | class TestTemplate(unittest.TestCase): | |
24 | def test_regular_templates(self): | |
25 | s = Template('$who likes to eat a bag of $what worth $$100') | |
26 | self.assertEqual(s.substitute(dict(who='tim', what='ham')), | |
27 | 'tim likes to eat a bag of ham worth $100') | |
28 | self.assertRaises(KeyError, s.substitute, dict(who='tim')) | |
29 | ||
30 | def test_regular_templates_with_braces(self): | |
31 | s = Template('$who likes ${what} for ${meal}') | |
32 | d = dict(who='tim', what='ham', meal='dinner') | |
33 | self.assertEqual(s.substitute(d), 'tim likes ham for dinner') | |
34 | self.assertRaises(KeyError, s.substitute, | |
35 | dict(who='tim', what='ham')) | |
36 | ||
37 | def test_escapes(self): | |
38 | eq = self.assertEqual | |
39 | s = Template('$who likes to eat a bag of $$what worth $$100') | |
40 | eq(s.substitute(dict(who='tim', what='ham')), | |
41 | 'tim likes to eat a bag of $what worth $100') | |
42 | s = Template('$who likes $$') | |
43 | eq(s.substitute(dict(who='tim', what='ham')), 'tim likes $') | |
44 | ||
45 | def test_percents(self): | |
46 | eq = self.assertEqual | |
47 | s = Template('%(foo)s $foo ${foo}') | |
48 | d = dict(foo='baz') | |
49 | eq(s.substitute(d), '%(foo)s baz baz') | |
50 | eq(s.safe_substitute(d), '%(foo)s baz baz') | |
51 | ||
52 | def test_stringification(self): | |
53 | eq = self.assertEqual | |
54 | s = Template('tim has eaten $count bags of ham today') | |
55 | d = dict(count=7) | |
56 | eq(s.substitute(d), 'tim has eaten 7 bags of ham today') | |
57 | eq(s.safe_substitute(d), 'tim has eaten 7 bags of ham today') | |
58 | s = Template('tim has eaten ${count} bags of ham today') | |
59 | eq(s.substitute(d), 'tim has eaten 7 bags of ham today') | |
60 | ||
61 | def test_SafeTemplate(self): | |
62 | eq = self.assertEqual | |
63 | s = Template('$who likes ${what} for ${meal}') | |
64 | eq(s.safe_substitute(dict(who='tim')), 'tim likes ${what} for ${meal}') | |
65 | eq(s.safe_substitute(dict(what='ham')), '$who likes ham for ${meal}') | |
66 | eq(s.safe_substitute(dict(what='ham', meal='dinner')), | |
67 | '$who likes ham for dinner') | |
68 | eq(s.safe_substitute(dict(who='tim', what='ham')), | |
69 | 'tim likes ham for ${meal}') | |
70 | eq(s.safe_substitute(dict(who='tim', what='ham', meal='dinner')), | |
71 | 'tim likes ham for dinner') | |
72 | ||
73 | def test_invalid_placeholders(self): | |
74 | raises = self.assertRaises | |
75 | s = Template('$who likes $') | |
76 | raises(ValueError, s.substitute, dict(who='tim')) | |
77 | s = Template('$who likes ${what)') | |
78 | raises(ValueError, s.substitute, dict(who='tim')) | |
79 | s = Template('$who likes $100') | |
80 | raises(ValueError, s.substitute, dict(who='tim')) | |
81 | ||
82 | def test_delimiter_override(self): | |
83 | class PieDelims(Template): | |
84 | delimiter = '@' | |
85 | s = PieDelims('@who likes to eat a bag of @{what} worth $100') | |
86 | self.assertEqual(s.substitute(dict(who='tim', what='ham')), | |
87 | 'tim likes to eat a bag of ham worth $100') | |
88 | ||
89 | def test_idpattern_override(self): | |
90 | class PathPattern(Template): | |
91 | idpattern = r'[_a-z][._a-z0-9]*' | |
92 | m = Mapping() | |
93 | m.bag = Bag() | |
94 | m.bag.foo = Bag() | |
95 | m.bag.foo.who = 'tim' | |
96 | m.bag.what = 'ham' | |
97 | s = PathPattern('$bag.foo.who likes to eat a bag of $bag.what') | |
98 | self.assertEqual(s.substitute(m), 'tim likes to eat a bag of ham') | |
99 | ||
100 | def test_pattern_override(self): | |
101 | class MyPattern(Template): | |
102 | pattern = r""" | |
103 | (?P<escaped>@{2}) | | |
104 | @(?P<named>[_a-z][._a-z0-9]*) | | |
105 | @{(?P<braced>[_a-z][._a-z0-9]*)} | | |
106 | (?P<invalid>@) | |
107 | """ | |
108 | m = Mapping() | |
109 | m.bag = Bag() | |
110 | m.bag.foo = Bag() | |
111 | m.bag.foo.who = 'tim' | |
112 | m.bag.what = 'ham' | |
113 | s = MyPattern('@bag.foo.who likes to eat a bag of @bag.what') | |
114 | self.assertEqual(s.substitute(m), 'tim likes to eat a bag of ham') | |
115 | ||
116 | class BadPattern(Template): | |
117 | pattern = r""" | |
118 | (?P<badname>.*) | | |
119 | (?P<escaped>@{2}) | | |
120 | @(?P<named>[_a-z][._a-z0-9]*) | | |
121 | @{(?P<braced>[_a-z][._a-z0-9]*)} | | |
122 | (?P<invalid>@) | | |
123 | """ | |
124 | s = BadPattern('@bag.foo.who likes to eat a bag of @bag.what') | |
125 | self.assertRaises(ValueError, s.substitute, {}) | |
126 | self.assertRaises(ValueError, s.safe_substitute, {}) | |
127 | ||
128 | def test_unicode_values(self): | |
129 | s = Template('$who likes $what') | |
130 | d = dict(who=u't\xffm', what=u'f\xfe\fed') | |
131 | self.assertEqual(s.substitute(d), u't\xffm likes f\xfe\x0ced') | |
132 | ||
133 | def test_keyword_arguments(self): | |
134 | eq = self.assertEqual | |
135 | s = Template('$who likes $what') | |
136 | eq(s.substitute(who='tim', what='ham'), 'tim likes ham') | |
137 | eq(s.substitute(dict(who='tim'), what='ham'), 'tim likes ham') | |
138 | eq(s.substitute(dict(who='fred', what='kung pao'), | |
139 | who='tim', what='ham'), | |
140 | 'tim likes ham') | |
141 | s = Template('the mapping is $mapping') | |
142 | eq(s.substitute(dict(foo='none'), mapping='bozo'), | |
143 | 'the mapping is bozo') | |
144 | eq(s.substitute(dict(mapping='one'), mapping='two'), | |
145 | 'the mapping is two') | |
146 | ||
147 | def test_keyword_arguments_safe(self): | |
148 | eq = self.assertEqual | |
149 | raises = self.assertRaises | |
150 | s = Template('$who likes $what') | |
151 | eq(s.safe_substitute(who='tim', what='ham'), 'tim likes ham') | |
152 | eq(s.safe_substitute(dict(who='tim'), what='ham'), 'tim likes ham') | |
153 | eq(s.safe_substitute(dict(who='fred', what='kung pao'), | |
154 | who='tim', what='ham'), | |
155 | 'tim likes ham') | |
156 | s = Template('the mapping is $mapping') | |
157 | eq(s.safe_substitute(dict(foo='none'), mapping='bozo'), | |
158 | 'the mapping is bozo') | |
159 | eq(s.safe_substitute(dict(mapping='one'), mapping='two'), | |
160 | 'the mapping is two') | |
161 | d = dict(mapping='one') | |
162 | raises(TypeError, s.substitute, d, {}) | |
163 | raises(TypeError, s.safe_substitute, d, {}) | |
164 | ||
165 | def test_delimiter_override(self): | |
166 | eq = self.assertEqual | |
167 | raises = self.assertRaises | |
168 | class AmpersandTemplate(Template): | |
169 | delimiter = '&' | |
170 | s = AmpersandTemplate('this &gift is for &{who} &&') | |
171 | eq(s.substitute(gift='bud', who='you'), 'this bud is for you &') | |
172 | raises(KeyError, s.substitute) | |
173 | eq(s.safe_substitute(gift='bud', who='you'), 'this bud is for you &') | |
174 | eq(s.safe_substitute(), 'this &gift is for &{who} &') | |
175 | s = AmpersandTemplate('this &gift is for &{who} &') | |
176 | raises(ValueError, s.substitute, dict(gift='bud', who='you')) | |
177 | eq(s.safe_substitute(), 'this &gift is for &{who} &') | |
178 | ||
179 | ||
180 | def test_main(): | |
181 | from test import test_support | |
182 | test_classes = [TestTemplate,] | |
183 | test_support.run_unittest(*test_classes) | |
184 | ||
185 | ||
186 | if __name__ == '__main__': | |
187 | test_main() |