summaryrefslogtreecommitdiffstats
path: root/Lib/_pyio.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/_pyio.py')
-rw-r--r--Lib/_pyio.py37
1 files changed, 23 insertions, 14 deletions
diff --git a/Lib/_pyio.py b/Lib/_pyio.py
index b3a8f37..f7370df 100644
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -1454,6 +1454,17 @@ class BufferedRandom(BufferedWriter, BufferedReader):
return BufferedWriter.write(self, b)
+def _new_buffersize(bytes_read):
+ # Parallels _io/fileio.c new_buffersize
+ if bytes_read > 65536:
+ addend = bytes_read >> 3
+ else:
+ addend = 256 + bytes_read
+ if addend < DEFAULT_BUFFER_SIZE:
+ addend = DEFAULT_BUFFER_SIZE
+ return bytes_read + addend
+
+
class FileIO(RawIOBase):
_fd = -1
_created = False
@@ -1672,22 +1683,20 @@ class FileIO(RawIOBase):
except OSError:
pass
- result = bytearray()
- while True:
- if len(result) >= bufsize:
- bufsize = len(result)
- bufsize += max(bufsize, DEFAULT_BUFFER_SIZE)
- n = bufsize - len(result)
- try:
- chunk = os.read(self._fd, n)
- except BlockingIOError:
- if result:
- break
+ result = bytearray(bufsize)
+ bytes_read = 0
+ try:
+ while n := os.readinto(self._fd, memoryview(result)[bytes_read:]):
+ bytes_read += n
+ if bytes_read >= len(result):
+ result.resize(_new_buffersize(bytes_read))
+ except BlockingIOError:
+ if not bytes_read:
return None
- if not chunk: # reached the end of the file
- break
- result += chunk
+ assert len(result) - bytes_read >= 1, \
+ "os.readinto buffer size 0 will result in erroneous EOF / returns 0"
+ result.resize(bytes_read)
return bytes(result)
def readinto(self, buffer):