[pypy-commit] pypy numpy-refactor: remove arrayimpl.Scalar

bdkearns noreply at buildbot.pypy.org
Thu Feb 27 01:59:45 CET 2014


Author: Brian Kearns <bdkearns at gmail.com>
Branch: numpy-refactor
Changeset: r69473:41743661d6f2
Date: 2014-02-26 05:00 -0500
http://bitbucket.org/pypy/pypy/changeset/41743661d6f2/

Log:	remove arrayimpl.Scalar

diff --git a/pypy/module/micronumpy/arrayimpl/base.py b/pypy/module/micronumpy/arrayimpl/base.py
deleted file mode 100644
--- a/pypy/module/micronumpy/arrayimpl/base.py
+++ /dev/null
@@ -1,20 +0,0 @@
-
-class BaseArrayImplementation(object):
-    def is_scalar(self):
-        return False
-
-    def base(self):
-        raise NotImplementedError
-
-    def create_iter(self, shape=None, backward_broadcast=False, require_index=False):
-        raise NotImplementedError
-
-class BaseArrayIterator(object):
-    def next(self):
-        raise NotImplementedError # purely abstract base class
-
-    def setitem(self, elem):
-        raise NotImplementedError
-
-    def set_scalar_object(self, value):
-        raise NotImplementedError # works only on scalars
diff --git a/pypy/module/micronumpy/arrayimpl/concrete.py b/pypy/module/micronumpy/arrayimpl/concrete.py
--- a/pypy/module/micronumpy/arrayimpl/concrete.py
+++ b/pypy/module/micronumpy/arrayimpl/concrete.py
@@ -1,4 +1,3 @@
-from pypy.module.micronumpy.arrayimpl import base, scalar
 from pypy.module.micronumpy import support, loop, iter
 from pypy.module.micronumpy.base import convert_to_array, W_NDimArray,\
      ArrayArgumentException
@@ -9,12 +8,12 @@
 from pypy.interpreter.buffer import RWBuffer
 from rpython.rlib import jit
 from rpython.rtyper.lltypesystem import rffi, lltype
-from rpython.rlib.rawstorage import free_raw_storage, raw_storage_getitem,\
-     raw_storage_setitem, RAW_STORAGE
+from rpython.rlib.rawstorage import alloc_raw_storage, free_raw_storage, \
+    raw_storage_getitem, raw_storage_setitem, RAW_STORAGE
 from rpython.rlib.debug import make_sure_not_resized
 
 
-class BaseConcreteArray(base.BaseArrayImplementation):
+class BaseConcreteArray(object):
     start = 0
     parent = None
 
@@ -46,9 +45,6 @@
 
     def setslice(self, space, arr):
         impl = arr.implementation
-        if impl.is_scalar():
-            self.fill(space, impl.get_scalar_value())
-            return
         shape = shape_agreement(space, self.get_shape(), arr)
         if impl.storage == self.storage:
             impl = impl.copy(space)
@@ -64,9 +60,12 @@
         # Since we got to here, prod(new_shape) == self.size
         new_strides = None
         if self.size > 0:
-            new_strides = calc_new_strides(new_shape, self.get_shape(),
-                                           self.get_strides(), self.order)
-        if new_strides:
+            if len(self.get_shape()) == 0:
+                new_strides = [self.dtype.elsize] * len(new_shape)
+            else:
+                new_strides = calc_new_strides(new_shape, self.get_shape(),
+                                               self.get_strides(), self.order)
+        if new_strides is not None:
             # We can create a view, strides somehow match up.
             ndims = len(new_shape)
             new_backstrides = [0] * ndims
@@ -75,10 +74,6 @@
             assert isinstance(orig_array, W_NDimArray) or orig_array is None
             return SliceArray(self.start, new_strides, new_backstrides,
                               new_shape, self, orig_array)
-        else:
-            if self.get_size() == 1 and len(new_shape) == 0:
-                return scalar.Scalar(self.dtype, self.getitem(0))
-            return None
 
     def get_view(self, space, orig_array, dtype, new_shape):
         strides, backstrides = support.calc_strides(new_shape, dtype,
@@ -92,7 +87,7 @@
         if self.dtype.is_complex():
             dtype = self.dtype.get_float_dtype(space)
             return SliceArray(self.start, strides, backstrides,
-                          self.get_shape(), self, orig_array, dtype=dtype)
+                              self.get_shape(), self, orig_array, dtype=dtype)
         return SliceArray(self.start, strides, backstrides,
                           self.get_shape(), self, orig_array)
 
@@ -105,10 +100,10 @@
         backstrides = self.get_backstrides()
         if self.dtype.is_complex():
             dtype = self.dtype.get_float_dtype(space)
-            return SliceArray(self.start + dtype.elsize, strides,
-                    backstrides, self.get_shape(), self, orig_array, dtype=dtype)
-        impl = NonWritableArray(self.get_shape(), self.dtype, self.order, strides,
-                             backstrides)
+            return SliceArray(self.start + dtype.elsize, strides, backstrides,
+                              self.get_shape(), self, orig_array, dtype=dtype)
+        impl = NonWritableArray(self.get_shape(), self.dtype, self.order,
+                                strides, backstrides)
         if not self.dtype.is_flexible():
             impl.fill(space, self.dtype.box(0))
         return impl
@@ -167,7 +162,7 @@
             space.isinstance_w(w_idx, space.w_slice) or
             space.is_w(w_idx, space.w_None)):
             raise IndexError
-        if isinstance(w_idx, W_NDimArray) and not isinstance(w_idx.implementation, scalar.Scalar):
+        if isinstance(w_idx, W_NDimArray) and not w_idx.is_scalar():
             raise ArrayArgumentException
         shape = self.get_shape()
         shape_len = len(shape)
@@ -208,11 +203,12 @@
                 raise OperationError(space.w_ValueError, space.wrap(
                     "field named %s not found" % idx))
             return RecordChunk(idx)
+        if len(self.get_shape()) == 0:
+            raise oefmt(space.w_IndexError, "0-d arrays can't be indexed")
         if (space.isinstance_w(w_idx, space.w_int) or
                 space.isinstance_w(w_idx, space.w_slice)):
             return Chunks([Chunk(*space.decode_index4(w_idx, self.get_shape()[0]))])
-        elif isinstance(w_idx, W_NDimArray) and \
-                isinstance(w_idx.implementation, scalar.Scalar):
+        elif isinstance(w_idx, W_NDimArray) and w_idx.is_scalar():
             w_idx = w_idx.get_scalar_value().item(space)
             if not space.isinstance_w(w_idx, space.w_int) and \
                     not space.isinstance_w(w_idx, space.w_bool):
@@ -319,7 +315,6 @@
 
 class ConcreteArrayNotOwning(BaseConcreteArray):
     def __init__(self, shape, dtype, order, strides, backstrides, storage):
-
         make_sure_not_resized(shape)
         make_sure_not_resized(strides)
         make_sure_not_resized(backstrides)
@@ -389,6 +384,7 @@
     def __del__(self):
         free_raw_storage(self.storage, track_allocation=False)
 
+
 class ConcreteArrayWithBase(ConcreteArrayNotOwning):
     def __init__(self, shape, dtype, order, strides, backstrides, storage, orig_base):
         ConcreteArrayNotOwning.__init__(self, shape, dtype, order,
@@ -460,7 +456,10 @@
             strides = []
             backstrides = []
             dtype = self.dtype
-            s = self.get_strides()[0] // dtype.elsize
+            try:
+                s = self.get_strides()[0] // dtype.elsize
+            except IndexError:
+                s = 1
             if self.order == 'C':
                 new_shape.reverse()
             for sh in new_shape:
@@ -486,6 +485,16 @@
                           self, orig_array)
 
 
+class VoidBoxStorage(BaseConcreteArray):
+    def __init__(self, size, dtype):
+        self.storage = alloc_raw_storage(size)
+        self.dtype = dtype
+        self.size = size
+
+    def __del__(self):
+        free_raw_storage(self.storage)
+
+
 class ArrayBuffer(RWBuffer):
     def __init__(self, impl):
         self.impl = impl
diff --git a/pypy/module/micronumpy/arrayimpl/scalar.py b/pypy/module/micronumpy/arrayimpl/scalar.py
deleted file mode 100644
--- a/pypy/module/micronumpy/arrayimpl/scalar.py
+++ /dev/null
@@ -1,209 +0,0 @@
-from pypy.module.micronumpy.arrayimpl import base
-from pypy.module.micronumpy.base import W_NDimArray, convert_to_array
-from pypy.module.micronumpy import support
-from pypy.interpreter.error import OperationError
-
-class ScalarIterator(base.BaseArrayIterator):
-    def __init__(self, v):
-        self.v = v
-        self.called_once = False
-
-    def next(self):
-        self.called_once = True
-
-    def next_skip_x(self, n):
-        self.called_once = True
-
-    def getitem(self):
-        return self.v.get_scalar_value()
-
-    def getitem_bool(self):
-        return self.v.dtype.itemtype.bool(self.v.value)
-
-    def setitem(self, v):
-        self.v.set_scalar_value(v)
-
-    def done(self):
-        return self.called_once
-
-    def reset(self):
-        pass
-
-class Scalar(base.BaseArrayImplementation):
-    def __init__(self, dtype, value=None):
-        self.dtype = dtype
-        self.value = value
-
-    def is_scalar(self):
-        return True
-
-    def get_shape(self):
-        return []
-
-    def get_strides(self):
-        return []
-
-    def get_backstrides(self):
-        return []
-
-    def create_iter(self, shape=None, backward_broadcast=False, require_index=False):
-        return ScalarIterator(self)
-
-    def get_scalar_value(self):
-        return self.value
-
-    def set_scalar_value(self, w_val):
-        self.value = w_val
-
-    def copy(self, space):
-        scalar = Scalar(self.dtype)
-        scalar.value = self.value
-        return scalar
-
-    def get_size(self):
-        return 1
-
-    def transpose(self, _):
-        return self
-
-    def get_view(self, space, orig_array, dtype, new_shape):
-        scalar = Scalar(dtype)
-        if dtype.is_str_or_unicode():
-            scalar.value = dtype.coerce(space, space.wrap(self.value.raw_str()))
-        elif dtype.is_record():
-            raise OperationError(space.w_NotImplementedError, space.wrap(
-                "viewing scalar as record not implemented"))
-        else:
-            scalar.value = dtype.itemtype.runpack_str(space, self.value.raw_str())
-        return scalar
-
-    def get_real(self, space, orig_array):
-        if self.dtype.is_complex():
-            scalar = Scalar(self.dtype.get_float_dtype(space))
-            scalar.value = self.value.convert_real_to(scalar.dtype)
-            return scalar
-        return self
-
-    def set_real(self, space, orig_array, w_val):
-        w_arr = convert_to_array(space, w_val)
-        if len(w_arr.get_shape()) > 0:
-            raise OperationError(space.w_ValueError, space.wrap(
-                "could not broadcast input array from shape " +
-                "(%s) into shape ()" % (
-                    ','.join([str(x) for x in w_arr.get_shape()],))))
-        if self.dtype.is_complex():
-            dtype = self.dtype.get_float_dtype(space)
-            self.value = self.dtype.itemtype.composite(
-                               w_arr.get_scalar_value().convert_to(space, dtype),
-                               self.value.convert_imag_to(dtype))
-        else:
-            self.value = w_arr.get_scalar_value()
-
-    def get_imag(self, space, orig_array):
-        if self.dtype.is_complex():
-            scalar = Scalar(self.dtype.get_float_dtype(space))
-            scalar.value = self.value.convert_imag_to(scalar.dtype)
-            return scalar
-        scalar = Scalar(self.dtype)
-        scalar.value = scalar.dtype.coerce(space, None)
-        return scalar
-
-    def set_imag(self, space, orig_array, w_val):
-        #Only called on complex dtype
-        assert self.dtype.is_complex()
-        w_arr = convert_to_array(space, w_val)
-        if len(w_arr.get_shape()) > 0:
-            raise OperationError(space.w_ValueError, space.wrap(
-                "could not broadcast input array from shape " +
-                "(%s) into shape ()" % (
-                    ','.join([str(x) for x in w_arr.get_shape()],))))
-        dtype = self.dtype.get_float_dtype(space)
-        self.value = self.dtype.itemtype.composite(
-                            self.value.convert_real_to(dtype),
-                            w_arr.get_scalar_value().convert_to(space, dtype))
-
-    def descr_getitem(self, space, _, w_idx):
-        if space.isinstance_w(w_idx, space.w_tuple):
-            if space.len_w(w_idx) == 0:
-                return self.get_scalar_value()
-        elif space.isinstance_w(w_idx, space.w_str):
-            if self.dtype.is_record():
-                w_val = self.value.descr_getitem(space, w_idx)
-                return convert_to_array(space, w_val)
-        elif space.is_none(w_idx):
-            new_shape = [1]
-            arr = W_NDimArray.from_shape(space, new_shape, self.dtype)
-            arr_iter = arr.create_iter(new_shape)
-            arr_iter.setitem(self.value)
-            return arr
-        raise OperationError(space.w_IndexError,
-                             space.wrap("0-d arrays can't be indexed"))
-
-    def getitem_index(self, space, idx):
-        raise OperationError(space.w_IndexError,
-                             space.wrap("0-d arrays can't be indexed"))
-
-    def descr_setitem(self, space, _, w_idx, w_val):
-        if space.isinstance_w(w_idx, space.w_tuple):
-            if space.len_w(w_idx) == 0:
-                return self.set_scalar_value(self.dtype.coerce(space, w_val))
-        elif space.isinstance_w(w_idx, space.w_str):
-            if self.dtype.is_record():
-                return self.value.descr_setitem(space, w_idx, w_val)
-        raise OperationError(space.w_IndexError,
-                             space.wrap("0-d arrays can't be indexed"))
-
-    def setitem_index(self, space, idx, w_val):
-        raise OperationError(space.w_IndexError,
-                             space.wrap("0-d arrays can't be indexed"))
-
-    def set_shape(self, space, orig_array, new_shape):
-        if not new_shape:
-            return self
-        if support.product(new_shape) == 1:
-            arr = W_NDimArray.from_shape(space, new_shape, self.dtype)
-            arr_iter = arr.create_iter(new_shape)
-            arr_iter.setitem(self.value)
-            return arr.implementation
-        raise OperationError(space.w_ValueError, space.wrap(
-            "total size of the array must be unchanged"))
-
-    def set_dtype(self, space, dtype):
-        self.value = self.value.convert_to(space, dtype)
-        self.dtype = dtype
-
-    def reshape(self, space, orig_array, new_shape):
-        return self.set_shape(space, orig_array, new_shape)
-
-    def create_axis_iter(self, shape, dim, cum):
-        raise Exception("axis iter should not happen on scalar")
-
-    def swapaxes(self, space, orig_array, axis1, axis2):
-        raise Exception("should not be called")
-
-    def nonzero(self, space, index_type):
-        s = self.dtype.itemtype.bool(self.value)
-        w_res = W_NDimArray.from_shape(space, [s], index_type)
-        if s == 1:
-            w_res.implementation.setitem(0, index_type.itemtype.box(0))
-        return space.newtuple([w_res])
-
-    def fill(self, space, w_value):
-        self.value = w_value
-
-    def get_storage_as_int(self, space):
-        raise OperationError(space.w_ValueError,
-                             space.wrap("scalars have no address"))
-
-    def argsort(self, space, w_axis):
-        return space.wrap(0)
-
-    def astype(self, space, dtype):
-        raise Exception("should not be called")
-
-    def base(self):
-        return None
-
-    def get_buffer(self, space):
-        raise OperationError(space.w_ValueError, space.wrap(
-            "cannot point buffer to a scalar"))
diff --git a/pypy/module/micronumpy/arrayimpl/voidbox.py b/pypy/module/micronumpy/arrayimpl/voidbox.py
deleted file mode 100644
--- a/pypy/module/micronumpy/arrayimpl/voidbox.py
+++ /dev/null
@@ -1,12 +0,0 @@
-
-from pypy.module.micronumpy.arrayimpl.base import BaseArrayImplementation
-from rpython.rlib.rawstorage import free_raw_storage, alloc_raw_storage
-
-class VoidBoxStorage(BaseArrayImplementation):
-    def __init__(self, size, dtype):
-        self.storage = alloc_raw_storage(size)
-        self.dtype = dtype
-        self.size = size
-
-    def __del__(self):
-        free_raw_storage(self.storage)
diff --git a/pypy/module/micronumpy/base.py b/pypy/module/micronumpy/base.py
--- a/pypy/module/micronumpy/base.py
+++ b/pypy/module/micronumpy/base.py
@@ -1,9 +1,7 @@
-
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.baseobjspace import W_Root
 from rpython.tool.pairtype import extendabletype
 from pypy.module.micronumpy.support import calc_strides
-from pypy.module.micronumpy.arrayimpl.base import BaseArrayImplementation
 
 
 def issequence_w(space, w_obj):
@@ -29,21 +27,18 @@
     __metaclass__ = extendabletype
 
     def __init__(self, implementation):
-        assert isinstance(implementation, BaseArrayImplementation)
+        from pypy.module.micronumpy.arrayimpl.concrete import BaseConcreteArray
+        assert isinstance(implementation, BaseConcreteArray)
         assert isinstance(self, W_NDimArray)
         self.implementation = implementation
 
     @staticmethod
     def from_shape(space, shape, dtype, order='C', w_instance=None):
-        from pypy.module.micronumpy.arrayimpl import concrete, scalar
+        from pypy.module.micronumpy.arrayimpl import concrete
 
-        if not shape:
-            w_val = dtype.base.coerce(space, None)
-            impl = scalar.Scalar(dtype.base, w_val)
-        else:
-            strides, backstrides = calc_strides(shape, dtype.base, order)
-            impl = concrete.ConcreteArray(shape, dtype.base, order, strides,
-                                      backstrides)
+        strides, backstrides = calc_strides(shape, dtype.base, order)
+        impl = concrete.ConcreteArray(shape, dtype.base, order, strides,
+                                  backstrides)
         if w_instance:
             return wrap_impl(space, space.type(w_instance), w_instance, impl)
         return W_NDimArray(impl)
@@ -90,36 +85,15 @@
 
     @staticmethod
     def new_scalar(space, dtype, w_val=None):
-        from pypy.module.micronumpy.arrayimpl import scalar
-
         if w_val is not None:
             w_val = dtype.coerce(space, w_val)
         else:
             w_val = dtype.coerce(space, space.wrap(0))
-        return W_NDimArray(scalar.Scalar(dtype, w_val))
+        return convert_to_array(space, w_val)
 
 
 def convert_to_array(space, w_obj):
-    #XXX: This whole routine should very likely simply be array()
     from pypy.module.micronumpy.interp_numarray import array
-    from pypy.module.micronumpy import interp_ufuncs
-
     if isinstance(w_obj, W_NDimArray):
         return w_obj
-    else:
-        # Use __array__() method if it exists
-        w_array = space.lookup(w_obj, "__array__")
-        if w_array is not None:
-            w_result = space.get_and_call_function(w_array, w_obj)
-            if isinstance(w_result, W_NDimArray):
-                return w_result
-            else:
-                raise OperationError(space.w_ValueError, 
-                        space.wrap("object __array__ method not producing an array"))
-        elif issequence_w(space, w_obj):
-            # Convert to array.
-            return array(space, w_obj, w_order=None)
-        else:
-            # If it's a scalar
-            dtype = interp_ufuncs.find_dtype_for_scalar(space, w_obj)
-            return W_NDimArray.new_scalar(space, dtype, w_obj)
+    return array(space, w_obj)
diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py
--- a/pypy/module/micronumpy/interp_boxes.py
+++ b/pypy/module/micronumpy/interp_boxes.py
@@ -10,7 +10,7 @@
 from rpython.rlib.rarithmetic import LONG_BIT
 from rpython.rtyper.lltypesystem import rffi
 from rpython.tool.sourcetools import func_with_new_name
-from pypy.module.micronumpy.arrayimpl.voidbox import VoidBoxStorage
+from pypy.module.micronumpy.arrayimpl.concrete import VoidBoxStorage
 from pypy.module.micronumpy.base import W_NDimArray
 from pypy.module.micronumpy.interp_flagsobj import W_FlagsObject
 from pypy.interpreter.mixedmodule import MixedModule
diff --git a/pypy/module/micronumpy/interp_flatiter.py b/pypy/module/micronumpy/interp_flatiter.py
--- a/pypy/module/micronumpy/interp_flatiter.py
+++ b/pypy/module/micronumpy/interp_flatiter.py
@@ -1,10 +1,10 @@
-
 from pypy.module.micronumpy.base import W_NDimArray, convert_to_array
 from pypy.module.micronumpy import loop
-from pypy.module.micronumpy.arrayimpl.base import BaseArrayImplementation
+from pypy.module.micronumpy.arrayimpl.concrete import BaseConcreteArray
 from pypy.interpreter.error import OperationError
 
-class FakeArrayImplementation(BaseArrayImplementation):
+
+class FakeArrayImplementation(BaseConcreteArray):
     """ The sole purpose of this class is to W_FlatIterator can behave
     like a real array for descr_eq and friends
     """
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
@@ -5,7 +5,7 @@
 from pypy.interpreter.gateway import interp2app, unwrap_spec, applevel, \
                                      WrappedDefault
 from pypy.module.micronumpy.base import W_NDimArray, convert_to_array,\
-     ArrayArgumentException, issequence_w, wrap_impl
+     ArrayArgumentException, wrap_impl
 from pypy.module.micronumpy import interp_dtype, interp_ufuncs, interp_boxes,\
      interp_arrayops
 from pypy.module.micronumpy.strides import find_shape_and_elems,\
@@ -16,11 +16,10 @@
 from pypy.module.micronumpy.appbridge import get_appbridge_cache
 from pypy.module.micronumpy import loop
 from pypy.module.micronumpy.interp_arrayops import repeat, choose, put
-from pypy.module.micronumpy.arrayimpl import scalar
 from rpython.tool.sourcetools import func_with_new_name
 from rpython.rlib import jit
 from rpython.rlib.rstring import StringBuilder
-from pypy.module.micronumpy.arrayimpl.base import BaseArrayImplementation
+from pypy.module.micronumpy.arrayimpl.concrete import BaseConcreteArray
 from pypy.module.micronumpy.conversion_utils import order_converter, multi_axis_converter
 from pypy.module.micronumpy import support
 from pypy.module.micronumpy import constants as NPY
@@ -292,7 +291,7 @@
         return s.build()
 
     def create_iter(self, shape=None, backward_broadcast=False, require_index=False):
-        assert isinstance(self.implementation, BaseArrayImplementation)
+        assert isinstance(self.implementation, BaseConcreteArray)
         return self.implementation.create_iter(shape=shape,
                                    backward_broadcast=backward_broadcast,
                                    require_index=require_index)
@@ -304,10 +303,10 @@
         return self.implementation.create_dot_iter(shape, skip)
 
     def is_scalar(self):
-        return self.implementation.is_scalar()
+        return len(self.get_shape()) == 0
 
     def set_scalar_value(self, w_val):
-        self.implementation.set_scalar_value(w_val)
+        return self.implementation.setitem(0, w_val)
 
     def fill(self, space, box):
         self.implementation.fill(space, box)
@@ -319,7 +318,8 @@
         return self.implementation.get_size()
 
     def get_scalar_value(self):
-        return self.implementation.get_scalar_value()
+        assert len(self.get_shape()) == 0
+        return self.implementation.getitem(0)
 
     def descr_copy(self, space, w_order=None):
         order = order_converter(space, w_order, NPY.KEEPORDER)
@@ -580,11 +580,8 @@
                 new_dtype = interp_dtype.variable_dtype(space,
                     'S' + str(cur_dtype.elsize))
         impl = self.implementation
-        if isinstance(impl, scalar.Scalar):
-            return W_NDimArray.new_scalar(space, new_dtype, impl.value)
-        else:
-            new_impl = impl.astype(space, new_dtype)
-            return wrap_impl(space, space.type(self), self, new_impl)
+        new_impl = impl.astype(space, new_dtype)
+        return wrap_impl(space, space.type(self), self, new_impl)
 
     def descr_get_base(self, space):
         impl = self.implementation
@@ -1038,65 +1035,42 @@
     descr_argmin = _reduce_argmax_argmin_impl("argmin")
 
     def descr_int(self, space):
-        shape = self.get_shape()
-        if len(shape) == 0:
-            assert isinstance(self.implementation, scalar.Scalar)
-            value = space.wrap(self.implementation.get_scalar_value())
-        elif shape == [1]:
-            value = self.descr_getitem(space, space.wrap(0))
-        else:
+        if self.get_size() != 1:
             raise OperationError(space.w_TypeError, space.wrap(
                 "only length-1 arrays can be converted to Python scalars"))
         if self.get_dtype().is_str_or_unicode():
             raise OperationError(space.w_TypeError, space.wrap(
                 "don't know how to convert scalar number to int"))
+        value = self.implementation.getitem(0)
         return space.int(value)
 
     def descr_long(self, space):
-        shape = self.get_shape()
-        if len(shape) == 0:
-            assert isinstance(self.implementation, scalar.Scalar)
-            value = space.wrap(self.implementation.get_scalar_value())
-        elif shape == [1]:
-            value = self.descr_getitem(space, space.wrap(0))
-        else:
+        if self.get_size() != 1:
             raise OperationError(space.w_TypeError, space.wrap(
                 "only length-1 arrays can be converted to Python scalars"))
         if self.get_dtype().is_str_or_unicode():
             raise OperationError(space.w_TypeError, space.wrap(
                 "don't know how to convert scalar number to long"))
+        value = self.implementation.getitem(0)
         return space.long(value)
 
     def descr_float(self, space):
-        shape = self.get_shape()
-        if len(shape) == 0:
-            assert isinstance(self.implementation, scalar.Scalar)
-            value = space.wrap(self.implementation.get_scalar_value())
-        elif shape == [1]:
-            value = self.descr_getitem(space, space.wrap(0))
-        else:
+        if self.get_size() != 1:
             raise OperationError(space.w_TypeError, space.wrap(
                 "only length-1 arrays can be converted to Python scalars"))
         if self.get_dtype().is_str_or_unicode():
             raise OperationError(space.w_TypeError, space.wrap(
                 "don't know how to convert scalar number to float"))
+        value = self.implementation.getitem(0)
         return space.float(value)
 
     def descr_index(self, space):
-        shape = self.get_shape()
-        if len(shape) == 0:
-            assert isinstance(self.implementation, scalar.Scalar)
-            value = space.wrap(self.implementation.get_scalar_value())
-        elif shape == [1]:
-            value = self.descr_getitem(space, space.wrap(0))
-        else:
+        if self.get_size() != 1 or \
+                not self.get_dtype().is_int() or self.get_dtype().is_bool():
             raise OperationError(space.w_TypeError, space.wrap(
                 "only integer arrays with one element "
                 "can be converted to an index"))
-        if not self.get_dtype().is_int() or self.get_dtype().is_bool():
-            raise OperationError(space.w_TypeError, space.wrap(
-                "only integer arrays with one element "
-                "can be converted to an index"))
+        value = self.implementation.getitem(0)
         assert isinstance(value, interp_boxes.W_GenericBox)
         return value.item(space)
 
@@ -1445,14 +1419,6 @@
 
     dtype = interp_dtype.decode_w_dtype(space, w_dtype)
 
-    # scalars and strings w/o __array__ method
-    isstr = space.isinstance_w(w_object, space.w_str)
-    if not issequence_w(space, w_object) or isstr:
-        if dtype is None or dtype.char != NPY.CHARLTR:
-            if dtype is None or (dtype.is_str_or_unicode() and dtype.elsize < 1):
-                dtype = interp_ufuncs.find_dtype_for_scalar(space, w_object)
-            return W_NDimArray.new_scalar(space, dtype, w_object)
-
     if space.is_none(w_order):
         order = 'C'
     else:
diff --git a/pypy/module/micronumpy/iter.py b/pypy/module/micronumpy/iter.py
--- a/pypy/module/micronumpy/iter.py
+++ b/pypy/module/micronumpy/iter.py
@@ -45,7 +45,6 @@
 from pypy.module.micronumpy.strides import enumerate_chunks,\
      calculate_slice_strides
 from pypy.module.micronumpy.base import W_NDimArray
-from pypy.module.micronumpy.arrayimpl import base
 from pypy.module.micronumpy.support import product
 from rpython.rlib import jit
 
@@ -169,7 +168,17 @@
     def get_index(self, space, shapelen):
         return [space.wrap(self.indexes[i]) for i in range(shapelen)]
 
-class ConcreteArrayIterator(base.BaseArrayIterator):
+class BaseArrayIterator(object):
+    def next(self):
+        raise NotImplementedError # purely abstract base class
+
+    def setitem(self, elem):
+        raise NotImplementedError
+
+    def set_scalar_object(self, value):
+        raise NotImplementedError # works only on scalars
+
+class ConcreteArrayIterator(BaseArrayIterator):
     _immutable_fields_ = ['array', 'skip', 'size']
     def __init__(self, array):
         self.array = array
@@ -275,7 +284,7 @@
     def get_index(self, d):
         return self.indexes[d]
 
-class AxisIterator(base.BaseArrayIterator):
+class AxisIterator(BaseArrayIterator):
     def __init__(self, array, shape, dim, cumulative):
         self.shape = shape
         strides = array.get_strides()
diff --git a/pypy/module/micronumpy/strides.py b/pypy/module/micronumpy/strides.py
--- a/pypy/module/micronumpy/strides.py
+++ b/pypy/module/micronumpy/strides.py
@@ -1,6 +1,7 @@
 from rpython.rlib import jit
 from pypy.interpreter.error import OperationError
-from pypy.module.micronumpy.base import W_NDimArray
+from pypy.module.micronumpy.base import W_NDimArray, issequence_w
+from pypy.module.micronumpy import constants as NPY
 
 @jit.look_inside_iff(lambda chunks: jit.isconstant(len(chunks)))
 def enumerate_chunks(chunks):
@@ -69,6 +70,10 @@
     return True
 
 def find_shape_and_elems(space, w_iterable, dtype):
+    isstr = space.isinstance_w(w_iterable, space.w_str)
+    if not issequence_w(space, w_iterable) or isstr:
+        if dtype is None or dtype.char != NPY.CHARLTR:
+            return [], [w_iterable]
     is_rec_type = dtype is not None and dtype.is_record()
     if is_rec_type and is_single_elem(space, w_iterable, is_rec_type):
         return [], [w_iterable]
diff --git a/pypy/module/micronumpy/test/test_iter.py b/pypy/module/micronumpy/test/test_iter.py
--- a/pypy/module/micronumpy/test/test_iter.py
+++ b/pypy/module/micronumpy/test/test_iter.py
@@ -1,5 +1,4 @@
 from pypy.module.micronumpy.iter import MultiDimViewIterator
-from pypy.module.micronumpy.arrayimpl.scalar import ScalarIterator
 
 
 class MockArray(object):
@@ -92,9 +91,3 @@
         assert i.indexes == [0,1]
         assert i.offset == 3
         assert i.done()
-
-    def test_scalar_iter(self):
-        i = ScalarIterator(MockArray)
-        i.next()
-        i.next_skip_x(3)
-        assert i.done()
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
@@ -2683,6 +2683,11 @@
 
     def test_array_interface(self):
         from numpypy import array
+        a = array(2.5)
+        i = a.__array_interface__
+        assert isinstance(i['data'][0], int)
+        assert i['shape'] == ()
+        assert i['strides'] is None
         a = array([1, 2, 3])
         i = a.__array_interface__
         assert isinstance(i['data'][0], int)
@@ -3194,6 +3199,7 @@
         assert str(array([1, 2, 3])) == '[1 2 3]'
         assert str(array(['abc'], 'S3')) == "['abc']"
         assert str(array('abc')) == 'abc'
+        assert str(array(1.5)) == '1.5'
 
 
 class AppTestRepr(BaseNumpyAppTest):
@@ -3211,6 +3217,7 @@
         from numpypy import array
         assert repr(array([1, 2, 3])) == 'array([1, 2, 3])'
         assert repr(array(['abc'], 'S3')) == "array(['abc'])"
+        assert repr(array(1.5)) == "array(1.5)"
 
     def teardown_class(cls):
         if option.runappdirect:
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
--- a/pypy/module/micronumpy/types.py
+++ b/pypy/module/micronumpy/types.py
@@ -4,8 +4,7 @@
 from pypy.interpreter.error import OperationError, oefmt
 from pypy.module.micronumpy import interp_boxes
 from pypy.module.micronumpy import support
-from pypy.module.micronumpy.arrayimpl.voidbox import VoidBoxStorage
-from pypy.module.micronumpy.arrayimpl.concrete import SliceArray
+from pypy.module.micronumpy.arrayimpl.concrete import SliceArray, VoidBoxStorage
 from pypy.objspace.std.floatobject import float2string
 from pypy.objspace.std.complexobject import str_format
 from rpython.rlib import rfloat, clibffi, rcomplex


More information about the pypy-commit mailing list