[pypy-commit] pypy py3.5: complex() should not allow .__complex__() to return non-complex (CPython issue #16290)

rlamy pypy.commits at gmail.com
Thu Oct 27 19:31:38 EDT 2016


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: py3.5
Changeset: r87968:47c2ae1fc893
Date: 2016-10-28 00:30 +0100
http://bitbucket.org/pypy/pypy/changeset/47c2ae1fc893/

Log:	complex() should not allow .__complex__() to return non-complex
	(CPython issue #16290)

diff --git a/pypy/objspace/std/complexobject.py b/pypy/objspace/std/complexobject.py
--- a/pypy/objspace/std/complexobject.py
+++ b/pypy/objspace/std/complexobject.py
@@ -132,12 +132,11 @@
     return format_float(x, 'g', DTSF_STR_PRECISION)
 
 
-def unpackcomplex(space, w_complex, strict_typing=True):
+def unpackcomplex(space, w_complex):
     """
-    convert w_complex into a complex and return the unwrapped (real, imag)
-    tuple. If strict_typing==True, we also typecheck the value returned by
-    __complex__ to actually be a complex (and not e.g. a float).
-    See test___complex___returning_non_complex.
+    Convert w_complex into a complex and return the unwrapped (real, imag)
+    tuple. Also, typecheck the value returned by __complex__ to actually be a
+    complex (and not e.g. a float).
     """
     if type(w_complex) is W_ComplexObject:
         return (w_complex.realval, w_complex.imagval)
@@ -149,12 +148,9 @@
         w_z = space.get_and_call_function(w_method, w_complex)
     #
     if w_z is not None:
-        # __complex__() must return a complex or (float,int,long) object
+        # __complex__() must return a complex
         # (XXX should not use isinstance here)
-        if not strict_typing and (space.isinstance_w(w_z, space.w_int) or
-                                  space.isinstance_w(w_z, space.w_float)):
-            return (space.float_w(w_z), 0.0)
-        elif isinstance(w_z, W_ComplexObject):
+        if isinstance(w_z, W_ComplexObject):
             return (w_z.realval, w_z.imagval)
         raise oefmt(space.w_TypeError,
                     "__complex__() must return a complex number")
@@ -302,14 +298,12 @@
 
         else:
             # non-string arguments
-            realval, imagval = unpackcomplex(space, w_real,
-                                             strict_typing=False)
+            realval, imagval = unpackcomplex(space, w_real)
 
             # now take w_imag into account
             if not noarg2:
                 # complex(x, y) == x+y*j, even if 'y' is already a complex.
-                realval2, imagval2 = unpackcomplex(space, w_imag,
-                                                   strict_typing=False)
+                realval2, imagval2 = unpackcomplex(space, w_imag)
 
                 # try to preserve the signs of zeroes of realval and realval2
                 if imagval2 != 0.0:
diff --git a/pypy/objspace/std/test/test_complexobject.py b/pypy/objspace/std/test/test_complexobject.py
--- a/pypy/objspace/std/test/test_complexobject.py
+++ b/pypy/objspace/std/test/test_complexobject.py
@@ -273,16 +273,13 @@
         assert complex(NS(1+10j)) == 1+10j
         assert complex(NS(1+10j), 5) == 1+15j
         assert complex(NS(1+10j), 5j) == -4+10j
-        assert complex(NS(2.0)) == 2+0j
-        assert complex(NS(2)) == 2+0j
+        raises(TypeError, complex, NS(2.0))
+        raises(TypeError, complex, NS(2))
         raises(TypeError, complex, NS(None))
         raises(TypeError, complex, b'10')
 
         # -- The following cases are not supported by CPython, but they
         # -- are supported by PyPy, which is most probably ok
-        #raises((TypeError, AttributeError), complex, OS(1+10j), OS(1+10j))
-        #raises((TypeError, AttributeError), complex, NS(1+10j), OS(1+10j))
-        #raises((TypeError, AttributeError), complex, OS(1+10j), NS(1+10j))
         #raises((TypeError, AttributeError), complex, NS(1+10j), NS(1+10j))
 
         class F(object):
@@ -381,23 +378,6 @@
         assert complex(s) == 1+2j
         assert complex('\N{EM SPACE}(\N{EN SPACE}1+1j ) ') == 1+1j
 
-    def test___complex___returning_non_complex(self):
-        import cmath
-        class Obj(object):
-            def __init__(self, value):
-                self.value = value
-            def __complex__(self):
-                return self.value
-
-        # "bug-to-bug" compatibility to CPython: complex() is more relaxed in
-        # what __complex__ can return. cmath functions really wants a complex
-        # number to be returned by __complex__.
-        assert complex(Obj(2.0)) == 2+0j
-        assert complex(Obj(2)) == 2+0j
-        #
-        assert cmath.polar(1) == (1.0, 0.0)
-        raises(TypeError, "cmath.polar(Obj(1))")
-
     def test_hash(self):
         for x in range(-30, 30):
             assert hash(x) == hash(complex(x, 0))


More information about the pypy-commit mailing list