Issue1955

classification
Title: NotImplemented incorrectly handled in Old style classes
Type: Severity: normal
Components: Versions:
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Arfrever, amak, fwierzbicki, pjenvey
Priority: normal Keywords:

Created on 2012-08-04.05:33:16 by Arfrever, last changed 2013-02-27.18:30:44 by fwierzbicki.

Messages
msg7350 (view) Author: Arfrever Frehtes Taifersar Arahesis (Arfrever) Date: 2012-08-04.05:33:15
When special methods (e.g. __add__ or __sub__) return NotImplemented, then operations which internally use these methods should raise appropriate TypeError exceptions.

In CPython:

>>> class A:
...   def __add__(self, other):
...     return NotImplemented
...   def __sub__(self, other):
...     return NotImplemented
... 
>>> A() + A()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'instance' and 'instance'
>>> A() - A()
Traceback (most recent call last):                                                                                                                           
  File "<stdin>", line 1, in <module>                                                                                                                        
TypeError: unsupported operand type(s) for -: 'instance' and 'instance'                                                                                      
>>>

In Jython:

>>> class A:
...   def __add__(self, other):
...     return NotImplemented
...   def __sub__(self, other):
...     return NotImplemented
... 
>>> A() + A()
NotImplemented
>>> A() - A()
NotImplemented
>>>
msg7352 (view) Author: Philip Jenvey (pjenvey) Date: 2012-08-04.18:10:37
This only affects old style classes
msg7353 (view) Author: Philip Jenvey (pjenvey) Date: 2012-08-04.18:56:09
The problem here is that PyInstance#__add__ does not follow the contract of PyObject#__add__ in that it must return null when a user defined add impl returns NotImplemented

Currently PyInstance#instance___add__ defers to invoke_ex to do the work. However there's an invoke_ex_richcmp method that is doing the right thing (returning null for NotImplemented). Either that method should be used instead (and more appropriately renamed) or maybe invoke_ex should just adopt that logic.

Note that this problem affects likely every binary op in PyInstance, not just add (which is one reason why invoke_ex might have to adopt the logic).

So this fix could use a few more tests other than add. You *might* be able to recycle some of test_descr_jy.BinopCombinationsTestCase for this (but there's no need to go overboard)
History
Date User Action Args
2013-02-27 18:30:44fwierzbickisetpriority: normal
2012-08-28 21:39:07amaksetnosy: + amak
2012-08-04 18:56:10pjenveysetmessages: + msg7353
2012-08-04 18:10:38pjenveysetnosy: + pjenvey
messages: + msg7352
title: NotImplemented incorrectly handled -> NotImplemented incorrectly handled in Old style classes
2012-08-04 05:33:16Arfrevercreate