Author: mattip <[email protected]>
Branch: 
Changeset: r76225:c5c4df0df240
Date: 2015-03-02 21:05 +0200
http://bitbucket.org/pypy/pypy/changeset/c5c4df0df240/

Log:    test, fix for mmap subtype not writeable; asarray not respecting
        implementation.start

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
@@ -46,7 +46,7 @@
     @staticmethod
     def from_shape_and_storage(space, shape, storage, dtype, storage_bytes=-1,
                                order='C', owning=False, w_subtype=None,
-                               w_base=None, writable=True, strides=None):
+                               w_base=None, writable=True, strides=None, 
start=0):
         from pypy.module.micronumpy import concrete
         from pypy.module.micronumpy.strides import (calc_strides,
                                                     calc_backstrides)
@@ -75,8 +75,9 @@
                 raise OperationError(space.w_ValueError,
                         space.wrap("Cannot have owning=True when specifying a 
buffer"))
             if writable:
-                impl = concrete.ConcreteArrayWithBase(shape, dtype, order, 
strides,
-                                                      backstrides, storage, 
w_base)
+                impl = concrete.ConcreteArrayWithBase(shape, dtype, order,
+                                    strides, backstrides, storage, w_base,
+                                    start=start)
             else:
                 impl = concrete.ConcreteNonWritableArrayWithBase(shape, dtype, 
order,
                                                                  strides, 
backstrides,
diff --git a/pypy/module/micronumpy/concrete.py 
b/pypy/module/micronumpy/concrete.py
--- a/pypy/module/micronumpy/concrete.py
+++ b/pypy/module/micronumpy/concrete.py
@@ -331,7 +331,7 @@
 
 
 class ConcreteArrayNotOwning(BaseConcreteArray):
-    def __init__(self, shape, dtype, order, strides, backstrides, storage):
+    def __init__(self, shape, dtype, order, strides, backstrides, storage, 
start=0):
         make_sure_not_resized(shape)
         make_sure_not_resized(strides)
         make_sure_not_resized(backstrides)
@@ -342,6 +342,7 @@
         self.strides = strides
         self.backstrides = backstrides
         self.storage = storage
+        self.start = start
 
     def fill(self, space, box):
         self.dtype.itemtype.fill(self.storage, self.dtype.elsize,
@@ -350,7 +351,7 @@
     def set_shape(self, space, orig_array, new_shape):
         strides, backstrides = calc_strides(new_shape, self.dtype,
                                                     self.order)
-        return SliceArray(0, strides, backstrides, new_shape, self,
+        return SliceArray(self.start, strides, backstrides, new_shape, self,
                           orig_array)
 
     def set_dtype(self, space, dtype):
@@ -384,9 +385,10 @@
 
 
 class ConcreteArrayWithBase(ConcreteArrayNotOwning):
-    def __init__(self, shape, dtype, order, strides, backstrides, storage, 
orig_base):
+    def __init__(self, shape, dtype, order, strides, backstrides, storage,
+                 orig_base, start=0):
         ConcreteArrayNotOwning.__init__(self, shape, dtype, order,
-                                        strides, backstrides, storage)
+                                        strides, backstrides, storage, start)
         self.orig_base = orig_base
 
     def base(self):
diff --git a/pypy/module/micronumpy/ctors.py b/pypy/module/micronumpy/ctors.py
--- a/pypy/module/micronumpy/ctors.py
+++ b/pypy/module/micronumpy/ctors.py
@@ -99,10 +99,11 @@
             for i in range(w_object.get_size()):
                 elems_w[i] = w_object.implementation.getitem(i * elsize)
         else:
+            imp = w_object.implementation
             sz = support.product(w_object.get_shape()) * dtype.elsize
             return W_NDimArray.from_shape_and_storage(space,
-                w_object.get_shape(),w_object.implementation.storage,
-                dtype, storage_bytes=sz, w_base=w_object)
+                w_object.get_shape(),imp.storage, dtype, storage_bytes=sz, 
+                w_base=w_object, start=imp.start)
     else:
         # not an array
         shape, elems_w = strides.find_shape_and_elems(space, w_object, dtype)
diff --git a/pypy/module/micronumpy/test/test_subtype.py 
b/pypy/module/micronumpy/test/test_subtype.py
--- a/pypy/module/micronumpy/test/test_subtype.py
+++ b/pypy/module/micronumpy/test/test_subtype.py
@@ -2,7 +2,7 @@
 
 
 class AppTestSupport(BaseNumpyAppTest):
-    spaceconfig = dict(usemodules=["micronumpy", "struct", "binascii"])
+    spaceconfig = dict(usemodules=["micronumpy", "struct", "binascii", "mmap"])
 
     def setup_class(cls):
         BaseNumpyAppTest.setup_class.im_func(cls)
@@ -476,3 +476,120 @@
         a = self.SubType(array([[1, 2], [3, 4]]))
         b = array(a, subok=False)
         assert type(b) is ndarray
+    
+    def test_numpypy_mmap(self):
+        # issue #21 on pypy/numpy 
+        from numpy import array, ndarray, arange, dtype as dtypedescr
+        import mmap
+        import os.path
+        from tempfile import mkdtemp
+        import os.path as path
+        valid_filemodes = ["r", "c", "r+", "w+"]
+        writeable_filemodes = ["r+", "w+"]
+        mode_equivalents = {
+            "readonly":"r",
+            "copyonwrite":"c",
+            "readwrite":"r+",
+            "write":"w+"
+            }
+
+        class memmap(ndarray):
+            def __new__(subtype, filename, dtype='uint8', mode='r+', offset=0, 
shape=None, order='C'):
+                # Import here to minimize 'import numpy' overhead
+                try:
+                    mode = mode_equivalents[mode]
+                except KeyError:
+                    if mode not in valid_filemodes:
+                        raise ValueError("mode must be one of %s" %
+                                         (valid_filemodes + 
list(mode_equivalents.keys())))
+
+                if hasattr(filename, 'read'):
+                    fid = filename
+                    own_file = False
+                else:
+                    fid = open(filename, (mode == 'c' and 'r' or mode)+'b')
+                    own_file = True
+
+                if (mode == 'w+') and shape is None:
+                    raise ValueError("shape must be given")
+
+                fid.seek(0, 2)
+                flen = fid.tell()
+                descr = dtypedescr(dtype)
+                _dbytes = descr.itemsize
+
+                if shape is None:
+                    bytes = flen - offset
+                    if (bytes % _dbytes):
+                        fid.close()
+                        raise ValueError("Size of available data is not a "
+                                "multiple of the data-type size.")
+                    size = bytes // _dbytes
+                    shape = (size,)
+                else:
+                    if not isinstance(shape, tuple):
+                        shape = (shape,)
+                    size = 1
+                    for k in shape:
+                        size *= k
+
+                bytes = long(offset + size*_dbytes)
+
+                if mode == 'w+' or (mode == 'r+' and flen < bytes):
+                    fid.seek(bytes - 1, 0)
+                    fid.write('\0')
+                    fid.flush()
+
+                if mode == 'c':
+                    acc = mmap.ACCESS_COPY
+                elif mode == 'r':
+                    acc = mmap.ACCESS_READ
+                else:
+                    acc = mmap.ACCESS_WRITE
+
+                start = offset - offset % mmap.ALLOCATIONGRANULARITY
+                bytes -= start
+                offset -= start
+                mm = mmap.mmap(fid.fileno(), bytes, access=acc, offset=start)
+
+                self = ndarray.__new__(subtype, shape, dtype=descr, buffer=mm,
+                    offset=offset, order=order)
+                self._mmap = mm
+                self.offset = offset
+                self.mode = mode
+
+                if isinstance(filename, basestring):
+                    self.filename = os.path.abspath(filename)
+                # py3 returns int for TemporaryFile().name
+                elif (hasattr(filename, "name") and
+                      isinstance(filename.name, basestring)):
+                    self.filename = os.path.abspath(filename.name)
+                # same as memmap copies (e.g. memmap + 1)
+                else:
+                    self.filename = None
+
+                if own_file:
+                    fid.close()
+
+                return self
+
+            def flush(self):
+                if self.base is not None and hasattr(self.base, 'flush'):
+                    self.base.flush() 
+
+        def asarray(obj, itemsize=None, order=None):
+            return array(obj, itemsize, copy=False, order=order)
+
+        filename = path.join(mkdtemp(), 'newfile.dat')
+        data = arange(10*10*36).reshape(10, 10, 36)
+        fp = memmap(filename, dtype='float32', mode='w+', shape=data.shape)
+        vals = [   242,    507,    255,    505,    315,    316,    308,    506,
+          309,    255,    211,    505,    315,    316,    308,    506,
+          309,    255,    255,    711,    194,    232,    711,    711,
+          709,    710,    709,    710,    882,    897,    711,    245,
+          711,    711,    168,    245]
+        fp[:] = data
+        fp[5:6][:,4] = vals
+        a = asarray(fp[5:6][:,4])
+        assert (a == vals).all()
+
diff --git a/pypy/module/mmap/interp_mmap.py b/pypy/module/mmap/interp_mmap.py
--- a/pypy/module/mmap/interp_mmap.py
+++ b/pypy/module/mmap/interp_mmap.py
@@ -22,6 +22,10 @@
         self.check_valid()
         return MMapBuffer(self.space, self.mmap, True)
 
+    def writebuf_w(self, space):
+        self.check_writeable()
+        return MMapBuffer(self.space, self.mmap, False)
+
     def close(self):
         self.mmap.close()
 
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to