[Python-checkins] cpython (merge 3.5 -> default): Merge #15944.

stefan.krah python-checkins at python.org
Sat Aug 8 13:39:40 CEST 2015


https://hg.python.org/cpython/rev/c7c4b8411037
changeset:   97326:c7c4b8411037
parent:      97324:b35df92f69e4
parent:      97325:e33f2b8b937f
user:        Stefan Krah <skrah at bytereef.org>
date:        Sat Aug 08 13:38:59 2015 +0200
summary:
  Merge #15944.

files:
  Doc/library/stdtypes.rst    |   5 +++-
  Lib/test/test_buffer.py     |  29 +++++++++++++++++++++++-
  Lib/test/test_memoryview.py |  21 ++++++++++++++++++
  Misc/NEWS                   |   3 ++
  Objects/memoryobject.c      |  10 +------
  5 files changed, 57 insertions(+), 11 deletions(-)


diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst
--- a/Doc/library/stdtypes.rst
+++ b/Doc/library/stdtypes.rst
@@ -3564,7 +3564,7 @@
       the buffer itself is not copied. Supported casts are 1D -> C-contiguous
       and C-contiguous -> 1D.
 
-      Both formats are restricted to single element native formats in
+      The destination format is restricted to a single element native format in
       :mod:`struct` syntax. One of the formats must be a byte format
       ('B', 'b' or 'c'). The byte length of the result must be the same
       as the original length.
@@ -3645,6 +3645,9 @@
 
       .. versionadded:: 3.3
 
+      .. versionchanged:: 3.5
+         The source format is no longer restricted when casting to a byte view.
+
    There are also several readonly attributes available:
 
    .. attribute:: obj
diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py
--- a/Lib/test/test_buffer.py
+++ b/Lib/test/test_buffer.py
@@ -2559,8 +2559,7 @@
             ex = ndarray(sitems, shape=[1], format=sfmt)
             msrc = memoryview(ex)
             for dfmt, _, _ in iter_format(1):
-                if (not is_memoryview_format(sfmt) or
-                    not is_memoryview_format(dfmt)):
+                if not is_memoryview_format(dfmt):
                     self.assertRaises(ValueError, msrc.cast, dfmt,
                                       [32//dsize])
                 else:
@@ -2773,6 +2772,32 @@
                                 ndim=ndim, shape=shape, strides=strides,
                                 lst=lst, cast=True)
 
+        if ctypes:
+            # format: "T{>l:x:>d:y:}"
+            class BEPoint(ctypes.BigEndianStructure):
+                _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_double)]
+            point = BEPoint(100, 200.1)
+            m1 = memoryview(point)
+            m2 = m1.cast('B')
+            self.assertEqual(m2.obj, point)
+            self.assertEqual(m2.itemsize, 1)
+            self.assertEqual(m2.readonly, 0)
+            self.assertEqual(m2.ndim, 1)
+            self.assertEqual(m2.shape, (m2.nbytes,))
+            self.assertEqual(m2.strides, (1,))
+            self.assertEqual(m2.suboffsets, ())
+
+            x = ctypes.c_double(1.2)
+            m1 = memoryview(x)
+            m2 = m1.cast('c')
+            self.assertEqual(m2.obj, x)
+            self.assertEqual(m2.itemsize, 1)
+            self.assertEqual(m2.readonly, 0)
+            self.assertEqual(m2.ndim, 1)
+            self.assertEqual(m2.shape, (m2.nbytes,))
+            self.assertEqual(m2.strides, (1,))
+            self.assertEqual(m2.suboffsets, ())
+
     def test_memoryview_tolist(self):
 
         # Most tolist() tests are in self.verify() etc.
diff --git a/Lib/test/test_memoryview.py b/Lib/test/test_memoryview.py
--- a/Lib/test/test_memoryview.py
+++ b/Lib/test/test_memoryview.py
@@ -492,5 +492,26 @@
     pass
 
 
+class OtherTest(unittest.TestCase):
+    def test_ctypes_cast(self):
+        # Issue 15944: Allow all source formats when casting to bytes.
+        ctypes = test.support.import_module("ctypes")
+        p6 = bytes(ctypes.c_double(0.6))
+
+        d = ctypes.c_double()
+        m = memoryview(d).cast("B")
+        m[:2] = p6[:2]
+        m[2:] = p6[2:]
+        self.assertEqual(d.value, 0.6)
+
+        for format in "Bbc":
+            with self.subTest(format):
+                d = ctypes.c_double()
+                m = memoryview(d).cast(format)
+                m[:2] = memoryview(p6).cast(format)[:2]
+                m[2:] = memoryview(p6).cast(format)[2:]
+                self.assertEqual(d.value, 0.6)
+
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -117,6 +117,9 @@
 - Issue #24687: Plug refleak on SyntaxError in function parameters
   annotations.
 
+- Issue #15944: memoryview: Allow arbitrary formats when casting to bytes.
+  Patch by Martin Panter.
+
 Library
 -------
 
diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c
--- a/Objects/memoryobject.c
+++ b/Objects/memoryobject.c
@@ -1197,13 +1197,6 @@
     assert(view->strides == mv->ob_array + view->ndim);
     assert(view->suboffsets == mv->ob_array + 2*view->ndim);
 
-    if (get_native_fmtchar(&srcchar, view->format) < 0) {
-        PyErr_SetString(PyExc_ValueError,
-            "memoryview: source format must be a native single character "
-            "format prefixed with an optional '@'");
-        return ret;
-    }
-
     asciifmt = PyUnicode_AsASCIIString(format);
     if (asciifmt == NULL)
         return ret;
@@ -1216,7 +1209,8 @@
         goto out;
     }
 
-    if (!IS_BYTE_FORMAT(srcchar) && !IS_BYTE_FORMAT(destchar)) {
+    if ((get_native_fmtchar(&srcchar, view->format) < 0 ||
+         !IS_BYTE_FORMAT(srcchar)) && !IS_BYTE_FORMAT(destchar)) {
         PyErr_SetString(PyExc_TypeError,
             "memoryview: cannot cast between two non-byte formats");
         goto out;

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list