[Python-checkins] bpo-15913: Implement PyBuffer_SizeFromFormat() (GH-13873)

Victor Stinner webhook-mailer at python.org
Tue Aug 20 10:46:50 EDT 2019


https://github.com/python/cpython/commit/9e66aba99925eebacfe137d9deb0ef1fdbc2d5db
commit: 9e66aba99925eebacfe137d9deb0ef1fdbc2d5db
branch: master
author: Joannah Nanjekye <33177550+nanjekyejoannah at users.noreply.github.com>
committer: Victor Stinner <vstinner at redhat.com>
date: 2019-08-20T15:46:36+01:00
summary:

bpo-15913: Implement PyBuffer_SizeFromFormat() (GH-13873)

Implement PyBuffer_SizeFromFormat() function (previously
documented but not implemented): call struct.calcsize().

files:
A Misc/NEWS.d/next/Core and Builtins/2019-06-06-20-52-38.bpo-15913.5Sg5cv.rst
M Doc/c-api/buffer.rst
M Include/cpython/abstract.h
M Lib/test/test_buffer.py
M Modules/_testcapimodule.c
M Objects/abstract.c

diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst
old mode 100644
new mode 100755
index fdb8bd19d218..2536c743b247
--- a/Doc/c-api/buffer.rst
+++ b/Doc/c-api/buffer.rst
@@ -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)
diff --git a/Include/cpython/abstract.h b/Include/cpython/abstract.h
old mode 100644
new mode 100755
index 62a113fc00e2..04e4a9e7bd27
--- a/Include/cpython/abstract.h
+++ b/Include/cpython/abstract.h
@@ -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,
diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py
old mode 100644
new mode 100755
index 47413c03d663..5fa52bffc22b
--- a/Lib/test/test_buffer.py
+++ b/Lib/test/test_buffer.py
@@ -43,6 +43,11 @@
 except ImportError:
     numpy_array = None
 
+try:
+    import _testcapi
+except ImportError:
+    _testcapi = None
+
 
 SHORT_TEST = True
 
@@ -4412,6 +4417,13 @@ def test_issue_7385(self):
         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()
diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-06-06-20-52-38.bpo-15913.5Sg5cv.rst b/Misc/NEWS.d/next/Core and Builtins/2019-06-06-20-52-38.bpo-15913.5Sg5cv.rst
new file mode 100644
index 000000000000..0fbfcb37abb4
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2019-06-06-20-52-38.bpo-15913.5Sg5cv.rst	
@@ -0,0 +1,3 @@
+Implement :c:func:`PyBuffer_SizeFromFormat()` function (previously
+documented but not implemented): call :func:`struct.calcsize`.
+Patch by Joannah Nanjekye.
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
old mode 100644
new mode 100755
index 8a6e741d2810..84f2651641c7
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -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},
diff --git a/Objects/abstract.c b/Objects/abstract.c
old mode 100644
new mode 100755
index f93d73fa7571..3db56fab2c8d
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -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)
 {



More information about the Python-checkins mailing list