Home | History | Annotate | Download | only in test
      1 import unittest
      2 import string
      3 from string import Template
      4 from test import test_support, string_tests
      5 from UserList import UserList
      6 
      7 class StringTest(
      8     string_tests.CommonTest,
      9     string_tests.MixinStrStringUserStringTest
     10     ):
     11 
     12     type2test = str
     13 
     14     def checkequal(self, result, object, methodname, *args):
     15         realresult = getattr(string, methodname)(object, *args)
     16         self.assertEqual(
     17             result,
     18             realresult
     19         )
     20 
     21     def checkraises(self, exc, obj, methodname, *args):
     22         with self.assertRaises(exc) as cm:
     23             getattr(string, methodname)(obj, *args)
     24         self.assertNotEqual(cm.exception.args[0], '')
     25 
     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', ' ')
     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 
     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')
    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')
    108 
    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):
    176                 # Track which arguments actually got used
    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 
    195         # Alternate formatting is not supported
    196         self.assertRaises(ValueError, format, '', '#')
    197         self.assertRaises(ValueError, format, '', '#20')
    198 
    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 
    211 class BytesAliasTest(unittest.TestCase):
    212 
    213     def test_builtin(self):
    214         self.assertTrue(str is bytes)
    215 
    216     def test_syntax(self):
    217         self.assertEqual(b"spam", "spam")
    218         self.assertEqual(br"egg\foo", "egg\\foo")
    219         self.assertTrue(type(b""), str)
    220         self.assertTrue(type(br""), str)
    221 
    222 
    223 # Template tests (formerly housed in test_pep292.py)
    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 
    238 
    239 class TestTemplate(unittest.TestCase):
    240     def test_regular_templates(self):
    241         s = Template('$who likes to eat a bag of $what worth $$100')
    242         self.assertEqual(s.substitute(dict(who='tim', what='ham')),
    243                          'tim likes to eat a bag of ham worth $100')
    244         self.assertRaises(KeyError, s.substitute, dict(who='tim'))
    245         self.assertRaises(TypeError, Template.substitute)
    246 
    247     def test_regular_templates_with_braces(self):
    248         s = Template('$who likes ${what} for ${meal}')
    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'))
    253 
    254     def test_escapes(self):
    255         eq = self.assertEqual
    256         s = Template('$who likes to eat a bag of $$what worth $$100')
    257         eq(s.substitute(dict(who='tim', what='ham')),
    258            'tim likes to eat a bag of $what worth $100')
    259         s = Template('$who likes $$')
    260         eq(s.substitute(dict(who='tim', what='ham')), 'tim likes $')
    261 
    262     def test_percents(self):
    263         eq = self.assertEqual
    264         s = Template('%(foo)s $foo ${foo}')
    265         d = dict(foo='baz')
    266         eq(s.substitute(d), '%(foo)s baz baz')
    267         eq(s.safe_substitute(d), '%(foo)s baz baz')
    268 
    269     def test_stringification(self):
    270         eq = self.assertEqual
    271         s = Template('tim has eaten $count bags of ham today')
    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')
    277 
    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 
    285     def test_SafeTemplate(self):
    286         eq = self.assertEqual
    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')),
    291            '$who likes ham for dinner')
    292         eq(s.safe_substitute(dict(who='tim', what='ham')),
    293            'tim likes ham for ${meal}')
    294         eq(s.safe_substitute(dict(who='tim', what='ham', meal='dinner')),
    295            'tim likes ham for dinner')
    296 
    297     def test_invalid_placeholders(self):
    298         raises = self.assertRaises
    299         s = Template('$who likes $')
    300         raises(ValueError, s.substitute, dict(who='tim'))
    301         s = Template('$who likes ${what)')
    302         raises(ValueError, s.substitute, dict(who='tim'))
    303         s = Template('$who likes $100')
    304         raises(ValueError, s.substitute, dict(who='tim'))
    305 
    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]*)}    |
    323             (?P<invalid>@)
    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 
    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 
    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 
    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')
    383 
    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 
    398         s = Template('the self is $self')
    399         eq(s.substitute(self='bozo'), 'the self is bozo')
    400 
    401     def test_keyword_arguments_safe(self):
    402         eq = self.assertEqual
    403         raises = self.assertRaises
    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')
    415         d = dict(mapping='one')
    416         raises(TypeError, s.substitute, d, {})
    417         raises(TypeError, s.safe_substitute, d, {})
    418 
    419         s = Template('the self is $self')
    420         eq(s.safe_substitute(self='bozo'), 'the self is bozo')
    421 
    422     def test_delimiter_override(self):
    423         eq = self.assertEqual
    424         raises = self.assertRaises
    425         class AmpersandTemplate(Template):
    426             delimiter = '&'
    427         s = AmpersandTemplate('this &gift is for &{who} &&')
    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} &')
    432         s = AmpersandTemplate('this &gift is for &{who} &')
    433         raises(ValueError, s.substitute, dict(gift='bud', who='you'))
    434         eq(s.safe_substitute(), 'this &gift is for &{who} &')
    435 
    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 
    442 
    443 def test_main():
    444     test_support.run_unittest(StringTest, ModuleTest, BytesAliasTest, TestTemplate)
    445 
    446 if __name__ == '__main__':
    447     test_main()
    448