]> granicus.if.org Git - python/commitdiff
Issue #12021: Make mmap's read() method argument optional. Patch by Petri
authorCharles-François Natali <neologix@free.fr>
Wed, 8 Jun 2011 17:18:14 +0000 (19:18 +0200)
committerCharles-François Natali <neologix@free.fr>
Wed, 8 Jun 2011 17:18:14 +0000 (19:18 +0200)
Lehtinen.

Doc/library/mmap.rst
Lib/test/test_mmap.py
Misc/ACKS
Misc/NEWS
Modules/mmapmodule.c

index 7a901c93f7e0f14b1c3d56fe3302fada5ca0cc3a..7708028d9726ab0a0bb353230540bcf486dc5331 100644 (file)
@@ -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()
 
index 712378b4a62851d9d23d30582f72680c86550929..4bbb19b99ede5ba2e6e598cc784ac299dade42e4 100644 (file)
@@ -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)))
index 08fc57264638363f35a182a84eb94a649fc198cf..900fae705ac1c6cfc2acab1eeaaa5333c8983221 100644 (file)
--- 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
index 8a70ce90f7865b70caed435e425e8b122b48577b..1995b14158dbf4432c2f6af0d42f376c7de20e74 100644 (file)
--- 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.
index 38f61577681cad1f43567aa3f75d023e61d789a6..ab12e2c54c5f99e81f80b11362a66f98aa6d436f 100644 (file)
@@ -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 */