Commit 9a54d7c3 authored by Georg Brandl's avatar Georg Brandl

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".
........
parent 01ca04cc
...@@ -17,6 +17,12 @@ import test.support ...@@ -17,6 +17,12 @@ import test.support
import test.string_tests import test.string_tests
import test.buffer_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): class BaseBytesTest(unittest.TestCase):
...@@ -53,15 +59,11 @@ class BaseBytesTest(unittest.TestCase): ...@@ -53,15 +59,11 @@ class BaseBytesTest(unittest.TestCase):
self.assertEqual(list(b), ints) self.assertEqual(list(b), ints)
def test_from_index(self): def test_from_index(self):
class C: b = self.type2test([Indexable(), Indexable(1), Indexable(254),
def __init__(self, i=0): Indexable(255)])
self.i = i
def __index__(self):
return self.i
b = self.type2test([C(), C(1), C(254), C(255)])
self.assertEqual(list(b), [0, 1, 254, 255]) self.assertEqual(list(b), [0, 1, 254, 255])
self.assertRaises(ValueError, bytearray, [C(-1)]) self.assertRaises(ValueError, bytearray, [Indexable(-1)])
self.assertRaises(ValueError, bytearray, [C(256)]) self.assertRaises(ValueError, bytearray, [Indexable(256)])
def test_from_ssize(self): def test_from_ssize(self):
self.assertEqual(bytearray(0), b'') self.assertEqual(bytearray(0), b'')
...@@ -506,12 +508,7 @@ class ByteArrayTest(BaseBytesTest): ...@@ -506,12 +508,7 @@ class ByteArrayTest(BaseBytesTest):
self.assertEqual(b, bytearray([1, 100, 3])) self.assertEqual(b, bytearray([1, 100, 3]))
b[-1] = 200 b[-1] = 200
self.assertEqual(b, bytearray([1, 100, 200])) self.assertEqual(b, bytearray([1, 100, 200]))
class C: b[0] = Indexable(10)
def __init__(self, i=0):
self.i = i
def __index__(self):
return self.i
b[0] = C(10)
self.assertEqual(b, bytearray([10, 100, 200])) self.assertEqual(b, bytearray([10, 100, 200]))
try: try:
b[3] = 0 b[3] = 0
...@@ -529,7 +526,7 @@ class ByteArrayTest(BaseBytesTest): ...@@ -529,7 +526,7 @@ class ByteArrayTest(BaseBytesTest):
except ValueError: except ValueError:
pass pass
try: try:
b[0] = C(-1) b[0] = Indexable(-1)
self.fail("Didn't raise ValueError") self.fail("Didn't raise ValueError")
except ValueError: except ValueError:
pass pass
...@@ -665,6 +662,9 @@ class ByteArrayTest(BaseBytesTest): ...@@ -665,6 +662,9 @@ class ByteArrayTest(BaseBytesTest):
self.assertRaises(ValueError, a.extend, [0, 1, 2, 256]) self.assertRaises(ValueError, a.extend, [0, 1, 2, 256])
self.assertRaises(ValueError, a.extend, [0, 1, 2, -1]) self.assertRaises(ValueError, a.extend, [0, 1, 2, -1])
self.assertEqual(len(a), 0) self.assertEqual(len(a), 0)
a = bytearray(b'')
a.extend([Indexable(ord('a'))])
self.assertEqual(a, b'a')
def test_remove(self): def test_remove(self):
b = bytearray(b'hello') b = bytearray(b'hello')
...@@ -680,6 +680,8 @@ class ByteArrayTest(BaseBytesTest): ...@@ -680,6 +680,8 @@ class ByteArrayTest(BaseBytesTest):
b.remove(ord('h')) b.remove(ord('h'))
self.assertEqual(b, b'e') self.assertEqual(b, b'e')
self.assertRaises(TypeError, lambda: b.remove(b'e')) self.assertRaises(TypeError, lambda: b.remove(b'e'))
b.remove(Indexable(ord('e')))
self.assertEqual(b, b'')
def test_pop(self): def test_pop(self):
b = bytearray(b'world') b = bytearray(b'world')
...@@ -701,6 +703,9 @@ class ByteArrayTest(BaseBytesTest): ...@@ -701,6 +703,9 @@ class ByteArrayTest(BaseBytesTest):
b.append(ord('A')) b.append(ord('A'))
self.assertEqual(len(b), 1) self.assertEqual(len(b), 1)
self.assertRaises(TypeError, lambda: b.append(b'o')) self.assertRaises(TypeError, lambda: b.append(b'o'))
b = bytearray()
b.append(Indexable(ord('A')))
self.assertEqual(b, b'A')
def test_insert(self): def test_insert(self):
b = bytearray(b'msssspp') b = bytearray(b'msssspp')
...@@ -710,6 +715,9 @@ class ByteArrayTest(BaseBytesTest): ...@@ -710,6 +715,9 @@ class ByteArrayTest(BaseBytesTest):
b.insert(1000, ord('i')) b.insert(1000, ord('i'))
self.assertEqual(b, b'mississippi') self.assertEqual(b, b'mississippi')
self.assertRaises(TypeError, lambda: b.insert(0, b'1')) 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): def test_partition_bytearray_doesnt_share_nullstring(self):
a, b, c = bytearray(b"x").partition(b"y") a, b, c = bytearray(b"x").partition(b"y")
......
...@@ -36,12 +36,19 @@ _getbytevalue(PyObject* arg, int *value) ...@@ -36,12 +36,19 @@ _getbytevalue(PyObject* arg, int *value)
if (PyLong_Check(arg)) { if (PyLong_Check(arg)) {
face_value = PyLong_AsLong(arg); face_value = PyLong_AsLong(arg);
if (face_value < 0 || face_value >= 256) { } else {
PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); PyObject *index = PyNumber_Index(arg);
if (index == NULL) {
PyErr_Format(PyExc_TypeError, "an integer is required");
return 0; return 0;
} }
} else { face_value = PyLong_AsLong(index);
PyErr_Format(PyExc_TypeError, "an integer is required"); 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; return 0;
} }
...@@ -358,10 +365,10 @@ bytes_getitem(PyByteArrayObject *self, Py_ssize_t i) ...@@ -358,10 +365,10 @@ bytes_getitem(PyByteArrayObject *self, Py_ssize_t i)
} }
static PyObject * static PyObject *
bytes_subscript(PyByteArrayObject *self, PyObject *item) bytes_subscript(PyByteArrayObject *self, PyObject *index)
{ {
if (PyIndex_Check(item)) { if (PyIndex_Check(index)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError);
if (i == -1 && PyErr_Occurred()) if (i == -1 && PyErr_Occurred())
return NULL; return NULL;
...@@ -375,9 +382,9 @@ bytes_subscript(PyByteArrayObject *self, PyObject *item) ...@@ -375,9 +382,9 @@ bytes_subscript(PyByteArrayObject *self, PyObject *item)
} }
return PyLong_FromLong((unsigned char)(self->ob_bytes[i])); 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; Py_ssize_t start, stop, step, slicelength, cur, i;
if (PySlice_GetIndicesEx((PySliceObject *)item, if (PySlice_GetIndicesEx((PySliceObject *)index,
PyByteArray_GET_SIZE(self), PyByteArray_GET_SIZE(self),
&start, &stop, &step, &slicelength) < 0) { &start, &stop, &step, &slicelength) < 0) {
return NULL; return NULL;
...@@ -501,7 +508,7 @@ bytes_setslice(PyByteArrayObject *self, Py_ssize_t lo, Py_ssize_t hi, ...@@ -501,7 +508,7 @@ bytes_setslice(PyByteArrayObject *self, Py_ssize_t lo, Py_ssize_t hi,
static int static int
bytes_setitem(PyByteArrayObject *self, Py_ssize_t i, PyObject *value) bytes_setitem(PyByteArrayObject *self, Py_ssize_t i, PyObject *value)
{ {
Py_ssize_t ival; int ival;
if (i < 0) if (i < 0)
i += Py_SIZE(self); i += Py_SIZE(self);
...@@ -514,27 +521,21 @@ bytes_setitem(PyByteArrayObject *self, Py_ssize_t i, PyObject *value) ...@@ -514,27 +521,21 @@ bytes_setitem(PyByteArrayObject *self, Py_ssize_t i, PyObject *value)
if (value == NULL) if (value == NULL)
return bytes_setslice(self, i, i+1, NULL); return bytes_setslice(self, i, i+1, NULL);
ival = PyNumber_AsSsize_t(value, PyExc_ValueError); if (!_getbytevalue(value, &ival))
if (ival == -1 && PyErr_Occurred())
return -1;
if (ival < 0 || ival >= 256) {
PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
return -1; return -1;
}
self->ob_bytes[i] = ival; self->ob_bytes[i] = ival;
return 0; return 0;
} }
static int 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; Py_ssize_t start, stop, step, slicelen, needed;
char *bytes; char *bytes;
if (PyIndex_Check(item)) { if (PyIndex_Check(index)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError);
if (i == -1 && PyErr_Occurred()) if (i == -1 && PyErr_Occurred())
return -1; return -1;
...@@ -555,20 +556,15 @@ bytes_ass_subscript(PyByteArrayObject *self, PyObject *item, PyObject *values) ...@@ -555,20 +556,15 @@ bytes_ass_subscript(PyByteArrayObject *self, PyObject *item, PyObject *values)
slicelen = 1; slicelen = 1;
} }
else { else {
Py_ssize_t ival = PyNumber_AsSsize_t(values, PyExc_ValueError); int ival;
if (ival == -1 && PyErr_Occurred()) if (!_getbytevalue(values, &ival))
return -1;
if (ival < 0 || ival >= 256) {
PyErr_SetString(PyExc_ValueError,
"byte must be in range(0, 256)");
return -1; return -1;
}
self->ob_bytes[i] = (char)ival; self->ob_bytes[i] = (char)ival;
return 0; return 0;
} }
} }
else if (PySlice_Check(item)) { else if (PySlice_Check(index)) {
if (PySlice_GetIndicesEx((PySliceObject *)item, if (PySlice_GetIndicesEx((PySliceObject *)index,
PyByteArray_GET_SIZE(self), PyByteArray_GET_SIZE(self),
&start, &stop, &step, &slicelen) < 0) { &start, &stop, &step, &slicelen) < 0) {
return -1; return -1;
...@@ -589,7 +585,7 @@ bytes_ass_subscript(PyByteArrayObject *self, PyObject *item, PyObject *values) ...@@ -589,7 +585,7 @@ bytes_ass_subscript(PyByteArrayObject *self, PyObject *item, PyObject *values)
values = PyByteArray_FromObject(values); values = PyByteArray_FromObject(values);
if (values == NULL) if (values == NULL)
return -1; return -1;
err = bytes_ass_subscript(self, item, values); err = bytes_ass_subscript(self, index, values);
Py_DECREF(values); Py_DECREF(values);
return err; return err;
} }
...@@ -789,7 +785,7 @@ bytes_init(PyByteArrayObject *self, PyObject *args, PyObject *kwds) ...@@ -789,7 +785,7 @@ bytes_init(PyByteArrayObject *self, PyObject *args, PyObject *kwds)
/* Run the iterator to exhaustion */ /* Run the iterator to exhaustion */
for (;;) { for (;;) {
PyObject *item; PyObject *item;
Py_ssize_t value; int rc, value;
/* Get the next item */ /* Get the next item */
item = iternext(it); item = iternext(it);
...@@ -803,18 +799,11 @@ bytes_init(PyByteArrayObject *self, PyObject *args, PyObject *kwds) ...@@ -803,18 +799,11 @@ bytes_init(PyByteArrayObject *self, PyObject *args, PyObject *kwds)
} }
/* Interpret it as an int (__index__) */ /* Interpret it as an int (__index__) */
value = PyNumber_AsSsize_t(item, PyExc_ValueError); rc = _getbytevalue(item, &value);
Py_DECREF(item); Py_DECREF(item);
if (value == -1 && PyErr_Occurred()) if (!rc)
goto error; 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 */ /* Append the byte */
if (Py_SIZE(self) < self->ob_alloc) if (Py_SIZE(self) < self->ob_alloc)
Py_SIZE(self)++; Py_SIZE(self)++;
...@@ -2517,10 +2506,11 @@ Insert a single item into the bytearray before the given index."); ...@@ -2517,10 +2506,11 @@ Insert a single item into the bytearray before the given index.");
static PyObject * static PyObject *
bytes_insert(PyByteArrayObject *self, PyObject *args) bytes_insert(PyByteArrayObject *self, PyObject *args)
{ {
int value; PyObject *value;
int ival;
Py_ssize_t where, n = Py_SIZE(self); 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; return NULL;
if (n == PY_SSIZE_T_MAX) { if (n == PY_SSIZE_T_MAX) {
...@@ -2528,11 +2518,8 @@ bytes_insert(PyByteArrayObject *self, PyObject *args) ...@@ -2528,11 +2518,8 @@ bytes_insert(PyByteArrayObject *self, PyObject *args)
"cannot add more objects to bytes"); "cannot add more objects to bytes");
return NULL; return NULL;
} }
if (value < 0 || value >= 256) { if (!_getbytevalue(value, &ival))
PyErr_SetString(PyExc_ValueError,
"byte must be in range(0, 256)");
return NULL; return NULL;
}
if (PyByteArray_Resize((PyObject *)self, n + 1) < 0) if (PyByteArray_Resize((PyObject *)self, n + 1) < 0)
return NULL; return NULL;
...@@ -2544,7 +2531,7 @@ bytes_insert(PyByteArrayObject *self, PyObject *args) ...@@ -2544,7 +2531,7 @@ bytes_insert(PyByteArrayObject *self, PyObject *args)
if (where > n) if (where > n)
where = n; where = n;
memmove(self->ob_bytes + where + 1, self->ob_bytes + where, n - where); 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; Py_RETURN_NONE;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment