Skip to content

Commit 7d8793a

Browse files
committed
Update docs, factor out peek_bytes, semantics
Semantic change: The default argument for peek is now size=1.
1 parent 2963dab commit 7d8793a

5 files changed

Lines changed: 44 additions & 28 deletions

File tree

Doc/library/io.rst

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -728,12 +728,15 @@ than raw I/O does.
728728

729729
Return :class:`bytes` containing the entire contents of the buffer.
730730

731-
.. method:: peek(size=0, /)
732-
733-
.. versionadded:: 3.13
731+
.. method:: peek(size=1, /)
734732

735733
Return bytes from the current position onwards but without advancing the
736-
position. The number of bytes returned may be less or more than requested.
734+
position. If the size argument is less than one or larger than the number
735+
of available bytes, a copy of the buffer from the current position until
736+
the end is returned.
737+
Return an empty bytes object at EOF.
738+
739+
.. versionadded:: 3.13
737740

738741
.. method:: read1(size=-1, /)
739742

Lib/_pyio.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -978,13 +978,12 @@ def tell(self):
978978
raise ValueError("tell on closed file")
979979
return self._pos
980980

981-
def peek(self, size=-1):
982-
pos = self.tell()
983-
if size == 0:
984-
size = -1
985-
b = self.read(size)
986-
self.seek(pos)
987-
return b
981+
def peek(self, size=1):
982+
if self.closed:
983+
raise ValueError("peek on closed file")
984+
if size < 1:
985+
size = len(self._buffer) - self._pos
986+
return self._buffer[self._pos : self._pos + size]
988987

989988
def truncate(self, pos=None):
990989
if self.closed:

Lib/test/test_memoryio.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -523,12 +523,13 @@ def test_peek(self):
523523
pos = memio.tell()
524524
self.assertEqual(memio.peek(1), buf[:1])
525525
self.assertEqual(memio.peek(1), buf[:1])
526-
self.assertEqual(memio.peek(), buf)
526+
self.assertEqual(memio.peek(), buf[:1])
527527
self.assertEqual(memio.peek(0), buf)
528528
self.assertEqual(memio.tell(), pos)
529529
memio.read(1)
530530
self.assertEqual(memio.peek(1), buf[1:2])
531-
self.assertEqual(memio.peek(), buf[1:])
531+
self.assertEqual(memio.peek(), buf[1:2])
532+
self.assertEqual(memio.peek(0), buf[1:])
532533
self.assertEqual(memio.peek(42), buf[1:])
533534
memio.read()
534535
self.assertEqual(memio.peek(1), self.EOF)

Modules/_io/bytesio.c

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -394,8 +394,9 @@ _io_BytesIO_tell_impl(bytesio *self)
394394
return PyLong_FromSsize_t(self->pos);
395395
}
396396

397+
// Read without advancing position
397398
static PyObject *
398-
read_bytes(bytesio *self, Py_ssize_t size)
399+
peek_bytes(bytesio *self, Py_ssize_t size)
399400
{
400401
const char *output;
401402

@@ -404,15 +405,20 @@ read_bytes(bytesio *self, Py_ssize_t size)
404405
if (size > 1 &&
405406
self->pos == 0 && size == PyBytes_GET_SIZE(self->buf) &&
406407
self->exports == 0) {
407-
self->pos += size;
408408
return Py_NewRef(self->buf);
409409
}
410410

411411
output = PyBytes_AS_STRING(self->buf) + self->pos;
412-
self->pos += size;
413412
return PyBytes_FromStringAndSize(output, size);
414413
}
415414

415+
static PyObject *
416+
read_bytes(bytesio *self, Py_ssize_t size) {
417+
PyObject *bytes = peek_bytes(self, size);
418+
self->pos += size;
419+
return bytes;
420+
}
421+
416422
/*[clinic input]
417423
_io.BytesIO.read
418424
size: Py_ssize_t(accept={int, NoneType}) = -1
@@ -465,17 +471,18 @@ _io_BytesIO_read1_impl(bytesio *self, Py_ssize_t size)
465471

466472
/*[clinic input]
467473
_io.BytesIO.peek
468-
size: Py_ssize_t(accept={int, NoneType}) = -1
474+
size: Py_ssize_t = 1
469475
/
470476
471477
Return bytes from the stream without advancing the position.
472478
479+
If the size argument is zero or negative, read until EOF is reached.
473480
Return an empty bytes object at EOF.
474481
[clinic start generated code]*/
475482

476483
static PyObject *
477484
_io_BytesIO_peek_impl(bytesio *self, Py_ssize_t size)
478-
/*[clinic end generated code: output=fa4d8ce28b35db9b input=afc80e71b37e7c59]*/
485+
/*[clinic end generated code: output=fa4d8ce28b35db9b input=cb06614a3ed0496e]*/
479486
{
480487
Py_ssize_t n;
481488

@@ -488,11 +495,7 @@ _io_BytesIO_peek_impl(bytesio *self, Py_ssize_t size)
488495
if (size < 0)
489496
size = 0;
490497
}
491-
Py_ssize_t prev_pos = self->pos;
492-
PyObject* result = read_bytes(self, size);
493-
self->pos = prev_pos;
494-
495-
return result;
498+
return peek_bytes(self, size);
496499
}
497500

498501

Modules/_io/clinic/bytesio.c.h

Lines changed: 15 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)