Skip to content

Commit 86d1821

Browse files
[3.13] gh-135487: fix reprlib.Repr.repr_int when given very large integers (GH-135506) (#135886)
gh-135487: fix `reprlib.Repr.repr_int` when given very large integers (GH-135506) (cherry picked from commit e5f03b9) Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
1 parent a27398d commit 86d1821

File tree

3 files changed

+50
-9
lines changed

3 files changed

+50
-9
lines changed

Lib/reprlib.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,22 @@ def repr_str(self, x, level):
181181
return s
182182

183183
def repr_int(self, x, level):
184-
s = builtins.repr(x) # XXX Hope this isn't too slow...
184+
try:
185+
s = builtins.repr(x)
186+
except ValueError as exc:
187+
assert 'sys.set_int_max_str_digits()' in str(exc)
188+
# Those imports must be deferred due to Python's build system
189+
# where the reprlib module is imported before the math module.
190+
import math, sys
191+
# Integers with more than sys.get_int_max_str_digits() digits
192+
# are rendered differently as their repr() raises a ValueError.
193+
# See https://github.com/python/cpython/issues/135487.
194+
k = 1 + int(math.log10(abs(x)))
195+
# Note: math.log10(abs(x)) may be overestimated or underestimated,
196+
# but for simplicity, we do not compute the exact number of digits.
197+
max_digits = sys.get_int_max_str_digits()
198+
return (f'<{x.__class__.__name__} instance with roughly {k} '
199+
f'digits (limit at {max_digits}) at 0x{id(x):x}>')
185200
if len(s) > self.maxlong:
186201
i = max(0, (self.maxlong-3)//2)
187202
j = max(0, self.maxlong-3-i)

Lib/test/test_reprlib.py

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -150,14 +150,38 @@ def test_frozenset(self):
150150
eq(r(frozenset({1, 2, 3, 4, 5, 6, 7})), "frozenset({1, 2, 3, 4, 5, 6, ...})")
151151

152152
def test_numbers(self):
153-
eq = self.assertEqual
154-
eq(r(123), repr(123))
155-
eq(r(123), repr(123))
156-
eq(r(1.0/3), repr(1.0/3))
157-
158-
n = 10**100
159-
expected = repr(n)[:18] + "..." + repr(n)[-19:]
160-
eq(r(n), expected)
153+
for x in [123, 1.0 / 3]:
154+
self.assertEqual(r(x), repr(x))
155+
156+
max_digits = sys.get_int_max_str_digits()
157+
for k in [100, max_digits - 1]:
158+
with self.subTest(f'10 ** {k}', k=k):
159+
n = 10 ** k
160+
expected = repr(n)[:18] + "..." + repr(n)[-19:]
161+
self.assertEqual(r(n), expected)
162+
163+
def re_msg(n, d):
164+
return (rf'<{n.__class__.__name__} instance with roughly {d} '
165+
rf'digits \(limit at {max_digits}\) at 0x[a-f0-9]+>')
166+
167+
k = max_digits
168+
with self.subTest(f'10 ** {k}', k=k):
169+
n = 10 ** k
170+
self.assertRaises(ValueError, repr, n)
171+
self.assertRegex(r(n), re_msg(n, k + 1))
172+
173+
for k in [max_digits + 1, 2 * max_digits]:
174+
self.assertGreater(k, 100)
175+
with self.subTest(f'10 ** {k}', k=k):
176+
n = 10 ** k
177+
self.assertRaises(ValueError, repr, n)
178+
self.assertRegex(r(n), re_msg(n, k + 1))
179+
with self.subTest(f'10 ** {k} - 1', k=k):
180+
n = 10 ** k - 1
181+
# Here, since math.log10(n) == math.log10(n-1),
182+
# the number of digits of n - 1 is overestimated.
183+
self.assertRaises(ValueError, repr, n)
184+
self.assertRegex(r(n), re_msg(n, k + 1))
161185

162186
def test_instance(self):
163187
eq = self.assertEqual
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix :meth:`!reprlib.Repr.repr_int` when given integers with more than
2+
:func:`sys.get_int_max_str_digits` digits. Patch by Bénédikt Tran.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy