Unverified Kaydet (Commit) d08ea704 authored tarafından Stefan Krah's avatar Stefan Krah Kaydeden (comit) GitHub

bpo-35845: Add order={'C', 'F', 'A'} parameter to memoryview.tobytes(). (#11730)

üst 4860f01a
...@@ -3600,7 +3600,7 @@ copying. ...@@ -3600,7 +3600,7 @@ copying.
Previous versions compared the raw memory disregarding the item format Previous versions compared the raw memory disregarding the item format
and the logical array structure. and the logical array structure.
.. method:: tobytes() .. method:: tobytes(order=None)
Return the data in the buffer as a bytestring. This is equivalent to Return the data in the buffer as a bytestring. This is equivalent to
calling the :class:`bytes` constructor on the memoryview. :: calling the :class:`bytes` constructor on the memoryview. ::
...@@ -3616,6 +3616,13 @@ copying. ...@@ -3616,6 +3616,13 @@ copying.
supports all format strings, including those that are not in supports all format strings, including those that are not in
:mod:`struct` module syntax. :mod:`struct` module syntax.
.. versionadded:: 3.8
*Order* can be {'C', 'F', 'A'}. When *order* is 'C' or 'F', the data
of the original array is converted to C or Fortran order. For contiguous
views, 'A' returns an exact copy of the physical memory. In particular,
in-memory Fortran order is preserved. For non-contiguous views, the
data is converted to C first. *order=None* is the same as *order='C'*.
.. method:: hex() .. method:: hex()
Return a string object containing two hexadecimal digits for each Return a string object containing two hexadecimal digits for each
......
...@@ -893,6 +893,15 @@ class TestBufferProtocol(unittest.TestCase): ...@@ -893,6 +893,15 @@ class TestBufferProtocol(unittest.TestCase):
y = ndarray(initlst, shape=shape, flags=ro, format=fmt) y = ndarray(initlst, shape=shape, flags=ro, format=fmt)
self.assertEqual(memoryview(y), memoryview(result)) self.assertEqual(memoryview(y), memoryview(result))
contig_bytes = memoryview(result).tobytes()
self.assertEqual(contig_bytes, contig)
contig_bytes = memoryview(result).tobytes(order=None)
self.assertEqual(contig_bytes, contig)
contig_bytes = memoryview(result).tobytes(order='C')
self.assertEqual(contig_bytes, contig)
# To 'F' # To 'F'
contig = py_buffer_to_contiguous(result, 'F', PyBUF_FULL_RO) contig = py_buffer_to_contiguous(result, 'F', PyBUF_FULL_RO)
self.assertEqual(len(contig), nmemb * itemsize) self.assertEqual(len(contig), nmemb * itemsize)
...@@ -905,6 +914,9 @@ class TestBufferProtocol(unittest.TestCase): ...@@ -905,6 +914,9 @@ class TestBufferProtocol(unittest.TestCase):
format=fmt) format=fmt)
self.assertEqual(memoryview(y), memoryview(result)) self.assertEqual(memoryview(y), memoryview(result))
contig_bytes = memoryview(result).tobytes(order='F')
self.assertEqual(contig_bytes, contig)
# To 'A' # To 'A'
contig = py_buffer_to_contiguous(result, 'A', PyBUF_FULL_RO) contig = py_buffer_to_contiguous(result, 'A', PyBUF_FULL_RO)
self.assertEqual(len(contig), nmemb * itemsize) self.assertEqual(len(contig), nmemb * itemsize)
...@@ -917,6 +929,9 @@ class TestBufferProtocol(unittest.TestCase): ...@@ -917,6 +929,9 @@ class TestBufferProtocol(unittest.TestCase):
y = ndarray(initlst, shape=shape, flags=f|ro, format=fmt) y = ndarray(initlst, shape=shape, flags=f|ro, format=fmt)
self.assertEqual(memoryview(y), memoryview(result)) self.assertEqual(memoryview(y), memoryview(result))
contig_bytes = memoryview(result).tobytes(order='A')
self.assertEqual(contig_bytes, contig)
if is_memoryview_format(fmt): if is_memoryview_format(fmt):
try: try:
m = memoryview(result) m = memoryview(result)
......
...@@ -2120,22 +2120,39 @@ memory_tolist(PyMemoryViewObject *mv, PyObject *noargs) ...@@ -2120,22 +2120,39 @@ memory_tolist(PyMemoryViewObject *mv, PyObject *noargs)
} }
static PyObject * static PyObject *
memory_tobytes(PyMemoryViewObject *self, PyObject *dummy) memory_tobytes(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
{ {
static char *kwlist[] = {"order", NULL};
Py_buffer *src = VIEW_ADDR(self); Py_buffer *src = VIEW_ADDR(self);
PyObject *bytes = NULL; char *order = NULL;
char ord = 'C';
PyObject *bytes;
CHECK_RELEASED(self); CHECK_RELEASED(self);
if (MV_C_CONTIGUOUS(self->flags)) { if (!PyArg_ParseTupleAndKeywords(args, kwds, "|z", kwlist, &order)) {
return PyBytes_FromStringAndSize(src->buf, src->len); return NULL;
}
if (order) {
if (strcmp(order, "F") == 0) {
ord = 'F';
}
else if (strcmp(order, "A") == 0) {
ord = 'A';
}
else if (strcmp(order, "C") != 0) {
PyErr_SetString(PyExc_ValueError,
"order must be 'C', 'F' or 'A'");
return NULL;
}
} }
bytes = PyBytes_FromStringAndSize(NULL, src->len); bytes = PyBytes_FromStringAndSize(NULL, src->len);
if (bytes == NULL) if (bytes == NULL)
return NULL; return NULL;
if (buffer_to_contiguous(PyBytes_AS_STRING(bytes), src, 'C') < 0) { if (PyBuffer_ToContiguous(PyBytes_AS_STRING(bytes), src, src->len, ord) < 0) {
Py_DECREF(bytes); Py_DECREF(bytes);
return NULL; return NULL;
} }
...@@ -2156,10 +2173,15 @@ memory_hex(PyMemoryViewObject *self, PyObject *dummy) ...@@ -2156,10 +2173,15 @@ memory_hex(PyMemoryViewObject *self, PyObject *dummy)
return _Py_strhex(src->buf, src->len); return _Py_strhex(src->buf, src->len);
} }
bytes = memory_tobytes(self, dummy); bytes = PyBytes_FromStringAndSize(NULL, src->len);
if (bytes == NULL) if (bytes == NULL)
return NULL; return NULL;
if (PyBuffer_ToContiguous(PyBytes_AS_STRING(bytes), src, src->len, 'C') < 0) {
Py_DECREF(bytes);
return NULL;
}
ret = _Py_strhex(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes)); ret = _Py_strhex(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
Py_DECREF(bytes); Py_DECREF(bytes);
...@@ -3061,9 +3083,13 @@ PyDoc_STRVAR(memory_release_doc, ...@@ -3061,9 +3083,13 @@ PyDoc_STRVAR(memory_release_doc,
\n\ \n\
Release the underlying buffer exposed by the memoryview object."); Release the underlying buffer exposed by the memoryview object.");
PyDoc_STRVAR(memory_tobytes_doc, PyDoc_STRVAR(memory_tobytes_doc,
"tobytes($self, /)\n--\n\ "tobytes($self, /, order=None)\n--\n\
\n\ \n\
Return the data in the buffer as a byte string."); Return the data in the buffer as a byte string. Order can be {'C', 'F', 'A'}.\n\
When order is 'C' or 'F', the data of the original array is converted to C or\n\
Fortran order. For contiguous views, 'A' returns an exact copy of the physical\n\
memory. In particular, in-memory Fortran order is preserved. For non-contiguous\n\
views, the data is converted to C first. order=None is the same as order='C'.");
PyDoc_STRVAR(memory_hex_doc, PyDoc_STRVAR(memory_hex_doc,
"hex($self, /)\n--\n\ "hex($self, /)\n--\n\
\n\ \n\
...@@ -3083,7 +3109,7 @@ Return a readonly version of the memoryview."); ...@@ -3083,7 +3109,7 @@ Return a readonly version of the memoryview.");
static PyMethodDef memory_methods[] = { static PyMethodDef memory_methods[] = {
{"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc}, {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc},
{"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, memory_tobytes_doc}, {"tobytes", (PyCFunction)memory_tobytes, METH_VARARGS|METH_KEYWORDS, memory_tobytes_doc},
{"hex", (PyCFunction)memory_hex, METH_NOARGS, memory_hex_doc}, {"hex", (PyCFunction)memory_hex, METH_NOARGS, memory_hex_doc},
{"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc}, {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc},
{"cast", (PyCFunction)(void(*)(void))memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc}, {"cast", (PyCFunction)(void(*)(void))memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment