Fixed #36810 -- Avoided infinite recursion in SimpleLazyObject.__repr__().

Detect when `SimpleLazyObject._setupfunc` is a bound method of the same
instance to use a safe representation and avoid infinite recursion.
This commit is contained in:
Sean
2025-12-19 00:37:07 +01:00
committed by nessita
parent 165c359996
commit 8e4b531111
2 changed files with 21 additions and 1 deletions

View File

@@ -407,7 +407,11 @@ class SimpleLazyObject(LazyObject):
# without evaluating the wrapped object.
def __repr__(self):
if self._wrapped is empty:
repr_attr = self._setupfunc
# Avoid recursion if setupfunc is a bound method of this instance.
if getattr(self._setupfunc, "__self__", None) is self:
repr_attr = f"<bound method {self._setupfunc.__name__}>"
else:
repr_attr = self._setupfunc
else:
repr_attr = self._wrapped
return "<%s: %r>" % (type(self).__name__, repr_attr)

View File

@@ -348,6 +348,22 @@ class SimpleLazyObjectTestCase(LazyObjectTestCase):
self.assertIsInstance(obj._wrapped, int)
self.assertEqual(repr(obj), "<SimpleLazyObject: 42>")
def test_repr_bound_method(self):
class MyLazyGenerator(SimpleLazyObject):
def __init__(self):
super().__init__(self._generate)
def _generate(self):
return "test-generated-value"
obj = MyLazyGenerator()
self.assertEqual(repr(obj), "<MyLazyGenerator: '<bound method _generate>'>")
self.assertIs(obj._wrapped, empty) # The evaluation hasn't happened.
self.assertEqual(str(obj), "test-generated-value") # Evaluate.
self.assertEqual(repr(obj), "<MyLazyGenerator: 'test-generated-value'>")
def test_add(self):
obj1 = self.lazy_wrap(1)
self.assertEqual(obj1 + 1, 2)