[pypy-commit] pypy default: Call __int__ or __float__ on item assignment in some cases. Fixes test_assign_object_with_special_methods from 6e2656749ce4

hakanardo noreply at buildbot.pypy.org
Fri Aug 16 09:56:22 CEST 2013


Author: Hakan Ardo <hakan at debian.org>
Branch: 
Changeset: r66171:2abb5e5f6bdf
Date: 2013-08-16 09:55 +0200
http://bitbucket.org/pypy/pypy/changeset/2abb5e5f6bdf/

Log:	Call __int__ or __float__ on item assignment in some cases. Fixes
	test_assign_object_with_special_methods from 6e2656749ce4

diff --git a/pypy/module/array/interp_array.py b/pypy/module/array/interp_array.py
--- a/pypy/module/array/interp_array.py
+++ b/pypy/module/array/interp_array.py
@@ -11,7 +11,7 @@
 from rpython.rlib.unroll import unrolling_iterable
 from rpython.rlib.objectmodel import keepalive_until_here
 from rpython.rtyper.lltypesystem import lltype, rffi
-
+from pypy.objspace.std.floatobject import W_FloatObject
 
 @unwrap_spec(typecode=str)
 def w_array(space, w_cls, typecode, __args__):
@@ -532,7 +532,7 @@
 
 
 class TypeCode(object):
-    def __init__(self, itemtype, unwrap, canoverflow=False, signed=False):
+    def __init__(self, itemtype, unwrap, canoverflow=False, signed=False, method='__int__'):
         self.itemtype = itemtype
         self.bytes = rffi.sizeof(itemtype)
         self.arraytype = lltype.Array(itemtype, hints={'nolength': True})
@@ -540,6 +540,7 @@
         self.signed = signed
         self.canoverflow = canoverflow
         self.w_class = None
+        self.method = method
 
         if self.canoverflow:
             assert self.bytes <= rffi.sizeof(rffi.ULONG)
@@ -554,8 +555,8 @@
         return True
 
 types = {
-    'c': TypeCode(lltype.Char,        'str_w'),
-    'u': TypeCode(lltype.UniChar,     'unicode_w'),
+    'c': TypeCode(lltype.Char,        'str_w', method=''),
+    'u': TypeCode(lltype.UniChar,     'unicode_w', method=''),
     'b': TypeCode(rffi.SIGNEDCHAR,    'int_w', True, True),
     'B': TypeCode(rffi.UCHAR,         'int_w', True),
     'h': TypeCode(rffi.SHORT,         'int_w', True, True),
@@ -567,8 +568,8 @@
                                                     # rbigint.touint() which
                                                     # corresponds to the
                                                     # C-type unsigned long
-    'f': TypeCode(lltype.SingleFloat, 'float_w'),
-    'd': TypeCode(lltype.Float,       'float_w'),
+    'f': TypeCode(lltype.SingleFloat, 'float_w', method='__float__'),
+    'd': TypeCode(lltype.Float,       'float_w', method='__float__'),
     }
 for k, v in types.items():
     v.typecode = k
@@ -613,7 +614,19 @@
         def item_w(self, w_item):
             space = self.space
             unwrap = getattr(space, mytype.unwrap)
-            item = unwrap(w_item)
+            try:
+                item = unwrap(w_item)
+            except OperationError, e:
+                if isinstance(w_item, W_FloatObject): # Odd special case from cpython
+                    raise
+                if mytype.method != '' and e.match(space, space.w_TypeError):
+                    try:
+                        item = unwrap(space.call_method(w_item, mytype.method))
+                    except OperationError:
+                        msg = 'array item must be ' + mytype.unwrap[:-2]
+                        raise OperationError(space.w_TypeError, space.wrap(msg))                        
+                else:
+                    raise
             if mytype.unwrap == 'bigint_w':
                 try:
                     item = item.touint()
diff --git a/pypy/module/array/test/test_array.py b/pypy/module/array/test/test_array.py
--- a/pypy/module/array/test/test_array.py
+++ b/pypy/module/array/test/test_array.py
@@ -937,6 +937,13 @@
             raises(TypeError, a.__setitem__, Silly())
             raises(TypeError, a.__setitem__, OldSilly())
             
+        a = array('c', 'hi')
+        a[0] = 'b'
+        assert a[0] == 'b'
+            
+        a = array('u', u'hi')
+        a[0] = u'b'
+        assert a[0] == u'b'
         
 
 class TestCPythonsOwnArray(BaseArrayTests):


More information about the pypy-commit mailing list