Skip to content

gh-132855: Use overridden custom format for inherited PrettyPrinter #133238

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Lib/pprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,23 @@ def _format(self, object, stream, indent, allowance, context, level):
self._recursive = True
self._readable = False
return

# If this is a subclass of PrettyPrinter, force all known
# container types through their pretty-printers so that any
# override of format() applies to their elements.
if type(self) is not PrettyPrinter:
fn = type(object).__repr__
# skip raw repr for str/bytes
if fn in self._dispatch and not isinstance(object, (str, bytes, bytearray)):
context[objid] = 1
self._dispatch[fn](
self, object, stream,
indent, allowance, context, level + 1
)
del context[objid]
return

# fallback to one-line repr + width
rep = self._repr(object, context, level)
max_width = self._width - indent - allowance
if len(rep) > max_width:
Expand All @@ -203,6 +220,7 @@ def _format(self, object, stream, indent, allowance, context, level):
self._pprint_dataclass(object, stream, indent, allowance, context, level + 1)
del context[objid]
return

stream.write(rep)

def _pprint_dataclass(self, object, stream, indent, allowance, context, level):
Expand Down
32 changes: 32 additions & 0 deletions Lib/test/test_pprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -1136,6 +1136,38 @@ def format(self, object, context, maxlevels, level):
return pprint.PrettyPrinter.format(
self, object, context, maxlevels, level)

# Issue 132855
SENTINAL = object()
class _hashable:
def __hash__(self):
return 1

HASHABLE_SENTINAL = _hashable()
class CustomPrettyPrinter(pprint.PrettyPrinter):
def format(self, obj, context, maxlevels, level):
if obj is SENTINAL:
return "SENTINAL", True, False
elif obj is HASHABLE_SENTINAL:
return "HASHABLE_SENTINAL", True, False
else:
return super().format(obj, context, maxlevels, level)

class CustomPrettyPrinterTest(unittest.TestCase):
def test_custom_printer(self):
# Test that the custom printer works as expected
obj = SENTINAL
formatted = CustomPrettyPrinter().pformat(obj)
self.assertEqual(formatted, "SENTINAL")

obj = HASHABLE_SENTINAL
formatted = CustomPrettyPrinter().pformat(obj)
self.assertEqual(formatted, "HASHABLE_SENTINAL")

# Test that the default printer works as expected
obj = object()
formatted = pprint.pformat(obj)
self.assertNotEqual(formatted, "SENTINAL")
self.assertNotEqual(formatted, "HASHABLE_SENTINAL")

if __name__ == "__main__":
unittest.main()
Loading