https://github.com/python/cpython/commit/74a4f8c1d0caece261b379d5a6cd4e41eae3557a
commit: 74a4f8c1d0caece261b379d5a6cd4e41eae3557a
branch: main
author: Loïc Simon <[email protected]>
committer: hugovk <[email protected]>
date: 2026-04-14T14:37:41+03:00
summary:

gh-134551: Add t-strings support to pprint (#134577)

Co-authored-by: Hugo van Kemenade <[email protected]>
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>

files:
A Misc/NEWS.d/next/Library/2025-05-23-10-28-51.gh-issue-134551.0rnq0X.rst
M Doc/whatsnew/3.15.rst
M Lib/pprint.py
M Lib/test/test_pprint.py

diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst
index c754b634ecccfa..fe2ddfdcd0e917 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 f197d7d17cdb96..7355021998081d 100644
--- a/Lib/pprint.py
+++ b/Lib/pprint.py
@@ -735,6 +735,61 @@ def _pprint_user_string(self, object, stream, indent, 
allowance, context, level)
 
     _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 45e081c233f0b0..041c2072b9e253 100644
--- a/Lib/test/test_pprint.py
+++ b/Lib/test/test_pprint.py
@@ -1515,6 +1515,86 @@ def test_user_string(self):
     '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 00000000000000..94e0c1e0b225d6
--- /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

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to