[Python-checkins] cpython (3.3): try to call __bytes__ before __index__ (closes #16722)
benjamin.peterson
python-checkins at python.org
Wed Dec 19 22:29:10 CET 2012
http://hg.python.org/cpython/rev/c744b6f8a09a
changeset: 80954:c744b6f8a09a
branch: 3.3
parent: 80950:55d86476d048
user: Benjamin Peterson <benjamin at python.org>
date: Wed Dec 19 15:27:41 2012 -0600
summary:
try to call __bytes__ before __index__ (closes #16722)
files:
Lib/test/test_bytes.py | 6 +++++
Misc/NEWS | 3 ++
Objects/bytesobject.c | 33 +++++++++++++++++++++++++----
3 files changed, 37 insertions(+), 5 deletions(-)
diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py
--- a/Lib/test/test_bytes.py
+++ b/Lib/test/test_bytes.py
@@ -701,6 +701,12 @@
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):
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@
Core and Builtins
-----------------
+- Issue #16722: In the bytes() constructor, try to call __bytes__ on the
+ argument before __index__.
+
- Issue #16602: When a weakref's target was part of a long deallocation
chain, the object could remain reachable through its weakref even though
its refcount had dropped to zero.
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -2505,8 +2505,10 @@
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);
@@ -2536,6 +2538,28 @@
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()) {
@@ -2549,12 +2573,10 @@
}
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;
}
@@ -2564,7 +2586,8 @@
"encoding or errors without a string argument");
return NULL;
}
- return PyObject_Bytes(x);
+
+ return PyBytes_FromObject(x);
}
PyObject *
--
Repository URL: http://hg.python.org/cpython
More information about the Python-checkins
mailing list