Skip to content

Commit d4e849f

Browse files
committed
Implement BytesIO.peek()
1 parent a302a27 commit d4e849f

File tree

4 files changed

+99
-1
lines changed

4 files changed

+99
-1
lines changed

Lib/_pyio.py

+8
Original file line numberDiff line numberDiff line change
@@ -993,6 +993,14 @@ def tell(self):
993993
raise ValueError("tell on closed file")
994994
return self._pos
995995

996+
def peek(self, size=-1):
997+
pos = self.tell()
998+
if size == 0:
999+
size = -1
1000+
b = self.read(size)
1001+
self.seek(pos)
1002+
return b
1003+
9961004
def truncate(self, pos=None):
9971005
if self.closed:
9981006
raise ValueError("truncate on closed file")

Lib/test/test_memoryio.py

+17
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

+37
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,42 @@ _io_BytesIO_read1_impl(bytesio *self, Py_ssize_t size)
459459
return _io_BytesIO_read_impl(self, size);
460460
}
461461

462+
463+
/*[clinic input]
464+
_io.BytesIO.peek
465+
size: Py_ssize_t(accept={int, NoneType}) = -1
466+
/
467+
468+
Return bytes from the stream without advancing the position.
469+
470+
Return an empty bytes object at EOF.
471+
[clinic start generated code]*/
472+
473+
static PyObject *
474+
_io_BytesIO_peek_impl(bytesio *self, Py_ssize_t size)
475+
/*[clinic end generated code: output=fa4d8ce28b35db9b input=afc80e71b37e7c59]*/
476+
{
477+
Py_ssize_t n;
478+
const char *output;
479+
480+
CHECK_CLOSED(self);
481+
482+
/* adjust invalid sizes */
483+
n = self->string_size - self->pos;
484+
if (size < 1 || size > n) {
485+
size = n;
486+
if (size < 0)
487+
size = 0;
488+
}
489+
490+
assert(self->buf != NULL);
491+
assert(size <= self->string_size);
492+
output = PyBytes_AS_STRING(self->buf) + self->pos;
493+
return PyBytes_FromStringAndSize(output, size);
494+
}
495+
496+
497+
462498
/*[clinic input]
463499
_io.BytesIO.readline
464500
size: Py_ssize_t(accept={int, NoneType}) = -1
@@ -1014,6 +1050,7 @@ static struct PyMethodDef bytesio_methods[] = {
10141050
_IO_BYTESIO_READLINE_METHODDEF
10151051
_IO_BYTESIO_READLINES_METHODDEF
10161052
_IO_BYTESIO_READ_METHODDEF
1053+
_IO_BYTESIO_PEEK_METHODDEF
10171054
_IO_BYTESIO_GETBUFFER_METHODDEF
10181055
_IO_BYTESIO_GETVALUE_METHODDEF
10191056
_IO_BYTESIO_SEEK_METHODDEF

Modules/_io/clinic/bytesio.c.h

+37-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)