From 3bf3ff7888b525de57103665858407f850ad50c0 Mon Sep 17 00:00:00 2001 From: Joannah nanjekye Date: Thu, 6 Jun 2019 17:43:28 -0300 Subject: [PATCH 01/20] Add PyBuffer_SizeFromFormat --- Doc/c-api/buffer.rst | 3 +-- Include/cpython/abstract.h | 2 +- Objects/abstract.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) mode change 100644 => 100755 Doc/c-api/buffer.rst mode change 100644 => 100755 Include/cpython/abstract.h mode change 100644 => 100755 Objects/abstract.c diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst old mode 100644 new mode 100755 index 72d965053cfda3..bfb7df0722e7f9 --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -460,10 +460,9 @@ 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. .. 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 7ab2045923d83d..ab0954cd278a0c --- a/Include/cpython/abstract.h +++ b/Include/cpython/abstract.h @@ -206,7 +206,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(int) PyBuffer_SizeFromFormat(const char *format); /* Implementation in memoryobject.c */ PyAPI_FUNC(int) PyBuffer_ToContiguous(void *buf, Py_buffer *view, diff --git a/Objects/abstract.c b/Objects/abstract.c old mode 100644 new mode 100755 index 77d09143aa0764..d1a1e996dc5003 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -7,6 +7,11 @@ #include "longintrepr.h" +/* struct module */ +static PyObject *structmodule = NULL; +static PyObject *calcsize = NULL; + + /* Shorthands to return certain errors */ @@ -495,6 +500,30 @@ _Py_add_one_to_index_C(int nd, Py_ssize_t *index, const Py_ssize_t *shape) } } +int +PyBuffer_SizeFromFormat(const char *format) +{ + PyObject *result; + int size; + + structmodule = PyImport_ImportModule("struct"); + if (structmodule == NULL) + return NULL; + + calcsize = PyObject_GetAttrString(structmodule, "calcsize"); + if (calcsize == NULL) + return NULL; + + result = PyObject_CallFunctionObjArgs(calcsize, format, NULL); + Py_DECREF(calcsize); + if (result == NULL) + return -1; + size = _PyLong_AsInt(result); + Py_DECREF(result); + + return size; +} + int PyBuffer_FromContiguous(Py_buffer *view, void *buf, Py_ssize_t len, char fort) { From 74dd813a47bdc9c0c84c528dedccd50b7826ab93 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" Date: Thu, 6 Jun 2019 20:52:42 +0000 Subject: [PATCH 02/20] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Core and Builtins/2019-06-06-20-52-38.bpo-15913.5Sg5cv.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-06-06-20-52-38.bpo-15913.5Sg5cv.rst 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 00000000000000..c1b88823bd9b8e --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-06-06-20-52-38.bpo-15913.5Sg5cv.rst @@ -0,0 +1 @@ +`PyBuffer_SizeFromFormat()` now added. \ No newline at end of file From caa5b6835c14976ce3af9042d206d3876dbd083c Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye <33177550+nanjekyejoannah@users.noreply.github.com> Date: Thu, 6 Jun 2019 18:15:09 -0300 Subject: [PATCH 03/20] Mark version --- Doc/c-api/buffer.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst index bfb7df0722e7f9..46a1e0d96ae4a8 100755 --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -463,6 +463,8 @@ Buffer-related functions .. c:function:: Py_ssize_t PyBuffer_SizeFromFormat(const char *format) Return the implied :c:data:`~Py_buffer.itemsize` from :c:data:`~Py_buffer.format`. + + .. versionchanged:: 3.9 .. c:function:: int PyBuffer_IsContiguous(Py_buffer *view, char order) From aef07450a960630eb00c379c7b6fa2008cb4eeeb Mon Sep 17 00:00:00 2001 From: Joannah nanjekye Date: Thu, 6 Jun 2019 18:23:56 -0300 Subject: [PATCH 04/20] remove white space --- Doc/c-api/buffer.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst index 46a1e0d96ae4a8..baf5cd05bfb6e4 100755 --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -463,7 +463,7 @@ Buffer-related functions .. c:function:: Py_ssize_t PyBuffer_SizeFromFormat(const char *format) Return the implied :c:data:`~Py_buffer.itemsize` from :c:data:`~Py_buffer.format`. - + .. versionchanged:: 3.9 From 30ac72a5a84a8daae81069d36b846d0e23ba03b2 Mon Sep 17 00:00:00 2001 From: Joannah nanjekye Date: Tue, 11 Jun 2019 16:39:26 -0300 Subject: [PATCH 05/20] Improve draft PR --- Doc/c-api/buffer.rst | 5 ++-- Include/cpython/abstract.h | 2 +- Lib/test/test_buffer.py | 16 +++++++++++ Objects/abstract.c | 55 +++++++++++++++++++++++--------------- 4 files changed, 53 insertions(+), 25 deletions(-) mode change 100644 => 100755 Lib/test/test_buffer.py diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst index baf5cd05bfb6e4..35fe2f1ae3c85e 100755 --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -462,9 +462,10 @@ Buffer-related functions .. c:function:: Py_ssize_t PyBuffer_SizeFromFormat(const char *format) - Return the implied :c:data:`~Py_buffer.itemsize` from :c:data:`~Py_buffer.format`. + Return the implied :c:data:`~Py_buffer.itemsize` from :c:data:`~Py_buffer.format`. on success, the + size of the *format* is returned. Otherwise, return -1. - .. versionchanged:: 3.9 + .. 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 index ab0954cd278a0c..7ab2045923d83d 100755 --- a/Include/cpython/abstract.h +++ b/Include/cpython/abstract.h @@ -206,7 +206,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 *format); +PyAPI_FUNC(int) PyBuffer_SizeFromFormat(const char *); /* 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 47413c03d6630e..303ca645646eeb --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -4412,6 +4412,22 @@ def test_issue_7385(self): x = ndarray([1,2,3], shape=[3], flags=ND_GETBUF_FAIL) self.assertRaises(BufferError, memoryview, x) + # Test PyBuffer_SizeFromFormat() + @support.cpython_only + def test_pybuffer_size_from_format(self): + from ctypes import pythonapi + PyBuffer_SizeFromFormat = pythonapi.PyBuffer_SizeFromFormat + + # basic tests + self.assertIs(PyBuffer_SizeFromFormat("abc") > 0 , True) + + #invalid input + self.assertRaises(struct.error, PyBuffer_SizeFromFormat, b'gg') + + #Empty strings + self.assertIs(PyBuffer_SizeFromFormat('') > 0 , True) + self.assertIs(PyBuffer_SizeFromFormat('%s') > 0 , True) + if __name__ == "__main__": unittest.main() diff --git a/Objects/abstract.c b/Objects/abstract.c index d1a1e996dc5003..8b873de73ea97a 100755 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -7,12 +7,6 @@ #include "longintrepr.h" -/* struct module */ -static PyObject *structmodule = NULL; -static PyObject *calcsize = NULL; - - - /* Shorthands to return certain errors */ static PyObject * @@ -503,25 +497,42 @@ _Py_add_one_to_index_C(int nd, Py_ssize_t *index, const Py_ssize_t *shape) int PyBuffer_SizeFromFormat(const char *format) { - PyObject *result; - int size; + PyObject *structmodule; + PyObject *Struct = NULL; + PyObject *structobj = NULL; + PyObject *fmt = NULL; + int itemsize; structmodule = PyImport_ImportModule("struct"); if (structmodule == NULL) - return NULL; - - calcsize = PyObject_GetAttrString(structmodule, "calcsize"); - if (calcsize == NULL) - return NULL; - - result = PyObject_CallFunctionObjArgs(calcsize, format, NULL); - Py_DECREF(calcsize); - if (result == NULL) - return -1; - size = _PyLong_AsInt(result); - Py_DECREF(result); - - return size; + goto error; + + Struct = PyObject_GetAttrString(structmodule, "calcsize"); + Py_DECREF(structmodule); + if (Struct == NULL) + goto error; + + fmt = PyBytes_FromString(format); + if (fmt == NULL) + goto error; + + structobj = PyObject_CallFunctionObjArgs(Struct, fmt, NULL); + if (structobj == NULL) + goto error; + + itemsize = (intptr_t)structobj; + if (itemsize < 0) + goto error; + +out: + Py_XDECREF(Struct); + Py_XDECREF(fmt); + Py_XDECREF(structobj); + return itemsize; + +error: + itemsize = -1; + goto out; } int From 31442ab671a2c5bc781cf021db19ae40d6d6da3a Mon Sep 17 00:00:00 2001 From: Joannah nanjekye Date: Tue, 11 Jun 2019 17:07:18 -0300 Subject: [PATCH 06/20] fix test --- Lib/test/test_buffer.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py index 303ca645646eeb..8151e123a864fb 100755 --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -4419,7 +4419,9 @@ def test_pybuffer_size_from_format(self): PyBuffer_SizeFromFormat = pythonapi.PyBuffer_SizeFromFormat # basic tests - self.assertIs(PyBuffer_SizeFromFormat("abc") > 0 , True) + self.assertIs(PyBuffer_SizeFromFormat("3si") > 0 , True) + self.assertIs(PyBuffer_SizeFromFormat("3s") > 0 , True) + self.assertIs(PyBuffer_SizeFromFormat("0i") > 0 , True) #invalid input self.assertRaises(struct.error, PyBuffer_SizeFromFormat, b'gg') From 98a5576045b22197138a75d3be501a4643be0e0c Mon Sep 17 00:00:00 2001 From: Joannah nanjekye Date: Sat, 15 Jun 2019 13:11:12 -0300 Subject: [PATCH 07/20] Fix tests, doc and logic --- Doc/c-api/buffer.rst | 2 +- Include/cpython/abstract.h | 2 +- Lib/test/test_buffer.py | 21 ++++++++----------- Modules/_testcapimodule.c | 14 +++++++++++++ Objects/abstract.c | 42 +++++++++++++++++++------------------- 5 files changed, 46 insertions(+), 35 deletions(-) mode change 100644 => 100755 Modules/_testcapimodule.c diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst index 35fe2f1ae3c85e..d13b918f668f1f 100755 --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -463,7 +463,7 @@ Buffer-related functions .. c:function:: Py_ssize_t PyBuffer_SizeFromFormat(const char *format) Return the implied :c:data:`~Py_buffer.itemsize` from :c:data:`~Py_buffer.format`. on success, the - size of the *format* is returned. Otherwise, return -1. + size of the return *format* and -1 Otherwise. .. versionadded:: 3.9 diff --git a/Include/cpython/abstract.h b/Include/cpython/abstract.h index 7ab2045923d83d..6ddc4eb66f9279 100755 --- a/Include/cpython/abstract.h +++ b/Include/cpython/abstract.h @@ -206,7 +206,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 index 8151e123a864fb..ca084b154554a6 100755 --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -4415,20 +4415,17 @@ def test_issue_7385(self): # Test PyBuffer_SizeFromFormat() @support.cpython_only def test_pybuffer_size_from_format(self): - from ctypes import pythonapi - PyBuffer_SizeFromFormat = pythonapi.PyBuffer_SizeFromFormat + from _testcapi import pybuffer_size_from_format # basic tests - self.assertIs(PyBuffer_SizeFromFormat("3si") > 0 , True) - self.assertIs(PyBuffer_SizeFromFormat("3s") > 0 , True) - self.assertIs(PyBuffer_SizeFromFormat("0i") > 0 , True) - - #invalid input - self.assertRaises(struct.error, PyBuffer_SizeFromFormat, b'gg') - - #Empty strings - self.assertIs(PyBuffer_SizeFromFormat('') > 0 , True) - self.assertIs(PyBuffer_SizeFromFormat('%s') > 0 , True) + for format in ("i", "3s", "0i", " "): + self.assertEqual(pybuffer_size_from_format(format.encode()), + struct.calcsize(format)) + + # invalid tests + for format in ("nn", "xxx", "xx"): + self.assertEqual(pybuffer_size_from_format(format.encode()), + struct.calcsize(format)) if __name__ == "__main__": diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c old mode 100644 new mode 100755 index f059b4df11b734..273082cd62aae0 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -3301,6 +3301,19 @@ getbuffer_with_null_view(PyObject* self, PyObject *obj) Py_RETURN_NONE; } +/* test PyBuffer_SizeFromFormat() */ +static Py_ssize_t +pybuffer_size_from_format(PyObject* self, PyObject *args) +{ + const char *format; + + if (!PyArg_ParseTuple(args, "s:pybuffer_size_from_format", + &format)) + return -1; + + return PyBuffer_SizeFromFormat(format); +} + /* 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 * @@ -5087,6 +5100,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_size_from_format", (PyCFunction)pybuffer_size_from_format, 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 index 8b873de73ea97a..d33d63fbf5fd9a 100755 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -494,45 +494,45 @@ _Py_add_one_to_index_C(int nd, Py_ssize_t *index, const Py_ssize_t *shape) } } -int +Py_ssize_t PyBuffer_SizeFromFormat(const char *format) { - PyObject *structmodule; + PyObject *structmodule = NULL; PyObject *Struct = NULL; - PyObject *structobj = NULL; + PyObject *res = NULL; PyObject *fmt = NULL; - int itemsize; + Py_ssize_t itemsize = -1; structmodule = PyImport_ImportModule("struct"); if (structmodule == NULL) - goto error; + goto done; Struct = PyObject_GetAttrString(structmodule, "calcsize"); Py_DECREF(structmodule); - if (Struct == NULL) - goto error; + if (Struct == NULL) { + goto done; + } fmt = PyBytes_FromString(format); - if (fmt == NULL) - goto error; + if (fmt == NULL) { + goto done; + } - structobj = PyObject_CallFunctionObjArgs(Struct, fmt, NULL); - if (structobj == NULL) - goto error; + res = PyObject_CallFunctionObjArgs(Struct, fmt, NULL); + if (res == NULL) { + goto done; + } - itemsize = (intptr_t)structobj; - if (itemsize < 0) - goto error; + itemsize = PyLong_AsSsize_t(res); + if (itemsize < 0) { + goto done; + } -out: +done: Py_XDECREF(Struct); Py_XDECREF(fmt); - Py_XDECREF(structobj); + Py_XDECREF(res); return itemsize; - -error: - itemsize = -1; - goto out; } int From 79d1e3f0a40a0eb87490e7cd5df16bf6f55b67c0 Mon Sep 17 00:00:00 2001 From: Joannah nanjekye Date: Thu, 20 Jun 2019 15:05:52 -0300 Subject: [PATCH 08/20] Fix segfault --- Doc/c-api/buffer.rst | 2 +- Lib/test/test_buffer.py | 17 +++++++---------- Modules/_testcapimodule.c | 13 +++++++------ Objects/abstract.c | 15 ++++++++------- 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst index d13b918f668f1f..fbeaf66c8dccf0 100755 --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -463,7 +463,7 @@ Buffer-related functions .. c:function:: Py_ssize_t PyBuffer_SizeFromFormat(const char *format) Return the implied :c:data:`~Py_buffer.itemsize` from :c:data:`~Py_buffer.format`. on success, the - size of the return *format* and -1 Otherwise. + size of the return *format*. Otherwise, raise an exception and return -1 on error. .. versionadded:: 3.9 diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py index ca084b154554a6..2da35e3610c7e7 100755 --- 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,21 +4417,13 @@ def test_issue_7385(self): x = ndarray([1,2,3], shape=[3], flags=ND_GETBUF_FAIL) self.assertRaises(BufferError, memoryview, x) - # Test PyBuffer_SizeFromFormat() @support.cpython_only + @unittest.skipUnless(_testcapi, 'requires _testcapi') def test_pybuffer_size_from_format(self): - from _testcapi import pybuffer_size_from_format - # basic tests for format in ("i", "3s", "0i", " "): - self.assertEqual(pybuffer_size_from_format(format.encode()), + self.assertEqual(_testcapi.pybuffer_size_from_format(format), struct.calcsize(format)) - # invalid tests - for format in ("nn", "xxx", "xx"): - self.assertEqual(pybuffer_size_from_format(format.encode()), - struct.calcsize(format)) - - if __name__ == "__main__": unittest.main() diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 273082cd62aae0..0d806c99a545ba 100755 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -3301,17 +3301,18 @@ getbuffer_with_null_view(PyObject* self, PyObject *obj) Py_RETURN_NONE; } -/* test PyBuffer_SizeFromFormat() */ -static Py_ssize_t -pybuffer_size_from_format(PyObject* self, PyObject *args) +/* PyBuffer_SizeFromFormat() */ +static PyObject * +pybuffer_size_from_format(PyObject *self, PyObject *args) { const char *format; if (!PyArg_ParseTuple(args, "s:pybuffer_size_from_format", - &format)) - return -1; + &format)) { + return NULL; + } - return PyBuffer_SizeFromFormat(format); + return PyLong_FromSsize_t(PyBuffer_SizeFromFormat(format)); } /* Test that the fatal error from not having a current thread doesn't diff --git a/Objects/abstract.c b/Objects/abstract.c index d33d63fbf5fd9a..17892e01a43209 100755 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -498,18 +498,18 @@ Py_ssize_t PyBuffer_SizeFromFormat(const char *format) { PyObject *structmodule = NULL; - PyObject *Struct = NULL; + PyObject *calcsize = NULL; PyObject *res = NULL; PyObject *fmt = NULL; Py_ssize_t itemsize = -1; structmodule = PyImport_ImportModule("struct"); - if (structmodule == NULL) + if (structmodule == NULL) { goto done; + } - Struct = PyObject_GetAttrString(structmodule, "calcsize"); - Py_DECREF(structmodule); - if (Struct == NULL) { + calcsize = PyObject_GetAttrString(structmodule, "calcsize"); + if (calcsize == NULL) { goto done; } @@ -518,7 +518,7 @@ PyBuffer_SizeFromFormat(const char *format) goto done; } - res = PyObject_CallFunctionObjArgs(Struct, fmt, NULL); + res = PyObject_CallFunctionObjArgs(calcsize, fmt, NULL); if (res == NULL) { goto done; } @@ -529,7 +529,8 @@ PyBuffer_SizeFromFormat(const char *format) } done: - Py_XDECREF(Struct); + Py_DECREF(structmodule); + Py_XDECREF(calcsize); Py_XDECREF(fmt); Py_XDECREF(res); return itemsize; From 618fb4022011b4d67b5c80074be5eb9f6350c9c9 Mon Sep 17 00:00:00 2001 From: Joannah nanjekye Date: Thu, 20 Jun 2019 15:35:59 -0300 Subject: [PATCH 09/20] bytes not str --- Lib/test/test_buffer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py index 2da35e3610c7e7..ad8ee06638ca2d 100755 --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -4423,7 +4423,7 @@ def test_pybuffer_size_from_format(self): # basic tests for format in ("i", "3s", "0i", " "): self.assertEqual(_testcapi.pybuffer_size_from_format(format), - struct.calcsize(format)) + struct.calcsize(format.encode())) if __name__ == "__main__": unittest.main() From 83e63d226be80a37e2639b728c84fbdcdab07cd5 Mon Sep 17 00:00:00 2001 From: nanjekyejoannah Date: Sun, 23 Jun 2019 15:56:50 -0300 Subject: [PATCH 10/20] Fix docs and test --- Doc/c-api/buffer.rst | 4 ++-- Lib/test/test_buffer.py | 1 - .../2019-06-06-20-52-38.bpo-15913.5Sg5cv.rst | 2 +- Objects/abstract.c | 1 + 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst index fbeaf66c8dccf0..63f32af7f23bec 100755 --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -462,8 +462,8 @@ Buffer-related functions .. c:function:: Py_ssize_t PyBuffer_SizeFromFormat(const char *format) - Return the implied :c:data:`~Py_buffer.itemsize` from :c:data:`~Py_buffer.format`. on success, the - size of the return *format*. Otherwise, raise an exception and return -1 on error. + Return the implied :c:data:`~Py_buffer.itemsize` from :c:data:`~Py_buffer.format`. + On error, raise an exception and return -1. .. versionadded:: 3.9 diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py index ad8ee06638ca2d..c0e84cd5001cbe 100755 --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -4418,7 +4418,6 @@ def test_issue_7385(self): self.assertRaises(BufferError, memoryview, x) @support.cpython_only - @unittest.skipUnless(_testcapi, 'requires _testcapi') def test_pybuffer_size_from_format(self): # basic tests for format in ("i", "3s", "0i", " "): 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 index c1b88823bd9b8e..a2fbe1f6fdd7ee 100644 --- 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 @@ -1 +1 @@ -`PyBuffer_SizeFromFormat()` now added. \ No newline at end of file +:c:func:`PyBuffer_SizeFromFormat()` now added. \ No newline at end of file diff --git a/Objects/abstract.c b/Objects/abstract.c index 17892e01a43209..c15fef93185421 100755 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -7,6 +7,7 @@ #include "longintrepr.h" + /* Shorthands to return certain errors */ static PyObject * From e12e737a8a9568eb4dff05f4d9c67b617a45d81a Mon Sep 17 00:00:00 2001 From: nanjekyejoannah Date: Sun, 23 Jun 2019 16:00:00 -0300 Subject: [PATCH 11/20] Fix whitespace --- Doc/c-api/buffer.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst index 63f32af7f23bec..fac3c9a880ff34 100755 --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -462,7 +462,7 @@ Buffer-related functions .. c:function:: Py_ssize_t PyBuffer_SizeFromFormat(const char *format) - Return the implied :c:data:`~Py_buffer.itemsize` from :c:data:`~Py_buffer.format`. + Return the implied :c:data:`~Py_buffer.itemsize` from :c:data:`~Py_buffer.format`. On error, raise an exception and return -1. .. versionadded:: 3.9 From bb8cdf8e88604200224e93d69b898752d2f5a599 Mon Sep 17 00:00:00 2001 From: Joannah nanjekye Date: Mon, 24 Jun 2019 11:40:50 -0300 Subject: [PATCH 12/20] make test consistent --- Lib/test/test_buffer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py index c0e84cd5001cbe..87d94791183eec 100755 --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -4422,7 +4422,7 @@ def test_pybuffer_size_from_format(self): # basic tests for format in ("i", "3s", "0i", " "): self.assertEqual(_testcapi.pybuffer_size_from_format(format), - struct.calcsize(format.encode())) + struct.calcsize(format)) if __name__ == "__main__": unittest.main() From 77f546b446fbc78d40859e790d557189e8e1b9d9 Mon Sep 17 00:00:00 2001 From: Joannah nanjekye Date: Mon, 24 Jun 2019 11:44:19 -0300 Subject: [PATCH 13/20] align call --- Lib/test/test_buffer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py index 87d94791183eec..e48687f7506c79 100755 --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -4422,7 +4422,7 @@ def test_pybuffer_size_from_format(self): # basic tests for format in ("i", "3s", "0i", " "): self.assertEqual(_testcapi.pybuffer_size_from_format(format), - struct.calcsize(format)) + struct.calcsize(format)) if __name__ == "__main__": unittest.main() From 2cbcec33aa21d877b9b485264d4d1e7ea40ae4d3 Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye <33177550+nanjekyejoannah@users.noreply.github.com> Date: Mon, 24 Jun 2019 12:09:03 -0300 Subject: [PATCH 14/20] Revert encode() --- Lib/test/test_buffer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py index e48687f7506c79..439576ffbde601 100755 --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -4422,7 +4422,7 @@ def test_pybuffer_size_from_format(self): # basic tests for format in ("i", "3s", "0i", " "): self.assertEqual(_testcapi.pybuffer_size_from_format(format), - struct.calcsize(format)) + struct.calcsize(format.encode())) if __name__ == "__main__": unittest.main() From 1dd3c2a8ad109b1464bdcdf13f4363e5fab33868 Mon Sep 17 00:00:00 2001 From: Joannah nanjekye Date: Mon, 24 Jun 2019 12:38:30 -0300 Subject: [PATCH 15/20] Fix segfault --- Modules/_testcapimodule.c | 8 +++++++- Objects/abstract.c | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 0d806c99a545ba..d21206dc6fdd81 100755 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -3306,13 +3306,19 @@ static PyObject * pybuffer_size_from_format(PyObject *self, PyObject *args) { const char *format; + Py_ssize_t result; if (!PyArg_ParseTuple(args, "s:pybuffer_size_from_format", &format)) { return NULL; } - return PyLong_FromSsize_t(PyBuffer_SizeFromFormat(format)); + 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 diff --git a/Objects/abstract.c b/Objects/abstract.c index c15fef93185421..07b04e383a9cfd 100755 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -506,7 +506,7 @@ PyBuffer_SizeFromFormat(const char *format) structmodule = PyImport_ImportModule("struct"); if (structmodule == NULL) { - goto done; + return itemsize; } calcsize = PyObject_GetAttrString(structmodule, "calcsize"); From 5cac74f6f63283f2566a2f4adeaadb42df1af1a8 Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye Date: Fri, 16 Aug 2019 16:54:48 +0000 Subject: [PATCH 16/20] Fix bytes and string comparison error --- Lib/test/test_buffer.py | 8 ++++---- Objects/abstract.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py index 439576ffbde601..043aa04270daf0 100755 --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -4419,10 +4419,10 @@ def test_issue_7385(self): @support.cpython_only def test_pybuffer_size_from_format(self): - # basic tests - for format in ("i", "3s", "0i", " "): - self.assertEqual(_testcapi.pybuffer_size_from_format(format), - struct.calcsize(format.encode())) + nitems = randrange(1, 30) + for fmt, _, _ in iter_format(nitems): + self.assertEqual(_testcapi.pybuffer_size_from_format(fmt), + struct.calcsize(fmt)) if __name__ == "__main__": unittest.main() diff --git a/Objects/abstract.c b/Objects/abstract.c index 07b04e383a9cfd..7b2ed9796184fd 100755 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -514,7 +514,7 @@ PyBuffer_SizeFromFormat(const char *format) goto done; } - fmt = PyBytes_FromString(format); + fmt = PyUnicode_FromString(format); if (fmt == NULL) { goto done; } From eddee93d50ba7eb91c9d233a0baf1cd736e5b148 Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye Date: Mon, 19 Aug 2019 12:50:44 +0000 Subject: [PATCH 17/20] rename function and update news entry --- Lib/test/test_buffer.py | 9 ++++----- Modules/_testcapimodule.c | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py index 043aa04270daf0..8ccb8e2967f347 100755 --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -4419,10 +4419,9 @@ def test_issue_7385(self): @support.cpython_only def test_pybuffer_size_from_format(self): - nitems = randrange(1, 30) - for fmt, _, _ in iter_format(nitems): - self.assertEqual(_testcapi.pybuffer_size_from_format(fmt), - struct.calcsize(fmt)) - + # basic tests + for format in ("i", "3s", "0i", " "): + self.assertEqual(_testcapi.PyBuffer_SizeFromFormat(format), + struct.calcsize(format)) if __name__ == "__main__": unittest.main() diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index d21206dc6fdd81..96da530c023b09 100755 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -3303,7 +3303,7 @@ getbuffer_with_null_view(PyObject* self, PyObject *obj) /* PyBuffer_SizeFromFormat() */ static PyObject * -pybuffer_size_from_format(PyObject *self, PyObject *args) +test_PyBuffer_SizeFromFormat(PyObject *self, PyObject *args) { const char *format; Py_ssize_t result; @@ -5107,7 +5107,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_size_from_format", (PyCFunction)pybuffer_size_from_format, METH_VARARGS}, + {"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}, From 244fdce8bb14793993aabe2e8dbfdda1d2142984 Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye <33177550+nanjekyejoannah@users.noreply.github.com> Date: Mon, 19 Aug 2019 10:16:47 -0300 Subject: [PATCH 18/20] update news entry --- .../2019-06-06-20-52-38.bpo-15913.5Sg5cv.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 index a2fbe1f6fdd7ee..0fbfcb37abb453 100644 --- 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 @@ -1 +1,3 @@ -:c:func:`PyBuffer_SizeFromFormat()` now added. \ No newline at end of file +Implement :c:func:`PyBuffer_SizeFromFormat()` function (previously +documented but not implemented): call :func:`struct.calcsize`. +Patch by Joannah Nanjekye. From dda73c3e5af09666ce4b3604f406d169d9107780 Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye Date: Mon, 19 Aug 2019 13:21:28 +0000 Subject: [PATCH 19/20] revert deleted line --- Lib/test/test_buffer.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py index 8ccb8e2967f347..5a45c41cd5e2f8 100755 --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -4423,5 +4423,7 @@ def test_pybuffer_size_from_format(self): for format in ("i", "3s", "0i", " "): self.assertEqual(_testcapi.PyBuffer_SizeFromFormat(format), struct.calcsize(format)) + + if __name__ == "__main__": unittest.main() From f3e8c5100459c1f1e98506ecaf2d8c6a891bc6f2 Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye Date: Mon, 19 Aug 2019 13:44:54 +0000 Subject: [PATCH 20/20] forgotten rename and test update --- Lib/test/test_buffer.py | 2 +- Modules/_testcapimodule.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py index 5a45c41cd5e2f8..5fa52bffc22be7 100755 --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -4420,7 +4420,7 @@ def test_issue_7385(self): @support.cpython_only def test_pybuffer_size_from_format(self): # basic tests - for format in ("i", "3s", "0i", " "): + for format in ('', 'ii', '3s'): self.assertEqual(_testcapi.PyBuffer_SizeFromFormat(format), struct.calcsize(format)) diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 96da530c023b09..812838c0919f2f 100755 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -3308,7 +3308,7 @@ test_PyBuffer_SizeFromFormat(PyObject *self, PyObject *args) const char *format; Py_ssize_t result; - if (!PyArg_ParseTuple(args, "s:pybuffer_size_from_format", + if (!PyArg_ParseTuple(args, "s:test_PyBuffer_SizeFromFormat", &format)) { return NULL; }