summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCharles-François Natali <neologix@free.fr>2011-06-08 17:18:14 (GMT)
committerCharles-François Natali <neologix@free.fr>2011-06-08 17:18:14 (GMT)
commit4dd453c6aab315954f19bf0b2f1541c2b37d8e34 (patch)
tree6123dfbe0ffc22f81ca942e357e128f36216ab29
parentdd696496605883a44da983ad81e55a01e996a004 (diff)
downloadcpython-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.rst12
-rw-r--r--Lib/test/test_mmap.py29
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/mmapmodule.c26
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)))
diff --git a/Misc/ACKS b/Misc/ACKS
index 08fc572..900fae7 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -548,6 +548,7 @@ Vincent Legoll
Kip Lehman
Joerg Lehmann
Robert Lehmann
+Petri Lehtinen
Luke Kenneth Casson Leighton
Marc-Andre Lemburg
John Lenton
diff --git a/Misc/NEWS b/Misc/NEWS
index 8a70ce9..1995b14 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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 */