[pypy-commit] pypy object-dtype2: - add failing test, fix to raise exception not segfault. How to store objects in record dtype?

mattip noreply at buildbot.pypy.org
Wed Apr 22 11:22:32 CEST 2015


Author: mattip <matti.picus at gmail.com>
Branch: object-dtype2
Changeset: r76865:2ba579dc3dfe
Date: 2015-04-21 22:51 +0300
http://bitbucket.org/pypy/pypy/changeset/2ba579dc3dfe/

Log:	- add failing test, fix to raise exception not segfault. How to
	store objects in record dtype?
	- prevent segfaults by instantiating NotImplemented methods on
	UnicodeType

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
@@ -344,6 +344,8 @@
 offset_of_length = llmemory.offsetof(OBJECTSTORE, 'length')
 offset_of_step = llmemory.offsetof(OBJECTSTORE, 'step')
 
+V_OBJECTSTORE = lltype.nullptr(OBJECTSTORE)
+
 def customtrace(gc, obj, callback, arg):
     #debug_print('in customtrace w/obj', obj)
     length = (obj + offset_of_length).signed[0]
@@ -385,7 +387,7 @@
         self.backstrides = backstrides
         self.storage = storage
         self.start = start
-        self.gcstruct = lltype.nullptr(OBJECTSTORE)
+        self.gcstruct = V_OBJECTSTORE
 
     def fill(self, space, box):
         self.dtype.itemtype.fill(self.storage, self.dtype.elsize,
@@ -416,7 +418,7 @@
 class ConcreteArray(ConcreteArrayNotOwning):
     def __init__(self, shape, dtype, order, strides, backstrides,
                  storage=lltype.nullptr(RAW_STORAGE), zero=True):
-        gcstruct = lltype.nullptr(OBJECTSTORE)
+        gcstruct = V_OBJECTSTORE
         if storage == lltype.nullptr(RAW_STORAGE):
             length = support.product(shape) 
             if dtype.num == NPY.OBJECT:
@@ -527,7 +529,7 @@
 class VoidBoxStorage(BaseConcreteArray):
     def __init__(self, size, dtype):
         self.storage = alloc_raw_storage(size)
-        self.gcstruct = lltype.nullptr(OBJECTSTORE)
+        self.gcstruct = V_OBJECTSTORE
         self.dtype = dtype
         self.size = size
 
diff --git a/pypy/module/micronumpy/test/test_object_arrays.py b/pypy/module/micronumpy/test/test_object_arrays.py
--- a/pypy/module/micronumpy/test/test_object_arrays.py
+++ b/pypy/module/micronumpy/test/test_object_arrays.py
@@ -126,3 +126,41 @@
         assert c.dtype == object
         assert d.dtype == object
 
+    def test_mem_array_creation_invalid_specification(self):
+        # while not specifically testing object dtype, this
+        # test segfaulted during ObjectType.store due to
+        # missing gc hooks
+        import numpy as np
+        dt = np.dtype([('x', int), ('y', np.object_)])
+        # Correct way
+        a = np.array([(1, 'object')], dt)
+        # Wrong way - should complain about writing buffer to object dtype
+        raises(np.array, [1, 'object'], dt)
+
+    def test_zeros(self):
+        skip('move this to unicode test when we have them')
+        import numpy as np
+        def sixu(s):
+            return unicode(s, 'unicode_escape')
+
+        def buffer_len(arr):
+            if isinstance(arr, np.ndarray):
+                return len(arr.data)
+            return len(buffer(arr))
+
+        def content_check(ua, ua_scalar, nbtyes):
+            assert int(ua.dtype.str[2:]) == ulen
+            assert buffer_len(ua) == 4*ulen    
+            assert ua_scalar -- sixu('')
+            assert ua_scalar.encode('ascii') == ''
+            assert buffer_len(ua_scalar) == 0
+
+        for ulen in [1, 2, 1099]:
+            ua = np.zeros((), dtype='U%s' % ulen)
+            content_check(ua, ua[()], 4 * ulen)
+            ua = zeros((2,), dtype='U%s' % ulen)
+            content_check(ua, ua[0], 4 * ulen*2)
+            content_check(ua, ua[1], 4 * ulen*2)
+            ua = zeros((2, 3, 4), dtype='U%s' % ulen)
+            content_check(ua, ua[0, 0, 0], 4 * ulen * 2 * 3 * 4)
+            content_check(ua, ua[-1, -1, -1], 4 * ulen * 2 * 3 * 4)
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
@@ -20,7 +20,7 @@
 from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
 from rpython.tool.sourcetools import func_with_new_name
 from pypy.module.micronumpy import boxes
-from pypy.module.micronumpy.concrete import SliceArray, VoidBoxStorage
+from pypy.module.micronumpy.concrete import SliceArray, VoidBoxStorage, V_OBJECTSTORE
 from pypy.module.micronumpy.strides import calc_strides
 
 degToRad = math.pi / 180.0
@@ -1653,6 +1653,9 @@
         return self.unbox(self.box(w_item))
 
     def store(self, arr, i, offset, box):
+        if arr.gcstruct is V_OBJECTSTORE:
+            raise oefmt(self.space.w_NotImplementedError,
+                "cannot store object in array with no gc hook")
         self._write(arr.storage, i, offset, self.unbox(box),
                     arr.gcstruct)
 
@@ -2054,6 +2057,57 @@
         raise OperationError(space.w_NotImplementedError, space.wrap(
             "coerce (probably from set_item) not implemented for unicode type"))
 
+    def store(self, arr, i, offset, box):
+        assert isinstance(box, boxes.W_UnicodeBox)
+        raise oefmt(self.space.w_NotImplementedError, "unicode type not completed")
+
+    def read(self, arr, i, offset, dtype=None):
+        raise oefmt(self.space.w_NotImplementedError, "unicode type not completed")
+
+    def str_format(self, item):
+        raise oefmt(self.space.w_NotImplementedError, "unicode type not completed")
+
+    def to_builtin_type(self, space, box):
+        raise oefmt(self.space.w_NotImplementedError, "unicode type not completed")
+
+    def eq(self, v1, v2):
+        raise oefmt(self.space.w_NotImplementedError, "unicode type not completed")
+
+    def ne(self, v1, v2):
+        raise oefmt(self.space.w_NotImplementedError, "unicode type not completed")
+
+    def lt(self, v1, v2):
+        raise oefmt(self.space.w_NotImplementedError, "unicode type not completed")
+
+    def le(self, v1, v2):
+        raise oefmt(self.space.w_NotImplementedError, "unicode type not completed")
+
+    def gt(self, v1, v2):
+        raise oefmt(self.space.w_NotImplementedError, "unicode type not completed")
+
+    def ge(self, v1, v2):
+        raise oefmt(self.space.w_NotImplementedError, "unicode type not completed")
+
+    def logical_and(self, v1, v2):
+        raise oefmt(self.space.w_NotImplementedError, "unicode type not completed")
+
+    def logical_or(self, v1, v2):
+        raise oefmt(self.space.w_NotImplementedError, "unicode type not completed")
+
+    def logical_not(self, v):
+        raise oefmt(self.space.w_NotImplementedError, "unicode type not completed")
+
+    @str_binary_op
+    def logical_xor(self, v1, v2):
+        raise oefmt(self.space.w_NotImplementedError, "unicode type not completed")
+
+    def bool(self, v):
+        raise oefmt(self.space.w_NotImplementedError, "unicode type not completed")
+
+    def fill(self, storage, width, box, start, stop, offset, gcstruct):
+        raise oefmt(self.space.w_NotImplementedError, "unicode type not completed")
+
+
 class VoidType(FlexibleType):
     T = lltype.Char
 
@@ -2161,6 +2215,9 @@
                 items_w = space.fixedview(w_item)
             elif isinstance(w_item, W_NDimArray) and w_item.is_scalar():
                 items_w = space.fixedview(w_item.get_scalar_value())
+            elif space.isinstance_w(w_item, space.w_list):
+                raise oefmt(space.w_TypeError,
+                            "expected a readable buffer object")
             else:
                 # XXX support initializing from readable buffers
                 items_w = [w_item] * len(dtype.fields)


More information about the pypy-commit mailing list