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