Update reprlib from v3.14.2

This commit is contained in:
CPython Developers authored and Lee Dogeon committed 2026-01-21 15:10:40 +09:00
1 parent d690b2d65e
commit d7dba07304
2 files changed
+87 -36

No files matched your search

+17 -2
View File
@@ -28,7 +28,7 @@ def recursive_repr(fillvalue='...'):
wrapper.__doc__ = getattr(user_function, '__doc__')
wrapper.__name__ = getattr(user_function, '__name__')
wrapper.__qualname__ = getattr(user_function, '__qualname__')
wrapper.__annotations__ = getattr(user_function, '__annotations__', {})
wrapper.__annotate__ = getattr(user_function, '__annotate__', None)
wrapper.__type_params__ = getattr(user_function, '__type_params__', ())
wrapper.__wrapped__ = user_function
return wrapper
@@ -181,7 +181,22 @@ class Repr:
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)
+70 -34
View File
@@ -3,6 +3,7 @@
Nick Mathewson
"""
import annotationlib
import sys
import os
import shutil
@@ -11,7 +12,7 @@ import importlib.util
import unittest
import textwrap
from test.support import verbose
from test.support import verbose, EqualToForwardRef
from test.support.os_helper import create_empty_file
from reprlib import repr as r # Don't shadow builtin repr
from reprlib import Repr
@@ -150,14 +151,38 @@ class ReprTests(unittest.TestCase):
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))
for x in [123, 1.0 / 3]:
self.assertEqual(r(x), repr(x))
n = 10**100
expected = repr(n)[:18] + "..." + repr(n)[-19:]
eq(r(n), expected)
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
@@ -172,24 +197,23 @@ class ReprTests(unittest.TestCase):
eq(r(i3), ("<ClassWithFailingRepr instance at %#x>"%id(i3)))
s = r(ClassWithFailingRepr)
self.assertTrue(s.startswith("<class "))
self.assertTrue(s.endswith(">"))
self.assertStartsWith(s, "<class ")
self.assertEndsWith(s, ">")
self.assertIn(s.find("..."), [12, 13])
def test_lambda(self):
r = repr(lambda x: x)
self.assertTrue(r.startswith("<function ReprTests.test_lambda.<locals>.<lambda"), r)
self.assertStartsWith(r, "<function ReprTests.test_lambda.<locals>.<lambda")
# XXX anonymous functions? see func_repr
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_builtin_function(self):
eq = self.assertEqual
# Functions
eq(repr(hash), '<built-in function hash>')
# Methods
self.assertTrue(repr(''.split).startswith(
'<built-in method split of str object at 0x'))
self.assertStartsWith(repr(''.split),
'<built-in method split of str object at 0x')
def test_range(self):
eq = self.assertEqual
@@ -214,8 +238,7 @@ class ReprTests(unittest.TestCase):
eq(r([[[[[[{}]]]]]]), "[[[[[[{}]]]]]]")
eq(r([[[[[[[{}]]]]]]]), "[[[[[[[...]]]]]]]")
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_cell(self):
def get_cell():
x = 42
@@ -376,20 +399,20 @@ class ReprTests(unittest.TestCase):
'object': {
1: 'two',
b'three': [
(4.5, 6.7),
(4.5, 6.25),
[set((8, 9)), frozenset((10, 11))],
],
},
'tests': (
(dict(indent=None), '''\
{1: 'two', b'three': [(4.5, 6.7), [{8, 9}, frozenset({10, 11})]]}'''),
{1: 'two', b'three': [(4.5, 6.25), [{8, 9}, frozenset({10, 11})]]}'''),
(dict(indent=False), '''\
{
1: 'two',
b'three': [
(
4.5,
6.7,
6.25,
),
[
{
@@ -409,7 +432,7 @@ class ReprTests(unittest.TestCase):
b'three': [
(
4.5,
6.7,
6.25,
),
[
{
@@ -429,7 +452,7 @@ class ReprTests(unittest.TestCase):
b'three': [
(
4.5,
6.7,
6.25,
),
[
{
@@ -449,7 +472,7 @@ class ReprTests(unittest.TestCase):
b'three': [
(
4.5,
6.7,
6.25,
),
[
{
@@ -469,7 +492,7 @@ class ReprTests(unittest.TestCase):
b'three': [
(
4.5,
6.7,
6.25,
),
[
{
@@ -497,7 +520,7 @@ class ReprTests(unittest.TestCase):
b'three': [
(
4.5,
6.7,
6.25,
),
[
{
@@ -517,7 +540,7 @@ class ReprTests(unittest.TestCase):
-->b'three': [
-->-->(
-->-->-->4.5,
-->-->-->6.7,
-->-->-->6.25,
-->-->),
-->-->[
-->-->-->{
@@ -537,7 +560,7 @@ class ReprTests(unittest.TestCase):
....b'three': [
........(
............4.5,
............6.7,
............6.25,
........),
........[
............{
@@ -733,8 +756,8 @@ class baz:
importlib.invalidate_caches()
from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import baz
ibaz = baz.baz()
self.assertTrue(repr(ibaz).startswith(
"<%s.baz object at 0x" % baz.__name__))
self.assertStartsWith(repr(ibaz),
"<%s.baz object at 0x" % baz.__name__)
def test_method(self):
self._check_path_limitations('qux')
@@ -747,13 +770,13 @@ class aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import qux
# Unbound methods first
r = repr(qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod)
self.assertTrue(r.startswith('<function aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod'), r)
self.assertStartsWith(r, '<function aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod')
# Bound method next
iqux = qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()
r = repr(iqux.amethod)
self.assertTrue(r.startswith(
self.assertStartsWith(r,
'<bound method aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod of <%s.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa object at 0x' \
% (qux.__name__,) ), r)
% (qux.__name__,) )
@unittest.skip('needs a built-in function with a really long name')
def test_builtin_function(self):
@@ -822,8 +845,7 @@ class TestRecursiveRepr(unittest.TestCase):
self.assertIs(X.f, X.__repr__.__wrapped__)
# TODO: RUSTPYTHON: AttributeError: 'TypeVar' object has no attribute '__name__'
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: 'TypeVar' object has no attribute '__name__'
def test__type_params__(self):
class My:
@recursive_repr()
@@ -835,5 +857,19 @@ class TestRecursiveRepr(unittest.TestCase):
self.assertEqual(type_params[0].__name__, 'T')
self.assertEqual(type_params[0].__bound__, str)
def test_annotations(self):
class My:
@recursive_repr()
def __repr__(self, default: undefined = ...):
return default
annotations = annotationlib.get_annotations(
My.__repr__, format=annotationlib.Format.FORWARDREF
)
self.assertEqual(
annotations,
{'default': EqualToForwardRef("undefined", owner=My.__repr__)}
)
if __name__ == "__main__":
unittest.main()