[pypy-commit] pypy default: Merge numpypy-issue1137

timo_jbo noreply at buildbot.pypy.org
Sat May 5 16:12:58 CEST 2012


Author: Timo Paulssen <timonator at perpetuum-immobile.de>
Branch: 
Changeset: r54898:629cfca82920
Date: 2012-05-05 16:12 +0200
http://bitbucket.org/pypy/pypy/changeset/629cfca82920/

Log:	Merge numpypy-issue1137

diff --git a/pypy/module/micronumpy/compile.py b/pypy/module/micronumpy/compile.py
--- a/pypy/module/micronumpy/compile.py
+++ b/pypy/module/micronumpy/compile.py
@@ -6,6 +6,7 @@
 import re
 
 from pypy.interpreter.baseobjspace import InternalSpaceCache, W_Root
+from pypy.interpreter.error import OperationError
 from pypy.module.micronumpy import interp_boxes
 from pypy.module.micronumpy.interp_dtype import get_dtype_cache
 from pypy.module.micronumpy.interp_numarray import (Scalar, BaseArray,
@@ -39,11 +40,11 @@
 THREE_ARG_FUNCTIONS = ['where']
 
 class FakeSpace(object):
-    w_ValueError = None
-    w_TypeError = None
-    w_IndexError = None
-    w_OverflowError = None
-    w_NotImplementedError = None
+    w_ValueError = "ValueError"
+    w_TypeError = "TypeError"
+    w_IndexError = "IndexError"
+    w_OverflowError = "OverflowError"
+    w_NotImplementedError = "NotImplementedError"
     w_None = None
 
     w_bool = "bool"
@@ -126,8 +127,13 @@
             return w_obj.intval
         elif isinstance(w_obj, FloatObject):
             return int(w_obj.floatval)
+        elif isinstance(w_obj, SliceObject):
+            raise OperationError(self.w_TypeError, self.wrap("slice."))
         raise NotImplementedError
 
+    def index(self, w_obj):
+        return self.wrap(self.int_w(w_obj))
+
     def str_w(self, w_obj):
         if isinstance(w_obj, StringObject):
             return w_obj.v
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -350,12 +350,31 @@
         if shape_len == 1:
             if space.isinstance_w(w_idx, space.w_int):
                 return True
+
+            try:
+                value = space.int_w(space.index(w_idx))
+                return True
+            except OperationError:
+                pass
+
+            try:
+                value = space.int_w(w_idx)
+                return True
+            except OperationError:
+                pass
+
             if space.isinstance_w(w_idx, space.w_slice):
                 return False
         elif (space.isinstance_w(w_idx, space.w_slice) or
               space.isinstance_w(w_idx, space.w_int)):
             return False
-        lgt = space.len_w(w_idx)
+
+        try:
+            lgt = space.len_w(w_idx)
+        except OperationError:
+            raise OperationError(space.w_IndexError,
+                                 space.wrap("index must be either an int or a sequence."))
+
         if lgt > shape_len:
             raise OperationError(space.w_IndexError,
                                  space.wrap("invalid index"))
@@ -1030,8 +1049,21 @@
 
     @jit.unroll_safe
     def _index_of_single_item(self, space, w_idx):
-        if space.isinstance_w(w_idx, space.w_int):
-            idx = space.int_w(w_idx)
+        is_valid = False
+        try:
+            idx = space.int_w(space.index(w_idx))
+            is_valid = True
+        except OperationError:
+            pass
+
+        if not is_valid:
+            try:
+                idx = space.int_w(w_idx)
+                is_valid = True
+            except OperationError:
+                pass
+
+        if is_valid:
             if idx < 0:
                 idx = self.shape[0] + idx
             if idx < 0 or idx >= self.shape[0]:
diff --git a/pypy/module/micronumpy/test/test_base.py b/pypy/module/micronumpy/test/test_base.py
--- a/pypy/module/micronumpy/test/test_base.py
+++ b/pypy/module/micronumpy/test/test_base.py
@@ -10,6 +10,7 @@
 import sys
 
 class BaseNumpyAppTest(object):
+    @classmethod
     def setup_class(cls):
         if option.runappdirect:
             if '__pypy__' not in sys.builtin_module_names:
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -8,7 +8,6 @@
 from pypy.module.micronumpy.interp_numarray import W_NDimArray, shape_agreement
 from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
 
-
 class MockDtype(object):
     class itemtype(object):
         @staticmethod
@@ -195,6 +194,36 @@
         assert _to_coords(13, 'F') == [1, 0, 2]
 
 class AppTestNumArray(BaseNumpyAppTest):
+    def w_CustomIndexObject(self, index):
+        class CustomIndexObject(object):
+            def __init__(self, index):
+                self.index = index
+            def __index__(self):
+                return self.index
+
+        return CustomIndexObject(index)
+
+    def w_CustomIndexIntObject(self, index, value):
+        class CustomIndexIntObject(object):
+            def __init__(self, index, value):
+                self.index = index
+                self.value = value
+            def __index__(self):
+                return self.index
+            def __int__(self):
+                return self.value
+
+        return CustomIndexIntObject(index, value)
+
+    def w_CustomIntObject(self, value):
+        class CustomIntObject(object):
+            def __init__(self, value):
+                self.value = value
+            def __index__(self):
+                return self.value
+
+        return CustomIntObject(value)
+
     def test_ndarray(self):
         from _numpypy import ndarray, array, dtype
 
@@ -329,6 +358,28 @@
         assert a[1, 3] == 8
         assert a.T[1, 2] == 11
 
+    def test_getitem_obj_index(self):
+        from _numpypy import arange
+
+        a = arange(10)
+
+        assert a[self.CustomIndexObject(1)] == 1
+
+    def test_getitem_obj_prefer_index_to_int(self):
+        from _numpypy import arange
+
+        a = arange(10)
+
+
+        assert a[self.CustomIndexIntObject(0, 1)] == 0
+
+    def test_getitem_obj_int(self):
+        from _numpypy import arange
+
+        a = arange(10)
+
+        assert a[self.CustomIntObject(1)] == 1
+
     def test_setitem(self):
         from _numpypy import array
         a = array(range(5))
@@ -348,6 +399,48 @@
         for i in xrange(5):
             assert a[i] == i
 
+    def test_setitem_obj_index(self):
+        from _numpypy import arange
+
+        a = arange(10)
+
+        a[self.CustomIndexObject(1)] = 100
+        assert a[1] == 100
+
+    def test_setitem_obj_prefer_index_to_int(self):
+        from _numpypy import arange
+
+        a = arange(10)
+
+        a[self.CustomIndexIntObject(0, 1)] = 100
+        assert a[0] == 100
+
+    def test_setitem_obj_int(self):
+        from _numpypy import arange
+
+        a = arange(10)
+
+        a[self.CustomIntObject(1)] = 100
+
+        assert a[1] == 100
+
+    def test_access_swallow_exception(self):
+        class ErrorIndex(object):
+            def __index__(self):
+                return 1 / 0
+
+        class ErrorInt(object):
+            def __int__(self):
+                return 1 / 0
+
+        # numpy will swallow errors in __int__ and __index__ and
+        # just raise IndexError.
+
+        from _numpypy import arange
+        a = arange(10)
+        raises(IndexError, "a[ErrorIndex()] == 0")
+        raises(IndexError, "a[ErrorInt()] == 0")
+
     def test_setslice_array(self):
         from _numpypy import array
         a = array(range(5))


More information about the pypy-commit mailing list