mirror of https://github.com/python/cpython
Issue #15944: memoryview: Allow arbitrary formats when casting to bytes.
Original patch by Martin Panter.
This commit is contained in:
parent
917c2c3654
commit
0c51595a78
|
@ -3564,7 +3564,7 @@ copying.
|
||||||
the buffer itself is not copied. Supported casts are 1D -> C-contiguous
|
the buffer itself is not copied. Supported casts are 1D -> C-contiguous
|
||||||
and C-contiguous -> 1D.
|
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
|
: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
|
('B', 'b' or 'c'). The byte length of the result must be the same
|
||||||
as the original length.
|
as the original length.
|
||||||
|
@ -3645,6 +3645,9 @@ copying.
|
||||||
|
|
||||||
.. versionadded:: 3.3
|
.. 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:
|
There are also several readonly attributes available:
|
||||||
|
|
||||||
.. attribute:: obj
|
.. attribute:: obj
|
||||||
|
|
|
@ -2559,8 +2559,7 @@ class TestBufferProtocol(unittest.TestCase):
|
||||||
ex = ndarray(sitems, shape=[1], format=sfmt)
|
ex = ndarray(sitems, shape=[1], format=sfmt)
|
||||||
msrc = memoryview(ex)
|
msrc = memoryview(ex)
|
||||||
for dfmt, _, _ in iter_format(1):
|
for dfmt, _, _ in iter_format(1):
|
||||||
if (not is_memoryview_format(sfmt) or
|
if not is_memoryview_format(dfmt):
|
||||||
not is_memoryview_format(dfmt)):
|
|
||||||
self.assertRaises(ValueError, msrc.cast, dfmt,
|
self.assertRaises(ValueError, msrc.cast, dfmt,
|
||||||
[32//dsize])
|
[32//dsize])
|
||||||
else:
|
else:
|
||||||
|
@ -2773,6 +2772,32 @@ class TestBufferProtocol(unittest.TestCase):
|
||||||
ndim=ndim, shape=shape, strides=strides,
|
ndim=ndim, shape=shape, strides=strides,
|
||||||
lst=lst, cast=True)
|
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):
|
def test_memoryview_tolist(self):
|
||||||
|
|
||||||
# Most tolist() tests are in self.verify() etc.
|
# Most tolist() tests are in self.verify() etc.
|
||||||
|
|
|
@ -492,5 +492,26 @@ class ArrayMemorySliceSliceTest(unittest.TestCase,
|
||||||
pass
|
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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -98,6 +98,9 @@ Core and Builtins
|
||||||
- Issue #24687: Plug refleak on SyntaxError in function parameters
|
- Issue #24687: Plug refleak on SyntaxError in function parameters
|
||||||
annotations.
|
annotations.
|
||||||
|
|
||||||
|
- Issue #15944: memoryview: Allow arbitrary formats when casting to bytes.
|
||||||
|
Patch by Martin Panter.
|
||||||
|
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
|
|
@ -1197,13 +1197,6 @@ cast_to_1D(PyMemoryViewObject *mv, PyObject *format)
|
||||||
assert(view->strides == mv->ob_array + view->ndim);
|
assert(view->strides == mv->ob_array + view->ndim);
|
||||||
assert(view->suboffsets == mv->ob_array + 2*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);
|
asciifmt = PyUnicode_AsASCIIString(format);
|
||||||
if (asciifmt == NULL)
|
if (asciifmt == NULL)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1216,7 +1209,8 @@ cast_to_1D(PyMemoryViewObject *mv, PyObject *format)
|
||||||
goto out;
|
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,
|
PyErr_SetString(PyExc_TypeError,
|
||||||
"memoryview: cannot cast between two non-byte formats");
|
"memoryview: cannot cast between two non-byte formats");
|
||||||
goto out;
|
goto out;
|
||||||
|
|
Loading…
Reference in New Issue