classification
Title: PyComplex_AsCComplex should allow __complex__ to return float.
Type: enhancement Stage: needs patch
Components: Interpreter Core Versions: Python 3.4
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: mark.dickinson Nosy List: antocuni, jcea, mark.dickinson, python-dev, serhiy.storchaka
Priority: normal Keywords: patch

Created on 2012-10-20 09:39 by mark.dickinson, last changed 2012-11-14 17:09 by mark.dickinson. This issue is now closed.

Files
File name Uploaded Description Edit
issue16290.patch mark.dickinson, 2012-10-20 09:51 review
issue16290v2.patch mark.dickinson, 2012-10-28 11:46 review
Messages (10)
msg173379 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2012-10-20 09:39
See thread starting at http://mail.python.org/pipermail/python-dev/2012-October/122241.html

The cmath module functions don't accept custom types that define __complex__, but whose __complex__ method returns a float rather than a complex number:

Python 3.4.0a0 (default:53a7c2226a2b+, Oct 19 2012, 12:16:36) 
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> class A:
...     def __complex__(self): return 42.0
... 
>>> import cmath
>>> cmath.sqrt(A())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __complex__ should return a complex object

In contrast, the complex constructor is happy to accept such objects.

The root cause is that PyArg_ParseTuple's 'D' format calls PyComplex_AsCComplex (in Objects/complexobject.c), which refuses to accept a __complex__ result of type float.
msg173380 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2012-10-20 09:51
Here's a patch
msg173384 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2012-10-20 11:40
Patch LGTM.

Is there a new feature, not a bugfix? If yes, then I expect some documentation changes.
msg173386 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2012-10-20 11:56
> Is there a new feature, not a bugfix?

There's an ongoing argument about that on the python-dev thread. :-)  But yes, I think this needs a doc update---even if it's considered a bugfix, the current docs could be clarified.

http://docs.python.org/dev/reference/datamodel.html?highlight=__complex__#object.__complex__

says

"Should return a value of the appropriate type."  My interpretation of that is that __int__ should return an int, __float__ a float, __complex__ a complex number;  with this change, that interpretation no longer works.

I'll update the patch (and add a Misc/NEWS entry, too).

Thanks!
msg173389 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2012-10-20 12:41
> My interpretation of that is that __int__ should return an int, __float__ a
> float, __complex__ a complex number; 

It's a reasonable interpretation. Changing it can be confusing.

On the other hand, int and float look like specialized subclasses of complex 
(they even have .real, .imag and .conjugate()). The ducktype principle 
requires that we can use ints or floats everywhere where complexes needed. This 
means that you should add a branch for integers too.
msg173390 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2012-10-20 13:17
> This means that you should add a branch for integers too.

I'd rather not go that far, at least in this issue:  we'd also end up changing __float__ to allow it to return an int, in that case.  If we're considering that, the discussion should go back to python-dev / python-ideas.

One difference is that int -> float is a lossy conversion that has to care about details like rounding and overflow.  float -> complex in contrast is much simpler.
msg174030 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2012-10-28 11:46
I've been convinced by the python-dev discussion that Antonio was right: it's complex_new that's in error rather than the cmath functions.  Even so, it would be unsafe to change the behaviour in the maintenance releases.

Attaching a new patch that disallows 'float'-type returns from the __complex__ method.
msg174095 - (view) Author: Jesús Cea Avión (jcea) * (Python committer) Date: 2012-10-29 01:39
Mark, for the sake of keeping a reference in this bug entry, could you possibly post the URL of the archived python-dev thread?

Thanks.
msg174105 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2012-10-29 08:05
Jesús:  see the first message.
msg175576 - (view) Author: Roundup Robot (python-dev) Date: 2012-11-14 17:08
New changeset 399e59ad0a70 by Mark Dickinson in branch 'default':
Issue #16290: __complex__ must now always return an instance of complex.
http://hg.python.org/cpython/rev/399e59ad0a70
History
Date User Action Args
2012-11-14 17:09:03mark.dickinsonsetstatus: open -> closed
resolution: fixed
2012-11-14 17:08:49python-devsetnosy: + python-dev
messages: + msg175576
2012-10-29 08:05:33mark.dickinsonsetmessages: + msg174105
2012-10-29 01:39:06jceasetmessages: + msg174095
2012-10-28 11:46:51mark.dickinsonsetfiles: + issue16290v2.patch

messages: + msg174030
2012-10-28 11:42:57mark.dickinsonsetnosy: + antocuni
2012-10-22 11:59:32jceasetnosy: + jcea
2012-10-20 13:17:44mark.dickinsonsetmessages: + msg173390
2012-10-20 12:41:13serhiy.storchakasetmessages: + msg173389
2012-10-20 11:56:17mark.dickinsonsetmessages: + msg173386
2012-10-20 11:40:27serhiy.storchakasetnosy: + serhiy.storchaka
messages: + msg173384
2012-10-20 09:51:34mark.dickinsonsetfiles: + issue16290.patch
keywords: + patch
messages: + msg173380
2012-10-20 09:39:39mark.dickinsoncreate