nltk/nltk — Issue #198: Infinite loop when modifying Tree children 
Author: heatherleaf
Created: 2012-02-01 21:51:53+00:00
State: open

Tree:s (and ParentedTree:s) go into an infinite loop if you try to change or delete a child by using a string as key:

>>> t = nltk.Tree("(a b c (d e) g f r)")
>>> t["2"]
Tree('d', ['e'])
>>> t["2"] = 42
Traceback (most recent call last):
File "", line 1, in
File "/Users/peter/Projekt/NLTK/nltk/nltk/tree.py", line 177, in __setitem__
self[index[0]] = value
(...)
File "/Users/peter/Projekt/NLTK/nltk/nltk/tree.py", line 170, in __setitem__
if isinstance(index, (int, slice)):
RuntimeError: maximum recursion depth exceeded in __instancecheck__

The reason is that neither __setitem__ nor __delitem__ tries to convert the key to an integer: `self[index[0]] = value`. __getitem__ does that on the other hand: `return self[int(index[0])]`

The solution is simple, but there are two possibilities:

1. Convert string keys to integers as is done in __getitem__: replace `index[0]` with `int(index[0])` in __setitem__ and __delitem__
2. Disallow string keys: replace `int(index[0])` with `index[0]` in __getitem__, and add a check `isinstance(index, (list, tuple))` to all three methods

Personally I prefer the second, since it is what Python does for lists. I don't see the reason why `tree["123"]`should be allowed, and have the same meaning as `tree[1,2,3]`. However, although I don't think the current behaviour is documented, the change might break some existing code.

What do the benevolent dictators think?