diff -r 0b04e5689c33 Lib/test/test_capi.py --- a/Lib/test/test_capi.py Wed Jul 15 22:12:33 2015 +0300 +++ b/Lib/test/test_capi.py Wed Jul 15 18:22:56 2015 -0400 @@ -477,7 +477,8 @@ # skip parentheses, the error reporting is inconsistent about them # skip 'e', it's always a two-character code # skip '|' and '$', they don't represent arguments anyway - if c in '()e|$': + # skip 'w' because it is invalid without a suffix. + if c in 'w()e|$': continue # test the format unit when not skipped diff -r 0b04e5689c33 Misc/NEWS --- a/Misc/NEWS Wed Jul 15 22:12:33 2015 +0300 +++ b/Misc/NEWS Wed Jul 15 18:22:56 2015 -0400 @@ -32,6 +32,9 @@ Core and Builtins ----------------- +- Issue: #23926: Fixed skipitem()'s handling of the old 'w' and 'w#' formatters. + These are no longer supported and now raise an exception if used. + - Issue #24569: Make PEP 448 dictionary evaluation more consistent. - Issue #24407: Fix crash when dict is mutated while being updated. diff -r 0b04e5689c33 Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c Wed Jul 15 22:12:33 2015 +0300 +++ b/Modules/_testcapimodule.c Wed Jul 15 18:22:56 2015 -0400 @@ -1443,6 +1443,77 @@ Py_RETURN_NONE; } +/* Test the old w and w# codes that no longer work */ +static PyObject * +test_w_code_invalid(PyObject *self) +{ + static const char * const keywords[] = {"a", "b", "c", "d", NULL}; + char *formats_3[] = {"O|w#$O", + "O|w$O", + "O|w#O", + "O|wO", + NULL}; + char *formats_4[] = {"O|w#O$O", + "O|wO$O", + "O|Ow#O", + "O|OwO", + "O|Ow#$O", + "O|Ow$O", + NULL}; + size_t n; + PyObject *args; + PyObject *kwargs; + PyObject *tmp; + + if (!(args = PyTuple_Pack(1, Py_None))) { + return NULL; + } + + if (!(kwargs = PyDict_New()) || PyDict_SetItemString(kwargs, "c", Py_None)) { + Py_DECREF(args); + Py_XDECREF(kwargs); + return NULL; + } + + for (n = 0;formats_3[n];++n) { + if (PyArg_ParseTupleAndKeywords(args, kwargs, formats_3[n], + (char**) keywords, + &tmp, &tmp, &tmp)) { + Py_DECREF(args); + return raiseTestError("test_w_code_invalid_suffix", + formats_3[n]); + } + else { + PyErr_Clear(); + } + } + + if (PyDict_DelItemString(kwargs, "c") || + PyDict_SetItemString(kwargs, "d", Py_None)) { + + Py_DECREF(kwargs); + Py_DECREF(args); + return NULL; + } + + for (n = 0;formats_4[n];++n) { + if (PyArg_ParseTupleAndKeywords(args, kwargs, formats_4[n], + (char**) keywords, + &tmp, &tmp, &tmp, &tmp)) { + Py_DECREF(args); + return raiseTestError("test_w_code_invalid_suffix", + formats_4[n]); + } + else { + PyErr_Clear(); + } + } + + Py_DECREF(args); + Py_DECREF(kwargs); + Py_RETURN_NONE; +} + static PyObject * test_widechar(PyObject *self) { @@ -3600,6 +3671,7 @@ {"test_s_code", (PyCFunction)test_s_code, METH_NOARGS}, {"test_u_code", (PyCFunction)test_u_code, METH_NOARGS}, {"test_Z_code", (PyCFunction)test_Z_code, METH_NOARGS}, + {"test_w_code_invalid", (PyCFunction)test_w_code_invalid,METH_NOARGS}, {"test_widechar", (PyCFunction)test_widechar, METH_NOARGS}, {"unicode_aswidechar", unicode_aswidechar, METH_VARARGS}, {"unicode_aswidecharstring",unicode_aswidecharstring, METH_VARARGS}, diff -r 0b04e5689c33 Python/getargs.c --- a/Python/getargs.c Wed Jul 15 22:12:33 2015 +0300 +++ b/Python/getargs.c Wed Jul 15 18:22:56 2015 -0400 @@ -1671,6 +1671,14 @@ /* string codes */ + case 'w': /* buffer, read-write */ + if (*format != '*') { + /* after 'w', only '*' is allowed */ + goto err; + } + format++; + break; + case 'e': /* string with encoding */ { (void) va_arg(*p_va, const char *); @@ -1686,7 +1694,6 @@ case 'y': /* bytes */ case 'u': /* unicode string */ case 'Z': /* unicode string or None */ - case 'w': /* buffer, read-write */ { (void) va_arg(*p_va, char **); if (*format == '#') {