| import pickle |
| import unittest |
| from collections.abc import Iterator, Iterable |
| from string.templatelib import Template, Interpolation, convert |
| |
| from test.test_string._support import TStringBaseCase, fstring |
| |
| |
| class TestTemplate(unittest.TestCase, TStringBaseCase): |
| |
| def test_common(self): |
| self.assertEqual(type(t'').__name__, 'Template') |
| self.assertEqual(type(t'').__qualname__, 'Template') |
| self.assertEqual(type(t'').__module__, 'string.templatelib') |
| |
| a = 'a' |
| i = t'{a}'.interpolations[0] |
| self.assertEqual(type(i).__name__, 'Interpolation') |
| self.assertEqual(type(i).__qualname__, 'Interpolation') |
| self.assertEqual(type(i).__module__, 'string.templatelib') |
| |
| def test_final_types(self): |
| with self.assertRaisesRegex(TypeError, 'is not an acceptable base type'): |
| class Sub(Template): ... |
| |
| with self.assertRaisesRegex(TypeError, 'is not an acceptable base type'): |
| class Sub(Interpolation): ... |
| |
| def test_basic_creation(self): |
| # Simple t-string creation |
| t = t'Hello, world' |
| self.assertIsInstance(t, Template) |
| self.assertTStringEqual(t, ('Hello, world',), ()) |
| self.assertEqual(fstring(t), 'Hello, world') |
| |
| # Empty t-string |
| t = t'' |
| self.assertTStringEqual(t, ('',), ()) |
| self.assertEqual(fstring(t), '') |
| |
| # Multi-line t-string |
| t = t"""Hello, |
| world""" |
| self.assertEqual(t.strings, ('Hello,\nworld',)) |
| self.assertEqual(len(t.interpolations), 0) |
| self.assertEqual(fstring(t), 'Hello,\nworld') |
| |
| def test_interpolation_creation(self): |
| i = Interpolation('Maria', 'name', 'a', 'fmt') |
| self.assertInterpolationEqual(i, ('Maria', 'name', 'a', 'fmt')) |
| |
| i = Interpolation('Maria', 'name', 'a') |
| self.assertInterpolationEqual(i, ('Maria', 'name', 'a')) |
| |
| i = Interpolation('Maria', 'name') |
| self.assertInterpolationEqual(i, ('Maria', 'name')) |
| |
| i = Interpolation('Maria') |
| self.assertInterpolationEqual(i, ('Maria',)) |
| |
| def test_creation_interleaving(self): |
| # Should add strings on either side |
| t = Template(Interpolation('Maria', 'name', None, '')) |
| self.assertTStringEqual(t, ('', ''), [('Maria', 'name')]) |
| self.assertEqual(fstring(t), 'Maria') |
| |
| # Should prepend empty string |
| t = Template(Interpolation('Maria', 'name', None, ''), ' is my name') |
| self.assertTStringEqual(t, ('', ' is my name'), [('Maria', 'name')]) |
| self.assertEqual(fstring(t), 'Maria is my name') |
| |
| # Should append empty string |
| t = Template('Hello, ', Interpolation('Maria', 'name', None, '')) |
| self.assertTStringEqual(t, ('Hello, ', ''), [('Maria', 'name')]) |
| self.assertEqual(fstring(t), 'Hello, Maria') |
| |
| # Should concatenate strings |
| t = Template('Hello', ', ', Interpolation('Maria', 'name', None, ''), |
| '!') |
| self.assertTStringEqual(t, ('Hello, ', '!'), [('Maria', 'name')]) |
| self.assertEqual(fstring(t), 'Hello, Maria!') |
| |
| # Should add strings on either side and in between |
| t = Template(Interpolation('Maria', 'name', None, ''), |
| Interpolation('Python', 'language', None, '')) |
| self.assertTStringEqual( |
| t, ('', '', ''), [('Maria', 'name'), ('Python', 'language')] |
| ) |
| self.assertEqual(fstring(t), 'MariaPython') |
| |
| def test_template_values(self): |
| t = t'Hello, world' |
| self.assertEqual(t.values, ()) |
| |
| name = "Lys" |
| t = t'Hello, {name}' |
| self.assertEqual(t.values, ("Lys",)) |
| |
| country = "GR" |
| age = 0 |
| t = t'Hello, {name}, {age} from {country}' |
| self.assertEqual(t.values, ("Lys", 0, "GR")) |
| |
| def test_pickle_template(self): |
| user = 'test' |
| for template in ( |
| t'', |
| t"No values", |
| t'With inter {user}', |
| t'With ! {user!r}', |
| t'With format {1 / 0.3:.2f}', |
| Template(), |
| Template('a'), |
| Template(Interpolation('Nikita', 'name', None, '')), |
| Template('a', Interpolation('Nikita', 'name', 'r', '')), |
| ): |
| for proto in range(pickle.HIGHEST_PROTOCOL + 1): |
| with self.subTest(proto=proto, template=template): |
| pickled = pickle.dumps(template, protocol=proto) |
| unpickled = pickle.loads(pickled) |
| |
| self.assertEqual(unpickled.values, template.values) |
| self.assertEqual(fstring(unpickled), fstring(template)) |
| |
| def test_pickle_interpolation(self): |
| for interpolation in ( |
| Interpolation('Nikita', 'name', None, ''), |
| Interpolation('Nikita', 'name', 'r', ''), |
| Interpolation(1/3, 'x', None, '.2f'), |
| ): |
| for proto in range(pickle.HIGHEST_PROTOCOL + 1): |
| with self.subTest(proto=proto, interpolation=interpolation): |
| pickled = pickle.dumps(interpolation, protocol=proto) |
| unpickled = pickle.loads(pickled) |
| |
| self.assertEqual(unpickled.value, interpolation.value) |
| self.assertEqual(unpickled.expression, interpolation.expression) |
| self.assertEqual(unpickled.conversion, interpolation.conversion) |
| self.assertEqual(unpickled.format_spec, interpolation.format_spec) |
| |
| |
| class TemplateIterTests(unittest.TestCase): |
| def test_abc(self): |
| self.assertIsInstance(iter(t''), Iterable) |
| self.assertIsInstance(iter(t''), Iterator) |
| |
| def test_final(self): |
| TemplateIter = type(iter(t'')) |
| with self.assertRaisesRegex(TypeError, 'is not an acceptable base type'): |
| class Sub(TemplateIter): ... |
| |
| def test_iter(self): |
| x = 1 |
| res = list(iter(t'abc {x} yz')) |
| |
| self.assertEqual(res[0], 'abc ') |
| self.assertIsInstance(res[1], Interpolation) |
| self.assertEqual(res[1].value, 1) |
| self.assertEqual(res[1].expression, 'x') |
| self.assertEqual(res[1].conversion, None) |
| self.assertEqual(res[1].format_spec, '') |
| self.assertEqual(res[2], ' yz') |
| |
| def test_exhausted(self): |
| # See https://github.com/python/cpython/issues/134119. |
| template_iter = iter(t"{1}") |
| self.assertIsInstance(next(template_iter), Interpolation) |
| self.assertRaises(StopIteration, next, template_iter) |
| self.assertRaises(StopIteration, next, template_iter) |
| |
| |
| class TestFunctions(unittest.TestCase): |
| def test_convert(self): |
| from fractions import Fraction |
| |
| for obj in ('Café', None, 3.14, Fraction(1, 2)): |
| with self.subTest(f'{obj=}'): |
| self.assertEqual(convert(obj, None), obj) |
| self.assertEqual(convert(obj, 's'), str(obj)) |
| self.assertEqual(convert(obj, 'r'), repr(obj)) |
| self.assertEqual(convert(obj, 'a'), ascii(obj)) |
| |
| # Invalid conversion specifier |
| with self.assertRaises(ValueError): |
| convert(obj, 'z') |
| with self.assertRaises(ValueError): |
| convert(obj, 1) |
| with self.assertRaises(ValueError): |
| convert(obj, object()) |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |