bpo-25532: Protect against infinite loops in inspect.unwrap() by takluyver · Pull Request #1717 · python/cpython (original) (raw)
Some objects, such as unittest.mock.call
, generate a new similar object every time you access obj.__wrapped__
. This isn't caught by the memoise loop protection, because each object has a different ID. So a call like inspect.getsourcelines(unittest.mock.call)
goes into an infinite loop, using ever more memory as it creates new objects.
This implements @ncoghlan's suggestion in issue 22532: if we've unwrapped something sys.getrecursionlimit()
times, assume it's an infinite chain and give up. Things like getsourcelines()
will fail, but an exception is better than using up all the memory.
IPython's inspection machinery already has a similar check, with an arbitrary limit of 100 unwraps. That returns the original object if the limit is exceeded, rather than throwing an error.
https://github.com/ipython/ipython/blob/6.0.0/IPython/core/oinspect.py#L279