Make `MonoDictEraser` and `TripleDictEraser` safe against "recursion depth exceeded"
|Reported by:||SimonKing||Owned by:|
|Cc:||nthiery, nbruin, vbraun||Merged in:||sage-5.12.beta4|
|Authors:||Simon King||Reviewers:||Volker Braun|
|Report Upstream:||N/A||Work issues:|
The following happens both with Sage's MonoDict and with Python's weakref.WeakKeyDictionary:
from sage.structure.coerce_dict import MonoDict M = MonoDict(11) class A: pass a = A() prev = a for i in range(1000): newA = A() M[prev] = newA prev = newA len(M) del a Exception RuntimeError: 'maximum recursion depth exceeded while calling a Python object' in <sage.structure.coerce_dict.MonoDictEraser object at 0x5a13788> ignored
Replace M = MonoDict(11) by M = weakref.WeakKeyDictionary(), and you get essentially the same error:
sage: del a Exception RuntimeError: 'maximum recursion depth exceeded while calling a Python object' in <function remove at 0x5f9d578> ignored
However, a weakref.WeakValueDictionary seems safe:
sage: class A: pass sage: M = weakref.WeakValueDictionary() sage: a = A() ....: prev = a ....: for i in range(1000): ....: newA = A() ....: M[newA] = prev ....: prev = newA ....: sage: len(M) 1000 sage: del a sage: len(M) 0
even though the recursive deletion of dictionary items seems similar.
Aim of this ticket: Make it so that the erasers of MonoDict and TripleDict are not recursively called and thus the dreaded 'maximum recursion depth exceeded ... ignored' finally vanishes.
Change History (11)
Changed 4 months ago by SimonKing
comment:9 Changed 4 months ago by vbraun
- Reviewers set to Volker Braun
- Status changed from needs_review to positive_review