Author: Manuel Jacob <m...@manueljacob.de>
Branch: py3.5
Changeset: r90519:5adc6b27b53a
Date: 2017-03-04 00:43 +0100
http://bitbucket.org/pypy/pypy/changeset/5adc6b27b53a/

Log:    hg merge default

diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py
--- a/pypy/interpreter/error.py
+++ b/pypy/interpreter/error.py
@@ -672,15 +672,17 @@
                          w_filename2=w_filename2,
                          eintr_retry=eintr_retry)
 
-def exception_from_saved_errno(space, w_type):
-    from rpython.rlib.rposix import get_saved_errno
-
-    errno = get_saved_errno()
+def exception_from_errno(space, w_type, errno):
     msg = strerror(errno)
     w_error = space.call_function(w_type, space.newint(errno),
                                   space.newunicode(msg))
     return OperationError(w_type, w_error)
 
+def exception_from_saved_errno(space, w_type):
+    from rpython.rlib.rposix import get_saved_errno
+    errno = get_saved_errno()
+    return exception_from_errno(space, w_type, errno)
+
 def new_exception_class(space, name, w_bases=None, w_dict=None):
     """Create a new exception type.
     @param name: the name of the type.
diff --git a/pypy/module/_io/interp_bufferedio.py 
b/pypy/module/_io/interp_bufferedio.py
--- a/pypy/module/_io/interp_bufferedio.py
+++ b/pypy/module/_io/interp_bufferedio.py
@@ -5,6 +5,8 @@
     TypeDef, GetSetProperty, generic_new_descr, interp_attrproperty_w)
 from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
 from rpython.rlib.buffer import Buffer, SubBuffer
+from rpython.rlib.rgc import (
+    nonmoving_raw_ptr_for_resizable_list, resizable_list_supporting_raw_ptr)
 from rpython.rlib.rstring import StringBuilder
 from rpython.rlib.rarithmetic import r_longlong, intmask
 from rpython.rlib import rposix
@@ -159,7 +161,7 @@
 
     def __init__(self, n):
         self.length = n
-        self.buf = ['\0'] * n
+        self.buf = resizable_list_supporting_raw_ptr(['\0'] * n)
         self.readonly = False
 
     def getlength(self):
diff --git a/pypy/module/_io/interp_fileio.py b/pypy/module/_io/interp_fileio.py
--- a/pypy/module/_io/interp_fileio.py
+++ b/pypy/module/_io/interp_fileio.py
@@ -1,11 +1,13 @@
 from pypy.interpreter.typedef import TypeDef, interp_attrproperty, 
GetSetProperty
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.error import (
-    OperationError, oefmt, wrap_oserror, wrap_oserror2)
+    OperationError, oefmt, wrap_oserror, wrap_oserror2, exception_from_errno)
 from rpython.rlib.rarithmetic import r_longlong
+from rpython.rlib.rposix import get_saved_errno
 from rpython.rlib.rstring import StringBuilder
 from rpython.rlib import rposix
 from rpython.rlib.rposix_stat import STAT_FIELD_TYPES
+from rpython.rtyper.lltypesystem import lltype, rffi
 from os import O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_TRUNC, O_EXCL
 import sys, os, stat, errno
 from pypy.module._io.interp_iobase import (
@@ -126,6 +128,15 @@
             return currentsize + BIGCHUNK
     return currentsize + SMALLCHUNK
 
+
+_WIN32 = sys.platform.startswith('win')
+UNDERSCORE_ON_WIN32 = '_' if _WIN32 else ''
+
+os_read = rffi.llexternal(UNDERSCORE_ON_WIN32 + 'read',
+                          [rffi.INT, rffi.CCHARP, rffi.SIZE_T],
+                          rffi.SSIZE_T, save_err=rffi.RFFI_SAVE_ERRNO)
+
+
 class W_FileIO(W_RawIOBase):
     def __init__(self, space):
         W_RawIOBase.__init__(self, space)
@@ -447,18 +458,42 @@
         self._check_readable(space)
         rwbuffer = space.getarg_w('w*', w_buffer)
         length = rwbuffer.getlength()
-        while True:
+
+        target_address = lltype.nullptr(rffi.CCHARP.TO)
+        if length > 64:
             try:
-                buf = os.read(self.fd, length)
-                break
-            except OSError as e:
-                if e.errno == errno.EAGAIN:
+                target_address = rwbuffer.get_raw_address()
+            except ValueError:
+                pass
+
+        if not target_address:
+            # unoptimized case
+            while True:
+                try:
+                    buf = os.read(self.fd, length)
+                    break
+                except OSError as e:
+                    if e.errno == errno.EAGAIN:
+                        return space.w_None
+                    wrap_oserror(space, e,
+                                 exception_name='w_IOError',
+                                 eintr_retry=True)
+            rwbuffer.setslice(0, buf)
+            return space.newint(len(buf))
+        else:
+            # optimized case: reading more than 64 bytes into a rwbuffer
+            # with a valid raw address
+            # XXX TODO(mjacob): implement PEP 475 here!
+            got = os_read(self.fd, target_address, length)
+            got = rffi.cast(lltype.Signed, got)
+            if got >= 0:
+                return space.newint(got)
+            else:
+                err = get_saved_errno()
+                if err == errno.EAGAIN:
                     return space.w_None
-                wrap_oserror(space, e,
-                             exception_name='w_IOError',
-                             eintr_retry=True)
-        rwbuffer.setslice(0, buf)
-        return space.newint(len(buf))
+                raise exception_from_errno(space, space.w_IOError, err)
+            keepalive_until_here(rwbuffer)
 
     def readall_w(self, space):
         self._check_closed(space)
diff --git a/pypy/module/_io/test/test_fileio.py 
b/pypy/module/_io/test/test_fileio.py
--- a/pypy/module/_io/test/test_fileio.py
+++ b/pypy/module/_io/test/test_fileio.py
@@ -1,4 +1,5 @@
 # encoding: utf-8
+from pypy.interpreter.gateway import interp2app
 from rpython.tool.udir import udir
 import os
 
@@ -14,6 +15,11 @@
         self.w_posix = self.space.appexec([], """():
             import %s as m;
             return m""" % os.name)
+        def create_bigfile_w():
+            bigfile = udir.join('bigfile')
+            bigfile.write('a' * 1000, mode='wb')
+            return self.space.wrap(str(bigfile))
+        self.w_create_bigfile = self.space.wrap(interp2app(create_bigfile_w))
 
     def test_constructor(self):
         import _io
@@ -151,13 +157,10 @@
         import _io
         a = bytearray(b'x' * 10)
         f = _io.FileIO(self.tmpfile, 'r+')
-        f.seek(5)
-        f.write(b'\x00' * 5)
-        f.seek(0)
         assert f.readinto(a) == 5
         f.seek(0)
         m = memoryview(bytearray(b"helloworld"))
-        assert f.readinto(m) == 10
+        assert f.readinto(m) == 5
         #
         exc = raises(TypeError, f.readinto, u"hello")
         msg = str(exc.value)
@@ -179,6 +182,13 @@
         f.close()
         assert a == b'a\nbxxxxxxx'
 
+    def test_readinto_optimized(self):
+        import _io
+        a = bytearray(b'x' * 1024)
+        f = _io.FileIO(self.create_bigfile(), 'r+')
+        assert f.readinto(a) == 1000
+        assert a == b'a' * 1000 + b'x' * 24
+
     def test_nonblocking_read(self):
         try:
             import os, fcntl
@@ -194,6 +204,8 @@
         assert f.read(10) is None
         a = bytearray(b'x' * 10)
         assert f.readinto(a) is None
+        a2 = bytearray(b'x' * 1024)
+        assert f.readinto(a2) is None
 
     def test_repr(self):
         import _io
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to