test_string.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  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. class StringTest(
  7. string_tests.CommonTest,
  8. string_tests.MixinStrStringUserStringTest
  9. ):
  10. type2test = str
  11. def checkequal(self, result, object, methodname, *args):
  12. realresult = getattr(string, methodname)(object, *args)
  13. self.assertEqual(
  14. result,
  15. realresult
  16. )
  17. def checkraises(self, exc, obj, methodname, *args):
  18. with self.assertRaises(exc) as cm:
  19. getattr(string, methodname)(obj, *args)
  20. self.assertNotEqual(cm.exception.args[0], '')
  21. def checkcall(self, object, methodname, *args):
  22. getattr(string, methodname)(object, *args)
  23. def test_join(self):
  24. # These are the same checks as in string_test.ObjectTest.test_join
  25. # but the argument order ist different
  26. self.checkequal('a b c d', ['a', 'b', 'c', 'd'], 'join', ' ')
  27. self.checkequal('abcd', ('a', 'b', 'c', 'd'), 'join', '')
  28. self.checkequal('w x y z', string_tests.Sequence(), 'join', ' ')
  29. self.checkequal('abc', ('abc',), 'join', 'a')
  30. self.checkequal('z', UserList(['z']), 'join', 'a')
  31. if test_support.have_unicode:
  32. self.checkequal(unicode('a.b.c'), ['a', 'b', 'c'], 'join', unicode('.'))
  33. self.checkequal(unicode('a.b.c'), [unicode('a'), 'b', 'c'], 'join', '.')
  34. self.checkequal(unicode('a.b.c'), ['a', unicode('b'), 'c'], 'join', '.')
  35. self.checkequal(unicode('a.b.c'), ['a', 'b', unicode('c')], 'join', '.')
  36. self.checkraises(TypeError, ['a', unicode('b'), 3], 'join', '.')
  37. for i in [5, 25, 125]:
  38. self.checkequal(
  39. ((('a' * i) + '-') * i)[:-1],
  40. ['a' * i] * i, 'join', '-')
  41. self.checkequal(
  42. ((('a' * i) + '-') * i)[:-1],
  43. ('a' * i,) * i, 'join', '-')
  44. self.checkraises(TypeError, string_tests.BadSeq1(), 'join', ' ')
  45. self.checkequal('a b c', string_tests.BadSeq2(), 'join', ' ')
  46. try:
  47. def f():
  48. yield 4 + ""
  49. self.fixtype(' ').join(f())
  50. except TypeError, e:
  51. if '+' not in str(e):
  52. self.fail('join() ate exception message')
  53. else:
  54. self.fail('exception not raised')
  55. class ModuleTest(unittest.TestCase):
  56. def test_attrs(self):
  57. string.whitespace
  58. string.lowercase
  59. string.uppercase
  60. string.letters
  61. string.digits
  62. string.hexdigits
  63. string.octdigits
  64. string.punctuation
  65. string.printable
  66. def test_atoi(self):
  67. self.assertEqual(string.atoi(" 1 "), 1)
  68. self.assertRaises(ValueError, string.atoi, " 1x")
  69. self.assertRaises(ValueError, string.atoi, " x1 ")
  70. def test_atol(self):
  71. self.assertEqual(string.atol(" 1 "), 1L)
  72. self.assertRaises(ValueError, string.atol, " 1x ")
  73. self.assertRaises(ValueError, string.atol, " x1 ")
  74. def test_atof(self):
  75. self.assertAlmostEqual(string.atof(" 1 "), 1.0)
  76. self.assertRaises(ValueError, string.atof, " 1x ")
  77. self.assertRaises(ValueError, string.atof, " x1 ")
  78. def test_maketrans(self):
  79. 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'
  80. self.assertEqual(string.maketrans('abc', 'xyz'), transtable)
  81. self.assertRaises(ValueError, string.maketrans, 'abc', 'xyzq')
  82. def test_capwords(self):
  83. self.assertEqual(string.capwords('abc def ghi'), 'Abc Def Ghi')
  84. self.assertEqual(string.capwords('abc\tdef\nghi'), 'Abc Def Ghi')
  85. self.assertEqual(string.capwords('abc\t def \nghi'), 'Abc Def Ghi')
  86. self.assertEqual(string.capwords('ABC DEF GHI'), 'Abc Def Ghi')
  87. self.assertEqual(string.capwords('ABC-DEF-GHI', '-'), 'Abc-Def-Ghi')
  88. self.assertEqual(string.capwords('ABC-def DEF-ghi GHI'), 'Abc-def Def-ghi Ghi')
  89. self.assertEqual(string.capwords(' aBc DeF '), 'Abc Def')
  90. self.assertEqual(string.capwords('\taBc\tDeF\t'), 'Abc Def')
  91. self.assertEqual(string.capwords('\taBc\tDeF\t', '\t'), '\tAbc\tDef\t')
  92. def test_formatter(self):
  93. fmt = string.Formatter()
  94. self.assertEqual(fmt.format("foo"), "foo")
  95. self.assertEqual(fmt.format("foo{0}", "bar"), "foobar")
  96. self.assertEqual(fmt.format("foo{1}{0}-{1}", "bar", 6), "foo6bar-6")
  97. self.assertEqual(fmt.format("-{arg!r}-", arg='test'), "-'test'-")
  98. # override get_value ############################################
  99. class NamespaceFormatter(string.Formatter):
  100. def __init__(self, namespace={}):
  101. string.Formatter.__init__(self)
  102. self.namespace = namespace
  103. def get_value(self, key, args, kwds):
  104. if isinstance(key, str):
  105. try:
  106. # Check explicitly passed arguments first
  107. return kwds[key]
  108. except KeyError:
  109. return self.namespace[key]
  110. else:
  111. string.Formatter.get_value(key, args, kwds)
  112. fmt = NamespaceFormatter({'greeting':'hello'})
  113. self.assertEqual(fmt.format("{greeting}, world!"), 'hello, world!')
  114. # override format_field #########################################
  115. class CallFormatter(string.Formatter):
  116. def format_field(self, value, format_spec):
  117. return format(value(), format_spec)
  118. fmt = CallFormatter()
  119. self.assertEqual(fmt.format('*{0}*', lambda : 'result'), '*result*')
  120. # override convert_field ########################################
  121. class XFormatter(string.Formatter):
  122. def convert_field(self, value, conversion):
  123. if conversion == 'x':
  124. return None
  125. return super(XFormatter, self).convert_field(value, conversion)
  126. fmt = XFormatter()
  127. self.assertEqual(fmt.format("{0!r}:{0!x}", 'foo', 'foo'), "'foo':None")
  128. # override parse ################################################
  129. class BarFormatter(string.Formatter):
  130. # returns an iterable that contains tuples of the form:
  131. # (literal_text, field_name, format_spec, conversion)
  132. def parse(self, format_string):
  133. for field in format_string.split('|'):
  134. if field[0] == '+':
  135. # it's markup
  136. field_name, _, format_spec = field[1:].partition(':')
  137. yield '', field_name, format_spec, None
  138. else:
  139. yield field, None, None, None
  140. fmt = BarFormatter()
  141. self.assertEqual(fmt.format('*|+0:^10s|*', 'foo'), '* foo *')
  142. # test all parameters used
  143. class CheckAllUsedFormatter(string.Formatter):
  144. def check_unused_args(self, used_args, args, kwargs):
  145. # Track which arguments actually got used
  146. unused_args = set(kwargs.keys())
  147. unused_args.update(range(0, len(args)))
  148. for arg in used_args:
  149. unused_args.remove(arg)
  150. if unused_args:
  151. raise ValueError("unused arguments")
  152. fmt = CheckAllUsedFormatter()
  153. self.assertEqual(fmt.format("{0}", 10), "10")
  154. self.assertEqual(fmt.format("{0}{i}", 10, i=100), "10100")
  155. self.assertEqual(fmt.format("{0}{i}{1}", 10, 20, i=100), "1010020")
  156. self.assertRaises(ValueError, fmt.format, "{0}{i}{1}", 10, 20, i=100, j=0)
  157. self.assertRaises(ValueError, fmt.format, "{0}", 10, 20)
  158. self.assertRaises(ValueError, fmt.format, "{0}", 10, 20, i=100)
  159. self.assertRaises(ValueError, fmt.format, "{i}", 10, 20, i=100)
  160. # Alternate formatting is not supported
  161. self.assertRaises(ValueError, format, '', '#')
  162. self.assertRaises(ValueError, format, '', '#20')
  163. def test_format_keyword_arguments(self):
  164. fmt = string.Formatter()
  165. self.assertEqual(fmt.format("-{arg}-", arg='test'), '-test-')
  166. self.assertRaises(KeyError, fmt.format, "-{arg}-")
  167. self.assertEqual(fmt.format("-{self}-", self='test'), '-test-')
  168. self.assertRaises(KeyError, fmt.format, "-{self}-")
  169. self.assertEqual(fmt.format("-{format_string}-", format_string='test'),
  170. '-test-')
  171. self.assertRaises(KeyError, fmt.format, "-{format_string}-")
  172. self.assertEqual(fmt.format(arg='test', format_string="-{arg}-"),
  173. '-test-')
  174. class BytesAliasTest(unittest.TestCase):
  175. def test_builtin(self):
  176. self.assertTrue(str is bytes)
  177. def test_syntax(self):
  178. self.assertEqual(b"spam", "spam")
  179. self.assertEqual(br"egg\foo", "egg\\foo")
  180. self.assertTrue(type(b""), str)
  181. self.assertTrue(type(br""), str)
  182. # Template tests (formerly housed in test_pep292.py)
  183. class Bag:
  184. pass
  185. class Mapping:
  186. def __getitem__(self, name):
  187. obj = self
  188. for part in name.split('.'):
  189. try:
  190. obj = getattr(obj, part)
  191. except AttributeError:
  192. raise KeyError(name)
  193. return obj
  194. class TestTemplate(unittest.TestCase):
  195. def test_regular_templates(self):
  196. s = Template('$who likes to eat a bag of $what worth $$100')
  197. self.assertEqual(s.substitute(dict(who='tim', what='ham')),
  198. 'tim likes to eat a bag of ham worth $100')
  199. self.assertRaises(KeyError, s.substitute, dict(who='tim'))
  200. self.assertRaises(TypeError, Template.substitute)
  201. def test_regular_templates_with_braces(self):
  202. s = Template('$who likes ${what} for ${meal}')
  203. d = dict(who='tim', what='ham', meal='dinner')
  204. self.assertEqual(s.substitute(d), 'tim likes ham for dinner')
  205. self.assertRaises(KeyError, s.substitute,
  206. dict(who='tim', what='ham'))
  207. def test_escapes(self):
  208. eq = self.assertEqual
  209. s = Template('$who likes to eat a bag of $$what worth $$100')
  210. eq(s.substitute(dict(who='tim', what='ham')),
  211. 'tim likes to eat a bag of $what worth $100')
  212. s = Template('$who likes $$')
  213. eq(s.substitute(dict(who='tim', what='ham')), 'tim likes $')
  214. def test_percents(self):
  215. eq = self.assertEqual
  216. s = Template('%(foo)s $foo ${foo}')
  217. d = dict(foo='baz')
  218. eq(s.substitute(d), '%(foo)s baz baz')
  219. eq(s.safe_substitute(d), '%(foo)s baz baz')
  220. def test_stringification(self):
  221. eq = self.assertEqual
  222. s = Template('tim has eaten $count bags of ham today')
  223. d = dict(count=7)
  224. eq(s.substitute(d), 'tim has eaten 7 bags of ham today')
  225. eq(s.safe_substitute(d), 'tim has eaten 7 bags of ham today')
  226. s = Template('tim has eaten ${count} bags of ham today')
  227. eq(s.substitute(d), 'tim has eaten 7 bags of ham today')
  228. def test_tupleargs(self):
  229. eq = self.assertEqual
  230. s = Template('$who ate ${meal}')
  231. d = dict(who=('tim', 'fred'), meal=('ham', 'kung pao'))
  232. eq(s.substitute(d), "('tim', 'fred') ate ('ham', 'kung pao')")
  233. eq(s.safe_substitute(d), "('tim', 'fred') ate ('ham', 'kung pao')")
  234. def test_SafeTemplate(self):
  235. eq = self.assertEqual
  236. s = Template('$who likes ${what} for ${meal}')
  237. eq(s.safe_substitute(dict(who='tim')), 'tim likes ${what} for ${meal}')
  238. eq(s.safe_substitute(dict(what='ham')), '$who likes ham for ${meal}')
  239. eq(s.safe_substitute(dict(what='ham', meal='dinner')),
  240. '$who likes ham for dinner')
  241. eq(s.safe_substitute(dict(who='tim', what='ham')),
  242. 'tim likes ham for ${meal}')
  243. eq(s.safe_substitute(dict(who='tim', what='ham', meal='dinner')),
  244. 'tim likes ham for dinner')
  245. def test_invalid_placeholders(self):
  246. raises = self.assertRaises
  247. s = Template('$who likes $')
  248. raises(ValueError, s.substitute, dict(who='tim'))
  249. s = Template('$who likes ${what)')
  250. raises(ValueError, s.substitute, dict(who='tim'))
  251. s = Template('$who likes $100')
  252. raises(ValueError, s.substitute, dict(who='tim'))
  253. def test_idpattern_override(self):
  254. class PathPattern(Template):
  255. idpattern = r'[_a-z][._a-z0-9]*'
  256. m = Mapping()
  257. m.bag = Bag()
  258. m.bag.foo = Bag()
  259. m.bag.foo.who = 'tim'
  260. m.bag.what = 'ham'
  261. s = PathPattern('$bag.foo.who likes to eat a bag of $bag.what')
  262. self.assertEqual(s.substitute(m), 'tim likes to eat a bag of ham')
  263. def test_pattern_override(self):
  264. class MyPattern(Template):
  265. pattern = r"""
  266. (?P<escaped>@{2}) |
  267. @(?P<named>[_a-z][._a-z0-9]*) |
  268. @{(?P<braced>[_a-z][._a-z0-9]*)} |
  269. (?P<invalid>@)
  270. """
  271. m = Mapping()
  272. m.bag = Bag()
  273. m.bag.foo = Bag()
  274. m.bag.foo.who = 'tim'
  275. m.bag.what = 'ham'
  276. s = MyPattern('@bag.foo.who likes to eat a bag of @bag.what')
  277. self.assertEqual(s.substitute(m), 'tim likes to eat a bag of ham')
  278. class BadPattern(Template):
  279. pattern = r"""
  280. (?P<badname>.*) |
  281. (?P<escaped>@{2}) |
  282. @(?P<named>[_a-z][._a-z0-9]*) |
  283. @{(?P<braced>[_a-z][._a-z0-9]*)} |
  284. (?P<invalid>@) |
  285. """
  286. s = BadPattern('@bag.foo.who likes to eat a bag of @bag.what')
  287. self.assertRaises(ValueError, s.substitute, {})
  288. self.assertRaises(ValueError, s.safe_substitute, {})
  289. def test_braced_override(self):
  290. class MyTemplate(Template):
  291. pattern = r"""
  292. \$(?:
  293. (?P<escaped>$) |
  294. (?P<named>[_a-z][_a-z0-9]*) |
  295. @@(?P<braced>[_a-z][_a-z0-9]*)@@ |
  296. (?P<invalid>) |
  297. )
  298. """
  299. tmpl = 'PyCon in $@@location@@'
  300. t = MyTemplate(tmpl)
  301. self.assertRaises(KeyError, t.substitute, {})
  302. val = t.substitute({'location': 'Cleveland'})
  303. self.assertEqual(val, 'PyCon in Cleveland')
  304. def test_braced_override_safe(self):
  305. class MyTemplate(Template):
  306. pattern = r"""
  307. \$(?:
  308. (?P<escaped>$) |
  309. (?P<named>[_a-z][_a-z0-9]*) |
  310. @@(?P<braced>[_a-z][_a-z0-9]*)@@ |
  311. (?P<invalid>) |
  312. )
  313. """
  314. tmpl = 'PyCon in $@@location@@'
  315. t = MyTemplate(tmpl)
  316. self.assertEqual(t.safe_substitute(), tmpl)
  317. val = t.safe_substitute({'location': 'Cleveland'})
  318. self.assertEqual(val, 'PyCon in Cleveland')
  319. def test_unicode_values(self):
  320. s = Template('$who likes $what')
  321. d = dict(who=u't\xffm', what=u'f\xfe\fed')
  322. self.assertEqual(s.substitute(d), u't\xffm likes f\xfe\x0ced')
  323. def test_keyword_arguments(self):
  324. eq = self.assertEqual
  325. s = Template('$who likes $what')
  326. eq(s.substitute(who='tim', what='ham'), 'tim likes ham')
  327. eq(s.substitute(dict(who='tim'), what='ham'), 'tim likes ham')
  328. eq(s.substitute(dict(who='fred', what='kung pao'),
  329. who='tim', what='ham'),
  330. 'tim likes ham')
  331. s = Template('the mapping is $mapping')
  332. eq(s.substitute(dict(foo='none'), mapping='bozo'),
  333. 'the mapping is bozo')
  334. eq(s.substitute(dict(mapping='one'), mapping='two'),
  335. 'the mapping is two')
  336. s = Template('the self is $self')
  337. eq(s.substitute(self='bozo'), 'the self is bozo')
  338. def test_keyword_arguments_safe(self):
  339. eq = self.assertEqual
  340. raises = self.assertRaises
  341. s = Template('$who likes $what')
  342. eq(s.safe_substitute(who='tim', what='ham'), 'tim likes ham')
  343. eq(s.safe_substitute(dict(who='tim'), what='ham'), 'tim likes ham')
  344. eq(s.safe_substitute(dict(who='fred', what='kung pao'),
  345. who='tim', what='ham'),
  346. 'tim likes ham')
  347. s = Template('the mapping is $mapping')
  348. eq(s.safe_substitute(dict(foo='none'), mapping='bozo'),
  349. 'the mapping is bozo')
  350. eq(s.safe_substitute(dict(mapping='one'), mapping='two'),
  351. 'the mapping is two')
  352. d = dict(mapping='one')
  353. raises(TypeError, s.substitute, d, {})
  354. raises(TypeError, s.safe_substitute, d, {})
  355. s = Template('the self is $self')
  356. eq(s.safe_substitute(self='bozo'), 'the self is bozo')
  357. def test_delimiter_override(self):
  358. eq = self.assertEqual
  359. raises = self.assertRaises
  360. class AmpersandTemplate(Template):
  361. delimiter = '&'
  362. s = AmpersandTemplate('this &gift is for &{who} &&')
  363. eq(s.substitute(gift='bud', who='you'), 'this bud is for you &')
  364. raises(KeyError, s.substitute)
  365. eq(s.safe_substitute(gift='bud', who='you'), 'this bud is for you &')
  366. eq(s.safe_substitute(), 'this &gift is for &{who} &')
  367. s = AmpersandTemplate('this &gift is for &{who} &')
  368. raises(ValueError, s.substitute, dict(gift='bud', who='you'))
  369. eq(s.safe_substitute(), 'this &gift is for &{who} &')
  370. class PieDelims(Template):
  371. delimiter = '@'
  372. s = PieDelims('@who likes to eat a bag of @{what} worth $100')
  373. self.assertEqual(s.substitute(dict(who='tim', what='ham')),
  374. 'tim likes to eat a bag of ham worth $100')
  375. def test_main():
  376. test_support.run_unittest(StringTest, ModuleTest, BytesAliasTest, TestTemplate)
  377. if __name__ == '__main__':
  378. test_main()