accurate errors for "magic" methods

Hello, Below a post on python-tutor and my trial to explain what happens. ==============================================
This means the following: * You're trying to access an item inside something called self.opt, by using a key: 'inifile'. * self.opt should then be a kind of container able to return you an item from a key; in other words, it is supposed to be an object that behaves like a dictionary, right? * The "magic" method the allows this behaviour is called __getitem__ (the same as for list indexing, actually). So that python looks for this method attribute in the class of self.opt, that happens to be Values, and tells you... Sure, not very clear! ===================================================== Actually, I'm wrong: it's perfectly clear as long as the programmer is able to follow all the necessary reflexion path; then probably also able to solve the problem without any help from python. The issue here is that a very specific (and meaningful) case (dict-like behaviour missing) is adressed using a very generic (and thus helpless) message (attributeError). I think error cases about "magic" methods, that implement conceptually meaningful behaviours, should have appropriate messages. In the case above, maybe something like: "Values instance is not an item container (no __getitem__ method found)." There may be a sensible relationship with the ABC hierarchy that precisely provides naming and specification to types implementating (some of) the magic methods. I would love a BehaviourError ;-) Denis ------ la vita e estrany

On Thu, Apr 9, 2009 at 10:56 AM, Georg Brandl <g.brandl@gmx.net> wrote:
And if PEP 3134 (http://www.python.org/dev/peps/pep-3134/) were accepted+implemented, this could be made even clearer by using exception chaining to indicate that the TypeError was caused (at least semantically, disregarding optimizations) by the AttributeError. Cheers, Chris -- I have a blog: http://blog.rebertia.com

Benjamin Peterson wrote:
Not quite - I'm pretty sure 3134 only kicks in reliably if an exception makes it back into a Python exception handler. For C code, it isn't necessarily the case that __cause__ and __context__ will be hooked up automatically (and in the specific case of TypeErrors coming from abstract.c, there is never an AttributeError in the first place - the lookup code is checking specific slots on the type object rather than doing a normal attribute lookup). Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------

On Fri, 10 Apr 2009 03:56:16 am Georg Brandl wrote:
Except that the error "object is unsubscriptable" might as well be in Klingon to most people, particularly newbies. (1) It's easy to misread it as "unscriptable", which is even more mysterious. (2) As far as I know, there's no tradition of describing key or index lookup as "subscripting" in Python. I've never noticed it in doc strings or the online docs, and after hanging around comp.lang.python extensively for years, I feel safe to say it's not a common term among even experienced Python developers. I suppose that there's a weak connection between index lookup and subscripts in mathematics. (3) The classic error message tells the newbie exactly what the error is: the object has no __getitem__ method. The new error message tells the newbie nothing useful. Given that obj is unsubscriptable, what needs to be done to make it subscriptable? -- Steven D'Aprano

Le Fri, 10 Apr 2009 14:45:12 +1000, Steven D'Aprano <steve@pearwood.info> s'exprima ainsi:
I do agree with all of these comments. A useful error message in such a case should (1) Speak first at the conceptual level (if it's not a container of individual elements, it can't be indexed nore "key-ed"). (2) Do this using an idiom that a newbie has a good chance to figure out -- even if with some mental effort. (3) Point at the precise issue from which python itself could figure out there is an error (no __getitem__) In this specific case, an additional difficulty comes from the common __getitem__ for both index and key lookup (and even slicing). I have no real clue how to makes things better generally. I do not mean that somathing like "Values instance is not an item container (no __getitem__ method found)." if for the best. But I'm sure there is an issue. ABCs bring a common and consistent organisation. We could start from there, establish a standard vocabulary (including eg "subscript" as a superclass of "key" & "index") that would be reused in all docs and tutorials; and use this system for error messages instead of random (& helpless) formulation. Denis ------ la vita e estrany

Steven D'Aprano <steve@pearwood.info> wrote:
+1 And not just the newbie, either. The experienced python programmer looks at the original message and goes "ah ha". The experienced python programmer looks at the new message and has to _think about it_ before understanding arrives. I think that would be true even if you found a better word than 'unsubscriptable'. "Does not implement an item lookup method" might work. Or how about, 'Does not implement the Sequence or Mapping interface'? But you know what? Doing a google search for 'python mapping' gets you the description of dictionaries, while doing a google search for 'python __getitem__' gets you to the data model chapter that describes how the mapping/sequence behavior is implemented via __getitem__. The latter is more useful even to the newbie, I think. So even if it looks ugly, I think the error message should mention __getitem__. -- R. David Murray

On Fri, Apr 10, 2009 at 6:52 AM, R. David Murray <rdmurray@bitdance.com> wrote:
I have gone ahead and filed a bug: http://bugs.python.org/issue5760 Cheers, Chris -- I have a blog: http://blog.rebertia.com

Steven D'Aprano wrote:
This exact topic came up almost exactly a year ago: http://mail.python.org/pipermail/python-dev/2008-April/078744.html It seems the only thing that came out of that discussion was that set() now has a new error message (that is still inconsistent): Python 2.7a0 (trunk:71448, Apr 10 2009, 11:49:22) [GCC 4.1.2 (Gentoo 4.1.2 p1.1)] on linux2 Type "help", "copyright", "credits" or "license" for more information.
Perhaps the most relevant part though is GvR saying: """ I wouldn't bet my life on that. __getitem__ overloading for all sorts of nefarious purposes has quite a following. I'd prefer a message that doesn't get into what x "is" but sticks to the point at hand, which is that it doesn't support __getitem__. """ -- Scott Dial scott@scottdial.com scodial@cs.indiana.edu

Steven D'Aprano wrote:
(1) It's easy to misread it as "unscriptable", which is even more mysterious.
'Cannot be subscripted' might be clearer.
(2) As far as I know, there's no tradition of describing key or index lookup as "subscripting" in Python....
Reference / Expressions "Subscriptions A subscription selects an item of a sequence (string, tuple or list) or mapping (dictionary) object:..."
It says "Do not try to subscript this object'.
Given that obj is unsubscriptable, what needs to be done to make it subscriptable?
Typicallly, nothing. Usually, there is no __getitem__ because there should not be. How would you make a number subscriptable? To me, saying 'Int cannot be subscripted' (don't do it) is more helpful to newbies than 'Int has no __getitem__ method' (so it cannot be subscripted, so stop trying). tjr

On Thu, Apr 9, 2009 at 10:56 AM, Georg Brandl <g.brandl@gmx.net> wrote:
And if PEP 3134 (http://www.python.org/dev/peps/pep-3134/) were accepted+implemented, this could be made even clearer by using exception chaining to indicate that the TypeError was caused (at least semantically, disregarding optimizations) by the AttributeError. Cheers, Chris -- I have a blog: http://blog.rebertia.com

Benjamin Peterson wrote:
Not quite - I'm pretty sure 3134 only kicks in reliably if an exception makes it back into a Python exception handler. For C code, it isn't necessarily the case that __cause__ and __context__ will be hooked up automatically (and in the specific case of TypeErrors coming from abstract.c, there is never an AttributeError in the first place - the lookup code is checking specific slots on the type object rather than doing a normal attribute lookup). Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------

On Fri, 10 Apr 2009 03:56:16 am Georg Brandl wrote:
Except that the error "object is unsubscriptable" might as well be in Klingon to most people, particularly newbies. (1) It's easy to misread it as "unscriptable", which is even more mysterious. (2) As far as I know, there's no tradition of describing key or index lookup as "subscripting" in Python. I've never noticed it in doc strings or the online docs, and after hanging around comp.lang.python extensively for years, I feel safe to say it's not a common term among even experienced Python developers. I suppose that there's a weak connection between index lookup and subscripts in mathematics. (3) The classic error message tells the newbie exactly what the error is: the object has no __getitem__ method. The new error message tells the newbie nothing useful. Given that obj is unsubscriptable, what needs to be done to make it subscriptable? -- Steven D'Aprano

Le Fri, 10 Apr 2009 14:45:12 +1000, Steven D'Aprano <steve@pearwood.info> s'exprima ainsi:
I do agree with all of these comments. A useful error message in such a case should (1) Speak first at the conceptual level (if it's not a container of individual elements, it can't be indexed nore "key-ed"). (2) Do this using an idiom that a newbie has a good chance to figure out -- even if with some mental effort. (3) Point at the precise issue from which python itself could figure out there is an error (no __getitem__) In this specific case, an additional difficulty comes from the common __getitem__ for both index and key lookup (and even slicing). I have no real clue how to makes things better generally. I do not mean that somathing like "Values instance is not an item container (no __getitem__ method found)." if for the best. But I'm sure there is an issue. ABCs bring a common and consistent organisation. We could start from there, establish a standard vocabulary (including eg "subscript" as a superclass of "key" & "index") that would be reused in all docs and tutorials; and use this system for error messages instead of random (& helpless) formulation. Denis ------ la vita e estrany

Steven D'Aprano <steve@pearwood.info> wrote:
+1 And not just the newbie, either. The experienced python programmer looks at the original message and goes "ah ha". The experienced python programmer looks at the new message and has to _think about it_ before understanding arrives. I think that would be true even if you found a better word than 'unsubscriptable'. "Does not implement an item lookup method" might work. Or how about, 'Does not implement the Sequence or Mapping interface'? But you know what? Doing a google search for 'python mapping' gets you the description of dictionaries, while doing a google search for 'python __getitem__' gets you to the data model chapter that describes how the mapping/sequence behavior is implemented via __getitem__. The latter is more useful even to the newbie, I think. So even if it looks ugly, I think the error message should mention __getitem__. -- R. David Murray

On Fri, Apr 10, 2009 at 6:52 AM, R. David Murray <rdmurray@bitdance.com> wrote:
I have gone ahead and filed a bug: http://bugs.python.org/issue5760 Cheers, Chris -- I have a blog: http://blog.rebertia.com

Steven D'Aprano wrote:
This exact topic came up almost exactly a year ago: http://mail.python.org/pipermail/python-dev/2008-April/078744.html It seems the only thing that came out of that discussion was that set() now has a new error message (that is still inconsistent): Python 2.7a0 (trunk:71448, Apr 10 2009, 11:49:22) [GCC 4.1.2 (Gentoo 4.1.2 p1.1)] on linux2 Type "help", "copyright", "credits" or "license" for more information.
Perhaps the most relevant part though is GvR saying: """ I wouldn't bet my life on that. __getitem__ overloading for all sorts of nefarious purposes has quite a following. I'd prefer a message that doesn't get into what x "is" but sticks to the point at hand, which is that it doesn't support __getitem__. """ -- Scott Dial scott@scottdial.com scodial@cs.indiana.edu

Steven D'Aprano wrote:
(1) It's easy to misread it as "unscriptable", which is even more mysterious.
'Cannot be subscripted' might be clearer.
(2) As far as I know, there's no tradition of describing key or index lookup as "subscripting" in Python....
Reference / Expressions "Subscriptions A subscription selects an item of a sequence (string, tuple or list) or mapping (dictionary) object:..."
It says "Do not try to subscript this object'.
Given that obj is unsubscriptable, what needs to be done to make it subscriptable?
Typicallly, nothing. Usually, there is no __getitem__ because there should not be. How would you make a number subscriptable? To me, saying 'Int cannot be subscripted' (don't do it) is more helpful to newbies than 'Int has no __getitem__ method' (so it cannot be subscripted, so stop trying). tjr
participants (10)
-
Benjamin Peterson
-
Chris Rebert
-
Georg Brandl
-
Jim Jewett
-
Nick Coghlan
-
R. David Murray
-
Scott Dial
-
spir
-
Steven D'Aprano
-
Terry Reedy