# HG changeset patch # Parent cdc3837cb1fcfc4273b46e84c533ec7e91246b71 Issue 21071: Struct.format is now a str diff -r cdc3837cb1fc Doc/library/struct.rst --- a/Doc/library/struct.rst Tue Dec 16 03:21:54 2014 -0500 +++ b/Doc/library/struct.rst Thu Dec 18 05:23:42 2014 +0000 @@ -420,6 +420,10 @@ The format string used to construct this Struct object. + .. versionchanged:: 3.5 + Previously this was a :class:`bytes` object; + now it is a :class:`str` object. + .. attribute:: size The calculated size of the struct (and hence of the bytes object produced diff -r cdc3837cb1fc Lib/test/test_struct.py --- a/Lib/test/test_struct.py Tue Dec 16 03:21:54 2014 -0500 +++ b/Lib/test/test_struct.py Thu Dec 18 05:23:42 2014 +0000 @@ -589,6 +589,16 @@ self.check_sizeof('20p', 1) self.check_sizeof('0s', 1) self.check_sizeof('0c', 0) + + def test_format_attr(self): + """Make sure the "format" attribute is a text string""" + self.assertEqual("x", struct.Struct("x").format) + + def test_format_utf(self): + """Check error handling for unencodable format string""" + surrogate = "\uDC80" + self.assertRaises(UnicodeError, struct.pack, surrogate) + self.assertRaises(UnicodeError, struct.Struct, surrogate) class UnpackIteratorTest(unittest.TestCase): diff -r cdc3837cb1fc Modules/_struct.c --- a/Modules/_struct.c Tue Dec 16 03:21:54 2014 -0500 +++ b/Modules/_struct.c Thu Dec 18 05:23:42 2014 +0000 @@ -1266,7 +1266,10 @@ Py_ssize_t size, len, num, itemsize; size_t ncodes; - fmt = PyBytes_AS_STRING(self->s_format); + fmt = PyUnicode_AsUTF8(self->s_format); + if (fmt == NULL) { + return -1; + } f = whichtable((char **)&fmt); @@ -1419,8 +1422,10 @@ &o_format)) return -1; - if (PyUnicode_Check(o_format)) { - o_format = PyUnicode_AsASCIIString(o_format); + if (PyBytes_Check(o_format)) { + o_format = PyUnicode_DecodeASCII( + PyBytes_AS_STRING(o_format), PyBytes_GET_SIZE(o_format), + "strict"); if (o_format == NULL) return -1; } @@ -1429,10 +1434,10 @@ Py_INCREF(o_format); } - if (!PyBytes_Check(o_format)) { + if (!PyUnicode_Check(o_format)) { Py_DECREF(o_format); PyErr_Format(PyExc_TypeError, - "Struct() argument 1 must be a bytes object, not %.200s", + "Struct() argument 1 must be a string object, not %.200s", Py_TYPE(o_format)->tp_name); return -1; } @@ -2221,9 +2226,8 @@ PyDoc_STRVAR(module_doc, "Functions to convert between Python values and C structs.\n\ -Python bytes objects are used to hold the data representing the C struct\n\ -and also as format strings (explained below) to describe the layout of data\n\ -in the C struct.\n\ +Python bytes objects are used to hold the data representing the C struct.\n\ +Format strings describe the layout of data in the C struct.\n\ \n\ The optional first format char indicates byte order, size and alignment:\n\ @: native order, size & alignment (default)\n\