[Python-checkins] cpython (3.5): Issue #15944: memoryview: Allow arbitrary formats when casting to bytes.

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


https://hg.python.org/cpython/rev/e33f2b8b937f
changeset: 97325:e33f2b8b937f
branch: 3.5
parent: 97323:6a1c2c7b0ee0
user: Stefan Krah <skrah at bytereef.org>
date: Sat Aug 08 13:38:10 2015 +0200
summary:
 Issue #15944: memoryview: Allow arbitrary formats when casting to bytes.
Original patch by Martin Panter.
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
@@ -98,6 +98,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

AltStyle によって変換されたページ (->オリジナル) /