import sys
def assert_recursion_message(exc, context):
msg = str(exc)
if sys.platform == 'monty':
assert msg == 'maximum recursion depth exceeded', f'unexpected {context} recursion message: {msg}'
else:
stack_msg = msg.startswith('Stack overflow (used ') and ' kB)' in msg
assert msg == 'maximum recursion depth exceeded' or stack_msg, f'unexpected {context} recursion message: {msg}'
class SelfRepr:
def __repr__(self):
return repr(self)
try:
repr(SelfRepr())
raise AssertionError('expected RecursionError from self-referential __repr__')
except RecursionError as exc:
assert_recursion_message(exc, 'repr')
class SelfStr:
def __str__(self):
return str(self)
try:
str(SelfStr())
raise AssertionError('expected RecursionError from self-referential __str__')
except RecursionError as exc:
assert_recursion_message(exc, 'str')
class Node:
def __init__(self, value, child=None):
self.value = value
self.child = child
def __repr__(self):
if self.child is None:
return f'Node({self.value})'
return f'Node({self.value}, {self.child!r})'
chain = None
for i in range(5):
chain = Node(i, chain)
result = repr(chain)
assert result == 'Node(4, Node(3, Node(2, Node(1, Node(0)))))', f'unexpected repr: {result}'
class A:
pass
A.__init__ = A
try:
A()
raise AssertionError('expected RecursionError from class-valued __init__ cycle')
except RecursionError as exc:
assert_recursion_message(exc, '__init__')