Skip to content

Commit 6046aec

Browse files
authored
gh-111835: Add seekable method to mmap.mmap (gh-111852)
1 parent 30ec968 commit 6046aec

File tree

5 files changed

+40
-12
lines changed

5 files changed

+40
-12
lines changed

Doc/library/mmap.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,14 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
285285
values are ``os.SEEK_CUR`` or ``1`` (seek relative to the current
286286
position) and ``os.SEEK_END`` or ``2`` (seek relative to the file's end).
287287

288+
.. versionchanged:: 3.13
289+
Return the new absolute position instead of ``None``.
290+
291+
.. method:: seekable()
292+
293+
Return whether the file supports seeking, and the return value is always ``True``.
294+
295+
.. versionadded:: 3.13
288296

289297
.. method:: size()
290298

Doc/whatsnew/3.13.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,14 @@ ipaddress
198198
* Add the :attr:`ipaddress.IPv4Address.ipv6_mapped` property, which returns the IPv4-mapped IPv6 address.
199199
(Contributed by Charles Machalow in :gh:`109466`.)
200200

201+
mmap
202+
----
203+
204+
* The :class:`mmap.mmap` class now has an :meth:`~mmap.mmap.seekable` method
205+
that can be used where it requires a file-like object with seekable and
206+
the :meth:`~mmap.mmap.seek` method return the new absolute position.
207+
(Contributed by Donghee Na and Sylvie Liberman in :gh:`111835`.)
208+
201209
opcode
202210
------
203211

Lib/test/test_mmap.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,12 @@ def test_basic(self):
9393
self.assertEqual(end, PAGESIZE + 6)
9494

9595
# test seeking around (try to overflow the seek implementation)
96-
m.seek(0,0)
96+
self.assertTrue(m.seekable())
97+
self.assertEqual(m.seek(0, 0), 0)
9798
self.assertEqual(m.tell(), 0)
98-
m.seek(42,1)
99+
self.assertEqual(m.seek(42, 1), 42)
99100
self.assertEqual(m.tell(), 42)
100-
m.seek(0,2)
101+
self.assertEqual(m.seek(0, 2), len(m))
101102
self.assertEqual(m.tell(), len(m))
102103

103104
# Try to seek to negative position...
@@ -162,7 +163,7 @@ def test_access_parameter(self):
162163

163164
# Ensuring that readonly mmap can't be write() to
164165
try:
165-
m.seek(0,0)
166+
m.seek(0, 0)
166167
m.write(b'abc')
167168
except TypeError:
168169
pass
@@ -171,7 +172,7 @@ def test_access_parameter(self):
171172

172173
# Ensuring that readonly mmap can't be write_byte() to
173174
try:
174-
m.seek(0,0)
175+
m.seek(0, 0)
175176
m.write_byte(b'd')
176177
except TypeError:
177178
pass
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
The :class:`mmap.mmap` class now has an :meth:`~mmap.mmap.seekable` method
2+
that can be used where it requires a file-like object with seekable and
3+
the :meth:`~mmap.mmap.seek` method return the new absolute position.
4+
Patch by Donghee Na.

Modules/mmapmodule.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ mmap_object_dealloc(mmap_object *m_obj)
171171
}
172172

173173
static PyObject *
174-
mmap_close_method(mmap_object *self, PyObject *unused)
174+
mmap_close_method(mmap_object *self, PyObject *Py_UNUSED(ignored))
175175
{
176176
if (self->exports > 0) {
177177
PyErr_SetString(PyExc_BufferError, "cannot close "\
@@ -260,7 +260,7 @@ do { \
260260

261261
static PyObject *
262262
mmap_read_byte_method(mmap_object *self,
263-
PyObject *unused)
263+
PyObject *Py_UNUSED(ignored))
264264
{
265265
CHECK_VALID(NULL);
266266
if (self->pos >= self->size) {
@@ -272,7 +272,7 @@ mmap_read_byte_method(mmap_object *self,
272272

273273
static PyObject *
274274
mmap_read_line_method(mmap_object *self,
275-
PyObject *unused)
275+
PyObject *Py_UNUSED(ignored))
276276
{
277277
Py_ssize_t remaining;
278278
char *start, *eol;
@@ -460,7 +460,7 @@ mmap_write_byte_method(mmap_object *self,
460460

461461
static PyObject *
462462
mmap_size_method(mmap_object *self,
463-
PyObject *unused)
463+
PyObject *Py_UNUSED(ignored))
464464
{
465465
CHECK_VALID(NULL);
466466

@@ -657,7 +657,7 @@ mmap_resize_method(mmap_object *self,
657657
}
658658

659659
static PyObject *
660-
mmap_tell_method(mmap_object *self, PyObject *unused)
660+
mmap_tell_method(mmap_object *self, PyObject *Py_UNUSED(ignored))
661661
{
662662
CHECK_VALID(NULL);
663663
return PyLong_FromSize_t(self->pos);
@@ -729,14 +729,20 @@ mmap_seek_method(mmap_object *self, PyObject *args)
729729
if (where > self->size || where < 0)
730730
goto onoutofrange;
731731
self->pos = where;
732-
Py_RETURN_NONE;
732+
return PyLong_FromSsize_t(self->pos);
733733
}
734734

735735
onoutofrange:
736736
PyErr_SetString(PyExc_ValueError, "seek out of range");
737737
return NULL;
738738
}
739739

740+
static PyObject *
741+
mmap_seekable_method(mmap_object *self, PyObject *Py_UNUSED(ignored))
742+
{
743+
Py_RETURN_TRUE;
744+
}
745+
740746
static PyObject *
741747
mmap_move_method(mmap_object *self, PyObject *args)
742748
{
@@ -835,7 +841,7 @@ mmap__repr__method(PyObject *self)
835841

836842
#ifdef MS_WINDOWS
837843
static PyObject *
838-
mmap__sizeof__method(mmap_object *self, void *unused)
844+
mmap__sizeof__method(mmap_object *self, void *Py_UNUSED(ignored))
839845
{
840846
size_t res = _PyObject_SIZE(Py_TYPE(self));
841847
if (self->tagname) {
@@ -905,6 +911,7 @@ static struct PyMethodDef mmap_object_methods[] = {
905911
{"readline", (PyCFunction) mmap_read_line_method, METH_NOARGS},
906912
{"resize", (PyCFunction) mmap_resize_method, METH_VARARGS},
907913
{"seek", (PyCFunction) mmap_seek_method, METH_VARARGS},
914+
{"seekable", (PyCFunction) mmap_seekable_method, METH_NOARGS},
908915
{"size", (PyCFunction) mmap_size_method, METH_NOARGS},
909916
{"tell", (PyCFunction) mmap_tell_method, METH_NOARGS},
910917
{"write", (PyCFunction) mmap_write_method, METH_VARARGS},

0 commit comments

Comments
 (0)