From 9a54d7c3506441bb017b06a2cecd0de9888645a9 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Wed, 16 Jul 2008 23:15:30 +0000 Subject: [PATCH] Merged revisions 65041 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r65041 | georg.brandl | 2008-07-17 00:57:41 +0200 (Thu, 17 Jul 2008) | 3 lines #3156: fix consistency in what type bytearray methods accept as items. Also rename confusing "item" parameters to "index". ........ --- Lib/test/test_bytes.py | 38 ++++++++++-------- Objects/bytearrayobject.c | 81 ++++++++++++++++----------------------- 2 files changed, 57 insertions(+), 62 deletions(-) diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py index 4b346d6fee..5bda9354d2 100644 --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -17,6 +17,12 @@ import test.support import test.string_tests import test.buffer_tests +class Indexable: + def __init__(self, value=0): + self.value = value + def __index__(self): + return self.value + class BaseBytesTest(unittest.TestCase): @@ -53,15 +59,11 @@ class BaseBytesTest(unittest.TestCase): self.assertEqual(list(b), ints) def test_from_index(self): - class C: - def __init__(self, i=0): - self.i = i - def __index__(self): - return self.i - b = self.type2test([C(), C(1), C(254), C(255)]) + b = self.type2test([Indexable(), Indexable(1), Indexable(254), + Indexable(255)]) self.assertEqual(list(b), [0, 1, 254, 255]) - self.assertRaises(ValueError, bytearray, [C(-1)]) - self.assertRaises(ValueError, bytearray, [C(256)]) + self.assertRaises(ValueError, bytearray, [Indexable(-1)]) + self.assertRaises(ValueError, bytearray, [Indexable(256)]) def test_from_ssize(self): self.assertEqual(bytearray(0), b'') @@ -506,12 +508,7 @@ class ByteArrayTest(BaseBytesTest): self.assertEqual(b, bytearray([1, 100, 3])) b[-1] = 200 self.assertEqual(b, bytearray([1, 100, 200])) - class C: - def __init__(self, i=0): - self.i = i - def __index__(self): - return self.i - b[0] = C(10) + b[0] = Indexable(10) self.assertEqual(b, bytearray([10, 100, 200])) try: b[3] = 0 @@ -529,7 +526,7 @@ class ByteArrayTest(BaseBytesTest): except ValueError: pass try: - b[0] = C(-1) + b[0] = Indexable(-1) self.fail("Didn't raise ValueError") except ValueError: pass @@ -665,6 +662,9 @@ class ByteArrayTest(BaseBytesTest): self.assertRaises(ValueError, a.extend, [0, 1, 2, 256]) self.assertRaises(ValueError, a.extend, [0, 1, 2, -1]) self.assertEqual(len(a), 0) + a = bytearray(b'') + a.extend([Indexable(ord('a'))]) + self.assertEqual(a, b'a') def test_remove(self): b = bytearray(b'hello') @@ -680,6 +680,8 @@ class ByteArrayTest(BaseBytesTest): b.remove(ord('h')) self.assertEqual(b, b'e') self.assertRaises(TypeError, lambda: b.remove(b'e')) + b.remove(Indexable(ord('e'))) + self.assertEqual(b, b'') def test_pop(self): b = bytearray(b'world') @@ -701,6 +703,9 @@ class ByteArrayTest(BaseBytesTest): b.append(ord('A')) self.assertEqual(len(b), 1) self.assertRaises(TypeError, lambda: b.append(b'o')) + b = bytearray() + b.append(Indexable(ord('A'))) + self.assertEqual(b, b'A') def test_insert(self): b = bytearray(b'msssspp') @@ -710,6 +715,9 @@ class ByteArrayTest(BaseBytesTest): b.insert(1000, ord('i')) self.assertEqual(b, b'mississippi') self.assertRaises(TypeError, lambda: b.insert(0, b'1')) + b = bytearray() + b.insert(0, Indexable(ord('A'))) + self.assertEqual(b, b'A') def test_partition_bytearray_doesnt_share_nullstring(self): a, b, c = bytearray(b"x").partition(b"y") diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 0dfd25be6f..0d256b9696 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -36,12 +36,19 @@ _getbytevalue(PyObject* arg, int *value) if (PyLong_Check(arg)) { face_value = PyLong_AsLong(arg); - if (face_value < 0 || face_value >= 256) { - PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); + } else { + PyObject *index = PyNumber_Index(arg); + if (index == NULL) { + PyErr_Format(PyExc_TypeError, "an integer is required"); return 0; } - } else { - PyErr_Format(PyExc_TypeError, "an integer is required"); + face_value = PyLong_AsLong(index); + Py_DECREF(index); + } + + if (face_value < 0 || face_value >= 256) { + /* this includes the OverflowError in case the long is too large */ + PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); return 0; } @@ -358,10 +365,10 @@ bytes_getitem(PyByteArrayObject *self, Py_ssize_t i) } static PyObject * -bytes_subscript(PyByteArrayObject *self, PyObject *item) +bytes_subscript(PyByteArrayObject *self, PyObject *index) { - if (PyIndex_Check(item)) { - Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (PyIndex_Check(index)) { + Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) return NULL; @@ -375,9 +382,9 @@ bytes_subscript(PyByteArrayObject *self, PyObject *item) } return PyLong_FromLong((unsigned char)(self->ob_bytes[i])); } - else if (PySlice_Check(item)) { + else if (PySlice_Check(index)) { Py_ssize_t start, stop, step, slicelength, cur, i; - if (PySlice_GetIndicesEx((PySliceObject *)item, + if (PySlice_GetIndicesEx((PySliceObject *)index, PyByteArray_GET_SIZE(self), &start, &stop, &step, &slicelength) < 0) { return NULL; @@ -501,7 +508,7 @@ bytes_setslice(PyByteArrayObject *self, Py_ssize_t lo, Py_ssize_t hi, static int bytes_setitem(PyByteArrayObject *self, Py_ssize_t i, PyObject *value) { - Py_ssize_t ival; + int ival; if (i < 0) i += Py_SIZE(self); @@ -514,27 +521,21 @@ bytes_setitem(PyByteArrayObject *self, Py_ssize_t i, PyObject *value) if (value == NULL) return bytes_setslice(self, i, i+1, NULL); - ival = PyNumber_AsSsize_t(value, PyExc_ValueError); - if (ival == -1 && PyErr_Occurred()) - return -1; - - if (ival < 0 || ival >= 256) { - PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); + if (!_getbytevalue(value, &ival)) return -1; - } self->ob_bytes[i] = ival; return 0; } static int -bytes_ass_subscript(PyByteArrayObject *self, PyObject *item, PyObject *values) +bytes_ass_subscript(PyByteArrayObject *self, PyObject *index, PyObject *values) { Py_ssize_t start, stop, step, slicelen, needed; char *bytes; - if (PyIndex_Check(item)) { - Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (PyIndex_Check(index)) { + Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) return -1; @@ -555,20 +556,15 @@ bytes_ass_subscript(PyByteArrayObject *self, PyObject *item, PyObject *values) slicelen = 1; } else { - Py_ssize_t ival = PyNumber_AsSsize_t(values, PyExc_ValueError); - if (ival == -1 && PyErr_Occurred()) - return -1; - if (ival < 0 || ival >= 256) { - PyErr_SetString(PyExc_ValueError, - "byte must be in range(0, 256)"); + int ival; + if (!_getbytevalue(values, &ival)) return -1; - } self->ob_bytes[i] = (char)ival; return 0; } } - else if (PySlice_Check(item)) { - if (PySlice_GetIndicesEx((PySliceObject *)item, + else if (PySlice_Check(index)) { + if (PySlice_GetIndicesEx((PySliceObject *)index, PyByteArray_GET_SIZE(self), &start, &stop, &step, &slicelen) < 0) { return -1; @@ -589,7 +585,7 @@ bytes_ass_subscript(PyByteArrayObject *self, PyObject *item, PyObject *values) values = PyByteArray_FromObject(values); if (values == NULL) return -1; - err = bytes_ass_subscript(self, item, values); + err = bytes_ass_subscript(self, index, values); Py_DECREF(values); return err; } @@ -789,7 +785,7 @@ bytes_init(PyByteArrayObject *self, PyObject *args, PyObject *kwds) /* Run the iterator to exhaustion */ for (;;) { PyObject *item; - Py_ssize_t value; + int rc, value; /* Get the next item */ item = iternext(it); @@ -803,18 +799,11 @@ bytes_init(PyByteArrayObject *self, PyObject *args, PyObject *kwds) } /* Interpret it as an int (__index__) */ - value = PyNumber_AsSsize_t(item, PyExc_ValueError); + rc = _getbytevalue(item, &value); Py_DECREF(item); - if (value == -1 && PyErr_Occurred()) + if (!rc) goto error; - /* Range check */ - if (value < 0 || value >= 256) { - PyErr_SetString(PyExc_ValueError, - "bytes must be in range(0, 256)"); - goto error; - } - /* Append the byte */ if (Py_SIZE(self) < self->ob_alloc) Py_SIZE(self)++; @@ -2517,10 +2506,11 @@ Insert a single item into the bytearray before the given index."); static PyObject * bytes_insert(PyByteArrayObject *self, PyObject *args) { - int value; + PyObject *value; + int ival; Py_ssize_t where, n = Py_SIZE(self); - if (!PyArg_ParseTuple(args, "ni:insert", &where, &value)) + if (!PyArg_ParseTuple(args, "nO:insert", &where, &value)) return NULL; if (n == PY_SSIZE_T_MAX) { @@ -2528,11 +2518,8 @@ bytes_insert(PyByteArrayObject *self, PyObject *args) "cannot add more objects to bytes"); return NULL; } - if (value < 0 || value >= 256) { - PyErr_SetString(PyExc_ValueError, - "byte must be in range(0, 256)"); + if (!_getbytevalue(value, &ival)) return NULL; - } if (PyByteArray_Resize((PyObject *)self, n + 1) < 0) return NULL; @@ -2544,7 +2531,7 @@ bytes_insert(PyByteArrayObject *self, PyObject *args) if (where > n) where = n; memmove(self->ob_bytes + where + 1, self->ob_bytes + where, n - where); - self->ob_bytes[where] = value; + self->ob_bytes[where] = ival; Py_RETURN_NONE; } -- 2.40.0