Skip to content

Commit b833b83

Browse files
committed
Implement BytesIO.peek()
1 parent 8f17140 commit b833b83

4 files changed

Lines changed: 99 additions & 1 deletion

File tree

Lib/_pyio.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,14 @@ def tell(self):
996996
raise ValueError("tell on closed file")
997997
return self._pos
998998

999+
def peek(self, size=-1):
1000+
pos = self.tell()
1001+
if size == 0:
1002+
size = -1
1003+
b = self.read(size)
1004+
self.seek(pos)
1005+
return b
1006+
9991007
def truncate(self, pos=None):
10001008
if self.closed:
10011009
raise ValueError("truncate on closed file")

Lib/test/test_io/test_memoryio.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,23 @@ def test_issue141311(self):
566566
buf = bytearray(2)
567567
self.assertEqual(0, memio.readinto(buf))
568568

569+
def test_peek(self):
570+
buf = self.buftype("1234567890")
571+
memio = self.ioclass(buf)
572+
573+
self.assertEqual(memio.peek(1), buf[:1])
574+
self.assertEqual(memio.peek(1), buf[:1])
575+
self.assertEqual(memio.peek(), buf)
576+
self.assertEqual(memio.peek(0), buf)
577+
memio.read(1)
578+
self.assertEqual(memio.peek(1), buf[1:2])
579+
self.assertEqual(memio.peek(), buf[1:])
580+
self.assertEqual(memio.peek(42), buf[1:])
581+
memio.read()
582+
self.assertEqual(memio.peek(1), self.EOF)
583+
memio.close()
584+
self.assertRaises(ValueError, memio.peek)
585+
569586
def test_unicode(self):
570587
memio = self.ioclass()
571588

Modules/_io/bytesio.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,42 @@ _io_BytesIO_read1_impl(bytesio *self, Py_ssize_t size)
499499
return _io_BytesIO_read_impl(self, size);
500500
}
501501

502+
503+
/*[clinic input]
504+
_io.BytesIO.peek
505+
size: Py_ssize_t(accept={int, NoneType}) = -1
506+
/
507+
508+
Return bytes from the stream without advancing the position.
509+
510+
Return an empty bytes object at EOF.
511+
[clinic start generated code]*/
512+
513+
static PyObject *
514+
_io_BytesIO_peek_impl(bytesio *self, Py_ssize_t size)
515+
/*[clinic end generated code: output=fa4d8ce28b35db9b input=afc80e71b37e7c59]*/
516+
{
517+
Py_ssize_t n;
518+
const char *output;
519+
520+
CHECK_CLOSED(self);
521+
522+
/* adjust invalid sizes */
523+
n = self->string_size - self->pos;
524+
if (size < 1 || size > n) {
525+
size = n;
526+
if (size < 0)
527+
size = 0;
528+
}
529+
530+
assert(self->buf != NULL);
531+
assert(size <= self->string_size);
532+
output = PyBytes_AS_STRING(self->buf) + self->pos;
533+
return PyBytes_FromStringAndSize(output, size);
534+
}
535+
536+
537+
502538
/*[clinic input]
503539
@critical_section
504540
_io.BytesIO.readline
@@ -1135,6 +1171,7 @@ static struct PyMethodDef bytesio_methods[] = {
11351171
_IO_BYTESIO_READLINE_METHODDEF
11361172
_IO_BYTESIO_READLINES_METHODDEF
11371173
_IO_BYTESIO_READ_METHODDEF
1174+
_IO_BYTESIO_PEEK_METHODDEF
11381175
_IO_BYTESIO_GETBUFFER_METHODDEF
11391176
_IO_BYTESIO_GETVALUE_METHODDEF
11401177
_IO_BYTESIO_SEEK_METHODDEF

Modules/_io/clinic/bytesio.c.h

Lines changed: 37 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)