Skip to content
6 changes: 5 additions & 1 deletion Lib/pprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

"""

import cmath as _cmath
import collections as _collections
import sys as _sys
import types as _types
Expand Down Expand Up @@ -627,7 +628,10 @@ def _safe_repr(self, object, context, maxlevels, level):
# Return triple (repr_string, isreadable, isrecursive).
typ = type(object)
if typ in _builtin_scalars:
return repr(object), True, False
rep = repr(object)
if (typ is float or typ is complex) and not _cmath.isfinite(object):
return rep, False, False
return rep, True, False

r = getattr(typ, "__repr__", None)

Expand Down
14 changes: 14 additions & 0 deletions Lib/test/test_pprint.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-

import cmath
import collections
import contextlib
import dataclasses
Expand Down Expand Up @@ -182,6 +183,19 @@ def test_basic(self):
self.assertTrue(pp.isreadable(safe),
"expected isreadable for %r" % (safe,))

def test_isreadable_float_specials(self):
# inf, -inf, nan are not valid Python literals so isreadable should be False
# same applies to complex numbers with non-finite components
non_finite = (float("inf"), float("-inf"), float("nan"))
for v in (*non_finite,
*(complex(x, y) for x in (*non_finite, 0)
for y in (*non_finite, 0)
if not cmath.isfinite(complex(x, y)))):
self.assertFalse(pprint.isreadable(v),
"expected not isreadable for %r" % (v,))
self.assertFalse(pprint.PrettyPrinter().isreadable(v),
"expected not isreadable for %r" % (v,))

def test_stdout_is_None(self):
with contextlib.redirect_stdout(None):
# smoke test - there is no output to check
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Fix :func:`pprint.isreadable` to return ``False`` for non-finite :class:`float`
and :class:`complex` values (``inf``, ``-inf``, ``nan`` and complex numbers with
non-finite components). Their string representations are not valid Python
expressions and cannot be reconstructed via :func:`eval`, violating the
documented contract of :func:`~pprint.isreadable`.
Loading