[pypy-commit] pypy default: test, implement memoryview(dtype record array).format

mattip pypy.commits at gmail.com
Tue Oct 4 15:16:13 EDT 2016


Author: Matti Picus <matti.picus at gmail.com>
Branch: 
Changeset: r87580:12582f578775
Date: 2016-10-04 20:27 +0300
http://bitbucket.org/pypy/pypy/changeset/12582f578775/

Log:	test, implement memoryview(dtype record array).format

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
@@ -4,6 +4,7 @@
 from rpython.rlib.listsort import make_timsort_class
 from rpython.rlib.buffer import Buffer
 from rpython.rlib.debug import make_sure_not_resized
+from rpython.rlib.rstring import StringBuilder
 from rpython.rlib.rawstorage import alloc_raw_storage, free_raw_storage, \
     raw_storage_getitem, raw_storage_setitem, RAW_STORAGE
 from rpython.rtyper.lltypesystem import rffi, lltype, llmemory
@@ -725,7 +726,9 @@
         return rffi.ptradd(self.impl.storage, self.impl.start)
 
     def getformat(self):
-        return self.impl.dtype.char
+        sb = StringBuilder()
+        self.impl.dtype.getformat(sb)
+        return sb.build()
 
     def getitemsize(self):
         return self.impl.dtype.elsize
diff --git a/pypy/module/micronumpy/descriptor.py b/pypy/module/micronumpy/descriptor.py
--- a/pypy/module/micronumpy/descriptor.py
+++ b/pypy/module/micronumpy/descriptor.py
@@ -24,7 +24,6 @@
     return space.interp_w(
         W_Dtype, space.call_function(space.gettypefor(W_Dtype), w_dtype))
 
-
 @jit.unroll_safe
 def dtype_agreement(space, w_arr_list, shape, out=None):
     """ agree on dtype from a list of arrays. if out is allocated,
@@ -179,6 +178,38 @@
         assert dtype.is_float()
         return dtype
 
+    def getformat(self, stringbuilder):
+        # adapted from _buffer_format_string in multiarray/buffer.c
+        # byte-order not supported yet
+        if self.is_record():
+            #subs = sorted(self.fields.items(), key=lambda (k,v): v[0])
+            subs = []
+            for name in self.fields:
+                offset, dtyp = self.fields[name]
+                i = 0
+                for i in range(len(subs)):
+                    if offset < subs[i][0]:
+                        break
+                else:
+                    i = len(subs)
+                subs.insert(i, (offset, dtyp, name))
+            start = 0
+            stringbuilder.append('T{')
+            for s in subs:
+                stringbuilder.append('x' * (s[0] - start))
+                start = s[0] + s[1].elsize
+                s[1].getformat(stringbuilder)
+                stringbuilder.append(':')
+                stringbuilder.append(s[2])
+                stringbuilder.append(':')
+            stringbuilder.append('}')
+        else:
+            if self.byteorder == NPY.OPPBYTE:
+                raise oefmt(self.itemtype.space.w_NotImplementedError,
+                                 "non-native byte order not supported yet")
+            # even if not, NumPy adds a '=', '@', for 'i' types
+            stringbuilder.append(self.char)
+
     def get_name(self):
         name = self.w_box_type.getname(self.itemtype.space)
         if name.endswith('_'):
@@ -743,6 +774,9 @@
                         offsets[j+1] = delta + offsets[j]
                 if  i + 1 < len(offsets) and offsets[i + 1] == 0:
                     offsets[i + 1] = offsets[i] + max(delta, subdtype.elsize)
+                # sanity check
+                if offsets[i] % maxalign:
+                    offsets[i] = ((offsets[i] // maxalign) + 1) * maxalign
         elif not use_supplied_offsets:
             if  i + 1 < len(offsets) and offsets[i + 1] == 0:
                 offsets[i+1] = offsets[i] + subdtype.elsize
diff --git a/pypy/module/micronumpy/test/test_ndarray.py b/pypy/module/micronumpy/test/test_ndarray.py
--- a/pypy/module/micronumpy/test/test_ndarray.py
+++ b/pypy/module/micronumpy/test/test_ndarray.py
@@ -3668,6 +3668,28 @@
         assert z.dtype == 'O'
         assert (z == x).all()
 
+        dt1 = np.dtype(
+             [('a', 'b'), ('b', 'i'), ('sub', np.dtype('b,i')), ('c', 'i')],
+             align=True)
+        x = np.arange(dt1.itemsize, dtype=np.int8).view(dt1)
+        y = memoryview(x)
+        if '__pypy__' in sys.builtin_module_names:
+            assert y.format == 'T{b:a:xxxi:b:T{b:f0:i:f1:}:sub:xxxi:c:}'
+        else:
+            assert y.format == 'T{b:a:xxxi:b:T{b:f0:=i:f1:}:sub:xxx at i:c:}'
+ 
+
+        dt1 = np.dtype(
+             [('a', 'b'), ('b', 'i'), ('sub', np.dtype('b,i')), ('c', 'i')],
+             align=True)
+        x = np.arange(dt1.itemsize, dtype=np.int8).view(dt1)
+        y = memoryview(x)
+        if '__pypy__' in sys.builtin_module_names:
+            assert y.format == 'T{b:a:xxxi:b:T{b:f0:i:f1:}:sub:xxxi:c:}'
+        else:
+            assert y.format == 'T{b:a:xxxi:b:T{b:f0:=i:f1:}:sub:xxx at i:c:}'
+ 
+
     def test_fromstring(self):
         import sys
         from numpy import fromstring, dtype


More information about the pypy-commit mailing list