Author: Armin Rigo <[email protected]>
Branch:
Changeset: r57823:52c909884ae5
Date: 2012-10-07 17:44 +0200
http://bitbucket.org/pypy/pypy/changeset/52c909884ae5/
Log: Redo a solution that is very inefficient but maybe not as bad as
before.
diff --git a/pypy/rlib/streamio.py b/pypy/rlib/streamio.py
--- a/pypy/rlib/streamio.py
+++ b/pypy/rlib/streamio.py
@@ -41,6 +41,7 @@
from pypy.rlib.objectmodel import specialize, we_are_translated
from pypy.rlib.rarithmetic import r_longlong, intmask
from pypy.rlib import rposix
+from pypy.rlib.rstring import StringBuilder
from os import O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_TRUNC
O_BINARY = getattr(os, "O_BINARY", 0)
@@ -141,11 +142,7 @@
def construct_stream_tower(stream, buffering, universal, reading, writing,
binary):
if buffering == 0: # no buffering
- # XXX we cannot really use ReadlineInputStream: see module/_file/
- # test/test_file.py:test_readline_unbuffered_should_read_one_line_only
pass
- #if reading: # force some minimal buffering for readline()
- # stream = ReadlineInputStream(stream)
elif buffering == 1: # line-buffering
if writing:
stream = LineBufferingOutputStream(stream)
@@ -306,6 +303,26 @@
raise
# else try again
+ def readline(self):
+ # mostly inefficient, but not as laughably bad as with the default
+ # readline() from Stream
+ result = StringBuilder()
+ while True:
+ try:
+ c = os.read(self.fd, 1)
+ except OSError, e:
+ if e.errno != errno.EINTR:
+ raise
+ else:
+ continue # try again
+ if not c:
+ break
+ c = c[0]
+ result.append(c)
+ if c == '\n':
+ break
+ return result.build()
+
def write(self, data):
while data:
try:
@@ -703,113 +720,6 @@
flush_buffers=False)
-class ReadlineInputStream(Stream):
-
- """Minimal buffering input stream.
-
- Only does buffering for readline(). The other kinds of reads, and
- all writes, are not buffered at all.
- """
-
- bufsize = 2**13 # 8 K
-
- def __init__(self, base, bufsize=-1):
- self.base = base
- self.do_read = base.read # function to fill buffer some more
- self.do_seek = base.seek # seek to a byte offset
- if bufsize == -1: # Get default from the class
- bufsize = self.bufsize
- self.bufsize = bufsize # buffer size (hint only)
- self.buf = None # raw data (may contain "\n")
- self.bufstart = 0
-
- def flush_buffers(self):
- if self.buf is not None:
- try:
- self.do_seek(self.bufstart-len(self.buf), 1)
- except (MyNotImplementedError, OSError):
- pass
- else:
- self.buf = None
- self.bufstart = 0
-
- def readline(self):
- if self.buf is not None:
- i = self.buf.find('\n', self.bufstart)
- else:
- self.buf = ''
- i = -1
- #
- if i < 0:
- self.buf = self.buf[self.bufstart:]
- self.bufstart = 0
- while True:
- bufsize = max(self.bufsize, len(self.buf) >> 2)
- data = self.do_read(bufsize)
- if not data:
- result = self.buf # end-of-file reached
- self.buf = None
- return result
- startsearch = len(self.buf) # there is no '\n' in buf so far
- self.buf += data
- i = self.buf.find('\n', startsearch)
- if i >= 0:
- break
- #
- i += 1
- result = self.buf[self.bufstart:i]
- self.bufstart = i
- return result
-
- def peek(self):
- if self.buf is None:
- return ''
- if self.bufstart > 0:
- self.buf = self.buf[self.bufstart:]
- self.bufstart = 0
- return self.buf
-
- def tell(self):
- pos = self.base.tell()
- if self.buf is not None:
- pos -= (len(self.buf) - self.bufstart)
- return pos
-
- def readall(self):
- result = self.base.readall()
- if self.buf is not None:
- result = self.buf[self.bufstart:] + result
- self.buf = None
- self.bufstart = 0
- return result
-
- def read(self, n):
- if self.buf is None:
- return self.do_read(n)
- else:
- m = n - (len(self.buf) - self.bufstart)
- start = self.bufstart
- if m > 0:
- result = self.buf[start:] + self.do_read(m)
- self.buf = None
- self.bufstart = 0
- return result
- elif n >= 0:
- self.bufstart = start + n
- return self.buf[start : self.bufstart]
- else:
- return ''
-
- seek = PassThrough("seek", flush_buffers=True)
- write = PassThrough("write", flush_buffers=True)
- truncate = PassThrough("truncate", flush_buffers=True)
- flush = PassThrough("flush", flush_buffers=True)
- flushable = PassThrough("flushable", flush_buffers=False)
- close = PassThrough("close", flush_buffers=False)
- try_to_find_file_descriptor = PassThrough("try_to_find_file_descriptor",
- flush_buffers=False)
-
-
class BufferingOutputStream(Stream):
"""Standard buffering output stream.
diff --git a/pypy/rlib/test/test_streamio.py b/pypy/rlib/test/test_streamio.py
--- a/pypy/rlib/test/test_streamio.py
+++ b/pypy/rlib/test/test_streamio.py
@@ -1026,7 +1026,7 @@
base.tell = f
if not seek:
base.seek = f
- return streamio.ReadlineInputStream(base, bufsize)
+ return base
def test_readline(self):
for file in [self.makeStream(), self.makeStream(bufsize=2)]:
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit