RecursionError: maximum recursion depth exceeded / breaks other add-on / changes how mw.col.models works
ijgnd opened this issue · 3 comments
When you have only the add-on "Enhanced Cloze" installed (in Anki 2.1.49) running print(mw.col.models)
from the debug console does not work for me but instead throws an error message like this:
Traceback (most recent call last):
File "aqt/main.py", line 1524, in onDebugRet
File "<string>", line 1, in <module>
...
File "anki/models.py", line 91, in __repr__
File "pprint.py", line 58, in pformat
File "pprint.py", line 153, in pformat
File "pprint.py", line 170, in _format
File "pprint.py", line 404, in _repr
File "pprint.py", line 417, in format
File "pprint.py", line 523, in _safe_repr
File "pprint.py", line 101, in _safe_tuple
RecursionError: maximum recursion depth exceeded while calling a Python object
The add-on "Enhanced Cloze" also breaks the add-on "CrowdAnki" with a similar error message. I tested with just these two add-ons with Anki 2.1.49 in linux and 2.1.54 in Windows.
@aplaice found out that your compat.add_compatibility_alias
seems to cause a problem and posted a preliminary fix, see Stvad/CrowdAnki#179 (comment).
I'm posting here because this might also be relevant for other add-ons. As far as I see you have the same line if new_name not in list(namespace.__dict__.keys())
also in the AnKing Note Types (Easy Customization) add-on though "AnKing Note Types" doesn't seem to break the CrowdAnki add-on.
@ijgnd Thanks, I'll look into it.
From a cursory analysis, AFAIU there are two issues with the compat code:
-
An object's methods are usually not listed in
object.__dict__
. (They are/should be present indir(object)
, though.)This means that
if new_name not in list(...)
will always be true, for all Anki versions, so the compat renaming will occur even when it's not necessary.I believe that this can be easily fixed by using
dir(namespace)
. -
setattr
andgetattr
behave asymmetrically.getattr
will "get" an attribute/method even if it's not present in the class's/objects__dict__
.setattr
however, will add the attribute to the object's__dict__
. (i.e.setattr(foo, "x", bar)
is not completely equivalent tofoo.x = bar
.)This means that when the object is serialized, python will also try to serialise the newly added attributes. (This is what happens in CrowdAnki.)
I'm not sure how to easily/properly/neatly fix this, though. However, it's also a far more niche problem than 1 — most of the time Anki classes/objects don't need to be serialised.
(Fixing 1 will fix the crash from print(mw.col.models)
in the console and from the combination of CrowdAnki and Enhanced cloze for current versions of Anki.)
(Sorry for jumping from a crash triggered by CrowdAnki, to your add-on, but it's easier to fix on your end :) (I'd have to exclude the various attributes from the serialisation of models
which would be tricky and ugly), and I think that 1 at least is a very minor bug in your add-on, in itself, (e.g. it causes spurious byName is deprecated: please use 'by_name'
background messages).)
also in the AnKing Note Types (Easy Customization) add-on though "AnKing Note Types" doesn't seem to break the CrowdAnki add-on
I'd expect that's because the attributes of aqt.col.models
probably aren't being aliased, there (only those of other objects).