Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4dd453c

Browse files
author
Charles-François Natali
committed
Issue python#12021: Make mmap's read() method argument optional. Patch by Petri
Lehtinen.
1 parent dd69649 commit 4dd453c

5 files changed

Lines changed: 65 additions & 6 deletions

File tree

Doc/library/mmap.rst

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,12 +190,16 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
190190
move will raise a :exc:`TypeError` exception.
191191

192192

193-
.. method:: read(num)
193+
.. method:: read([n])
194194

195-
Return a :class:`bytes` containing up to *num* bytes starting from the
196-
current file position; the file position is updated to point after the
197-
bytes that were returned.
195+
Return a :class:`bytes` containing up to *n* bytes starting from the
196+
current file position. If the argument is omitted, *None* or negative,
197+
return all bytes from the current file position to the end of the
198+
mapping. The file position is updated to point after the bytes that were
199+
returned.
198200

201+
.. versionchanged:: 3.3
202+
Argument can be omitted or *None*.
199203

200204
.. method:: read_byte()
201205

Lib/test/test_mmap.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,35 @@ def test_anonymous(self):
417417
m[x] = b
418418
self.assertEqual(m[x], b)
419419

420+
def test_read_all(self):
421+
m = mmap.mmap(-1, 16)
422+
self.addCleanup(m.close)
423+
424+
# With no parameters, or None or a negative argument, reads all
425+
m.write(bytes(range(16)))
426+
m.seek(0)
427+
self.assertEqual(m.read(), bytes(range(16)))
428+
m.seek(8)
429+
self.assertEqual(m.read(), bytes(range(8, 16)))
430+
m.seek(16)
431+
self.assertEqual(m.read(), b'')
432+
m.seek(3)
433+
self.assertEqual(m.read(None), bytes(range(3, 16)))
434+
m.seek(4)
435+
self.assertEqual(m.read(-1), bytes(range(4, 16)))
436+
m.seek(5)
437+
self.assertEqual(m.read(-2), bytes(range(5, 16)))
438+
m.seek(9)
439+
self.assertEqual(m.read(-42), bytes(range(9, 16)))
440+
441+
def test_read_invalid_arg(self):
442+
m = mmap.mmap(-1, 16)
443+
self.addCleanup(m.close)
444+
445+
self.assertRaises(TypeError, m.read, 'foo')
446+
self.assertRaises(TypeError, m.read, 5.5)
447+
self.assertRaises(TypeError, m.read, [1, 2, 3])
448+
420449
def test_extended_getslice(self):
421450
# Test extended slicing by comparing with list slicing.
422451
s = bytes(reversed(range(256)))

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,7 @@ Vincent Legoll
548548
Kip Lehman
549549
Joerg Lehmann
550550
Robert Lehmann
551+
Petri Lehtinen
551552
Luke Kenneth Casson Leighton
552553
Marc-Andre Lemburg
553554
John Lenton

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ Core and Builtins
187187
Library
188188
-------
189189

190+
- Issue #12021: Make mmap's read() method argument optional. Patch by Petri
191+
Lehtinen.
192+
190193
- Issue #9205: concurrent.futures.ProcessPoolExecutor now detects killed
191194
children and raises BrokenProcessPool in such a situation. Previously it
192195
would reliably freeze/deadlock.

Modules/mmapmodule.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,15 +240,37 @@ mmap_read_line_method(mmap_object *self,
240240
return result;
241241
}
242242

243+
/* Basically the "n" format code with the ability to turn None into -1. */
244+
static int
245+
mmap_convert_ssize_t(PyObject *obj, void *result) {
246+
Py_ssize_t limit;
247+
if (obj == Py_None) {
248+
limit = -1;
249+
}
250+
else if (PyNumber_Check(obj)) {
251+
limit = PyNumber_AsSsize_t(obj, PyExc_OverflowError);
252+
if (limit == -1 && PyErr_Occurred())
253+
return 0;
254+
}
255+
else {
256+
PyErr_Format(PyExc_TypeError,
257+
"integer argument expected, got '%.200s'",
258+
Py_TYPE(obj)->tp_name);
259+
return 0;
260+
}
261+
*((Py_ssize_t *)result) = limit;
262+
return 1;
263+
}
264+
243265
static PyObject *
244266
mmap_read_method(mmap_object *self,
245267
PyObject *args)
246268
{
247-
Py_ssize_t num_bytes, n;
269+
Py_ssize_t num_bytes = -1, n;
248270
PyObject *result;
249271

250272
CHECK_VALID(NULL);
251-
if (!PyArg_ParseTuple(args, "n:read", &num_bytes))
273+
if (!PyArg_ParseTuple(args, "|O&:read", mmap_convert_ssize_t, &num_bytes))
252274
return(NULL);
253275

254276
/* silently 'adjust' out-of-range requests */

0 commit comments

Comments
 (0)