blob: 94d2b67174c31e81e510cad106c36602839dc3f9 [file] [log] [blame]
Barry Warsaw8bee7612004-08-25 02:22:30 +00001import unittest
Serhiy Storchaka6d38c2b2016-06-03 09:36:15 +03002import string
Barry Warsaw12827c12004-09-10 03:08:08 +00003from string import Template
Walter Dörwald0fd583c2003-02-21 12:53:50 +00004from test import test_support, string_tests
5from UserList import UserList
Barry Warsaw50f0e161999-06-10 22:53:10 +00006
Walter Dörwald0fd583c2003-02-21 12:53:50 +00007class StringTest(
8 string_tests.CommonTest,
9 string_tests.MixinStrStringUserStringTest
10 ):
Barry Warsaw6e1d78a1999-06-15 16:49:11 +000011
Walter Dörwald0fd583c2003-02-21 12:53:50 +000012 type2test = str
Barry Warsaw50f0e161999-06-10 22:53:10 +000013
Walter Dörwald0fd583c2003-02-21 12:53:50 +000014 def checkequal(self, result, object, methodname, *args):
15 realresult = getattr(string, methodname)(object, *args)
16 self.assertEqual(
17 result,
18 realresult
19 )
Barry Warsaw50f0e161999-06-10 22:53:10 +000020
Benjamin Peterson1643d5c2014-09-28 12:48:46 -040021 def checkraises(self, exc, obj, methodname, *args):
22 with self.assertRaises(exc) as cm:
23 getattr(string, methodname)(obj, *args)
Terry Jan Reedyc0dc65e2014-10-12 22:00:10 -040024 self.assertNotEqual(cm.exception.args[0], '')
Marc-André Lemburg79f57832002-12-29 19:44:06 +000025
Walter Dörwald0fd583c2003-02-21 12:53:50 +000026 def checkcall(self, object, methodname, *args):
27 getattr(string, methodname)(object, *args)
28
29 def test_join(self):
30 # These are the same checks as in string_test.ObjectTest.test_join
31 # but the argument order ist different
32 self.checkequal('a b c d', ['a', 'b', 'c', 'd'], 'join', ' ')
33 self.checkequal('abcd', ('a', 'b', 'c', 'd'), 'join', '')
34 self.checkequal('w x y z', string_tests.Sequence(), 'join', ' ')
35 self.checkequal('abc', ('abc',), 'join', 'a')
36 self.checkequal('z', UserList(['z']), 'join', 'a')
37 if test_support.have_unicode:
38 self.checkequal(unicode('a.b.c'), ['a', 'b', 'c'], 'join', unicode('.'))
39 self.checkequal(unicode('a.b.c'), [unicode('a'), 'b', 'c'], 'join', '.')
40 self.checkequal(unicode('a.b.c'), ['a', unicode('b'), 'c'], 'join', '.')
41 self.checkequal(unicode('a.b.c'), ['a', 'b', unicode('c')], 'join', '.')
42 self.checkraises(TypeError, ['a', unicode('b'), 3], 'join', '.')
43 for i in [5, 25, 125]:
44 self.checkequal(
45 ((('a' * i) + '-') * i)[:-1],
46 ['a' * i] * i, 'join', '-')
47 self.checkequal(
48 ((('a' * i) + '-') * i)[:-1],
49 ('a' * i,) * i, 'join', '-')
50
51 self.checkraises(TypeError, string_tests.BadSeq1(), 'join', ' ')
52 self.checkequal('a b c', string_tests.BadSeq2(), 'join', ' ')
Michael W. Hudsonb2308bb2005-10-21 11:45:01 +000053 try:
54 def f():
55 yield 4 + ""
56 self.fixtype(' ').join(f())
57 except TypeError, e:
58 if '+' not in str(e):
59 self.fail('join() ate exception message')
60 else:
61 self.fail('exception not raised')
62
63
Walter Dörwald0fd583c2003-02-21 12:53:50 +000064class ModuleTest(unittest.TestCase):
65
66 def test_attrs(self):
67 string.whitespace
68 string.lowercase
69 string.uppercase
70 string.letters
71 string.digits
72 string.hexdigits
73 string.octdigits
74 string.punctuation
75 string.printable
76
77 def test_atoi(self):
78 self.assertEqual(string.atoi(" 1 "), 1)
79 self.assertRaises(ValueError, string.atoi, " 1x")
80 self.assertRaises(ValueError, string.atoi, " x1 ")
81
82 def test_atol(self):
83 self.assertEqual(string.atol(" 1 "), 1L)
84 self.assertRaises(ValueError, string.atol, " 1x ")
85 self.assertRaises(ValueError, string.atol, " x1 ")
86
87 def test_atof(self):
88 self.assertAlmostEqual(string.atof(" 1 "), 1.0)
89 self.assertRaises(ValueError, string.atof, " 1x ")
90 self.assertRaises(ValueError, string.atof, " x1 ")
91
92 def test_maketrans(self):
93 transtable = '\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`xyzdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377'
94
95 self.assertEqual(string.maketrans('abc', 'xyz'), transtable)
96 self.assertRaises(ValueError, string.maketrans, 'abc', 'xyzq')
97
98 def test_capwords(self):
99 self.assertEqual(string.capwords('abc def ghi'), 'Abc Def Ghi')
100 self.assertEqual(string.capwords('abc\tdef\nghi'), 'Abc Def Ghi')
101 self.assertEqual(string.capwords('abc\t def \nghi'), 'Abc Def Ghi')
102 self.assertEqual(string.capwords('ABC DEF GHI'), 'Abc Def Ghi')
103 self.assertEqual(string.capwords('ABC-DEF-GHI', '-'), 'Abc-Def-Ghi')
104 self.assertEqual(string.capwords('ABC-def DEF-ghi GHI'), 'Abc-def Def-ghi Ghi')
Ezio Melotti9aac2452009-09-26 11:20:53 +0000105 self.assertEqual(string.capwords(' aBc DeF '), 'Abc Def')
106 self.assertEqual(string.capwords('\taBc\tDeF\t'), 'Abc Def')
107 self.assertEqual(string.capwords('\taBc\tDeF\t', '\t'), '\tAbc\tDef\t')
Walter Dörwald0fd583c2003-02-21 12:53:50 +0000108
Eric Smitha9f7d622008-02-17 19:46:49 +0000109 def test_formatter(self):
110 fmt = string.Formatter()
111 self.assertEqual(fmt.format("foo"), "foo")
112
113 self.assertEqual(fmt.format("foo{0}", "bar"), "foobar")
114 self.assertEqual(fmt.format("foo{1}{0}-{1}", "bar", 6), "foo6bar-6")
115 self.assertEqual(fmt.format("-{arg!r}-", arg='test'), "-'test'-")
116
117 # override get_value ############################################
118 class NamespaceFormatter(string.Formatter):
119 def __init__(self, namespace={}):
120 string.Formatter.__init__(self)
121 self.namespace = namespace
122
123 def get_value(self, key, args, kwds):
124 if isinstance(key, str):
125 try:
126 # Check explicitly passed arguments first
127 return kwds[key]
128 except KeyError:
129 return self.namespace[key]
130 else:
131 string.Formatter.get_value(key, args, kwds)
132
133 fmt = NamespaceFormatter({'greeting':'hello'})
134 self.assertEqual(fmt.format("{greeting}, world!"), 'hello, world!')
135
136
137 # override format_field #########################################
138 class CallFormatter(string.Formatter):
139 def format_field(self, value, format_spec):
140 return format(value(), format_spec)
141
142 fmt = CallFormatter()
143 self.assertEqual(fmt.format('*{0}*', lambda : 'result'), '*result*')
144
145
146 # override convert_field ########################################
147 class XFormatter(string.Formatter):
148 def convert_field(self, value, conversion):
149 if conversion == 'x':
150 return None
151 return super(XFormatter, self).convert_field(value, conversion)
152
153 fmt = XFormatter()
154 self.assertEqual(fmt.format("{0!r}:{0!x}", 'foo', 'foo'), "'foo':None")
155
156
157 # override parse ################################################
158 class BarFormatter(string.Formatter):
159 # returns an iterable that contains tuples of the form:
160 # (literal_text, field_name, format_spec, conversion)
161 def parse(self, format_string):
162 for field in format_string.split('|'):
163 if field[0] == '+':
164 # it's markup
165 field_name, _, format_spec = field[1:].partition(':')
166 yield '', field_name, format_spec, None
167 else:
168 yield field, None, None, None
169
170 fmt = BarFormatter()
171 self.assertEqual(fmt.format('*|+0:^10s|*', 'foo'), '* foo *')
172
173 # test all parameters used
174 class CheckAllUsedFormatter(string.Formatter):
175 def check_unused_args(self, used_args, args, kwargs):
Ezio Melotti24b07bc2011-03-15 18:55:01 +0200176 # Track which arguments actually got used
Eric Smitha9f7d622008-02-17 19:46:49 +0000177 unused_args = set(kwargs.keys())
178 unused_args.update(range(0, len(args)))
179
180 for arg in used_args:
181 unused_args.remove(arg)
182
183 if unused_args:
184 raise ValueError("unused arguments")
185
186 fmt = CheckAllUsedFormatter()
187 self.assertEqual(fmt.format("{0}", 10), "10")
188 self.assertEqual(fmt.format("{0}{i}", 10, i=100), "10100")
189 self.assertEqual(fmt.format("{0}{i}{1}", 10, 20, i=100), "1010020")
190 self.assertRaises(ValueError, fmt.format, "{0}{i}{1}", 10, 20, i=100, j=0)
191 self.assertRaises(ValueError, fmt.format, "{0}", 10, 20)
192 self.assertRaises(ValueError, fmt.format, "{0}", 10, 20, i=100)
193 self.assertRaises(ValueError, fmt.format, "{i}", 10, 20, i=100)
194
Eric Smithd0c84122008-07-15 10:10:07 +0000195 # Alternate formatting is not supported
196 self.assertRaises(ValueError, format, '', '#')
197 self.assertRaises(ValueError, format, '', '#20')
198
Serhiy Storchaka40fd0e82015-03-24 22:27:50 +0200199 def test_format_keyword_arguments(self):
200 fmt = string.Formatter()
201 self.assertEqual(fmt.format("-{arg}-", arg='test'), '-test-')
202 self.assertRaises(KeyError, fmt.format, "-{arg}-")
203 self.assertEqual(fmt.format("-{self}-", self='test'), '-test-')
204 self.assertRaises(KeyError, fmt.format, "-{self}-")
205 self.assertEqual(fmt.format("-{format_string}-", format_string='test'),
206 '-test-')
207 self.assertRaises(KeyError, fmt.format, "-{format_string}-")
208 self.assertEqual(fmt.format(arg='test', format_string="-{arg}-"),
209 '-test-')
210
Christian Heimes288e89a2008-01-18 18:24:07 +0000211class BytesAliasTest(unittest.TestCase):
212
213 def test_builtin(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000214 self.assertTrue(str is bytes)
Christian Heimes288e89a2008-01-18 18:24:07 +0000215
216 def test_syntax(self):
217 self.assertEqual(b"spam", "spam")
218 self.assertEqual(br"egg\foo", "egg\\foo")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000219 self.assertTrue(type(b""), str)
220 self.assertTrue(type(br""), str)
Christian Heimes288e89a2008-01-18 18:24:07 +0000221
Walter Dörwald0fd583c2003-02-21 12:53:50 +0000222
Serhiy Storchaka6d38c2b2016-06-03 09:36:15 +0300223# Template tests (formerly housed in test_pep292.py)
Barry Warsaw12827c12004-09-10 03:08:08 +0000224
225class Bag:
226 pass
227
228class Mapping:
229 def __getitem__(self, name):
230 obj = self
231 for part in name.split('.'):
232 try:
233 obj = getattr(obj, part)
234 except AttributeError:
235 raise KeyError(name)
236 return obj
237
Barry Warsaw8bee7612004-08-25 02:22:30 +0000238
239class TestTemplate(unittest.TestCase):
Barry Warsaw8bee7612004-08-25 02:22:30 +0000240 def test_regular_templates(self):
241 s = Template('$who likes to eat a bag of $what worth $$100')
Barry Warsaw12827c12004-09-10 03:08:08 +0000242 self.assertEqual(s.substitute(dict(who='tim', what='ham')),
Barry Warsaw8bee7612004-08-25 02:22:30 +0000243 'tim likes to eat a bag of ham worth $100')
Barry Warsaw12827c12004-09-10 03:08:08 +0000244 self.assertRaises(KeyError, s.substitute, dict(who='tim'))
Serhiy Storchaka40fd0e82015-03-24 22:27:50 +0200245 self.assertRaises(TypeError, Template.substitute)
Barry Warsaw8bee7612004-08-25 02:22:30 +0000246
247 def test_regular_templates_with_braces(self):
248 s = Template('$who likes ${what} for ${meal}')
Barry Warsaw12827c12004-09-10 03:08:08 +0000249 d = dict(who='tim', what='ham', meal='dinner')
250 self.assertEqual(s.substitute(d), 'tim likes ham for dinner')
251 self.assertRaises(KeyError, s.substitute,
252 dict(who='tim', what='ham'))
Barry Warsaw8bee7612004-08-25 02:22:30 +0000253
254 def test_escapes(self):
255 eq = self.assertEqual
256 s = Template('$who likes to eat a bag of $$what worth $$100')
Barry Warsaw12827c12004-09-10 03:08:08 +0000257 eq(s.substitute(dict(who='tim', what='ham')),
Barry Warsaw8bee7612004-08-25 02:22:30 +0000258 'tim likes to eat a bag of $what worth $100')
259 s = Template('$who likes $$')
Barry Warsaw12827c12004-09-10 03:08:08 +0000260 eq(s.substitute(dict(who='tim', what='ham')), 'tim likes $')
Barry Warsaw8bee7612004-08-25 02:22:30 +0000261
262 def test_percents(self):
Barry Warsaw12827c12004-09-10 03:08:08 +0000263 eq = self.assertEqual
Barry Warsaw8bee7612004-08-25 02:22:30 +0000264 s = Template('%(foo)s $foo ${foo}')
Barry Warsaw12827c12004-09-10 03:08:08 +0000265 d = dict(foo='baz')
266 eq(s.substitute(d), '%(foo)s baz baz')
267 eq(s.safe_substitute(d), '%(foo)s baz baz')
Barry Warsaw8bee7612004-08-25 02:22:30 +0000268
269 def test_stringification(self):
Barry Warsaw12827c12004-09-10 03:08:08 +0000270 eq = self.assertEqual
Barry Warsaw8bee7612004-08-25 02:22:30 +0000271 s = Template('tim has eaten $count bags of ham today')
Barry Warsaw12827c12004-09-10 03:08:08 +0000272 d = dict(count=7)
273 eq(s.substitute(d), 'tim has eaten 7 bags of ham today')
274 eq(s.safe_substitute(d), 'tim has eaten 7 bags of ham today')
275 s = Template('tim has eaten ${count} bags of ham today')
276 eq(s.substitute(d), 'tim has eaten 7 bags of ham today')
Barry Warsaw8bee7612004-08-25 02:22:30 +0000277
Thomas Woutersadd19112006-07-05 11:03:49 +0000278 def test_tupleargs(self):
279 eq = self.assertEqual
280 s = Template('$who ate ${meal}')
281 d = dict(who=('tim', 'fred'), meal=('ham', 'kung pao'))
282 eq(s.substitute(d), "('tim', 'fred') ate ('ham', 'kung pao')")
283 eq(s.safe_substitute(d), "('tim', 'fred') ate ('ham', 'kung pao')")
284
Barry Warsaw8bee7612004-08-25 02:22:30 +0000285 def test_SafeTemplate(self):
286 eq = self.assertEqual
Barry Warsaw12827c12004-09-10 03:08:08 +0000287 s = Template('$who likes ${what} for ${meal}')
288 eq(s.safe_substitute(dict(who='tim')), 'tim likes ${what} for ${meal}')
289 eq(s.safe_substitute(dict(what='ham')), '$who likes ham for ${meal}')
290 eq(s.safe_substitute(dict(what='ham', meal='dinner')),
Barry Warsaw8bee7612004-08-25 02:22:30 +0000291 '$who likes ham for dinner')
Barry Warsaw12827c12004-09-10 03:08:08 +0000292 eq(s.safe_substitute(dict(who='tim', what='ham')),
Barry Warsaw8bee7612004-08-25 02:22:30 +0000293 'tim likes ham for ${meal}')
Barry Warsaw12827c12004-09-10 03:08:08 +0000294 eq(s.safe_substitute(dict(who='tim', what='ham', meal='dinner')),
Barry Warsaw8bee7612004-08-25 02:22:30 +0000295 'tim likes ham for dinner')
296
297 def test_invalid_placeholders(self):
298 raises = self.assertRaises
299 s = Template('$who likes $')
Barry Warsaw12827c12004-09-10 03:08:08 +0000300 raises(ValueError, s.substitute, dict(who='tim'))
Barry Warsaw8bee7612004-08-25 02:22:30 +0000301 s = Template('$who likes ${what)')
Barry Warsaw12827c12004-09-10 03:08:08 +0000302 raises(ValueError, s.substitute, dict(who='tim'))
Barry Warsaw8bee7612004-08-25 02:22:30 +0000303 s = Template('$who likes $100')
Barry Warsaw12827c12004-09-10 03:08:08 +0000304 raises(ValueError, s.substitute, dict(who='tim'))
305
Barry Warsaw12827c12004-09-10 03:08:08 +0000306 def test_idpattern_override(self):
307 class PathPattern(Template):
308 idpattern = r'[_a-z][._a-z0-9]*'
309 m = Mapping()
310 m.bag = Bag()
311 m.bag.foo = Bag()
312 m.bag.foo.who = 'tim'
313 m.bag.what = 'ham'
314 s = PathPattern('$bag.foo.who likes to eat a bag of $bag.what')
315 self.assertEqual(s.substitute(m), 'tim likes to eat a bag of ham')
316
317 def test_pattern_override(self):
318 class MyPattern(Template):
319 pattern = r"""
320 (?P<escaped>@{2}) |
321 @(?P<named>[_a-z][._a-z0-9]*) |
322 @{(?P<braced>[_a-z][._a-z0-9]*)} |
Barry Warsaw3e773fb2004-09-13 20:53:27 +0000323 (?P<invalid>@)
Barry Warsaw12827c12004-09-10 03:08:08 +0000324 """
325 m = Mapping()
326 m.bag = Bag()
327 m.bag.foo = Bag()
328 m.bag.foo.who = 'tim'
329 m.bag.what = 'ham'
330 s = MyPattern('@bag.foo.who likes to eat a bag of @bag.what')
331 self.assertEqual(s.substitute(m), 'tim likes to eat a bag of ham')
332
Neal Norwitz6627a962004-10-17 16:27:18 +0000333 class BadPattern(Template):
334 pattern = r"""
335 (?P<badname>.*) |
336 (?P<escaped>@{2}) |
337 @(?P<named>[_a-z][._a-z0-9]*) |
338 @{(?P<braced>[_a-z][._a-z0-9]*)} |
339 (?P<invalid>@) |
340 """
341 s = BadPattern('@bag.foo.who likes to eat a bag of @bag.what')
342 self.assertRaises(ValueError, s.substitute, {})
343 self.assertRaises(ValueError, s.safe_substitute, {})
344
Florent Xiclunaff05e522010-09-18 23:34:07 +0000345 def test_braced_override(self):
346 class MyTemplate(Template):
347 pattern = r"""
348 \$(?:
349 (?P<escaped>$) |
350 (?P<named>[_a-z][_a-z0-9]*) |
351 @@(?P<braced>[_a-z][_a-z0-9]*)@@ |
352 (?P<invalid>) |
353 )
354 """
355
356 tmpl = 'PyCon in $@@location@@'
357 t = MyTemplate(tmpl)
358 self.assertRaises(KeyError, t.substitute, {})
359 val = t.substitute({'location': 'Cleveland'})
360 self.assertEqual(val, 'PyCon in Cleveland')
361
362 def test_braced_override_safe(self):
363 class MyTemplate(Template):
364 pattern = r"""
365 \$(?:
366 (?P<escaped>$) |
367 (?P<named>[_a-z][_a-z0-9]*) |
368 @@(?P<braced>[_a-z][_a-z0-9]*)@@ |
369 (?P<invalid>) |
370 )
371 """
372
373 tmpl = 'PyCon in $@@location@@'
374 t = MyTemplate(tmpl)
375 self.assertEqual(t.safe_substitute(), tmpl)
376 val = t.safe_substitute({'location': 'Cleveland'})
377 self.assertEqual(val, 'PyCon in Cleveland')
378
Barry Warsaw12827c12004-09-10 03:08:08 +0000379 def test_unicode_values(self):
380 s = Template('$who likes $what')
381 d = dict(who=u't\xffm', what=u'f\xfe\fed')
382 self.assertEqual(s.substitute(d), u't\xffm likes f\xfe\x0ced')
Barry Warsaw8bee7612004-08-25 02:22:30 +0000383
Barry Warsaw302bd582004-09-13 14:35:59 +0000384 def test_keyword_arguments(self):
385 eq = self.assertEqual
386 s = Template('$who likes $what')
387 eq(s.substitute(who='tim', what='ham'), 'tim likes ham')
388 eq(s.substitute(dict(who='tim'), what='ham'), 'tim likes ham')
389 eq(s.substitute(dict(who='fred', what='kung pao'),
390 who='tim', what='ham'),
391 'tim likes ham')
392 s = Template('the mapping is $mapping')
393 eq(s.substitute(dict(foo='none'), mapping='bozo'),
394 'the mapping is bozo')
395 eq(s.substitute(dict(mapping='one'), mapping='two'),
396 'the mapping is two')
397
Serhiy Storchaka40fd0e82015-03-24 22:27:50 +0200398 s = Template('the self is $self')
399 eq(s.substitute(self='bozo'), 'the self is bozo')
400
Barry Warsaw302bd582004-09-13 14:35:59 +0000401 def test_keyword_arguments_safe(self):
402 eq = self.assertEqual
Barry Warsawc7cd20c2004-09-13 15:24:43 +0000403 raises = self.assertRaises
Barry Warsaw302bd582004-09-13 14:35:59 +0000404 s = Template('$who likes $what')
405 eq(s.safe_substitute(who='tim', what='ham'), 'tim likes ham')
406 eq(s.safe_substitute(dict(who='tim'), what='ham'), 'tim likes ham')
407 eq(s.safe_substitute(dict(who='fred', what='kung pao'),
408 who='tim', what='ham'),
409 'tim likes ham')
410 s = Template('the mapping is $mapping')
411 eq(s.safe_substitute(dict(foo='none'), mapping='bozo'),
412 'the mapping is bozo')
413 eq(s.safe_substitute(dict(mapping='one'), mapping='two'),
414 'the mapping is two')
Barry Warsawc7cd20c2004-09-13 15:24:43 +0000415 d = dict(mapping='one')
416 raises(TypeError, s.substitute, d, {})
417 raises(TypeError, s.safe_substitute, d, {})
Barry Warsaw302bd582004-09-13 14:35:59 +0000418
Serhiy Storchaka40fd0e82015-03-24 22:27:50 +0200419 s = Template('the self is $self')
420 eq(s.safe_substitute(self='bozo'), 'the self is bozo')
421
Raymond Hettinger6d191112004-09-14 02:34:08 +0000422 def test_delimiter_override(self):
Barry Warsaw8c72eae2004-11-01 03:52:43 +0000423 eq = self.assertEqual
424 raises = self.assertRaises
Raymond Hettinger6d191112004-09-14 02:34:08 +0000425 class AmpersandTemplate(Template):
426 delimiter = '&'
427 s = AmpersandTemplate('this &gift is for &{who} &&')
Barry Warsaw8c72eae2004-11-01 03:52:43 +0000428 eq(s.substitute(gift='bud', who='you'), 'this bud is for you &')
429 raises(KeyError, s.substitute)
430 eq(s.safe_substitute(gift='bud', who='you'), 'this bud is for you &')
431 eq(s.safe_substitute(), 'this &gift is for &{who} &')
Raymond Hettinger6d191112004-09-14 02:34:08 +0000432 s = AmpersandTemplate('this &gift is for &{who} &')
Barry Warsaw8c72eae2004-11-01 03:52:43 +0000433 raises(ValueError, s.substitute, dict(gift='bud', who='you'))
434 eq(s.safe_substitute(), 'this &gift is for &{who} &')
435
Georg Brandl7ae60182010-02-07 12:16:12 +0000436 class PieDelims(Template):
437 delimiter = '@'
438 s = PieDelims('@who likes to eat a bag of @{what} worth $100')
439 self.assertEqual(s.substitute(dict(who='tim', what='ham')),
440 'tim likes to eat a bag of ham worth $100')
441
Barry Warsaw8bee7612004-08-25 02:22:30 +0000442
443def test_main():
Serhiy Storchaka6d38c2b2016-06-03 09:36:15 +0300444 test_support.run_unittest(StringTest, ModuleTest, BytesAliasTest, TestTemplate)
Barry Warsaw8bee7612004-08-25 02:22:30 +0000445
446if __name__ == '__main__':
Walter Dörwald0fd583c2003-02-21 12:53:50 +0000447 test_main()