cpython/Lib/test/test_string.py
R David Murray 0a8f43e85a #11754: test contents of string module attributes.
As noted in the comment, while the order of the items in the attributes is not
technically guaranteed, after all this time there is almost certainly user
code out there that relies on it, so we might as well test for it.

Patch by Chalmer Lowe.
2015-04-13 20:04:29 -04:00

189 lines
8.3 KiB
Python

import unittest, string
class ModuleTest(unittest.TestCase):
def test_attrs(self):
# While the exact order of the items in these attributes is not
# technically part of the "language spec", in practice there is almost
# certainly user code that depends on the order, so de-facto it *is*
# part of the spec.
self.assertEqual(string.whitespace, ' \t\n\r\x0b\x0c')
self.assertEqual(string.ascii_lowercase, 'abcdefghijklmnopqrstuvwxyz')
self.assertEqual(string.ascii_uppercase, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
self.assertEqual(string.ascii_letters, string.ascii_lowercase + string.ascii_uppercase)
self.assertEqual(string.digits, '0123456789')
self.assertEqual(string.hexdigits, string.digits + 'abcdefABCDEF')
self.assertEqual(string.octdigits, '01234567')
self.assertEqual(string.punctuation, '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~')
self.assertEqual(string.printable, string.digits + string.ascii_lowercase + string.ascii_uppercase + string.punctuation + string.whitespace)
def test_capwords(self):
self.assertEqual(string.capwords('abc def ghi'), 'Abc Def Ghi')
self.assertEqual(string.capwords('abc\tdef\nghi'), 'Abc Def Ghi')
self.assertEqual(string.capwords('abc\t def \nghi'), 'Abc Def Ghi')
self.assertEqual(string.capwords('ABC DEF GHI'), 'Abc Def Ghi')
self.assertEqual(string.capwords('ABC-DEF-GHI', '-'), 'Abc-Def-Ghi')
self.assertEqual(string.capwords('ABC-def DEF-ghi GHI'), 'Abc-def Def-ghi Ghi')
self.assertEqual(string.capwords(' aBc DeF '), 'Abc Def')
self.assertEqual(string.capwords('\taBc\tDeF\t'), 'Abc Def')
self.assertEqual(string.capwords('\taBc\tDeF\t', '\t'), '\tAbc\tDef\t')
def test_basic_formatter(self):
fmt = string.Formatter()
self.assertEqual(fmt.format("foo"), "foo")
self.assertEqual(fmt.format("foo{0}", "bar"), "foobar")
self.assertEqual(fmt.format("foo{1}{0}-{1}", "bar", 6), "foo6bar-6")
self.assertRaises(TypeError, fmt.format)
self.assertRaises(TypeError, string.Formatter.format)
def test_format_keyword_arguments(self):
fmt = string.Formatter()
self.assertEqual(fmt.format("-{arg}-", arg='test'), '-test-')
self.assertRaises(KeyError, fmt.format, "-{arg}-")
self.assertEqual(fmt.format("-{self}-", self='test'), '-test-')
self.assertRaises(KeyError, fmt.format, "-{self}-")
self.assertEqual(fmt.format("-{format_string}-", format_string='test'),
'-test-')
self.assertRaises(KeyError, fmt.format, "-{format_string}-")
with self.assertWarnsRegex(DeprecationWarning, "format_string"):
self.assertEqual(fmt.format(arg='test', format_string="-{arg}-"),
'-test-')
def test_auto_numbering(self):
fmt = string.Formatter()
self.assertEqual(fmt.format('foo{}{}', 'bar', 6),
'foo{}{}'.format('bar', 6))
self.assertEqual(fmt.format('foo{1}{num}{1}', None, 'bar', num=6),
'foo{1}{num}{1}'.format(None, 'bar', num=6))
self.assertEqual(fmt.format('{:^{}}', 'bar', 6),
'{:^{}}'.format('bar', 6))
self.assertEqual(fmt.format('{:^{pad}}{}', 'foo', 'bar', pad=6),
'{:^{pad}}{}'.format('foo', 'bar', pad=6))
with self.assertRaises(ValueError):
fmt.format('foo{1}{}', 'bar', 6)
with self.assertRaises(ValueError):
fmt.format('foo{}{1}', 'bar', 6)
def test_conversion_specifiers(self):
fmt = string.Formatter()
self.assertEqual(fmt.format("-{arg!r}-", arg='test'), "-'test'-")
self.assertEqual(fmt.format("{0!s}", 'test'), 'test')
self.assertRaises(ValueError, fmt.format, "{0!h}", 'test')
# issue13579
self.assertEqual(fmt.format("{0!a}", 42), '42')
self.assertEqual(fmt.format("{0!a}", string.ascii_letters),
"'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'")
self.assertEqual(fmt.format("{0!a}", chr(255)), "'\\xff'")
self.assertEqual(fmt.format("{0!a}", chr(256)), "'\\u0100'")
def test_name_lookup(self):
fmt = string.Formatter()
class AnyAttr:
def __getattr__(self, attr):
return attr
x = AnyAttr()
self.assertEqual(fmt.format("{0.lumber}{0.jack}", x), 'lumberjack')
with self.assertRaises(AttributeError):
fmt.format("{0.lumber}{0.jack}", '')
def test_index_lookup(self):
fmt = string.Formatter()
lookup = ["eggs", "and", "spam"]
self.assertEqual(fmt.format("{0[2]}{0[0]}", lookup), 'spameggs')
with self.assertRaises(IndexError):
fmt.format("{0[2]}{0[0]}", [])
with self.assertRaises(KeyError):
fmt.format("{0[2]}{0[0]}", {})
def test_override_get_value(self):
class NamespaceFormatter(string.Formatter):
def __init__(self, namespace={}):
string.Formatter.__init__(self)
self.namespace = namespace
def get_value(self, key, args, kwds):
if isinstance(key, str):
try:
# Check explicitly passed arguments first
return kwds[key]
except KeyError:
return self.namespace[key]
else:
string.Formatter.get_value(key, args, kwds)
fmt = NamespaceFormatter({'greeting':'hello'})
self.assertEqual(fmt.format("{greeting}, world!"), 'hello, world!')
def test_override_format_field(self):
class CallFormatter(string.Formatter):
def format_field(self, value, format_spec):
return format(value(), format_spec)
fmt = CallFormatter()
self.assertEqual(fmt.format('*{0}*', lambda : 'result'), '*result*')
def test_override_convert_field(self):
class XFormatter(string.Formatter):
def convert_field(self, value, conversion):
if conversion == 'x':
return None
return super().convert_field(value, conversion)
fmt = XFormatter()
self.assertEqual(fmt.format("{0!r}:{0!x}", 'foo', 'foo'), "'foo':None")
def test_override_parse(self):
class BarFormatter(string.Formatter):
# returns an iterable that contains tuples of the form:
# (literal_text, field_name, format_spec, conversion)
def parse(self, format_string):
for field in format_string.split('|'):
if field[0] == '+':
# it's markup
field_name, _, format_spec = field[1:].partition(':')
yield '', field_name, format_spec, None
else:
yield field, None, None, None
fmt = BarFormatter()
self.assertEqual(fmt.format('*|+0:^10s|*', 'foo'), '* foo *')
def test_check_unused_args(self):
class CheckAllUsedFormatter(string.Formatter):
def check_unused_args(self, used_args, args, kwargs):
# Track which arguments actually got used
unused_args = set(kwargs.keys())
unused_args.update(range(0, len(args)))
for arg in used_args:
unused_args.remove(arg)
if unused_args:
raise ValueError("unused arguments")
fmt = CheckAllUsedFormatter()
self.assertEqual(fmt.format("{0}", 10), "10")
self.assertEqual(fmt.format("{0}{i}", 10, i=100), "10100")
self.assertEqual(fmt.format("{0}{i}{1}", 10, 20, i=100), "1010020")
self.assertRaises(ValueError, fmt.format, "{0}{i}{1}", 10, 20, i=100, j=0)
self.assertRaises(ValueError, fmt.format, "{0}", 10, 20)
self.assertRaises(ValueError, fmt.format, "{0}", 10, 20, i=100)
self.assertRaises(ValueError, fmt.format, "{i}", 10, 20, i=100)
def test_vformat_recursion_limit(self):
fmt = string.Formatter()
args = ()
kwargs = dict(i=100)
with self.assertRaises(ValueError) as err:
fmt._vformat("{i}", args, kwargs, set(), -1)
self.assertIn("recursion", str(err.exception))
if __name__ == "__main__":
unittest.main()