diff --git a/Lib/pprint.py b/Lib/pprint.py index e111bd59d4152c..80056642c4ba70 100644 --- a/Lib/pprint.py +++ b/Lib/pprint.py @@ -627,7 +627,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 and rep in ("inf", "-inf", "nan"): + return rep, False, False + return rep, True, False r = getattr(typ, "__repr__", None) diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py index f3860a5d511989..92818efce9bebf 100644 --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -182,6 +182,14 @@ 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 + for v in (float("inf"), float("-inf"), float("nan")): + 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 diff --git a/Misc/NEWS.d/next/Library/2026-02-22-00-00-00.gh-issue-145117.pPrint.rst b/Misc/NEWS.d/next/Library/2026-02-22-00-00-00.gh-issue-145117.pPrint.rst new file mode 100644 index 00000000000000..c5af010378af16 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-22-00-00-00.gh-issue-145117.pPrint.rst @@ -0,0 +1,5 @@ +Fix :func:`pprint.isreadable` to return ``False`` for ``float('inf')``, +``float('-inf')``, and ``float('nan')``. Their string representations +(``inf``, ``-inf``, ``nan``) are not valid Python literals and cannot +be reconstructed via :func:`eval`, violating the documented contract of +:func:`~pprint.isreadable`.