ipython: Fix for infinite recursion in autoreload
I have a class which memoizes contains a link to itself as an attribute. This is used as a to ensure that a class specific memoized computation is unique and not inherited from bases.
It turns out that this causes an infinite recursion between update_generic and update_class in autoreload.
This is fixed with a quick check to prevent this case. added after the “prevent recursion” comment.
Furthermore in this code, the for loop also loops on “new” object attributes, which will fix #8771
def update_class(old, new):
"""Replace stuff in the __dict__ of a class, and upgrade
method code objects"""
#for key in list(old.__dict__.keys()):
for key in set(list(old.__dict__.keys()) + list(new.__dict__.keys())):
old_obj = getattr(old, key)
try:
new_obj = getattr(new, key)
except AttributeError:
# obsolete attribute: remove it
try:
delattr(old, key)
except (AttributeError, TypeError):
pass
continue
#prevent recursion
if old_obj not in [old, new] and new_obj not in [old, new]:
if update_generic(old_obj, new_obj): continue
try:
setattr(old, key, getattr(new, key))
except (AttributeError, TypeError):
pass # skip non-writable attributes
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 20 (11 by maintainers)
I was doing something a bit more strange to trigger it. It is a bit of a metaclass emulating behavior that needs some notion whether or not the logic has been run. In my case I was memoizing some class-specific values. This should be able to trigger it.