classification
Title: Incorrect semantics of __radd__ method for builtin types
Type: behavior Stage: resolved
Components: Versions: Python 3.1, Python 3.2
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: mark.dickinson Nosy List: Mark.Shannon, georg.brandl, mark.dickinson, r.david.murray
Priority: normal Keywords:

Created on 2010-09-23 18:39 by Mark.Shannon, last changed 2010-09-23 20:16 by mark.dickinson. This issue is now closed.

Files
File name Uploaded Description Edit
binary_op_mimic.py Mark.Shannon, 2010-09-23 18:39 Python implementation of binary operator
Messages (9)
msg117216 - (view) Author: Mark Shannon (Mark.Shannon) * (Python committer) Date: 2010-09-23 18:39
Attached program fails.
See comments in file for details and possible diagnosis
msg117218 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2010-09-23 18:56
Could you post some simple examples and an explanation of what you think the problem is?  I have no clue what problem your code is trying to show just by looking at it.  (Maybe it will be clear to someone else, but still, simple examples are usually better, and easier to turn into unit tests.)
msg117219 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2010-09-23 19:12
This is indeed weird.  PyNumber_Add ends up calling compare_add with the float as its first argument, which is impossible to do from Python.  And the wrap_binaryfunc_r check for subtypes means that compare.__radd__ claims it doesn't support floats either.  So from Python, it's impossible to add floats and complex numbers via __special__ methods :)

Maybe Mark wants to shed some light?
msg117221 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2010-09-23 19:23
If I understand correctly, the complaint is that (for example) in Python 3.x, we have:

Python 3.1.2 (r312:79147, Aug 20 2010, 20:06:00) 
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> float.__radd__(3.0, 1)
NotImplemented

while in Python 2.x:

Python 2.6.6 (r266:84292, Aug 28 2010, 18:05:46) 
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> float.__radd__(3.0, 1)
4.0

It's not clear to me whether there's any good reason for this change.



(I'm deliberately avoiding the original float + complex example, since complex is a little peculiar in 2.x for x <= 6 anyway---it's treated as an 'old-style' number (not to be confused with an old-style class)).

(Changing versions:  2.5 and 2.6 aren't getting bugfixes any more, and 2.7 appears to be behaving correctly.)
msg117222 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2010-09-23 19:31
> PyNumber_Add ends up calling compare_add with the float as its first
> argument, which is impossible to do from Python.

[Assuming you mean complex_add.]  I think this bit is expected, though.  complex_add (or float_add, or whatever) provides both the __add__ and __radd__ methods.
msg117223 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2010-09-23 19:35
Hmm, not sure.  I'm referring to Objects/abstract.c, binary_op1, which tries to call both slotv and slotw.
msg117224 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2010-09-23 19:50
It looks like Mark is right:  the wrap_binaryfunc_r subtype check should just be removed.  The corresponding check in 2.x only occurs for types which don't have the Py_TPFLAGS_CHECKTYPES flag set.  As of 2.7, *all* of the numeric types have this flag set (in 2.6, the complex type doesn't).

I'm not seeing any (relevant) test failures here after removing the check.
Actually, I'm not seeing any test failures at all.  Hooray!
msg117225 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2010-09-23 19:53
That's encouraging.  I would suggest making this fix; the fact that Jython and IronPython also get this right is another reason.
msg117227 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2010-09-23 20:16
Fixed in r84984 (py3k), r84986 (release31-maint).  Thanks for the report!
History
Date User Action Args
2010-09-23 20:16:51mark.dickinsonsetstatus: open -> closed
messages: + msg117227

assignee: mark.dickinson
resolution: fixed
stage: resolved
2010-09-23 19:53:27georg.brandlsetmessages: + msg117225
2010-09-23 19:50:25mark.dickinsonsetmessages: + msg117224
2010-09-23 19:35:42georg.brandlsetmessages: + msg117223
2010-09-23 19:31:16mark.dickinsonsetmessages: + msg117222
2010-09-23 19:25:22mark.dickinsonsetversions: + Python 3.2, - Python 2.6, Python 2.5, Python 2.7
2010-09-23 19:23:02mark.dickinsonsetnosy: + mark.dickinson
messages: + msg117221
2010-09-23 19:12:04georg.brandlsetnosy: + georg.brandl
messages: + msg117219
2010-09-23 18:56:13r.david.murraysetnosy: + r.david.murray
messages: + msg117218
2010-09-23 18:39:50Mark.Shannoncreate