[pypy-svn] pypy default: Test and fix for __complex__.

arigo commits-noreply at bitbucket.org
Mon Jan 31 11:25:09 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r41491:d02b905bb7bd
Date: 2011-01-30 18:18 +0100
http://bitbucket.org/pypy/pypy/changeset/d02b905bb7bd/

Log:	Test and fix for __complex__.

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
@@ -438,3 +438,12 @@
 
     def test_getnewargs(self):
         assert (1+2j).__getnewargs__() == (1.0, 2.0)
+
+    def test_method_not_found_on_newstyle_instance(self):
+        class A(object):
+            pass
+        a = A()
+        a.__complex__ = lambda: 5j     # ignored
+        raises(TypeError, complex, a)
+        A.__complex__ = lambda self: 42j
+        assert complex(a) == 42j

diff --git a/pypy/objspace/std/complextype.py b/pypy/objspace/std/complextype.py
--- a/pypy/objspace/std/complextype.py
+++ b/pypy/objspace/std/complextype.py
@@ -173,17 +173,22 @@
         return (w_complex.realval, w_complex.imagval)
     #
     # test for a '__complex__' method, and call it if found.
-    # A bit of a hack to support old-style classes: don't use
-    # space.lookup() (this is similar to CPython).
-    try:
-        w_method = space.getattr(w_complex, space.wrap('__complex__'))
-    except OperationError, e:
-        if not e.match(space, space.w_AttributeError):
-            raise
-        if isinstance(w_complex, W_ComplexObject):
-            return (w_complex.realval, w_complex.imagval)
+    # special case old-style instances, like CPython does.
+    w_z = None
+    if space.is_oldstyle_instance(w_complex):
+        try:
+            w_method = space.getattr(w_complex, space.wrap('__complex__'))
+        except OperationError, e:
+            if not e.match(space, space.w_AttributeError):
+                raise
+        else:
+            w_z = space.call_function(w_method)
     else:
-        w_z = space.call_function(w_method)
+        w_method = space.lookup(w_complex, '__complex__')
+        if w_method is not None:
+            w_z = space.get_and_call_function(w_method, w_complex)
+    #
+    if w_z is not None:
         # __complex__() must return a complex object
         # (XXX should not use isinstance here)
         if not isinstance(w_z, W_ComplexObject):
@@ -192,7 +197,11 @@
                                             " a complex number"))
         return (w_z.realval, w_z.imagval)
     #
-    # no '__complex__' method, so we assume it is a float.
+    # no '__complex__' method, so we assume it is a float,
+    # unless it is an instance of some subclass of complex.
+    if isinstance(w_complex, W_ComplexObject):
+        return (w_complex.realval, w_complex.imagval)
+    #
     # Check that it is not a string (on which space.float() would succeed).
     if (space.is_true(space.isinstance(w_complex, space.w_str)) or
         space.is_true(space.isinstance(w_complex, space.w_unicode))):


More information about the Pypy-commit mailing list