Author: Jeff Terrace <jterr...@gmail.com>
Branch: numpy-full-fromstring
Changeset: r50464:06bf54903f53
Date: 2011-12-13 10:33 -0500
http://bitbucket.org/pypy/pypy/changeset/06bf54903f53/

Log:    Refactor fromstring into text and binary

diff --git a/pypy/module/micronumpy/interp_support.py 
b/pypy/module/micronumpy/interp_support.py
--- a/pypy/module/micronumpy/interp_support.py
+++ b/pypy/module/micronumpy/interp_support.py
@@ -1,49 +1,68 @@
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.gateway import unwrap_spec
-from pypy.module.micronumpy.interp_dtype import get_dtype_cache
+from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.module.micronumpy import interp_dtype
-from pypy.rpython.lltypesystem import lltype, rffi
 
 
 FLOAT_SIZE = rffi.sizeof(lltype.Float)
 
+def _fromstring_text(space, s, count, sep, length, dtype):
+    import string
+    from pypy.module.micronumpy.interp_numarray import W_NDimArray
+
+    A = []
+    num_items = 0
+    ptr = 0
+    
+    while (num_items < count or count == -1) and ptr < len(s):
+        nextptr = s.find(sep, ptr)
+        if nextptr < 0:
+            nextptr = length
+        piece = s[ptr:nextptr]
+        #FIXME: need to check piece.isspace() also, but does not translate
+        if len(piece) > 0:
+            val = dtype.coerce(space, space.wrap(piece))
+            A.append(val)
+            num_items += 1
+        ptr = nextptr + 1
+    
+    if count > num_items:
+        raise OperationError(space.w_ValueError, space.wrap(
+            "string is smaller than requested size"))
+
+    a = W_NDimArray(num_items, [num_items], dtype=dtype)
+    for i, val in enumerate(A):
+        a.dtype.setitem(a.storage, i, val)
+    
+    return space.wrap(a)
+
+def _fromstring_bin(space, s, count, length, dtype):
+    from pypy.module.micronumpy.interp_numarray import W_NDimArray
+    
+    itemsize = dtype.itemtype.get_element_size()
+    if count == -1:
+        count = length / itemsize
+    if length % itemsize != 0:
+        raise OperationError(space.w_ValueError, space.wrap(
+            "string length %d not divisable by item size %d" % (length, 
itemsize)))
+    if count * itemsize > length:
+        raise OperationError(space.w_ValueError, space.wrap(
+            "string is smaller than requested size"))
+        
+    a = W_NDimArray(count, [count], dtype=dtype)
+    for i in range(count):
+        val = dtype.itemtype.runpack_str(s[i*itemsize:i*itemsize + itemsize])
+        a.dtype.setitem(a.storage, i, val)
+        
+    return space.wrap(a)
+
 @unwrap_spec(s=str, count=int, sep=str)
 def fromstring(space, s, w_dtype=None, count=-1, sep=''):
-    from pypy.module.micronumpy.interp_numarray import W_NDimArray
-    
     dtype = space.interp_w(interp_dtype.W_Dtype,
         space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
     )
-    itemsize = abs(space.int_w(dtype.descr_get_itemsize(space)))
     length = len(s)
-
-    A = []
-    num = 0
-    ptr = 0
-    
-    while (num < count or count == -1) and ptr < len(s):
-        if sep == '':
-            if length - ptr < itemsize:
-                raise OperationError(space.w_ValueError, space.wrap(
-                    "string length %d not divisable by item size %d" % 
(length, itemsize)))
-            val = dtype.itemtype.runpack_str(s[ptr:ptr+itemsize])
-            ptr += itemsize
-        else:
-            nextptr = s.find(sep, ptr)
-            if nextptr < 0:
-                nextptr = length
-            val = dtype.coerce(space, space.wrap(s[ptr:nextptr]))
-            ptr = nextptr + 1
-        
-        num += 1
-        A.append(val)
-    
-    if count > num:
-        raise OperationError(space.w_ValueError, space.wrap(
-            "string is smaller than requested size"))
-    
-    a = W_NDimArray(num, [num], dtype=dtype)
-    for i, val in enumerate(A):
-        a.dtype.setitem(a.storage, i, val)
-        
-    return space.wrap(a)
+    if sep == '':
+        return _fromstring_bin(space, s, count, length, dtype)
+    else:
+        return _fromstring_text(space, s, count, sep, length, dtype)
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
@@ -1196,7 +1196,17 @@
         assert f[0] == 1
         assert f[1] == 2
         assert f[2] == 3
-        raises(ValueError, fromstring, "3.4 2.0 3.8 2.2", dtype=int32, sep=" ")
+        g = fromstring("1  2    3 ", dtype=uint8, sep=" ")
+        assert len(g) == 3
+        assert g[0] == 1
+        assert g[1] == 2
+        assert g[2] == 3
+        #FIXME: below should work
+        #h = fromstring("1, , 2, 3", dtype=uint8, sep=",")
+        #assert len(h) == 3
+        #assert h[0] == 1
+        #assert h[1] == 2
+        #assert h[2] == 3
         
     def test_fromstring_types(self):
         from numpypy import fromstring
@@ -1224,13 +1234,15 @@
         
         
     def test_fromstring_invalid(self):
-        from numpypy import fromstring, uint16, uint8
+        from numpypy import fromstring, uint16, uint8, int32
         #default dtype is 64-bit float, so 3 bytes should fail
         raises(ValueError, fromstring, "\x01\x02\x03")
         #3 bytes is not modulo 2 bytes (int16)
         raises(ValueError, fromstring, "\x01\x03\x03", dtype=uint16)
         #5 bytes is larger than 3 bytes
         raises(ValueError, fromstring, "\x01\x02\x03", count=5, dtype=uint8)
+        #can't cast floats to ints with fromstring
+        raises(ValueError, fromstring, "3.4 2.0 3.8 2.2", dtype=int32, sep=" ")
 
 
 class AppTestRepr(BaseNumpyAppTest):
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to