gh-111835: Add seekable method to mmap.mmap (gh-111852)

This commit is contained in:
Donghee Na 2023-11-09 11:13:35 +00:00 committed by GitHub
parent 30ec968bef
commit 6046aec377
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 40 additions and 12 deletions

View file

@ -285,6 +285,14 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
values are ``os.SEEK_CUR`` or ``1`` (seek relative to the current values are ``os.SEEK_CUR`` or ``1`` (seek relative to the current
position) and ``os.SEEK_END`` or ``2`` (seek relative to the file's end). position) and ``os.SEEK_END`` or ``2`` (seek relative to the file's end).
.. versionchanged:: 3.13
Return the new absolute position instead of ``None``.
.. method:: seekable()
Return whether the file supports seeking, and the return value is always ``True``.
.. versionadded:: 3.13
.. method:: size() .. method:: size()

View file

@ -198,6 +198,14 @@ ipaddress
* Add the :attr:`ipaddress.IPv4Address.ipv6_mapped` property, which returns the IPv4-mapped IPv6 address. * Add the :attr:`ipaddress.IPv4Address.ipv6_mapped` property, which returns the IPv4-mapped IPv6 address.
(Contributed by Charles Machalow in :gh:`109466`.) (Contributed by Charles Machalow in :gh:`109466`.)
mmap
----
* The :class:`mmap.mmap` class now has an :meth:`~mmap.mmap.seekable` method
that can be used where it requires a file-like object with seekable and
the :meth:`~mmap.mmap.seek` method return the new absolute position.
(Contributed by Donghee Na and Sylvie Liberman in :gh:`111835`.)
opcode opcode
------ ------

View file

@ -93,11 +93,12 @@ class MmapTests(unittest.TestCase):
self.assertEqual(end, PAGESIZE + 6) self.assertEqual(end, PAGESIZE + 6)
# test seeking around (try to overflow the seek implementation) # test seeking around (try to overflow the seek implementation)
m.seek(0,0) self.assertTrue(m.seekable())
self.assertEqual(m.seek(0, 0), 0)
self.assertEqual(m.tell(), 0) self.assertEqual(m.tell(), 0)
m.seek(42,1) self.assertEqual(m.seek(42, 1), 42)
self.assertEqual(m.tell(), 42) self.assertEqual(m.tell(), 42)
m.seek(0,2) self.assertEqual(m.seek(0, 2), len(m))
self.assertEqual(m.tell(), len(m)) self.assertEqual(m.tell(), len(m))
# Try to seek to negative position... # Try to seek to negative position...
@ -162,7 +163,7 @@ class MmapTests(unittest.TestCase):
# Ensuring that readonly mmap can't be write() to # Ensuring that readonly mmap can't be write() to
try: try:
m.seek(0,0) m.seek(0, 0)
m.write(b'abc') m.write(b'abc')
except TypeError: except TypeError:
pass pass
@ -171,7 +172,7 @@ class MmapTests(unittest.TestCase):
# Ensuring that readonly mmap can't be write_byte() to # Ensuring that readonly mmap can't be write_byte() to
try: try:
m.seek(0,0) m.seek(0, 0)
m.write_byte(b'd') m.write_byte(b'd')
except TypeError: except TypeError:
pass pass

View file

@ -0,0 +1,4 @@
The :class:`mmap.mmap` class now has an :meth:`~mmap.mmap.seekable` method
that can be used where it requires a file-like object with seekable and
the :meth:`~mmap.mmap.seek` method return the new absolute position.
Patch by Donghee Na.

View file

@ -171,7 +171,7 @@ mmap_object_dealloc(mmap_object *m_obj)
} }
static PyObject * static PyObject *
mmap_close_method(mmap_object *self, PyObject *unused) mmap_close_method(mmap_object *self, PyObject *Py_UNUSED(ignored))
{ {
if (self->exports > 0) { if (self->exports > 0) {
PyErr_SetString(PyExc_BufferError, "cannot close "\ PyErr_SetString(PyExc_BufferError, "cannot close "\
@ -260,7 +260,7 @@ do { \
static PyObject * static PyObject *
mmap_read_byte_method(mmap_object *self, mmap_read_byte_method(mmap_object *self,
PyObject *unused) PyObject *Py_UNUSED(ignored))
{ {
CHECK_VALID(NULL); CHECK_VALID(NULL);
if (self->pos >= self->size) { if (self->pos >= self->size) {
@ -272,7 +272,7 @@ mmap_read_byte_method(mmap_object *self,
static PyObject * static PyObject *
mmap_read_line_method(mmap_object *self, mmap_read_line_method(mmap_object *self,
PyObject *unused) PyObject *Py_UNUSED(ignored))
{ {
Py_ssize_t remaining; Py_ssize_t remaining;
char *start, *eol; char *start, *eol;
@ -460,7 +460,7 @@ mmap_write_byte_method(mmap_object *self,
static PyObject * static PyObject *
mmap_size_method(mmap_object *self, mmap_size_method(mmap_object *self,
PyObject *unused) PyObject *Py_UNUSED(ignored))
{ {
CHECK_VALID(NULL); CHECK_VALID(NULL);
@ -657,7 +657,7 @@ mmap_resize_method(mmap_object *self,
} }
static PyObject * static PyObject *
mmap_tell_method(mmap_object *self, PyObject *unused) mmap_tell_method(mmap_object *self, PyObject *Py_UNUSED(ignored))
{ {
CHECK_VALID(NULL); CHECK_VALID(NULL);
return PyLong_FromSize_t(self->pos); return PyLong_FromSize_t(self->pos);
@ -729,7 +729,7 @@ mmap_seek_method(mmap_object *self, PyObject *args)
if (where > self->size || where < 0) if (where > self->size || where < 0)
goto onoutofrange; goto onoutofrange;
self->pos = where; self->pos = where;
Py_RETURN_NONE; return PyLong_FromSsize_t(self->pos);
} }
onoutofrange: onoutofrange:
@ -737,6 +737,12 @@ mmap_seek_method(mmap_object *self, PyObject *args)
return NULL; return NULL;
} }
static PyObject *
mmap_seekable_method(mmap_object *self, PyObject *Py_UNUSED(ignored))
{
Py_RETURN_TRUE;
}
static PyObject * static PyObject *
mmap_move_method(mmap_object *self, PyObject *args) mmap_move_method(mmap_object *self, PyObject *args)
{ {
@ -835,7 +841,7 @@ mmap__repr__method(PyObject *self)
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
static PyObject * static PyObject *
mmap__sizeof__method(mmap_object *self, void *unused) mmap__sizeof__method(mmap_object *self, void *Py_UNUSED(ignored))
{ {
size_t res = _PyObject_SIZE(Py_TYPE(self)); size_t res = _PyObject_SIZE(Py_TYPE(self));
if (self->tagname) { if (self->tagname) {
@ -905,6 +911,7 @@ static struct PyMethodDef mmap_object_methods[] = {
{"readline", (PyCFunction) mmap_read_line_method, METH_NOARGS}, {"readline", (PyCFunction) mmap_read_line_method, METH_NOARGS},
{"resize", (PyCFunction) mmap_resize_method, METH_VARARGS}, {"resize", (PyCFunction) mmap_resize_method, METH_VARARGS},
{"seek", (PyCFunction) mmap_seek_method, METH_VARARGS}, {"seek", (PyCFunction) mmap_seek_method, METH_VARARGS},
{"seekable", (PyCFunction) mmap_seekable_method, METH_NOARGS},
{"size", (PyCFunction) mmap_size_method, METH_NOARGS}, {"size", (PyCFunction) mmap_size_method, METH_NOARGS},
{"tell", (PyCFunction) mmap_tell_method, METH_NOARGS}, {"tell", (PyCFunction) mmap_tell_method, METH_NOARGS},
{"write", (PyCFunction) mmap_write_method, METH_VARARGS}, {"write", (PyCFunction) mmap_write_method, METH_VARARGS},