Skip to content
44 changes: 28 additions & 16 deletions Lib/test/test_string/_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,45 @@


class TStringBaseCase:
def assertInterpolationEqual(self, i, exp):
"""Test Interpolation equality.

The *i* argument must be an Interpolation instance.

The *exp* argument must be a tuple of the form
(value, expression, conversion, format_spec) where the final three
items may be omitted and are assumed to be '', None and '' respectively.
"""
if len(exp) == 4:
actual = (i.value, i.expression, i.conversion, i.format_spec)
self.assertEqual(actual, exp)
elif len(exp) == 3:
self.assertEqual((i.value, i.expression, i.conversion), exp)
self.assertEqual(i.format_spec, "")
elif len(exp) == 2:
self.assertEqual((i.value, i.expression), exp)
self.assertEqual(i.conversion, None)
self.assertEqual(i.format_spec, "")
elif len(exp) == 1:
self.assertEqual((i.value,), exp)
self.assertEqual(i.expression, "")
self.assertEqual(i.conversion, None)
self.assertEqual(i.format_spec, "")

def assertTStringEqual(self, t, strings, interpolations):
"""Test template string literal equality.

The *strings* argument must be a tuple of strings equal to *t.strings*.

The *interpolations* argument must be a sequence of tuples which are
compared against *t.interpolations*. Each tuple consists of
(value, expression, conversion, format_spec), though the final two
items may be omitted, and are assumed to be None and '' respectively.
compared against *t.interpolations*. Each tuple must match the form
described in the `assertInterpolationEqual` method.
"""
self.assertEqual(t.strings, strings)
self.assertEqual(len(t.interpolations), len(interpolations))

for i, exp in zip(t.interpolations, interpolations, strict=True):
if len(exp) == 4:
actual = (i.value, i.expression, i.conversion, i.format_spec)
self.assertEqual(actual, exp)
continue

if len(exp) == 3:
self.assertEqual((i.value, i.expression, i.conversion), exp)
self.assertEqual(i.format_spec, '')
continue

self.assertEqual((i.value, i.expression), exp)
self.assertEqual(i.format_spec, '')
self.assertIsNone(i.conversion)
self.assertInterpolationEqual(i, exp)


def convert(value, conversion):
Expand Down
13 changes: 13 additions & 0 deletions Lib/test/test_string/test_templatelib.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,19 @@ def test_basic_creation(self):
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, ''))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
``Interpolation.expression`` now has a default, the empty string.
23 changes: 14 additions & 9 deletions Objects/clinic/interpolationobject.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Objects/interpolationobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ typedef struct {
Interpolation.__new__ as interpolation_new

value: object
expression: object(subclass_of='&PyUnicode_Type')
expression: object(subclass_of='&PyUnicode_Type', c_default='&_Py_STR(empty)') = ""
conversion: object(converter='_conversion_converter') = None
format_spec: object(subclass_of='&PyUnicode_Type', c_default='&_Py_STR(empty)') = ""
[clinic start generated code]*/
Expand All @@ -63,7 +63,7 @@ static PyObject *
interpolation_new_impl(PyTypeObject *type, PyObject *value,
PyObject *expression, PyObject *conversion,
PyObject *format_spec)
/*[clinic end generated code: output=6488e288765bc1a9 input=d91711024068528c]*/
/*[clinic end generated code: output=6488e288765bc1a9 input=fc5c285c1dd23d36]*/
{
interpolationobject *self = PyObject_GC_New(interpolationobject, type);
if (!self) {
Expand Down
Loading