#16518: Bring error messages in harmony with docs ("bytes-like object")

Some time ago we changed the docs to consistently use the term 'bytes-like
object' in all the contexts where bytes, bytearray, memoryview, etc are used.
This patch (by Ezio Melotti) completes that work by changing the error
messages that previously reported that certain types did "not support the
buffer interface" to instead say that a bytes-like object is required.  (The
glossary entry for bytes-like object references the discussion of the buffer
protocol in the docs.)
This commit is contained in:
R David Murray 2014-10-05 11:47:01 -04:00
parent d577cea8ab
commit 861470c836
11 changed files with 30 additions and 22 deletions

View File

@ -393,6 +393,12 @@ Changes in the Python API
The *convert_charrefs* argument of :class:`~html.parser.HTMLParser` is The *convert_charrefs* argument of :class:`~html.parser.HTMLParser` is
now ``True`` by default (contributed by Berker Peksag in :issue:`21047`). now ``True`` by default (contributed by Berker Peksag in :issue:`21047`).
* Although it is not formally part of the API, it is worth noting for porting
purposes (ie: fixing tests) that error messages that were previously of the
form "'sometype' does not support the buffer protocol" are now of the form "a
bytes-like object is required, not 'sometype'" (contributed by Ezio Melotti
in :issue:`16518`).
Changes in the C API Changes in the C API
-------------------- --------------------

View File

@ -711,11 +711,11 @@ class GeneralModuleTests(unittest.TestCase):
with self.assertRaises(TypeError) as cm: with self.assertRaises(TypeError) as cm:
s.sendto('\u2620', sockname) s.sendto('\u2620', sockname)
self.assertEqual(str(cm.exception), self.assertEqual(str(cm.exception),
"'str' does not support the buffer interface") "a bytes-like object is required, not 'str'")
with self.assertRaises(TypeError) as cm: with self.assertRaises(TypeError) as cm:
s.sendto(5j, sockname) s.sendto(5j, sockname)
self.assertEqual(str(cm.exception), self.assertEqual(str(cm.exception),
"'complex' does not support the buffer interface") "a bytes-like object is required, not 'complex'")
with self.assertRaises(TypeError) as cm: with self.assertRaises(TypeError) as cm:
s.sendto(b'foo', None) s.sendto(b'foo', None)
self.assertIn('not NoneType',str(cm.exception)) self.assertIn('not NoneType',str(cm.exception))
@ -723,11 +723,11 @@ class GeneralModuleTests(unittest.TestCase):
with self.assertRaises(TypeError) as cm: with self.assertRaises(TypeError) as cm:
s.sendto('\u2620', 0, sockname) s.sendto('\u2620', 0, sockname)
self.assertEqual(str(cm.exception), self.assertEqual(str(cm.exception),
"'str' does not support the buffer interface") "a bytes-like object is required, not 'str'")
with self.assertRaises(TypeError) as cm: with self.assertRaises(TypeError) as cm:
s.sendto(5j, 0, sockname) s.sendto(5j, 0, sockname)
self.assertEqual(str(cm.exception), self.assertEqual(str(cm.exception),
"'complex' does not support the buffer interface") "a bytes-like object is required, not 'complex'")
with self.assertRaises(TypeError) as cm: with self.assertRaises(TypeError) as cm:
s.sendto(b'foo', 0, None) s.sendto(b'foo', 0, None)
self.assertIn('not NoneType', str(cm.exception)) self.assertIn('not NoneType', str(cm.exception))

View File

@ -10,6 +10,10 @@ Release date: TBA
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #16518: Use 'bytes-like object required' in error messages that
previously used the far more cryptic "'x' does not support the buffer
protocol.
- Issue #22470: Fixed integer overflow issues in "backslashreplace", - Issue #22470: Fixed integer overflow issues in "backslashreplace",
"xmlcharrefreplace", and "surrogatepass" error handlers. "xmlcharrefreplace", and "surrogatepass" error handlers.

View File

@ -241,7 +241,7 @@ PyDoc_STRVAR(compare_digest__doc__,
"Return 'a == b'. This function uses an approach designed to prevent\n" "Return 'a == b'. This function uses an approach designed to prevent\n"
"timing analysis, making it appropriate for cryptography.\n" "timing analysis, making it appropriate for cryptography.\n"
"a and b must both be of the same type: either str (ASCII only),\n" "a and b must both be of the same type: either str (ASCII only),\n"
"or any type that supports the buffer protocol (e.g. bytes).\n" "or any bytes-like object.\n"
"\n" "\n"
"Note: If a and b are of different lengths, or if an error occurs,\n" "Note: If a and b are of different lengths, or if an error occurs,\n"
"a timing attack could theoretically reveal information about the\n" "a timing attack could theoretically reveal information about the\n"

View File

@ -260,8 +260,7 @@ PyObject_AsCharBuffer(PyObject *obj,
pb = obj->ob_type->tp_as_buffer; pb = obj->ob_type->tp_as_buffer;
if (pb == NULL || pb->bf_getbuffer == NULL) { if (pb == NULL || pb->bf_getbuffer == NULL) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"expected bytes, bytearray " "expected a bytes-like object");
"or buffer compatible object");
return -1; return -1;
} }
if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE)) return -1; if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE)) return -1;
@ -306,7 +305,7 @@ int PyObject_AsReadBuffer(PyObject *obj,
if (pb == NULL || if (pb == NULL ||
pb->bf_getbuffer == NULL) { pb->bf_getbuffer == NULL) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"expected an object with a buffer interface"); "expected a bytes-like object");
return -1; return -1;
} }
@ -336,7 +335,7 @@ int PyObject_AsWriteBuffer(PyObject *obj,
pb->bf_getbuffer == NULL || pb->bf_getbuffer == NULL ||
((*pb->bf_getbuffer)(obj, &view, PyBUF_WRITABLE) != 0)) { ((*pb->bf_getbuffer)(obj, &view, PyBUF_WRITABLE) != 0)) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"expected an object with a writable buffer interface"); "expected a writable bytes-like object");
return -1; return -1;
} }
@ -355,7 +354,7 @@ PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags)
{ {
if (!PyObject_CheckBuffer(obj)) { if (!PyObject_CheckBuffer(obj)) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"'%.100s' does not support the buffer interface", "a bytes-like object is required, not '%.100s'",
Py_TYPE(obj)->tp_name); Py_TYPE(obj)->tp_name);
return -1; return -1;
} }
@ -530,8 +529,8 @@ int PyObject_CopyData(PyObject *dest, PyObject *src)
if (!PyObject_CheckBuffer(dest) || if (!PyObject_CheckBuffer(dest) ||
!PyObject_CheckBuffer(src)) { !PyObject_CheckBuffer(src)) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"both destination and source must have the "\ "both destination and source must be "\
"buffer interface"); "bytes-like objects");
return -1; return -1;
} }

View File

@ -87,7 +87,7 @@ _getbuffer(PyObject *obj, Py_buffer *view)
if (buffer == NULL || buffer->bf_getbuffer == NULL) if (buffer == NULL || buffer->bf_getbuffer == NULL)
{ {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"Type %.100s doesn't support the buffer API", "a bytes-like object is required, not '%.100s'",
Py_TYPE(obj)->tp_name); Py_TYPE(obj)->tp_name);
return -1; return -1;
} }

View File

@ -371,7 +371,7 @@ _getbuffer(PyObject *obj, Py_buffer *view)
if (buffer == NULL || buffer->bf_getbuffer == NULL) if (buffer == NULL || buffer->bf_getbuffer == NULL)
{ {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"Type %.100s doesn't support the buffer API", "a bytes-like object is required, not '%.100s'",
Py_TYPE(obj)->tp_name); Py_TYPE(obj)->tp_name);
return -1; return -1;
} }

View File

@ -29,7 +29,7 @@ _getbuffer(PyObject *obj, Py_buffer *view)
if (bufferprocs == NULL || bufferprocs->bf_getbuffer == NULL) if (bufferprocs == NULL || bufferprocs->bf_getbuffer == NULL)
{ {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"Type %.100s doesn't support the buffer API", "a bytes-like object is required, not '%.100s'",
Py_TYPE(obj)->tp_name); Py_TYPE(obj)->tp_name);
return -1; return -1;
} }

View File

@ -4873,9 +4873,7 @@ PyDoc_STRVAR(long_from_bytes_doc,
\n\ \n\
Return the integer represented by the given array of bytes.\n\ Return the integer represented by the given array of bytes.\n\
\n\ \n\
The bytes argument must either support the buffer protocol or be an\n\ The bytes argument must be a bytes-like object (e.g. bytes or bytearray).\n\
iterable object producing bytes. Bytes and bytearray are examples of\n\
built-in objects that support the buffer protocol.\n\
\n\ \n\
The byteorder argument determines the byte order used to represent the\n\ The byteorder argument determines the byte order used to represent the\n\
integer. If byteorder is 'big', the most significant byte is at the\n\ integer. If byteorder is 'big', the most significant byte is at the\n\

View File

@ -792,7 +792,7 @@ PyMemoryView_FromObject(PyObject *v)
} }
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"memoryview: %.200s object does not have the buffer interface", "memoryview: a bytes-like object is required, not '%.200s'",
Py_TYPE(v)->tp_name); Py_TYPE(v)->tp_name);
return NULL; return NULL;
} }

View File

@ -1244,7 +1244,8 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
supports it directly. */ supports it directly. */
if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) {
PyErr_Clear(); PyErr_Clear();
return converterr("read-write buffer", arg, msgbuf, bufsize); return converterr("read-write bytes-like object",
arg, msgbuf, bufsize);
} }
if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) { if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) {
PyBuffer_Release((Py_buffer*)p); PyBuffer_Release((Py_buffer*)p);
@ -1282,7 +1283,7 @@ convertbuffer(PyObject *arg, void **p, char **errmsg)
*errmsg = NULL; *errmsg = NULL;
*p = NULL; *p = NULL;
if (pb != NULL && pb->bf_releasebuffer != NULL) { if (pb != NULL && pb->bf_releasebuffer != NULL) {
*errmsg = "read-only pinned buffer"; *errmsg = "read-only bytes-like object";
return -1; return -1;
} }
@ -1298,7 +1299,7 @@ static int
getbuffer(PyObject *arg, Py_buffer *view, char **errmsg) getbuffer(PyObject *arg, Py_buffer *view, char **errmsg)
{ {
if (PyObject_GetBuffer(arg, view, PyBUF_SIMPLE) != 0) { if (PyObject_GetBuffer(arg, view, PyBUF_SIMPLE) != 0) {
*errmsg = "bytes or buffer"; *errmsg = "bytes-like object";
return -1; return -1;
} }
if (!PyBuffer_IsContiguous(view, 'C')) { if (!PyBuffer_IsContiguous(view, 'C')) {