Skip to content

Make MonoDictEraser and TripleDictEraser safe against "recursion depth exceeded" #15069

@simon-king-jena

Description

@simon-king-jena

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.

CC: @nthiery @nbruin @vbraun

Component: performance

Author: Simon King

Reviewer: Volker Braun

Merged: sage-5.12.beta4

Issue created by migration from https://trac.sagemath.org/ticket/15069

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions