bpo-15913: Implement PyBuffer_SizeFromFormat() (GH-13873)
Implement PyBuffer_SizeFromFormat() function (previously documented but not implemented): call struct.calcsize().
This commit is contained in:
parent
18f8dcfa10
commit
9e66aba999
|
@ -462,10 +462,12 @@ Buffer-related functions
|
|||
:c:func:`PyObject_GetBuffer`.
|
||||
|
||||
|
||||
.. c:function:: Py_ssize_t PyBuffer_SizeFromFormat(const char *)
|
||||
.. c:function:: Py_ssize_t PyBuffer_SizeFromFormat(const char *format)
|
||||
|
||||
Return the implied :c:data:`~Py_buffer.itemsize` from :c:data:`~Py_buffer.format`.
|
||||
This function is not yet implemented.
|
||||
On error, raise an exception and return -1.
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
.. c:function:: int PyBuffer_IsContiguous(Py_buffer *view, char order)
|
||||
|
|
|
@ -243,7 +243,7 @@ PyAPI_FUNC(void *) PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices);
|
|||
|
||||
/* Return the implied itemsize of the data-format area from a
|
||||
struct-style description. */
|
||||
PyAPI_FUNC(int) PyBuffer_SizeFromFormat(const char *);
|
||||
PyAPI_FUNC(Py_ssize_t) PyBuffer_SizeFromFormat(const char *format);
|
||||
|
||||
/* Implementation in memoryobject.c */
|
||||
PyAPI_FUNC(int) PyBuffer_ToContiguous(void *buf, Py_buffer *view,
|
||||
|
|
|
@ -43,6 +43,11 @@ try:
|
|||
except ImportError:
|
||||
numpy_array = None
|
||||
|
||||
try:
|
||||
import _testcapi
|
||||
except ImportError:
|
||||
_testcapi = None
|
||||
|
||||
|
||||
SHORT_TEST = True
|
||||
|
||||
|
@ -4412,6 +4417,13 @@ class TestBufferProtocol(unittest.TestCase):
|
|||
x = ndarray([1,2,3], shape=[3], flags=ND_GETBUF_FAIL)
|
||||
self.assertRaises(BufferError, memoryview, x)
|
||||
|
||||
@support.cpython_only
|
||||
def test_pybuffer_size_from_format(self):
|
||||
# basic tests
|
||||
for format in ('', 'ii', '3s'):
|
||||
self.assertEqual(_testcapi.PyBuffer_SizeFromFormat(format),
|
||||
struct.calcsize(format))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
Implement :c:func:`PyBuffer_SizeFromFormat()` function (previously
|
||||
documented but not implemented): call :func:`struct.calcsize`.
|
||||
Patch by Joannah Nanjekye.
|
|
@ -3363,6 +3363,26 @@ getbuffer_with_null_view(PyObject* self, PyObject *obj)
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
/* PyBuffer_SizeFromFormat() */
|
||||
static PyObject *
|
||||
test_PyBuffer_SizeFromFormat(PyObject *self, PyObject *args)
|
||||
{
|
||||
const char *format;
|
||||
Py_ssize_t result;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s:test_PyBuffer_SizeFromFormat",
|
||||
&format)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = PyBuffer_SizeFromFormat(format);
|
||||
if (result == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PyLong_FromSsize_t(result);
|
||||
}
|
||||
|
||||
/* Test that the fatal error from not having a current thread doesn't
|
||||
cause an infinite loop. Run via Lib/test/test_capi.py */
|
||||
static PyObject *
|
||||
|
@ -5153,6 +5173,7 @@ static PyMethodDef TestMethods[] = {
|
|||
{"test_pep3118_obsolete_write_locks", (PyCFunction)test_pep3118_obsolete_write_locks, METH_NOARGS},
|
||||
#endif
|
||||
{"getbuffer_with_null_view", getbuffer_with_null_view, METH_O},
|
||||
{"PyBuffer_SizeFromFormat", test_PyBuffer_SizeFromFormat, METH_VARARGS},
|
||||
{"test_buildvalue_N", test_buildvalue_N, METH_NOARGS},
|
||||
{"get_args", get_args, METH_VARARGS},
|
||||
{"get_kwargs", (PyCFunction)(void(*)(void))get_kwargs, METH_VARARGS|METH_KEYWORDS},
|
||||
|
|
|
@ -495,6 +495,48 @@ _Py_add_one_to_index_C(int nd, Py_ssize_t *index, const Py_ssize_t *shape)
|
|||
}
|
||||
}
|
||||
|
||||
Py_ssize_t
|
||||
PyBuffer_SizeFromFormat(const char *format)
|
||||
{
|
||||
PyObject *structmodule = NULL;
|
||||
PyObject *calcsize = NULL;
|
||||
PyObject *res = NULL;
|
||||
PyObject *fmt = NULL;
|
||||
Py_ssize_t itemsize = -1;
|
||||
|
||||
structmodule = PyImport_ImportModule("struct");
|
||||
if (structmodule == NULL) {
|
||||
return itemsize;
|
||||
}
|
||||
|
||||
calcsize = PyObject_GetAttrString(structmodule, "calcsize");
|
||||
if (calcsize == NULL) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
fmt = PyUnicode_FromString(format);
|
||||
if (fmt == NULL) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
res = PyObject_CallFunctionObjArgs(calcsize, fmt, NULL);
|
||||
if (res == NULL) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
itemsize = PyLong_AsSsize_t(res);
|
||||
if (itemsize < 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
Py_DECREF(structmodule);
|
||||
Py_XDECREF(calcsize);
|
||||
Py_XDECREF(fmt);
|
||||
Py_XDECREF(res);
|
||||
return itemsize;
|
||||
}
|
||||
|
||||
int
|
||||
PyBuffer_FromContiguous(Py_buffer *view, void *buf, Py_ssize_t len, char fort)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue