From cf16b041f5d9a27dbd02bd002ad38ecab563d376 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 2 May 2026 12:30:40 +0200 Subject: [PATCH] Change array.typecodes type to tuple --- Doc/library/array.rst | 5 +++- Doc/whatsnew/3.15.rst | 7 ++++- Lib/test/test_array.py | 9 ++++++ ...-05-02-12-30-35.gh-issue-148675.cu2YFT.rst | 3 ++ Modules/arraymodule.c | 29 ++++++++++++++----- 5 files changed, 44 insertions(+), 9 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-05-02-12-30-35.gh-issue-148675.cu2YFT.rst diff --git a/Doc/library/array.rst b/Doc/library/array.rst index 0bca9239bb5..3b8a7a02822 100644 --- a/Doc/library/array.rst +++ b/Doc/library/array.rst @@ -109,7 +109,10 @@ The module defines the following item: .. data:: typecodes - A string with all available type codes. + A tuple with all available type codes. + + .. versionchanged:: next + The type changed from :str:`str` to :class:`tuple`. The module defines the following type: diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 03e9e544ff9..ff92a8649e9 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -680,12 +680,17 @@ array * Support the :c:expr:`float complex` and :c:expr:`double complex` C types: formatting characters ``'F'``/``'Zd'`` and ``'D'``/``'Zd'`` respectively. - (Contributed by Sergey B Kirpichev in :gh:`146151`.) + (Contributed by Sergey B Kirpichev and Victor Stinner in :gh:`146151` + and :gh:`148675`.) * Support half-floats (16-bit IEEE 754 binary interchange format): formatting character ``'e'``. (Contributed by Sergey B Kirpichev in :gh:`146238`.) +* The :data:`array.typecodes` type changed from :str:`str` to :class:`tuple` + to support type codes longer than 1 character (``Zf`` and ``Zd``). + (Contributed by Victor Stinner in :gh:`148675`.) + base64 ------ diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py index 4ee1fea6a92..13a347908a6 100755 --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -85,6 +85,12 @@ def __index__(self): with self.assertRaises(TypeError): a.fromlist(lst) + def test_typecodes(self): + self.assertIsInstance(array.typecodes, tuple) + for typecode in array.typecodes: + self.assertIsInstance(typecode, str) + self.assertGreaterEqual(len(typecode), 1) + # Machine format codes. # @@ -1237,6 +1243,9 @@ def test_free_after_iterating(self): support.check_free_after_iterating(self, reversed, array.array, (self.typecode,)) + def test_known_typecode(self): + self.assertIn(self.typecode, array.typecodes) + class StringTest(BaseTest): def test_setitem(self): diff --git a/Misc/NEWS.d/next/Library/2026-05-02-12-30-35.gh-issue-148675.cu2YFT.rst b/Misc/NEWS.d/next/Library/2026-05-02-12-30-35.gh-issue-148675.cu2YFT.rst new file mode 100644 index 00000000000..b300c16bf11 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-02-12-30-35.gh-issue-148675.cu2YFT.rst @@ -0,0 +1,3 @@ +The :data:`array.typecodes` type changed from :str:`str` to :class:`tuple` +to support type codes longer than 1 character (``Zf`` and ``Zd``). Patch by +Victor Stinner. diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index dadf7fd82b8..e962eecd49d 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -3493,7 +3493,6 @@ static int array_modexec(PyObject *m) { array_state *state = get_array_state(m); - char buffer[Py_ARRAY_LENGTH(descriptors)*2], *p; PyObject *typecodes; const struct arraydescr *descr; @@ -3532,13 +3531,29 @@ array_modexec(PyObject *m) return -1; } - p = buffer; - for (descr = descriptors; descr->typecode != NULL; descr++) { - strcpy(p, descr->typecode); - p += strlen(descr->typecode); + typecodes = PyList_New(0); + if (typecodes == NULL) { + return -1; } - typecodes = PyUnicode_DecodeASCII(buffer, p - buffer, NULL); - if (PyModule_Add(m, "typecodes", typecodes) < 0) { + for (descr = descriptors; descr->typecode != NULL; descr++) { + PyObject *typecode = PyUnicode_DecodeASCII(descr->typecode, strlen(descr->typecode), NULL); + if (typecode == NULL) { + Py_DECREF(typecodes); + return -1; + } + int res = PyList_Append(typecodes, typecode); + Py_DECREF(typecode); + if (res < 0) { + Py_DECREF(typecodes); + return -1; + } + } + PyObject *tuple = PyList_AsTuple(typecodes); + Py_DECREF(typecodes); + if (tuple == NULL) { + return -1; + } + if (PyModule_Add(m, "typecodes", tuple) < 0) { return -1; }