From 5493d5ea2afec8a1ff3227e08e908c6e433638cc Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 8 Dec 2013 17:44:50 +0200 Subject: [PATCH] Issue #19099: The struct module now supports Unicode format strings. --- Lib/test/test_struct.py | 12 ++++++++++++ Misc/NEWS | 2 ++ Modules/_struct.c | 23 +++++++++++++++++++---- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py index 2e613f7577b..4811974970e 100644 --- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -574,6 +574,18 @@ class StructTest(unittest.TestCase): self.check_sizeof('0s', 1) self.check_sizeof('0c', 0) + def test_unicode_format(self): + try: + unicode + except NameError: + self.skipTest('no unicode support') + # Issue #19099 + s = struct.Struct(unichr(ord('I'))) + self.assertEqual(s.format, 'I') + self.assertIs(type(s.format), str) + self.assertRaises(ValueError, struct.Struct, unichr(0x80)) + + def test_main(): support.run_unittest(StructTest) diff --git a/Misc/NEWS b/Misc/NEWS index 928a18ed262..e3abaec898f 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,8 @@ Core and Builtins Library ------- +- Issue #19099: The struct module now supports Unicode format strings. + - Issue #19878: Fix segfault in bz2 module after calling __init__ twice with non-existent filename. Initial patch by Vajrasky Kok. diff --git a/Modules/_struct.c b/Modules/_struct.c index 80569561f98..f035847b7ec 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -1371,13 +1371,28 @@ s_init(PyObject *self, PyObject *args, PyObject *kwds) assert(PyStruct_Check(self)); - if (!PyArg_ParseTupleAndKeywords(args, kwds, "S:Struct", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:Struct", kwlist, &o_format)) return -1; - Py_INCREF(o_format); - Py_CLEAR(soself->s_format); - soself->s_format = o_format; + if (PyString_Check(o_format)) { + Py_INCREF(o_format); + Py_CLEAR(soself->s_format); + soself->s_format = o_format; + } + else if (PyUnicode_Check(o_format)) { + PyObject *str = PyUnicode_AsEncodedString(o_format, "ascii", NULL); + if (str == NULL) + return -1; + Py_CLEAR(soself->s_format); + soself->s_format = str; + } + else { + PyErr_Format(PyExc_TypeError, + "Struct() argument 1 must be string, not %s", + Py_TYPE(o_format)->tp_name); + return -1; + } ret = prepare_s(soself); return ret;