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