diff -r c852c7d8d681 Lib/test/test_bytes.py --- a/Lib/test/test_bytes.py Sun Nov 29 13:14:00 2015 +0200 +++ b/Lib/test/test_bytes.py Sun Nov 29 22:23:41 2015 +0200 @@ -793,6 +793,11 @@ class BytesTest(BaseBytesTest, unittest. def __index__(self): return 42 self.assertEqual(bytes(A()), b'a') + # Issue #XXX + class A(str): + def __bytes__(self): + return b'abc' + self.assertEqual(bytes(A()), b'abc') # Issue #24731 class A: def __bytes__(self): diff -r c852c7d8d681 Objects/bytesobject.c --- a/Objects/bytesobject.c Sun Nov 29 13:14:00 2015 +0200 +++ b/Objects/bytesobject.c Sun Nov 29 22:23:41 2015 +0200 @@ -3320,11 +3320,11 @@ bytes_new(PyTypeObject *type, PyObject * return PyBytes_FromStringAndSize(NULL, 0); } - if (PyUnicode_Check(x)) { + if (encoding != NULL) { /* Encode via the codec registry */ - if (encoding == NULL) { + if (!PyUnicode_Check(x)) { PyErr_SetString(PyExc_TypeError, - "string argument without an encoding"); + "encoding without a string argument"); return NULL; } new = PyUnicode_AsEncodedString(x, encoding, errors); @@ -3334,10 +3334,11 @@ bytes_new(PyTypeObject *type, PyObject * return new; } - /* If it's not unicode, there can't be encoding or errors */ - if (encoding != NULL || errors != NULL) { + if (errors != NULL) { PyErr_SetString(PyExc_TypeError, - "encoding or errors without a string argument"); + PyUnicode_Check(x) ? + "string argument without an encoding" : + "errors without a string argument"); return NULL; } @@ -3362,6 +3363,11 @@ bytes_new(PyTypeObject *type, PyObject * else if (PyErr_Occurred()) return NULL; + if (PyUnicode_Check(x)) { + PyErr_SetString(PyExc_TypeError, + "string argument without an encoding"); + return NULL; + } /* Is it an integer? */ size = PyNumber_AsSsize_t(x, PyExc_OverflowError); if (size == -1 && PyErr_Occurred()) {