diff options
author | Charles-François Natali <neologix@free.fr> | 2011-06-08 17:18:14 (GMT) |
---|---|---|
committer | Charles-François Natali <neologix@free.fr> | 2011-06-08 17:18:14 (GMT) |
commit | 4dd453c6aab315954f19bf0b2f1541c2b37d8e34 (patch) | |
tree | 6123dfbe0ffc22f81ca942e357e128f36216ab29 | |
parent | dd696496605883a44da983ad81e55a01e996a004 (diff) | |
download | cpython-4dd453c6aab315954f19bf0b2f1541c2b37d8e34.zip cpython-4dd453c6aab315954f19bf0b2f1541c2b37d8e34.tar.gz cpython-4dd453c6aab315954f19bf0b2f1541c2b37d8e34.tar.bz2 |
Issue #12021: Make mmap's read() method argument optional. Patch by Petri
Lehtinen.
-rw-r--r-- | Doc/library/mmap.rst | 12 | ||||
-rw-r--r-- | Lib/test/test_mmap.py | 29 | ||||
-rw-r--r-- | Misc/ACKS | 1 | ||||
-rw-r--r-- | Misc/NEWS | 3 | ||||
-rw-r--r-- | Modules/mmapmodule.c | 26 |
5 files changed, 65 insertions, 6 deletions
diff --git a/Doc/library/mmap.rst b/Doc/library/mmap.rst index 7a901c9..7708028 100644 --- a/Doc/library/mmap.rst +++ b/Doc/library/mmap.rst @@ -190,12 +190,16 @@ To map anonymous memory, -1 should be passed as the fileno along with the length move will raise a :exc:`TypeError` exception. - .. method:: read(num) + .. method:: read([n]) - Return a :class:`bytes` containing up to *num* bytes starting from the - current file position; the file position is updated to point after the - bytes that were returned. + Return a :class:`bytes` containing up to *n* bytes starting from the + current file position. If the argument is omitted, *None* or negative, + return all bytes from the current file position to the end of the + mapping. The file position is updated to point after the bytes that were + returned. + .. versionchanged:: 3.3 + Argument can be omitted or *None*. .. method:: read_byte() diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py index 712378b..4bbb19b 100644 --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -417,6 +417,35 @@ class MmapTests(unittest.TestCase): m[x] = b self.assertEqual(m[x], b) + def test_read_all(self): + m = mmap.mmap(-1, 16) + self.addCleanup(m.close) + + # With no parameters, or None or a negative argument, reads all + m.write(bytes(range(16))) + m.seek(0) + self.assertEqual(m.read(), bytes(range(16))) + m.seek(8) + self.assertEqual(m.read(), bytes(range(8, 16))) + m.seek(16) + self.assertEqual(m.read(), b'') + m.seek(3) + self.assertEqual(m.read(None), bytes(range(3, 16))) + m.seek(4) + self.assertEqual(m.read(-1), bytes(range(4, 16))) + m.seek(5) + self.assertEqual(m.read(-2), bytes(range(5, 16))) + m.seek(9) + self.assertEqual(m.read(-42), bytes(range(9, 16))) + + def test_read_invalid_arg(self): + m = mmap.mmap(-1, 16) + self.addCleanup(m.close) + + self.assertRaises(TypeError, m.read, 'foo') + self.assertRaises(TypeError, m.read, 5.5) + self.assertRaises(TypeError, m.read, [1, 2, 3]) + def test_extended_getslice(self): # Test extended slicing by comparing with list slicing. s = bytes(reversed(range(256))) @@ -548,6 +548,7 @@ Vincent Legoll Kip Lehman Joerg Lehmann Robert Lehmann +Petri Lehtinen Luke Kenneth Casson Leighton Marc-Andre Lemburg John Lenton @@ -187,6 +187,9 @@ Core and Builtins Library ------- +- Issue #12021: Make mmap's read() method argument optional. Patch by Petri + Lehtinen. + - Issue #9205: concurrent.futures.ProcessPoolExecutor now detects killed children and raises BrokenProcessPool in such a situation. Previously it would reliably freeze/deadlock. diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c index 38f6157..ab12e2c 100644 --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -240,15 +240,37 @@ mmap_read_line_method(mmap_object *self, return result; } +/* Basically the "n" format code with the ability to turn None into -1. */ +static int +mmap_convert_ssize_t(PyObject *obj, void *result) { + Py_ssize_t limit; + if (obj == Py_None) { + limit = -1; + } + else if (PyNumber_Check(obj)) { + limit = PyNumber_AsSsize_t(obj, PyExc_OverflowError); + if (limit == -1 && PyErr_Occurred()) + return 0; + } + else { + PyErr_Format(PyExc_TypeError, + "integer argument expected, got '%.200s'", + Py_TYPE(obj)->tp_name); + return 0; + } + *((Py_ssize_t *)result) = limit; + return 1; +} + static PyObject * mmap_read_method(mmap_object *self, PyObject *args) { - Py_ssize_t num_bytes, n; + Py_ssize_t num_bytes = -1, n; PyObject *result; CHECK_VALID(NULL); - if (!PyArg_ParseTuple(args, "n:read", &num_bytes)) + if (!PyArg_ParseTuple(args, "|O&:read", mmap_convert_ssize_t, &num_bytes)) return(NULL); /* silently 'adjust' out-of-range requests */ |