Skip to content

Commit cddfcad

Browse files
author
georg.brandl
committed
Backport r67974:
#4759: allow None as first argument of bytearray.translate(), for consistency with bytes.translate(). Also fix segfault for bytearray.translate(x, None) -- will backport this part to 3.0 and 2.6. git-svn-id: http://svn.python.org/projects/python/trunk@67976 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent 951c05e commit cddfcad

3 files changed

Lines changed: 38 additions & 16 deletions

File tree

Lib/test/test_bytes.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,11 +872,21 @@ def test_literal(self):
872872

873873
def test_translate(self):
874874
b = b'hello'
875+
ba = bytearray(b)
875876
rosetta = bytearray(range(0, 256))
876877
rosetta[ord('o')] = ord('e')
877878
c = b.translate(rosetta, b'l')
878879
self.assertEqual(b, b'hello')
879880
self.assertEqual(c, b'hee')
881+
c = ba.translate(rosetta, b'l')
882+
self.assertEqual(ba, b'hello')
883+
self.assertEqual(c, b'hee')
884+
c = b.translate(None, b'e')
885+
self.assertEqual(c, b'hllo')
886+
c = ba.translate(None, b'e')
887+
self.assertEqual(c, b'hllo')
888+
self.assertRaises(TypeError, b.translate, None, None)
889+
self.assertRaises(TypeError, ba.translate, None, None)
880890

881891
def test_split_bytearray(self):
882892
self.assertEqual(b'a b'.split(memoryview(b' ')), [b'a', b'b'])

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ What's New in Python 2.7 alpha 1
1212
Core and Builtins
1313
-----------------
1414

15+
- Issue #4759: None is now allowed as the first argument of
16+
bytearray.translate(). It was always allowed for bytes.translate().
17+
1518
- Added test case to ensure attempts to read from a file opened for writing
1619
fail.
1720

Objects/bytearrayobject.c

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,28 +1443,32 @@ bytes_translate(PyByteArrayObject *self, PyObject *args)
14431443
PyObject *input_obj = (PyObject*)self;
14441444
const char *output_start;
14451445
Py_ssize_t inlen;
1446-
PyObject *result;
1446+
PyObject *result = NULL;
14471447
int trans_table[256];
1448-
PyObject *tableobj, *delobj = NULL;
1448+
PyObject *tableobj = NULL, *delobj = NULL;
14491449
Py_buffer vtable, vdel;
14501450

14511451
if (!PyArg_UnpackTuple(args, "translate", 1, 2,
14521452
&tableobj, &delobj))
14531453
return NULL;
14541454

1455-
if (_getbuffer(tableobj, &vtable) < 0)
1455+
if (tableobj == Py_None) {
1456+
table = NULL;
1457+
tableobj = NULL;
1458+
} else if (_getbuffer(tableobj, &vtable) < 0) {
14561459
return NULL;
1457-
1458-
if (vtable.len != 256) {
1459-
PyErr_SetString(PyExc_ValueError,
1460-
"translation table must be 256 characters long");
1461-
result = NULL;
1462-
goto done;
1460+
} else {
1461+
if (vtable.len != 256) {
1462+
PyErr_SetString(PyExc_ValueError,
1463+
"translation table must be 256 characters long");
1464+
goto done;
1465+
}
1466+
table = (const char*)vtable.buf;
14631467
}
14641468

14651469
if (delobj != NULL) {
14661470
if (_getbuffer(delobj, &vdel) < 0) {
1467-
result = NULL;
1471+
delobj = NULL; /* don't try to release vdel buffer on exit */
14681472
goto done;
14691473
}
14701474
}
@@ -1473,25 +1477,29 @@ bytes_translate(PyByteArrayObject *self, PyObject *args)
14731477
vdel.len = 0;
14741478
}
14751479

1476-
table = (const char *)vtable.buf;
14771480
inlen = PyByteArray_GET_SIZE(input_obj);
14781481
result = PyByteArray_FromStringAndSize((char *)NULL, inlen);
14791482
if (result == NULL)
14801483
goto done;
14811484
output_start = output = PyByteArray_AsString(result);
14821485
input = PyByteArray_AS_STRING(input_obj);
14831486

1484-
if (vdel.len == 0) {
1487+
if (vdel.len == 0 && table != NULL) {
14851488
/* If no deletions are required, use faster code */
14861489
for (i = inlen; --i >= 0; ) {
14871490
c = Py_CHARMASK(*input++);
14881491
*output++ = table[c];
14891492
}
14901493
goto done;
14911494
}
1492-
1493-
for (i = 0; i < 256; i++)
1494-
trans_table[i] = Py_CHARMASK(table[i]);
1495+
1496+
if (table == NULL) {
1497+
for (i = 0; i < 256; i++)
1498+
trans_table[i] = Py_CHARMASK(i);
1499+
} else {
1500+
for (i = 0; i < 256; i++)
1501+
trans_table[i] = Py_CHARMASK(table[i]);
1502+
}
14951503

14961504
for (i = 0; i < vdel.len; i++)
14971505
trans_table[(int) Py_CHARMASK( ((unsigned char*)vdel.buf)[i] )] = -1;
@@ -1507,7 +1515,8 @@ bytes_translate(PyByteArrayObject *self, PyObject *args)
15071515
PyByteArray_Resize(result, output - output_start);
15081516

15091517
done:
1510-
PyBuffer_Release(&vtable);
1518+
if (tableobj != NULL)
1519+
PyBuffer_Release(&vtable);
15111520
if (delobj != NULL)
15121521
PyBuffer_Release(&vdel);
15131522
return result;

0 commit comments

Comments
 (0)