Skip to content

Commit 1e5e3ab

Browse files
committed
Implement BytesIO.peek()
1 parent f65497f commit 1e5e3ab

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
@@ -978,6 +978,14 @@ 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
988+
981989
def truncate(self, pos=None):
982990
if self.closed:
983991
raise ValueError("truncate on closed file")

Lib/test/test_memoryio.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,23 @@ def test_relative_seek(self):
517517
memio.seek(1, 1)
518518
self.assertEqual(memio.read(), buf[1:])
519519

520+
def test_peek(self):
521+
buf = self.buftype("1234567890")
522+
memio = self.ioclass(buf)
523+
524+
self.assertEqual(memio.peek(1), buf[:1])
525+
self.assertEqual(memio.peek(1), buf[:1])
526+
self.assertEqual(memio.peek(), buf)
527+
self.assertEqual(memio.peek(0), buf)
528+
memio.read(1)
529+
self.assertEqual(memio.peek(1), buf[1:2])
530+
self.assertEqual(memio.peek(), buf[1:])
531+
self.assertEqual(memio.peek(42), buf[1:])
532+
memio.read()
533+
self.assertEqual(memio.peek(1), self.EOF)
534+
memio.close()
535+
self.assertRaises(ValueError, memio.peek)
536+
520537
def test_unicode(self):
521538
memio = self.ioclass()
522539

Modules/_io/bytesio.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,42 @@ _io_BytesIO_read1_impl(bytesio *self, Py_ssize_t size)
462462
return _io_BytesIO_read_impl(self, size);
463463
}
464464

465+
466+
/*[clinic input]
467+
_io.BytesIO.peek
468+
size: Py_ssize_t(accept={int, NoneType}) = -1
469+
/
470+
471+
Return bytes from the stream without advancing the position.
472+
473+
Return an empty bytes object at EOF.
474+
[clinic start generated code]*/
475+
476+
static PyObject *
477+
_io_BytesIO_peek_impl(bytesio *self, Py_ssize_t size)
478+
/*[clinic end generated code: output=fa4d8ce28b35db9b input=afc80e71b37e7c59]*/
479+
{
480+
Py_ssize_t n;
481+
const char *output;
482+
483+
CHECK_CLOSED(self);
484+
485+
/* adjust invalid sizes */
486+
n = self->string_size - self->pos;
487+
if (size < 1 || size > n) {
488+
size = n;
489+
if (size < 0)
490+
size = 0;
491+
}
492+
493+
assert(self->buf != NULL);
494+
assert(size <= self->string_size);
495+
output = PyBytes_AS_STRING(self->buf) + self->pos;
496+
return PyBytes_FromStringAndSize(output, size);
497+
}
498+
499+
500+
465501
/*[clinic input]
466502
_io.BytesIO.readline
467503
size: Py_ssize_t(accept={int, NoneType}) = -1
@@ -1019,6 +1055,7 @@ static struct PyMethodDef bytesio_methods[] = {
10191055
_IO_BYTESIO_READLINE_METHODDEF
10201056
_IO_BYTESIO_READLINES_METHODDEF
10211057
_IO_BYTESIO_READ_METHODDEF
1058+
_IO_BYTESIO_PEEK_METHODDEF
10221059
_IO_BYTESIO_GETBUFFER_METHODDEF
10231060
_IO_BYTESIO_GETVALUE_METHODDEF
10241061
_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)