Issue2442

classification
Title: Overriding __len__, __iter__, and __getitem__ in a tuple subclass causes an infinite recursion
Type: behaviour Severity: normal
Components: Core Versions: Jython 2.7
Milestone: Jython 2.7.1
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: zyasoft Nosy List: ceridwen, zyasoft
Priority: high Keywords:

Created on 2015-12-08.20:50:24 by ceridwen, last changed 2016-02-21.01:55:31 by zyasoft.

Messages
msg10519 (view) Author: Ceridwen (ceridwen) Date: 2015-12-08.20:50:24
I have a tuple subclass that overrides those methods.  When trying to iterate over it, it enters an infinite loop between `__iter__` and `__len__`:

```
  File "spf.py", line 187, in __iter__
    yield getitem(node, 0)
  File "spf.py", line 203, in __len__
    return sum(1 for _ in self)
  File "spf.py", line 203, in <genexpr>
    return sum(1 for _ in self)
```

Here `getitem` is a call to `super(<tuple_subclass>, type(self)).__getitem__`, which in this case evaluates to `tuple.__getitem__`.

My working hypothesis for why this happens is that `tuple.__getitem__` calls the __len__ method of my subclass.

```
>>> class C(tuple):
...   def __len__(self):
...      print('Length')
...      return super(C, type(self)).__len__(self)
>>> c = C([1, 2])
>>> c[1]
Length
2
>>> tuple.__getitem__(c, 1)
Length
2
```

In general, my understanding is that calls to the methods of builtin types shouldn't call overridden methods.  This code works on CPython and PyPy.
msg10523 (view) Author: Jim Baker (zyasoft) Date: 2015-12-09.01:42:58
This seems to be the fault of this code in org.python.core.__builtin__:

    public static int len(PyObject obj) {
        return obj.__len__();
    }

Rather related discussion here:
http://sourceforge.net/p/jython/mailman/message/34677839/
msg10524 (view) Author: Jim Baker (zyasoft) Date: 2015-12-09.01:44:27
Also, I believe __getitem__ and __iter__ are implemented properly when used implicitly with [] and a foreach loop respectively. So it's just len/__len__ we have to fix.
msg10723 (view) Author: Jim Baker (zyasoft) Date: 2016-02-05.16:08:07
Target RC
msg10741 (view) Author: Jim Baker (zyasoft) Date: 2016-02-13.03:33:21
The problem is in __iter__, per Ceridwen's original message in msg10519

Fixed as of https://hg.python.org/jython/rev/85d99f6152b1 - I refactored iteration for list and tuple classes to not use other special methods.
History
Date User Action Args
2016-02-21 01:55:31zyasoftsetstatus: pending -> closed
2016-02-13 03:33:22zyasoftsetstatus: open -> pending
resolution: accepted -> fixed
messages: + msg10741
2016-02-05 16:08:07zyasoftsetpriority: normal -> high
messages: + msg10723
2015-12-30 00:02:04zyasoftsetpriority: normal
2015-12-11 02:16:39zyasoftsetassignee: zyasoft
2015-12-11 00:12:25zyasoftsetmilestone: Jython 2.7.1
2015-12-09 01:44:27zyasoftsetmessages: + msg10524
2015-12-09 01:42:59zyasoftsetresolution: accepted
messages: + msg10523
nosy: + zyasoft
2015-12-08 20:50:24ceridwencreate