Author: Armin Rigo <ar...@tunes.org> 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 pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit