classification
Title: Inconsistent error message for TypeError with subscripting
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 2.7
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: rhettinger Nosy List: Anthony Sottile, rhettinger, serhiy.storchaka
Priority: normal Keywords: patch

Created on 2017-09-22 03:32 by Anthony Sottile, last changed 2018-03-27 15:39 by rhettinger. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 3692 closed Anthony Sottile, 2017-09-22 03:43
PR 6151 closed Anthony Sottile, 2018-03-19 17:41
Messages (11)
msg302736 - (view) Author: Anthony Sottile (Anthony Sottile) * Date: 2017-09-22 03:32
There's a bit of history I don't understand and couldn't find the appropriate trail for.

The original error message from the 2.6 era:

$ python2.6 -c 0[0]
Traceback (most recent call last):
  File "<string>", line 1, in <module>
TypeError: 'int' object is unsubscriptable


This was changed in https://github.com/python/cpython/commit/f5fd5239819c5dfb1d7a33484be49dc705544d02 for clarity

As seen in 2.7.1

$ ./python2.7.1 -c 0[0]
Traceback (most recent call last):
  File "<string>", line 1, in <module>
TypeError: 'int' object is not subscriptable


It was later changed in the 2.7 era here: 
https://github.com/python/cpython/commit/7d1483cbadbe48620964348a2039690624e7dc8e


To this error message (as demonstrated with 2.7.12):

$ python2.7 -c 0[0]
Traceback (most recent call last):
  File "<string>", line 1, in <module>
TypeError: 'int' object has no attribute '__getitem__'


However, this patch never made it into the 3.x branch:

$ python3.6 -c 0[0]
Traceback (most recent call last):
  File "<string>", line 1, in <module>
TypeError: 'int' object is not subscriptable


Should this patch be (have been) cherry picked into master?
msg302738 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-09-22 06:26
I'm not sure that this is an enhancement. It makes an error message inconsistent with other error messages.

>>> class I(int): pass
... 
>>> I()[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'I' object does not support indexing
>>> 0[0] = 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object does not support item assignment
>>> del 0[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object does not support item deletion
>>> ''['']                                                                                                                                                                                                                                   
Traceback (most recent call last):                                                                                                                                                                                                           
  File "<stdin>", line 1, in <module>                                                                                                                                                                                                        
TypeError: string indices must be integers, not str                                                                                                                                                                                          
>>> iter(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
>>> reversed(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: argument to reversed() must be a sequence
>>> next(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: int object is not an iterator
>>> {}[[]]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

And actually this message is misleading. An attribute '__getitem__' is not looked up on objects.

>>> class I(int): pass
... 
>>> x = I()
>>> x.__getitem__ = lambda *args: None
>>> I()[0:]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'I' object has no attribute '__getitem__'
>>> x.__getitem__
<function <lambda> at 0x7f11b62dd648>
msg302756 - (view) Author: Anthony Sottile (Anthony Sottile) * Date: 2017-09-22 17:08
All I'm really looking for is consistency -- should the change to 2.7 be reverted instead?
msg302848 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-09-24 11:28
I think it should. But let to hear Raymond's arguments.
msg302868 - (view) Author: Anthony Sottile (Anthony Sottile) * Date: 2017-09-24 16:52
Shouldn't you wait for Raymond's arguments before outright closing the PR?
msg314106 - (view) Author: Anthony Sottile (Anthony Sottile) * Date: 2018-03-19 17:44
I made a new PR which instead *reverts* the python2.7 patch to restore consistency
msg314115 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2018-03-19 19:51
I would like to leave this as-is.  Consistency between error message wording is one of our least important considerations.  The __getitem__ message is somewhat useful -- it helps learners know which magic method is being called and what they would need to add to a class to make it work.  This was the typical wording for old-style classes.  For example, calling len() on an old-style class without __len__ gave this message, "AttributeError: A instance has no attribute '__len__'".

In addition, we are getting very close to end-of-life for Python2.7.  Accordingly, any changes at this point should be limited to things that really matter.  It will be too easy to introduce a new problem that we won't have an opportunity to fix later.

I recommend closing this and shifting attention to things that matter.
msg314116 - (view) Author: Anthony Sottile (Anthony Sottile) * Date: 2018-03-19 20:00
I think the main concern here is ease in portability coupled with the incorrectness of the current message (pointed out in https://bugs.python.org/issue31550#msg302738)

For instance it was consistent in 2.7.1, but not later on in the 2.7.x tree.  *And* it's different than python3 (for no good reason?)

The message is misleading as well, it's not looking for __getitem__ on the instance but on the type.
msg314118 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2018-03-19 20:45
> it's different than python3 (for no good reason?)
Python 3 has new style classes which were always different.

> main concern here is ease in portability  
We've long stated that there should never be dependency on the exact wording of an error message.  We're allowed to change that.

> For instance it was consistent in 2.7.1
To the extent we care about this, it is more important to be consistent with later releases than earlier releases.

Since I don't see any evidence that there is a real world problem, I would like to see this left alone.  At this point, in Python 2.7's life we need to have a strong aversion to any changes at all.  Not only has that ship sailed, its voyage is almost over.
msg314506 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2018-03-27 09:18
If the reason of this change was making the error message more consistent with other error messages in classic classes (at the cost of larger dereference with Python 3), it LGTM.
msg314535 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2018-03-27 15:39
Marked as closed for the reasons listed.

Thank you for the suggestion, but we're going to decline.
History
Date User Action Args
2018-03-27 15:39:31rhettingersetstatus: open -> closed
resolution: rejected
messages: + msg314535

stage: patch review -> resolved
2018-03-27 09:18:28serhiy.storchakasetmessages: + msg314506
2018-03-19 20:45:55rhettingersetmessages: + msg314118
versions: + Python 2.7, - Python 3.7
2018-03-19 20:00:19Anthony Sottilesetmessages: + msg314116
2018-03-19 19:51:35rhettingersetassignee: rhettinger
messages: + msg314115
2018-03-19 17:44:23Anthony Sottilesetmessages: + msg314106
2018-03-19 17:41:26Anthony Sottilesetpull_requests: + pull_request5909
2017-09-24 16:52:18Anthony Sottilesetmessages: + msg302868
2017-09-24 11:28:15serhiy.storchakasetmessages: + msg302848
2017-09-22 17:08:33Anthony Sottilesetmessages: + msg302756
2017-09-22 06:26:33serhiy.storchakasetnosy: + rhettinger, serhiy.storchaka
messages: + msg302738
2017-09-22 03:43:59Anthony Sottilesetkeywords: + patch
stage: patch review
pull_requests: + pull_request3679
2017-09-22 03:32:38Anthony Sottilecreate