From: Loïc Simon Date: Tue, 14 Apr 2026 11:37:41 +0000 (+0200) Subject: gh-134551: Add t-strings support to pprint (#134577) X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=74a4f8c1d0caece261b379d5a6cd4e41eae3557a;p=thirdparty%2FPython%2Fcpython.git gh-134551: Add t-strings support to pprint (#134577) Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> --- diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index c754b634eccc..fe2ddfdcd0e9 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -1551,7 +1551,11 @@ pprint :func:`pprint.pformat`, :func:`pprint.pp`. If true, the output will be formatted similar to pretty-printed :func:`json.dumps` when *indent* is supplied. - (Contributed by Stefan Todoran and Semyon Moroz in :gh:`112632`.) + (Contributed by Stefan Todoran, Semyon Moroz and Hugo van Kemenade in + :gh:`112632`.) + +* Add t-string support to :mod:`pprint`. + (Contributed by Loïc Simon and Hugo van Kemenade in :gh:`134551`.) sre_* diff --git a/Lib/pprint.py b/Lib/pprint.py index f197d7d17cdb..735502199808 100644 --- a/Lib/pprint.py +++ b/Lib/pprint.py @@ -735,6 +735,61 @@ class PrettyPrinter: _dispatch[_collections.UserString.__repr__] = _pprint_user_string + def _pprint_template(self, object, stream, indent, allowance, context, level): + cls_name = object.__class__.__name__ + if self._expand: + indent += self._indent_per_level + else: + indent += len(cls_name) + 1 + + items = ( + ("strings", object.strings), + ("interpolations", object.interpolations), + ) + stream.write(self._format_block_start(cls_name + "(", indent)) + self._format_namespace_items( + items, stream, indent, allowance, context, level + ) + stream.write( + self._format_block_end(")", indent - self._indent_per_level) + ) + + def _pprint_interpolation(self, object, stream, indent, allowance, context, level): + cls_name = object.__class__.__name__ + if self._expand: + indent += self._indent_per_level + items = ( + ("value", object.value), + ("expression", object.expression), + ("conversion", object.conversion), + ("format_spec", object.format_spec), + ) + stream.write(self._format_block_start(cls_name + "(", indent)) + self._format_namespace_items( + items, stream, indent, allowance, context, level + ) + stream.write( + self._format_block_end(")", indent - self._indent_per_level) + ) + else: + indent += len(cls_name) + items = ( + object.value, + object.expression, + object.conversion, + object.format_spec, + ) + stream.write(cls_name + "(") + self._format_items( + items, stream, indent, allowance, context, level + ) + stream.write(")") + + t = t"{0}" + _dispatch[type(t).__repr__] = _pprint_template + _dispatch[type(t.interpolations[0]).__repr__] = _pprint_interpolation + del t + def _safe_repr(self, object, context, maxlevels, level): # Return triple (repr_string, isreadable, isrecursive). typ = type(object) diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py index 45e081c233f0..041c2072b9e2 100644 --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -1515,6 +1515,86 @@ ValuesView({'a': 6, 'jumped over a ' 'lazy dog'}""") + def test_template(self): + d = t"" + self.assertEqual(pprint.pformat(d), + "Template(strings=('',), interpolations=())") + self.assertEqual(pprint.pformat(d), repr(d)) + self.assertEqual(pprint.pformat(d, width=1), +"""\ +Template(strings=('',), + interpolations=())""") + name = "World" + d = t"Hello {name}" + self.assertEqual(pprint.pformat(d), +"""\ +Template(strings=('Hello ', ''), + interpolations=(Interpolation('World', 'name', None, ''),))""") + ver = {3.13: False, 3.14: True} + d = t"Hello { {"name": "Python", "version": ver}!s:z}!" + self.assertEqual(pprint.pformat(d, width=1), +"""\ +Template(strings=('Hello ', + '!'), + interpolations=(Interpolation({'name': 'Python', + 'version': {3.13: False, + 3.14: True}}, + ' ' + '{"name": ' + '"Python", ' + '"version": ' + 'ver}', + 's', + 'z'),))""") + + def test_expand_template(self): + d = t"" + self.assertEqual( + pprint.pformat(d, expand=True), + "Template(strings=('',), interpolations=())", + ) + name = "World" + d = t"Hello {name}" + self.assertEqual( + pprint.pformat(d, width=40, indent=4, expand=True), + """\ +Template( + strings=('Hello ', ''), + interpolations=( + Interpolation( + value='World', + expression='name', + conversion=None, + format_spec='', + ), + ), +)""", + ) + ver = {3.13: False, 3.14: True} + d = t"Hello { {"name": "Python", "version": ver}!s:z}!" + self.assertEqual( + pprint.pformat(d, width=40, indent=4, expand=True), + """\ +Template( + strings=('Hello ', '!'), + interpolations=( + Interpolation( + value={ + 'name': 'Python', + 'version': { + 3.13: False, + 3.14: True, + }, + }, + expression=' {"name": "Python", ' + '"version": ver}', + conversion='s', + format_spec='z', + ), + ), +)""", + ) + def test_expand_dataclass(self): @dataclasses.dataclass class DummyDataclass: diff --git a/Misc/NEWS.d/next/Library/2025-05-23-10-28-51.gh-issue-134551.0rnq0X.rst b/Misc/NEWS.d/next/Library/2025-05-23-10-28-51.gh-issue-134551.0rnq0X.rst new file mode 100644 index 000000000000..94e0c1e0b225 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-05-23-10-28-51.gh-issue-134551.0rnq0X.rst @@ -0,0 +1 @@ +Add t-strings support to pprint functions