8000 [3.14] gh-135487: fix `reprlib.Repr.repr_int` when given very large integers (GH-135506) by miss-islington · Pull Request #135887 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

[3.14] gh-135487: fix reprlib.Repr.repr_int when given very large integers (GH-135506) #135887

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

Merged
merged 1 commit into from
Jun 24, 2025
Merged
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
17 changes: 16 additions & 1 deletion Lib/reprlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,22 @@ def repr_str(self, x, level):
return s

def repr_int(self, x, level):
s = builtins.repr(x) # XXX Hope this isn't too slow...
try:
s = builtins.repr(x)
except ValueError as exc:
assert 'sys.set_int_max_str_digits()' in str(exc)
# Those imports must be deferred due to Python's build system
# where the reprlib module is imported before the math module.
import math, sys
# Integers with more than sys.get_int_max_str_digits() digits
# are rendered differently as their repr() raises a ValueError.
# See https://github.com/python/cpython/issues/135487.
k = 1 + int(math.log10(abs(x)))
# Note: math.log10(abs(x)) may be overestimated or underestimated,
# but for simplicity, we do not compute the exact number of digits.
max_digits = sys.get_int_max_str_digits()
return (f'<{x.__class__.__name__} instance with roughly {k} '
f'digits (limit at {max_digits}) at 0x{id(x):x}>')
if len(s) > self.maxlong:
i = max(0, (self.maxlong-3)//2)
j = max(0, self.maxlong-3-i)
Expand Down
40 changes: 32 additions & 8 deletions Lib/test/test_reprlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,14 +151,38 @@ def test_frozenset(self):
eq(r(frozenset({1, 2, 3, 4, 5, 6, 7})), "frozenset({1, 2, 3, 4, 5, 6, ...})")

def test_numbers(self):
eq = self.assertEqual
eq(r(123), repr(123))
eq(r(123), repr(123))
eq(r(1.0/3), repr(1.0/3))

n = 10**100
expected = repr(n)[:18] + "..." + repr(n)[-19:]
eq(r(n), expected)
for x in [123, 1.0 / 3]:
self.assertEqual(r(x), repr(x))

max_digits = sys.get_int_max_str_digits()
for k in [100, max_digits - 1]:
with self.subTest(f'10 ** {k}', k=k):
n = 10 ** k
expected = repr(n)[:18] + "..." + repr(n)[-19:]
self.assertEqual(r(n), expected)

def re_msg(n, d):
return (rf'<{n.__class__.__name__} instance with roughly {d} '
rf'digits \(limit at {max_digits}\) at 0x[a-f0-9]+>')

k = max_digits
with self.subTest(f'10 ** {k}', k=k):
n = 10 ** k
self.assertRaises(ValueError, repr, n)
self.assertRegex(r(n), re_msg(n, k + 1))

for k in [max_digits + 1, 2 * max_digits]:
self.assertGreater(k, 100)
with self.subTest(f'10 ** {k}', k=k):
n = 10 ** k
self.assertRaises(ValueError, repr, n)
self.assertRegex(r(n), re_msg(n, k + 1))
with self.subTest(f'10 ** {k} - 1', k=k):
n = 10 ** k - 1
# Here, since math.log10(n) == math.log10(n-1),
# the number of digits of n - 1 is overestimated.
self.assertRaises(ValueError, repr, n)
self.assertRegex(r(n), re_msg(n, k + 1))

def test_instance(self):
eq = self.assertEqual
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix :meth:`!reprlib.Repr.repr_int` when given integers with more than
:func:`sys.get_int_max_str_digits` digits. Patch by Bénédikt Tran.
Loading
0