Index: Python/getargs.c =================================================================== --- Python/getargs.c (revision 58252) +++ Python/getargs.c (working copy) @@ -1238,33 +1238,19 @@ break; } - case 't': { /* 8-bit character buffer, read-only access */ - char **p = va_arg(*p_va, char **); - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; - int count; - Py_buffer view; + case 't': { /* 8-bit buffer, read-only access */ + void **p = (void **)va_arg(*p_va, char **); + char* buf; + Py_ssize_t count; if (*format++ != '#') return converterr( "invalid use of 't' format character", arg, msgbuf, bufsize); - if (pb == NULL || pb->bf_getbuffer == NULL) - return converterr( - "string or read-only character buffer", - arg, msgbuf, bufsize); - if ((*pb->bf_getbuffer)(arg, &view, PyBUF_CHARACTER) != 0) - return converterr("string or single-segment read-only buffer", - arg, msgbuf, bufsize); - - count = view.len; - *p = view.buf; - /* XXX : shouldn't really release buffer, but it should be O.K. - */ - if (pb->bf_releasebuffer != NULL) - (*pb->bf_releasebuffer)(arg, &view); + count = convertbuffer(arg, p, &buf); if (count < 0) - return converterr("(unspecified)", arg, msgbuf, bufsize); + return converterr(buf, arg, msgbuf, bufsize); { FETCH_SIZE; STORE_SIZE(count); Index: Lib/test/test_getargs2.py =================================================================== --- Lib/test/test_getargs2.py (revision 58252) +++ Lib/test/test_getargs2.py (working copy) @@ -250,8 +250,24 @@ self.assertRaises(TypeError, getargs_tuple, 1, seq()) +class Strings_TestCase(unittest.TestCase): + def test_t(self): + from _testcapi import getargs_t + from array import array + + self.assertEquals(getargs_t(b'abcd\xfe'), b'abcd\xfe') + self.assertEquals(getargs_t(array('B', b'abcd\xfe')), b'abcd\xfe') + if sys.byteorder == 'big': + self.assertEquals(getargs_t(array('h', [65,66,67])), b'\0A\0B\0C') + self.assertEquals(getargs_t('abcd\u1234'), b'\0a\0b\0c\0d\x12\x34') + else: + self.assertEquals(getargs_t(array('h', [65,66,67])), b'A\0B\0C\0') + self.assertEquals(getargs_t('abcd\u1234'), b'a\0b\0c\0d\0\x34\x12') + + def test_main(): - tests = [Signed_TestCase, Unsigned_TestCase, Tuple_TestCase] + tests = [Signed_TestCase, Unsigned_TestCase, Tuple_TestCase, + Strings_TestCase] try: from _testcapi import getargs_L, getargs_K except ImportError: Index: Modules/arraymodule.c =================================================================== --- Modules/arraymodule.c (revision 58252) +++ Modules/arraymodule.c (working copy) @@ -1788,7 +1788,7 @@ { if ((flags & PyBUF_CHARACTER)) { PyErr_SetString(PyExc_TypeError, - "Cannot be a character buffer"); + "Cannot view array as a character buffer"); return -1; } if ((flags & PyBUF_LOCKDATA)) { Index: Modules/_testcapimodule.c =================================================================== --- Modules/_testcapimodule.c (revision 58252) +++ Modules/_testcapimodule.c (working copy) @@ -456,7 +456,19 @@ return Py_None; } +// Parses the arguments with the t# format code and returns the result +// as a bytes. +static PyObject * +getargs_t(PyObject *self, PyObject *args) +{ + char *bytes; + int len; + if (!PyArg_ParseTuple(args, "t#", &bytes, &len)) + return NULL; + return PyBytes_FromStringAndSize(bytes, len); +} + /* Test the u and u# codes for PyArg_ParseTuple. May leak memory in case of an error. */ @@ -907,6 +919,7 @@ #ifdef HAVE_LONG_LONG {"getargs_L", getargs_L, METH_VARARGS}, {"getargs_K", getargs_K, METH_VARARGS}, + {"getargs_t", getargs_t, METH_VARARGS}, {"test_longlong_api", test_longlong_api, METH_NOARGS}, {"test_L_code", (PyCFunction)test_L_code, METH_NOARGS}, {"codec_incrementalencoder",