[pypy-commit] pypy default: fix the case of nonblocking sys.stdin

fijal noreply at buildbot.pypy.org
Sat Oct 8 21:06:29 CEST 2011


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: 
Changeset: r47882:3f96afe7cdc2
Date: 2011-10-08 21:06 +0200
http://bitbucket.org/pypy/pypy/changeset/3f96afe7cdc2/

Log:	fix the case of nonblocking sys.stdin

diff --git a/pypy/module/_file/test/test_file.py b/pypy/module/_file/test/test_file.py
--- a/pypy/module/_file/test/test_file.py
+++ b/pypy/module/_file/test/test_file.py
@@ -1,5 +1,5 @@
 from __future__ import with_statement
-import py
+import py, os, errno
 
 from pypy.conftest import gettestobjspace, option
 
@@ -257,6 +257,35 @@
             assert self.temppath in g.getvalue()
 
 
+class AppTestNonblocking(object):
+    def setup_class(cls):
+        from pypy.module._file.interp_file import W_File
+        
+        cls.old_read = os.read
+        state = [0]
+        def read(fd, n=None):
+            if fd != 42:
+                return cls.old_read(fd, n)
+            if state[0] == 0:
+                state[0] += 1
+                return "xyz"
+            if state[0] < 3:
+                state[0] += 1
+                raise OSError(errno.EAGAIN, "xyz")
+            return ''
+        os.read = read
+        stdin = W_File(cls.space)
+        stdin.file_fdopen(42, "r", 1)
+        stdin.name = '<stdin>'
+        cls.w_stream = stdin
+
+    def teardown_class(cls):
+        os.read = cls.old_read
+        
+    def test_nonblocking_file(self):
+        res = self.stream.read()
+        assert res == 'xyz'
+
 class AppTestConcurrency(object):
     # these tests only really make sense on top of a translated pypy-c,
     # because on top of py.py the inner calls to os.write() don't
diff --git a/pypy/rlib/streamio.py b/pypy/rlib/streamio.py
--- a/pypy/rlib/streamio.py
+++ b/pypy/rlib/streamio.py
@@ -37,7 +37,7 @@
 # return value of tell(), but not as argument to read().
 #
 
-import os, sys
+import os, sys, errno
 from pypy.rlib.objectmodel import specialize, we_are_translated
 from pypy.rlib.rarithmetic import r_longlong, intmask
 from pypy.rlib import rposix
@@ -587,12 +587,22 @@
     def readall(self):
         pos = self.pos
         assert pos >= 0
-        chunks = [self.buf[pos:]]
+        if self.buf:
+            chunks = [self.buf[pos:]]
+        else:
+            chunks = []
         self.buf = ""
         self.pos = 0
         bufsize = self.bufsize
         while 1:
-            data = self.do_read(bufsize)
+            try:
+                data = self.do_read(bufsize)
+            except OSError, o:
+                if o.errno != errno.EAGAIN:
+                    raise
+                if not chunks:
+                    raise
+                break
             if not data:
                 break
             chunks.append(data)


More information about the pypy-commit mailing list