This commit is contained in:
Benjamin Peterson 2012-12-19 15:28:46 -06:00
commit 7643c92cdd
3 changed files with 37 additions and 5 deletions

View File

@ -715,6 +715,12 @@ class BytesTest(BaseBytesTest):
def __bytes__(self):
return None
self.assertRaises(TypeError, bytes, A())
class A:
def __bytes__(self):
return b'a'
def __index__(self):
return 42
self.assertEqual(bytes(A()), b'a')
# Test PyBytes_FromFormat()
def test_from_format(self):

View File

@ -10,6 +10,9 @@ What's New in Python 3.4.0 Alpha 1?
Core and Builtins
-----------------
- Issue #16722: In the bytes() constructor, try to call __bytes__ on the
argument before __index__.
- Issue #16421: loading multiple modules from one shared object is now
handled correctly (previously, the first module loaded from that file
was silently returned). Patch by Václav Šmilauer.

View File

@ -2428,8 +2428,10 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
const char *encoding = NULL;
const char *errors = NULL;
PyObject *new = NULL;
PyObject *func;
Py_ssize_t size;
static char *kwlist[] = {"source", "encoding", "errors", 0};
_Py_IDENTIFIER(__bytes__);
if (type != &PyBytes_Type)
return str_subtype_new(type, args, kwds);
@ -2459,6 +2461,28 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
assert(PyBytes_Check(new));
return new;
}
/* We'd like to call PyObject_Bytes here, but we need to check for an
integer argument before deferring to PyBytes_FromObject, something
PyObject_Bytes doesn't do. */
func = _PyObject_LookupSpecial(x, &PyId___bytes__);
if (func != NULL) {
new = PyObject_CallFunctionObjArgs(func, NULL);
Py_DECREF(func);
if (new == NULL)
return NULL;
if (!PyBytes_Check(new)) {
PyErr_Format(PyExc_TypeError,
"__bytes__ returned non-bytes (type %.200s)",
Py_TYPE(new)->tp_name);
Py_DECREF(new);
return NULL;
}
return new;
}
else if (PyErr_Occurred())
return NULL;
/* Is it an integer? */
size = PyNumber_AsSsize_t(x, PyExc_OverflowError);
if (size == -1 && PyErr_Occurred()) {
@ -2472,12 +2496,10 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
}
else {
new = PyBytes_FromStringAndSize(NULL, size);
if (new == NULL) {
if (new == NULL)
return NULL;
}
if (size > 0) {
if (size > 0)
memset(((PyBytesObject*)new)->ob_sval, 0, size);
}
return new;
}
@ -2487,7 +2509,8 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
"encoding or errors without a string argument");
return NULL;
}
return PyObject_Bytes(x);
return PyBytes_FromObject(x);
}
PyObject *