diff -r 45280c44d9c0 Lib/test/test_unicode.py --- a/Lib/test/test_unicode.py Wed Sep 28 07:48:23 2016 +0300 +++ b/Lib/test/test_unicode.py Wed Sep 28 23:10:56 2016 +0800 @@ -2594,6 +2594,19 @@ self.assertEqual(size, nchar) self.assertEqual(wchar, nonbmp + '\0') + # Test PyUnicode_AsUCS4() + @support.cpython_only + def test_asucs4(self): + from _testcapi import unicode_asucs4 + self.assertEqual(unicode_asucs4('abc', 3, 1), 'abc\0') + self.assertEqual(unicode_asucs4('abc', 3, 0), 'abc\uffff') + self.assertEqual(unicode_asucs4('abc\0abc', 7, 1), 'abc\0abc\0') + self.assertEqual(unicode_asucs4('abc\0abc', 7, 0), 'abc\0abc\uffff') + self.assertEqual(unicode_asucs4('abc', 4, 1), 'abc\0\uffff') + self.assertEqual(unicode_asucs4('abc', 4, 0), 'abc\0\uffff') + self.assertRaises(ValueError, unicode_asucs4, 'abc', 2, 1) + self.assertRaises(ValueError, unicode_asucs4, 'abc', 1, 0) + def test_subclass_add(self): class S(str): def __add__(self, o): diff -r 45280c44d9c0 Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c Wed Sep 28 07:48:23 2016 +0300 +++ b/Modules/_testcapimodule.c Wed Sep 28 23:10:56 2016 +0800 @@ -1829,6 +1829,36 @@ } static PyObject * +unicode_asucs4(PyObject *self, PyObject *args) +{ + PyObject *unicode, *result; + Py_UCS4 *buffer; + int copy_null; + Py_ssize_t strlen, buflen; + + if (!PyArg_ParseTuple(args, "Unp:unicode_asucs4", &unicode, &strlen, ©_null)) { + return NULL; + } + + buflen = strlen + 1; + buffer = PyMem_NEW(Py_UCS4, buflen); + if (buffer == NULL) { + return PyErr_NoMemory(); + } + memset(buffer, 0, sizeof(Py_UCS4)*buflen); + buffer[strlen] = 0xffffU; + + if (!PyUnicode_AsUCS4(unicode, buffer, buflen, copy_null)) { + PyMem_FREE(buffer); + return NULL; + } + + result = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buffer, buflen); + PyMem_FREE(buffer); + return result; +} + +static PyObject * unicode_encodedecimal(PyObject *self, PyObject *args) { Py_UNICODE *unicode; @@ -4030,6 +4060,7 @@ {"test_widechar", (PyCFunction)test_widechar, METH_NOARGS}, {"unicode_aswidechar", unicode_aswidechar, METH_VARARGS}, {"unicode_aswidecharstring",unicode_aswidecharstring, METH_VARARGS}, + {"unicode_asucs4", unicode_asucs4, METH_VARARGS}, {"unicode_encodedecimal", unicode_encodedecimal, METH_VARARGS}, {"unicode_transformdecimaltoascii", unicode_transformdecimaltoascii, METH_VARARGS}, {"unicode_legacy_string", unicode_legacy_string, METH_VARARGS}, diff -r 45280c44d9c0 Objects/unicodeobject.c --- a/Objects/unicodeobject.c Wed Sep 28 07:48:23 2016 +0300 +++ b/Objects/unicodeobject.c Wed Sep 28 23:10:56 2016 +0800 @@ -2437,7 +2437,7 @@ } else { if (targetsize < targetlen) { - PyErr_Format(PyExc_SystemError, + PyErr_Format(PyExc_ValueError, "string is longer than the buffer"); if (copy_null && 0 < targetsize) target[0] = 0;