Author: Timo Paulssen <timona...@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)) _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit