Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r75887:b1c4fcb04a42
Date: 2015-02-15 11:16 +0100
http://bitbucket.org/pypy/pypy/changeset/b1c4fcb04a42/

Log:    Test (thanks vpelletier on irc) and fix for a case where we'd
        propagate EAGAIN to app-level even though the BufferingInputStream
        still has buffered data

diff --git a/pypy/module/_file/interp_file.py b/pypy/module/_file/interp_file.py
--- a/pypy/module/_file/interp_file.py
+++ b/pypy/module/_file/interp_file.py
@@ -206,7 +206,12 @@
                     # a special-case only for read() (similar to CPython, which
                     # also loses partial data with other methods): if we get
                     # EAGAIN after already some data was received, return it.
+                    # Note that we can get EAGAIN while there is buffered data
+                    # waiting; read that too.
                     if is_wouldblock_error(e):
+                        pos, buf = stream.peek()
+                        if len(buf) > pos:
+                            result.append(stream.read(min(n, len(buf) - pos)))
                         got = result.build()
                         if len(got) > 0:
                             return got
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
@@ -302,15 +302,14 @@
 
         if cls.runappdirect:
             py.test.skip("works with internals of _file impl on py.py")
-        state = [0]
         def read(fd, n=None):
             if fd != 424242:
                 return cls.old_read(fd, n)
-            if state[0] == 0:
-                state[0] += 1
+            if cls.state == 0:
+                cls.state += 1
                 return "xyz"
-            if state[0] < 3:
-                state[0] += 1
+            if cls.state < 3:
+                cls.state += 1
                 raise OSError(errno.EAGAIN, "xyz")
             return ''
         os.read = read
@@ -319,13 +318,20 @@
         stdin.name = '<stdin>'
         cls.w_stream = stdin
 
+    def setup_method(self, meth):
+        self.__class__.state = 0
+
     def teardown_class(cls):
         os.read = cls.old_read
 
-    def test_nonblocking_file(self):
+    def test_nonblocking_file_all(self):
         res = self.stream.read()
         assert res == 'xyz'
 
+    def test_nonblocking_file_max(self):
+        res = self.stream.read(100)
+        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
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to