https://github.com/python/cpython/commit/13aa41f4e253f23c8a2adb5565996cc9227d596e
commit: 13aa41f4e253f23c8a2adb5565996cc9227d596e
branch: main
author: Vyron Vasileiadis <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-08-16T10:51:56+03:00
summary:

gh-155389: Return bytes from _pyio.BytesIO.peek() (GH-155390)

peek() returned a slice of the internal bytearray, where read() converts with
take_bytes(). It also did not coerce its size through __index__ and did not
hold the lock while slicing, both of which read() and the C implementation do.

files:
M Lib/_pyio.py
M Lib/test/test_io/test_memoryio.py

diff --git a/Lib/_pyio.py b/Lib/_pyio.py
index ac301180d284fa9..cf4ef04f37d26cc 100644
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -1003,9 +1003,19 @@ def tell(self):
     def peek(self, size=0):
         if self.closed:
             raise ValueError("peek on closed file")
+        try:
+            size_index = size.__index__
+        except AttributeError:
+            raise TypeError(f"{size!r} is not an integer")
+        else:
+            size = size_index()
+
         if size < 1:
-            return self._buffer[self._pos:self._pos + io.DEFAULT_BUFFER_SIZE]
-        return self._buffer[self._pos:self._pos + size]
+            size = io.DEFAULT_BUFFER_SIZE
+
+        with self._lock:
+            b = self._buffer[self._pos:self._pos + size]
+            return b.take_bytes()
 
     def truncate(self, pos=None):
         if self.closed:
diff --git a/Lib/test/test_io/test_memoryio.py 
b/Lib/test/test_io/test_memoryio.py
index 0037fdc2fd67c1a..e934e3fb2bdf124 100644
--- a/Lib/test/test_io/test_memoryio.py
+++ b/Lib/test/test_io/test_memoryio.py
@@ -596,6 +596,11 @@ def test_peek(self):
         buf = self.buftype("1234567890")
         with self.ioclass(buf) as memio:
             self.assertEqual(memio.tell(), 0)
+            # bytearray(b'1') == b'1', so the type has to be asserted 
separately.
+            self.assertIsInstance(memio.peek(), bytes)
+            self.assertIsInstance(memio.peek(1), bytes)
+            self.assertEqual(memio.peek(IntLike(3)), buf[:3])
+            self.assertRaises(TypeError, memio.peek, 1.5)
             self.assertEqual(memio.peek(1), buf[:1])
             self.assertEqual(memio.peek(1), buf[:1])
             self.assertEqual(memio.peek(), buf)

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to