Author: David Schneider <[email protected]>
Branch:
Changeset: r63267:6ed5e557b6b1
Date: 2013-04-12 09:13 +0200
http://bitbucket.org/pypy/pypy/changeset/6ed5e557b6b1/
Log: merge heads
diff --git a/pypy/module/_io/interp_bytesio.py
b/pypy/module/_io/interp_bytesio.py
--- a/pypy/module/_io/interp_bytesio.py
+++ b/pypy/module/_io/interp_bytesio.py
@@ -2,37 +2,25 @@
TypeDef, generic_new_descr, GetSetProperty)
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.error import OperationError, operationerrfmt
+from rpython.rlib.rStringIO import RStringIO
from rpython.rlib.rarithmetic import r_longlong
from pypy.module._io.interp_bufferedio import W_BufferedIOBase
from pypy.module._io.interp_iobase import convert_size
import sys
-def buffer2string(buffer, start, end):
- from rpython.rlib.rstring import StringBuilder
- builder = StringBuilder(end - start)
- for i in range(start, end):
- builder.append(buffer[i])
- return builder.build()
-class W_BytesIO(W_BufferedIOBase):
+class W_BytesIO(RStringIO, W_BufferedIOBase):
def __init__(self, space):
W_BufferedIOBase.__init__(self, space)
- self.pos = 0
- self.string_size = 0
- self.buf = None
+ self.init()
def descr_init(self, space, w_initial_bytes=None):
- # In case __init__ is called multiple times
- self.buf = []
- self.string_size = 0
- self.pos = 0
-
if not space.is_none(w_initial_bytes):
self.write_w(space, w_initial_bytes)
- self.pos = 0
+ self.seek(0)
def _check_closed(self, space, message=None):
- if self.buf is None:
+ if self.is_closed():
if message is None:
message = "I/O operation on closed file"
raise OperationError(space.w_ValueError, space.wrap(message))
@@ -40,36 +28,12 @@
def read_w(self, space, w_size=None):
self._check_closed(space)
size = convert_size(space, w_size)
-
- # adjust invalid sizes
- available = self.string_size - self.pos
- if not 0 <= size <= available:
- size = available
- if size < 0:
- size = 0
-
- output = buffer2string(self.buf, self.pos, self.pos + size)
- self.pos += size
- return space.wrap(output)
+ return space.wrap(self.read(size))
def readline_w(self, space, w_limit=None):
self._check_closed(space)
limit = convert_size(space, w_limit)
-
- cur_pos = self.pos
- if limit < 0:
- end_pos = self.string_size
- else:
- end_pos = min(cur_pos + limit, self.string_size)
- while cur_pos != end_pos:
- if self.buf[cur_pos] == '\n':
- cur_pos += 1
- break
- cur_pos += 1
-
- output = buffer2string(self.buf, self.pos, cur_pos)
- self.pos = cur_pos
- return space.wrap(output)
+ return space.wrap(self.readline(limit))
def read1_w(self, space, w_size):
return self.read_w(space, w_size)
@@ -79,56 +43,28 @@
rwbuffer = space.rwbuffer_w(w_buffer)
size = rwbuffer.getlength()
- if self.pos + size > self.string_size:
- size = self.string_size - self.pos
-
- output = buffer2string(self.buf, self.pos, self.pos + size)
- length = len(output)
+ output = self.read(size)
rwbuffer.setslice(0, output)
- self.pos += length
- return space.wrap(length)
+ return space.wrap(len(output))
def write_w(self, space, w_data):
self._check_closed(space)
if space.isinstance_w(w_data, space.w_unicode):
raise OperationError(space.w_TypeError, space.wrap(
"bytes string of buffer expected"))
- buf = space.buffer_w(w_data)
- length = buf.getlength()
+ buf = space.bufferstr_w(w_data)
+ length = len(buf)
if length <= 0:
- return
-
- if self.pos + length > len(self.buf):
- self.buf.extend(['\0'] * (self.pos + length - len(self.buf)))
-
- if self.pos > self.string_size:
- # In case of overseek, pad with null bytes the buffer region
- # between the end of stream and the current position.
- #
- # 0 lo string_size hi
- # | |<---used--->|<----------available----------->|
- # | | <--to pad-->|<---to write---> |
- # 0 buf position
- for i in range(self.string_size, self.pos):
- self.buf[i] = '\0'
-
- # Copy the data to the internal buffer, overwriting some of the
- # existing data if self->pos < self->string_size.
- for i in range(length):
- self.buf[self.pos + i] = buf.getitem(i)
- self.pos += length
-
- # Set the new length of the internal string if it has changed
- if self.string_size < self.pos:
- self.string_size = self.pos
-
+ return space.wrap(0)
+ self.write(buf)
return space.wrap(length)
def truncate_w(self, space, w_size=None):
self._check_closed(space)
+ pos = self.tell()
if space.is_none(w_size):
- size = self.pos
+ size = pos
else:
size = space.r_longlong_w(w_size)
@@ -136,19 +72,17 @@
raise OperationError(space.w_ValueError, space.wrap(
"negative size value"))
- if size < self.string_size:
- self.string_size = size
- del self.buf[size:]
-
+ self.truncate(size)
+ self.seek(pos)
return space.wrap(size)
def getvalue_w(self, space):
self._check_closed(space)
- return space.wrap(buffer2string(self.buf, 0, self.string_size))
+ return space.wrap(self.getvalue())
def tell_w(self, space):
self._check_closed(space)
- return space.wrap(self.pos)
+ return space.wrap(self.tell())
@unwrap_spec(pos=r_longlong, whence=int)
def seek_w(self, space, pos, whence=0):
@@ -159,24 +93,19 @@
raise OperationError(space.w_ValueError, space.wrap(
"negative seek value"))
elif whence == 1:
- if pos > sys.maxint - self.pos:
+ if pos > sys.maxint - self.tell():
raise OperationError(space.w_OverflowError, space.wrap(
"new position too large"))
- pos += self.pos
elif whence == 2:
- if pos > sys.maxint - self.string_size:
+ if pos > sys.maxint - self.getsize():
raise OperationError(space.w_OverflowError, space.wrap(
"new position too large"))
- pos += self.string_size
else:
raise operationerrfmt(space.w_ValueError,
"whence must be between 0 and 2, not %d", whence)
- if pos >= 0:
- self.pos = pos
- else:
- self.pos = 0
- return space.wrap(self.pos)
+ self.seek(pos, whence)
+ return space.wrap(self.tell())
def readable_w(self, space):
return space.w_True
@@ -188,17 +117,16 @@
return space.w_True
def close_w(self, space):
- self.buf = None
+ self.close()
def closed_get_w(self, space):
- return space.wrap(self.buf is None)
+ return space.wrap(self.is_closed())
def getstate_w(self, space):
self._check_closed(space)
- w_content = space.wrap(buffer2string(self.buf, 0, self.string_size))
return space.newtuple([
- w_content,
- space.wrap(self.pos),
+ space.wrap(self.getvalue()),
+ space.wrap(self.tell()),
self.getdict(space)])
def setstate_w(self, space, w_state):
@@ -211,13 +139,13 @@
space.type(w_state).getname(space)
)
w_content, w_pos, w_dict = space.unpackiterable(w_state, 3)
+ self.truncate(0)
+ self.write_w(space, w_content)
pos = space.int_w(w_pos)
- self.buf = []
- self.write_w(space, w_content)
if pos < 0:
raise OperationError(space.w_ValueError, space.wrap(
"position value cannot be negative"))
- self.pos = pos
+ self.seek(pos)
if not space.is_w(w_dict, space.w_None):
space.call_method(self.getdict(space), "update", w_dict)
diff --git a/pypy/module/_io/interp_stringio.py
b/pypy/module/_io/interp_stringio.py
--- a/pypy/module/_io/interp_stringio.py
+++ b/pypy/module/_io/interp_stringio.py
@@ -169,9 +169,9 @@
self.pos = end
return space.wrap(u''.join(self.buf[start:end]))
- @unwrap_spec(limit=int)
- def readline_w(self, space, limit=-1):
+ def readline_w(self, space, w_limit=None):
self._check_closed(space)
+ limit = convert_size(space, w_limit)
if self.pos >= len(self.buf):
return space.wrap(u"")
diff --git a/pypy/module/_io/test/test_bytesio.py
b/pypy/module/_io/test/test_bytesio.py
--- a/pypy/module/_io/test/test_bytesio.py
+++ b/pypy/module/_io/test/test_bytesio.py
@@ -24,6 +24,7 @@
def test_write(self):
import _io
f = _io.BytesIO()
+ assert f.write("") == 0
assert f.write("hello") == 5
import gc; gc.collect()
assert f.getvalue() == "hello"
@@ -47,10 +48,17 @@
def test_truncate(self):
import _io
- f = _io.BytesIO("hello")
+ f = _io.BytesIO()
+ f.write("hello")
+ assert f.truncate(0) == 0
+ assert f.tell() == 5
+ f.seek(0)
+ f.write("hello")
f.seek(3)
assert f.truncate() == 3
assert f.getvalue() == "hel"
+ assert f.truncate(2) == 2
+ assert f.tell() == 3
def test_setstate(self):
# state is (content, position, __dict__)
@@ -73,7 +81,13 @@
import _io
b = _io.BytesIO("hello")
+ a1 = bytearray('t')
+ a2 = bytearray('testing')
+ assert b.readinto(a1) == 1
+ assert b.readinto(a2) == 4
b.close()
+ assert a1 == "h"
+ assert a2 == "elloing"
raises(ValueError, b.readinto, bytearray("hello"))
def test_readline(self):
diff --git a/pypy/module/_io/test/test_stringio.py
b/pypy/module/_io/test/test_stringio.py
--- a/pypy/module/_io/test/test_stringio.py
+++ b/pypy/module/_io/test/test_stringio.py
@@ -32,7 +32,7 @@
raises(ValueError, sio.read, 1)
raises(ValueError, sio.write, u"text")
- def testRead(self):
+ def test_read(self):
import io
buf = u"1234567890"
sio = io.StringIO(buf)
@@ -42,6 +42,13 @@
assert buf[5:] == sio.read(900)
assert u"" == sio.read()
+ def test_readline(self):
+ import io
+ sio = io.StringIO(u'123\n456')
+ assert sio.readline(2) == '12'
+ assert sio.readline(None) == '3\n'
+ assert sio.readline() == '456'
+
def test_seek(self):
import io
diff --git a/pypy/module/cStringIO/interp_stringio.py
b/pypy/module/cStringIO/interp_stringio.py
--- a/pypy/module/cStringIO/interp_stringio.py
+++ b/pypy/module/cStringIO/interp_stringio.py
@@ -146,7 +146,7 @@
class W_OutputType(RStringIO, W_InputOutputType):
def __init__(self, space):
- RStringIO.__init__(self)
+ self.init()
self.space = space
def descr_truncate(self, w_size=None):
@@ -159,6 +159,7 @@
if size < 0:
raise OperationError(space.w_IOError, space.wrap("negative size"))
self.truncate(size)
+ self.seek(0, 2)
@unwrap_spec(buffer='bufferstr')
def descr_write(self, buffer):
diff --git a/pypy/module/cStringIO/test/test_interp_stringio.py
b/pypy/module/cStringIO/test/test_interp_stringio.py
--- a/pypy/module/cStringIO/test/test_interp_stringio.py
+++ b/pypy/module/cStringIO/test/test_interp_stringio.py
@@ -142,8 +142,11 @@
f.write(' world')
f.truncate(30)
assert f.getvalue() == '\x00' * 20 + 'hello worl'
+ assert f.tell() == 30
+ f.seek(0)
f.truncate(25)
assert f.getvalue() == '\x00' * 20 + 'hello'
+ assert f.tell() == 25
f.write('baz')
f.write('egg')
f.truncate(3)
diff --git a/rpython/rlib/rStringIO.py b/rpython/rlib/rStringIO.py
--- a/rpython/rlib/rStringIO.py
+++ b/rpython/rlib/rStringIO.py
@@ -11,167 +11,166 @@
_mixin_ = True # for interp_stringio.py
def __init__(self):
+ self.init()
+
+ def init(self):
# The real content is the join of the following data:
- # * the list of characters self.bigbuffer;
- # * each of the strings in self.strings.
+ # * the list of characters self.__bigbuffer;
+ # * each of the strings in self.__strings.
#
- self.closed = False
- self.strings = None
- self.bigbuffer = None
- self.pos = AT_END
+ self.__closed = False
+ self.__strings = None
+ self.__bigbuffer = None
+ self.__pos = AT_END
def close(self):
- self.closed = True
- self.strings = None
- self.bigbuffer = None
- self.pos = AT_END
+ self.__closed = True
+ self.__strings = None
+ self.__bigbuffer = None
+ self.__pos = AT_END
def is_closed(self):
- return self.closed
+ return self.__closed
- def _copy_into_bigbuffer(self):
- """Copy all the data into the list of characters self.bigbuffer."""
- if self.bigbuffer is None:
- self.bigbuffer = []
- if self.strings is not None:
- self.bigbuffer += self.strings.build()
- self.strings = None
+ def __copy_into_bigbuffer(self):
+ """Copy all the data into the list of characters self.__bigbuffer."""
+ if self.__bigbuffer is None:
+ self.__bigbuffer = []
+ if self.__strings is not None:
+ self.__bigbuffer += self.__strings.build()
+ self.__strings = None
def getvalue(self):
- """If self.strings contains more than 1 string, join all the
+ """If self.__strings contains more than 1 string, join all the
strings together. Return the final single string."""
- if self.bigbuffer is not None:
- self._copy_into_bigbuffer()
- return ''.join(self.bigbuffer)
- if self.strings is not None:
- return self.strings.build()
+ if self.__bigbuffer is not None:
+ self.__copy_into_bigbuffer()
+ return ''.join(self.__bigbuffer)
+ if self.__strings is not None:
+ return self.__strings.build()
return ''
def getsize(self):
result = 0
- if self.bigbuffer is not None:
- result += len(self.bigbuffer)
- if self.strings is not None:
- result += self.strings.getlength()
+ if self.__bigbuffer is not None:
+ result += len(self.__bigbuffer)
+ if self.__strings is not None:
+ result += self.__strings.getlength()
return result
def write(self, buffer):
# Idea: for the common case of a sequence of write() followed
- # by only getvalue(), self.bigbuffer remains empty. It is only
+ # by only getvalue(), self.__bigbuffer remains empty. It is only
# used to handle the more complicated cases.
- if self.pos == AT_END:
- self._fast_write(buffer)
+ if self.__pos == AT_END:
+ self.__fast_write(buffer)
else:
- self._slow_write(buffer)
+ self.__slow_write(buffer)
- def _fast_write(self, buffer):
- if self.strings is None:
- self.strings = StringBuilder()
- self.strings.append(buffer)
+ def __fast_write(self, buffer):
+ if self.__strings is None:
+ self.__strings = StringBuilder()
+ self.__strings.append(buffer)
- def _slow_write(self, buffer):
- p = self.pos
+ def __slow_write(self, buffer):
+ p = self.__pos
assert p >= 0
endp = p + len(buffer)
- if self.bigbuffer is not None and len(self.bigbuffer) >= endp:
- # semi-fast path: the write is entirely inside self.bigbuffer
+ if self.__bigbuffer is not None and len(self.__bigbuffer) >= endp:
+ # semi-fast path: the write is entirely inside self.__bigbuffer
for i in range(len(buffer)):
- self.bigbuffer[p + i] = buffer[i]
+ self.__bigbuffer[p + i] = buffer[i]
else:
- # slow path: collect all data into self.bigbuffer and
+ # slow path: collect all data into self.__bigbuffer and
# handle the various cases
- self._copy_into_bigbuffer()
- fitting = len(self.bigbuffer) - p
+ self.__copy_into_bigbuffer()
+ fitting = len(self.__bigbuffer) - p
if fitting > 0:
# the write starts before the end of the data
fitting = min(len(buffer), fitting)
for i in range(fitting):
- self.bigbuffer[p + i] = buffer[i]
+ self.__bigbuffer[p + i] = buffer[i]
if len(buffer) > fitting:
# the write extends beyond the end of the data
- self.bigbuffer += buffer[fitting:]
+ self.__bigbuffer += buffer[fitting:]
endp = AT_END
else:
# the write starts at or beyond the end of the data
- self.bigbuffer += '\x00' * (-fitting) + buffer
+ self.__bigbuffer += '\x00' * (-fitting) + buffer
endp = AT_END
- self.pos = endp
+ self.__pos = endp
def seek(self, position, mode=0):
if mode == 1:
- if self.pos == AT_END:
- self.pos = self.getsize()
- position += self.pos
+ if self.__pos == AT_END:
+ self.__pos = self.getsize()
+ position += self.__pos
elif mode == 2:
if position == 0:
- self.pos = AT_END
+ self.__pos = AT_END
return
position += self.getsize()
if position < 0:
position = 0
- self.pos = position
+ self.__pos = position
def tell(self):
- if self.pos == AT_END:
+ if self.__pos == AT_END:
result = self.getsize()
else:
- result = self.pos
+ result = self.__pos
assert result >= 0
return result
def read(self, n=-1):
- p = self.pos
+ p = self.__pos
if p == 0 and n < 0:
- self.pos = AT_END
+ self.__pos = AT_END
return self.getvalue() # reading everything
if p == AT_END or n == 0:
return ''
assert p >= 0
- self._copy_into_bigbuffer()
- mysize = len(self.bigbuffer)
+ self.__copy_into_bigbuffer()
+ mysize = len(self.__bigbuffer)
count = mysize - p
if n >= 0:
count = min(n, count)
if count <= 0:
return ''
if p == 0 and count == mysize:
- self.pos = AT_END
- return ''.join(self.bigbuffer)
+ self.__pos = AT_END
+ return ''.join(self.__bigbuffer)
else:
- self.pos = p + count
- return ''.join(self.bigbuffer[p:p+count])
+ self.__pos = p + count
+ return ''.join(self.__bigbuffer[p:p+count])
def readline(self, size=-1):
- p = self.pos
+ p = self.__pos
if p == AT_END or size == 0:
return ''
assert p >= 0
- self._copy_into_bigbuffer()
- end = len(self.bigbuffer)
+ self.__copy_into_bigbuffer()
+ end = len(self.__bigbuffer)
if size >= 0 and size < end - p:
end = p + size
i = p
while i < end:
- finished = self.bigbuffer[i] == '\n'
+ finished = self.__bigbuffer[i] == '\n'
i += 1
if finished:
break
- self.seek(i)
- return ''.join(self.bigbuffer[p:i])
+ self.__pos = i
+ return ''.join(self.__bigbuffer[p:i])
def truncate(self, size):
- # NB. 'size' is mandatory. This has the same un-Posix-y semantics
- # than CPython: it never grows the buffer, and it sets the current
- # position to the end.
assert size >= 0
- if self.bigbuffer is None or size > len(self.bigbuffer):
- self._copy_into_bigbuffer()
+ if self.__bigbuffer is None or size > len(self.__bigbuffer):
+ self.__copy_into_bigbuffer()
else:
# we can drop all extra strings
- if self.strings is not None:
- self.strings = None
- if size < len(self.bigbuffer):
- del self.bigbuffer[size:]
- if len(self.bigbuffer) == 0:
- self.bigbuffer = None
- self.pos = AT_END
+ if self.__strings is not None:
+ self.__strings = None
+ if size < len(self.__bigbuffer):
+ del self.__bigbuffer[size:]
+ if len(self.__bigbuffer) == 0:
+ self.__bigbuffer = None
diff --git a/rpython/rtyper/rlist.py b/rpython/rtyper/rlist.py
--- a/rpython/rtyper/rlist.py
+++ b/rpython/rtyper/rlist.py
@@ -950,6 +950,7 @@
count = l2.ll_length()
ll_assert(start >= 0, "l[start:x] = l with unexpectedly negative start")
ll_assert(start <= l1.ll_length(), "l[start:x] = l with start > len(l)")
+ ll_assert(stop <= l1.ll_length(), "stop cannot be past the end of l1")
ll_assert(count == stop - start,
"setslice cannot resize lists in RPython")
# XXX ...but it would be easy enough to support if really needed
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit