Barry Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 1 | import unittest |
Serhiy Storchaka | 6d38c2b | 2016-06-03 09:36:15 +0300 | [diff] [blame] | 2 | import string |
Barry Warsaw | 12827c1 | 2004-09-10 03:08:08 +0000 | [diff] [blame] | 3 | from string import Template |
Walter Dörwald | 0fd583c | 2003-02-21 12:53:50 +0000 | [diff] [blame] | 4 | from test import test_support, string_tests |
| 5 | from UserList import UserList |
Barry Warsaw | 50f0e16 | 1999-06-10 22:53:10 +0000 | [diff] [blame] | 6 | |
Walter Dörwald | 0fd583c | 2003-02-21 12:53:50 +0000 | [diff] [blame] | 7 | class StringTest( |
| 8 | string_tests.CommonTest, |
| 9 | string_tests.MixinStrStringUserStringTest |
| 10 | ): |
Barry Warsaw | 6e1d78a | 1999-06-15 16:49:11 +0000 | [diff] [blame] | 11 | |
Walter Dörwald | 0fd583c | 2003-02-21 12:53:50 +0000 | [diff] [blame] | 12 | type2test = str |
Barry Warsaw | 50f0e16 | 1999-06-10 22:53:10 +0000 | [diff] [blame] | 13 | |
Walter Dörwald | 0fd583c | 2003-02-21 12:53:50 +0000 | [diff] [blame] | 14 | def checkequal(self, result, object, methodname, *args): |
| 15 | realresult = getattr(string, methodname)(object, *args) |
| 16 | self.assertEqual( |
| 17 | result, |
| 18 | realresult |
| 19 | ) |
Barry Warsaw | 50f0e16 | 1999-06-10 22:53:10 +0000 | [diff] [blame] | 20 | |
Benjamin Peterson | 1643d5c | 2014-09-28 12:48:46 -0400 | [diff] [blame] | 21 | def checkraises(self, exc, obj, methodname, *args): |
| 22 | with self.assertRaises(exc) as cm: |
| 23 | getattr(string, methodname)(obj, *args) |
Terry Jan Reedy | c0dc65e | 2014-10-12 22:00:10 -0400 | [diff] [blame] | 24 | self.assertNotEqual(cm.exception.args[0], '') |
Marc-André Lemburg | 79f5783 | 2002-12-29 19:44:06 +0000 | [diff] [blame] | 25 | |
Walter Dörwald | 0fd583c | 2003-02-21 12:53:50 +0000 | [diff] [blame] | 26 | 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. Hudson | b2308bb | 2005-10-21 11:45:01 +0000 | [diff] [blame] | 53 | 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örwald | 0fd583c | 2003-02-21 12:53:50 +0000 | [diff] [blame] | 64 | class 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 Melotti | 9aac245 | 2009-09-26 11:20:53 +0000 | [diff] [blame] | 105 | 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örwald | 0fd583c | 2003-02-21 12:53:50 +0000 | [diff] [blame] | 108 | |
Eric Smith | a9f7d62 | 2008-02-17 19:46:49 +0000 | [diff] [blame] | 109 | 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 Melotti | 24b07bc | 2011-03-15 18:55:01 +0200 | [diff] [blame] | 176 | # Track which arguments actually got used |
Eric Smith | a9f7d62 | 2008-02-17 19:46:49 +0000 | [diff] [blame] | 177 | 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 Smith | d0c8412 | 2008-07-15 10:10:07 +0000 | [diff] [blame] | 195 | # Alternate formatting is not supported |
| 196 | self.assertRaises(ValueError, format, '', '#') |
| 197 | self.assertRaises(ValueError, format, '', '#20') |
| 198 | |
Serhiy Storchaka | 40fd0e8 | 2015-03-24 22:27:50 +0200 | [diff] [blame] | 199 | 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 Heimes | 288e89a | 2008-01-18 18:24:07 +0000 | [diff] [blame] | 211 | class BytesAliasTest(unittest.TestCase): |
| 212 | |
| 213 | def test_builtin(self): |
Benjamin Peterson | 5c8da86 | 2009-06-30 22:57:08 +0000 | [diff] [blame] | 214 | self.assertTrue(str is bytes) |
Christian Heimes | 288e89a | 2008-01-18 18:24:07 +0000 | [diff] [blame] | 215 | |
| 216 | def test_syntax(self): |
| 217 | self.assertEqual(b"spam", "spam") |
| 218 | self.assertEqual(br"egg\foo", "egg\\foo") |
Benjamin Peterson | 5c8da86 | 2009-06-30 22:57:08 +0000 | [diff] [blame] | 219 | self.assertTrue(type(b""), str) |
| 220 | self.assertTrue(type(br""), str) |
Christian Heimes | 288e89a | 2008-01-18 18:24:07 +0000 | [diff] [blame] | 221 | |
Walter Dörwald | 0fd583c | 2003-02-21 12:53:50 +0000 | [diff] [blame] | 222 | |
Serhiy Storchaka | 6d38c2b | 2016-06-03 09:36:15 +0300 | [diff] [blame] | 223 | # Template tests (formerly housed in test_pep292.py) |
Barry Warsaw | 12827c1 | 2004-09-10 03:08:08 +0000 | [diff] [blame] | 224 | |
| 225 | class Bag: |
| 226 | pass |
| 227 | |
| 228 | class 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 Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 238 | |
| 239 | class TestTemplate(unittest.TestCase): |
Barry Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 240 | def test_regular_templates(self): |
| 241 | s = Template('$who likes to eat a bag of $what worth $$100') |
Barry Warsaw | 12827c1 | 2004-09-10 03:08:08 +0000 | [diff] [blame] | 242 | self.assertEqual(s.substitute(dict(who='tim', what='ham')), |
Barry Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 243 | 'tim likes to eat a bag of ham worth $100') |
Barry Warsaw | 12827c1 | 2004-09-10 03:08:08 +0000 | [diff] [blame] | 244 | self.assertRaises(KeyError, s.substitute, dict(who='tim')) |
Serhiy Storchaka | 40fd0e8 | 2015-03-24 22:27:50 +0200 | [diff] [blame] | 245 | self.assertRaises(TypeError, Template.substitute) |
Barry Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 246 | |
| 247 | def test_regular_templates_with_braces(self): |
| 248 | s = Template('$who likes ${what} for ${meal}') |
Barry Warsaw | 12827c1 | 2004-09-10 03:08:08 +0000 | [diff] [blame] | 249 | 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 Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 253 | |
| 254 | def test_escapes(self): |
| 255 | eq = self.assertEqual |
| 256 | s = Template('$who likes to eat a bag of $$what worth $$100') |
Barry Warsaw | 12827c1 | 2004-09-10 03:08:08 +0000 | [diff] [blame] | 257 | eq(s.substitute(dict(who='tim', what='ham')), |
Barry Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 258 | 'tim likes to eat a bag of $what worth $100') |
| 259 | s = Template('$who likes $$') |
Barry Warsaw | 12827c1 | 2004-09-10 03:08:08 +0000 | [diff] [blame] | 260 | eq(s.substitute(dict(who='tim', what='ham')), 'tim likes $') |
Barry Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 261 | |
| 262 | def test_percents(self): |
Barry Warsaw | 12827c1 | 2004-09-10 03:08:08 +0000 | [diff] [blame] | 263 | eq = self.assertEqual |
Barry Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 264 | s = Template('%(foo)s $foo ${foo}') |
Barry Warsaw | 12827c1 | 2004-09-10 03:08:08 +0000 | [diff] [blame] | 265 | d = dict(foo='baz') |
| 266 | eq(s.substitute(d), '%(foo)s baz baz') |
| 267 | eq(s.safe_substitute(d), '%(foo)s baz baz') |
Barry Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 268 | |
| 269 | def test_stringification(self): |
Barry Warsaw | 12827c1 | 2004-09-10 03:08:08 +0000 | [diff] [blame] | 270 | eq = self.assertEqual |
Barry Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 271 | s = Template('tim has eaten $count bags of ham today') |
Barry Warsaw | 12827c1 | 2004-09-10 03:08:08 +0000 | [diff] [blame] | 272 | 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 Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 277 | |
Thomas Wouters | add1911 | 2006-07-05 11:03:49 +0000 | [diff] [blame] | 278 | 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 Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 285 | def test_SafeTemplate(self): |
| 286 | eq = self.assertEqual |
Barry Warsaw | 12827c1 | 2004-09-10 03:08:08 +0000 | [diff] [blame] | 287 | 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 Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 291 | '$who likes ham for dinner') |
Barry Warsaw | 12827c1 | 2004-09-10 03:08:08 +0000 | [diff] [blame] | 292 | eq(s.safe_substitute(dict(who='tim', what='ham')), |
Barry Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 293 | 'tim likes ham for ${meal}') |
Barry Warsaw | 12827c1 | 2004-09-10 03:08:08 +0000 | [diff] [blame] | 294 | eq(s.safe_substitute(dict(who='tim', what='ham', meal='dinner')), |
Barry Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 295 | 'tim likes ham for dinner') |
| 296 | |
| 297 | def test_invalid_placeholders(self): |
| 298 | raises = self.assertRaises |
| 299 | s = Template('$who likes $') |
Barry Warsaw | 12827c1 | 2004-09-10 03:08:08 +0000 | [diff] [blame] | 300 | raises(ValueError, s.substitute, dict(who='tim')) |
Barry Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 301 | s = Template('$who likes ${what)') |
Barry Warsaw | 12827c1 | 2004-09-10 03:08:08 +0000 | [diff] [blame] | 302 | raises(ValueError, s.substitute, dict(who='tim')) |
Barry Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 303 | s = Template('$who likes $100') |
Barry Warsaw | 12827c1 | 2004-09-10 03:08:08 +0000 | [diff] [blame] | 304 | raises(ValueError, s.substitute, dict(who='tim')) |
| 305 | |
Barry Warsaw | 12827c1 | 2004-09-10 03:08:08 +0000 | [diff] [blame] | 306 | 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 Warsaw | 3e773fb | 2004-09-13 20:53:27 +0000 | [diff] [blame] | 323 | (?P<invalid>@) |
Barry Warsaw | 12827c1 | 2004-09-10 03:08:08 +0000 | [diff] [blame] | 324 | """ |
| 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 Norwitz | 6627a96 | 2004-10-17 16:27:18 +0000 | [diff] [blame] | 333 | 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 Xicluna | ff05e52 | 2010-09-18 23:34:07 +0000 | [diff] [blame] | 345 | 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 Warsaw | 12827c1 | 2004-09-10 03:08:08 +0000 | [diff] [blame] | 379 | 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 Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 383 | |
Barry Warsaw | 302bd58 | 2004-09-13 14:35:59 +0000 | [diff] [blame] | 384 | 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 Storchaka | 40fd0e8 | 2015-03-24 22:27:50 +0200 | [diff] [blame] | 398 | s = Template('the self is $self') |
| 399 | eq(s.substitute(self='bozo'), 'the self is bozo') |
| 400 | |
Barry Warsaw | 302bd58 | 2004-09-13 14:35:59 +0000 | [diff] [blame] | 401 | def test_keyword_arguments_safe(self): |
| 402 | eq = self.assertEqual |
Barry Warsaw | c7cd20c | 2004-09-13 15:24:43 +0000 | [diff] [blame] | 403 | raises = self.assertRaises |
Barry Warsaw | 302bd58 | 2004-09-13 14:35:59 +0000 | [diff] [blame] | 404 | 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 Warsaw | c7cd20c | 2004-09-13 15:24:43 +0000 | [diff] [blame] | 415 | d = dict(mapping='one') |
| 416 | raises(TypeError, s.substitute, d, {}) |
| 417 | raises(TypeError, s.safe_substitute, d, {}) |
Barry Warsaw | 302bd58 | 2004-09-13 14:35:59 +0000 | [diff] [blame] | 418 | |
Serhiy Storchaka | 40fd0e8 | 2015-03-24 22:27:50 +0200 | [diff] [blame] | 419 | s = Template('the self is $self') |
| 420 | eq(s.safe_substitute(self='bozo'), 'the self is bozo') |
| 421 | |
Raymond Hettinger | 6d19111 | 2004-09-14 02:34:08 +0000 | [diff] [blame] | 422 | def test_delimiter_override(self): |
Barry Warsaw | 8c72eae | 2004-11-01 03:52:43 +0000 | [diff] [blame] | 423 | eq = self.assertEqual |
| 424 | raises = self.assertRaises |
Raymond Hettinger | 6d19111 | 2004-09-14 02:34:08 +0000 | [diff] [blame] | 425 | class AmpersandTemplate(Template): |
| 426 | delimiter = '&' |
| 427 | s = AmpersandTemplate('this &gift is for &{who} &&') |
Barry Warsaw | 8c72eae | 2004-11-01 03:52:43 +0000 | [diff] [blame] | 428 | 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 Hettinger | 6d19111 | 2004-09-14 02:34:08 +0000 | [diff] [blame] | 432 | s = AmpersandTemplate('this &gift is for &{who} &') |
Barry Warsaw | 8c72eae | 2004-11-01 03:52:43 +0000 | [diff] [blame] | 433 | raises(ValueError, s.substitute, dict(gift='bud', who='you')) |
| 434 | eq(s.safe_substitute(), 'this &gift is for &{who} &') |
| 435 | |
Georg Brandl | 7ae6018 | 2010-02-07 12:16:12 +0000 | [diff] [blame] | 436 | 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 Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 442 | |
| 443 | def test_main(): |
Serhiy Storchaka | 6d38c2b | 2016-06-03 09:36:15 +0300 | [diff] [blame] | 444 | test_support.run_unittest(StringTest, ModuleTest, BytesAliasTest, TestTemplate) |
Barry Warsaw | 8bee761 | 2004-08-25 02:22:30 +0000 | [diff] [blame] | 445 | |
| 446 | if __name__ == '__main__': |
Walter Dörwald | 0fd583c | 2003-02-21 12:53:50 +0000 | [diff] [blame] | 447 | test_main() |