Author: Jeff Terrace <[email protected]>
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
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit