Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1b6c6da

Browse files
committed
Issue #27506: Support bytes/bytearray.translate() delete as keyword argument
Patch by Xiang Zhang.
1 parent 8c3c52b commit 1b6c6da

7 files changed

Lines changed: 76 additions & 80 deletions

File tree

Doc/library/stdtypes.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2631,8 +2631,8 @@ arbitrary binary data.
26312631
The prefix(es) to search for may be any :term:`bytes-like object`.
26322632

26332633

2634-
.. method:: bytes.translate(table[, delete])
2635-
bytearray.translate(table[, delete])
2634+
.. method:: bytes.translate(table, delete=b'')
2635+
bytearray.translate(table, delete=b'')
26362636

26372637
Return a copy of the bytes or bytearray object where all bytes occurring in
26382638
the optional argument *delete* are removed, and the remaining bytes have
@@ -2648,6 +2648,9 @@ arbitrary binary data.
26482648
>>> b'read this short text'.translate(None, b'aeiou')
26492649
b'rd ths shrt txt'
26502650

2651+
.. versionchanged:: 3.6
2652+
*delete* is now supported as a keyword argument.
2653+
26512654

26522655
The following methods on bytes and bytearray objects have default behaviours
26532656
that assume the use of ASCII compatible binary formats, but can still be used

Lib/test/test_bytes.py

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,37 @@ def test_free_after_iterating(self):
689689
test.support.check_free_after_iterating(self, iter, self.type2test)
690690
test.support.check_free_after_iterating(self, reversed, self.type2test)
691691

692+
def test_translate(self):
693+
b = self.type2test(b'hello')
694+
rosetta = bytearray(range(256))
695+
rosetta[ord('o')] = ord('e')
696+
697+
self.assertRaises(TypeError, b.translate)
698+
self.assertRaises(TypeError, b.translate, None, None)
699+
self.assertRaises(ValueError, b.translate, bytes(range(255)))
700+
701+
c = b.translate(rosetta, b'hello')
702+
self.assertEqual(b, b'hello')
703+
self.assertIsInstance(c, self.type2test)
704+
705+
c = b.translate(rosetta)
706+
d = b.translate(rosetta, b'')
707+
self.assertEqual(c, d)
708+
self.assertEqual(c, b'helle')
709+
710+
c = b.translate(rosetta, b'l')
711+
self.assertEqual(c, b'hee')
712+
c = b.translate(None, b'e')
713+
self.assertEqual(c, b'hllo')
714+
715+
# test delete as a keyword argument
716+
c = b.translate(rosetta, delete=b'')
717+
self.assertEqual(c, b'helle')
718+
c = b.translate(rosetta, delete=b'l')
719+
self.assertEqual(c, b'hee')
720+
c = b.translate(None, delete=b'e')
721+
self.assertEqual(c, b'hllo')
722+
692723

693724
class BytesTest(BaseBytesTest, unittest.TestCase):
694725
type2test = bytes
@@ -1449,24 +1480,6 @@ def test_literal(self):
14491480
self.assertRaises(SyntaxError, eval,
14501481
'b"%s"' % chr(c))
14511482

1452-
def test_translate(self):
1453-
b = b'hello'
1454-
ba = bytearray(b)
1455-
rosetta = bytearray(range(0, 256))
1456-
rosetta[ord('o')] = ord('e')
1457-
c = b.translate(rosetta, b'l')
1458-
self.assertEqual(b, b'hello')
1459-
self.assertEqual(c, b'hee')
1460-
c = ba.translate(rosetta, b'l')
1461-
self.assertEqual(ba, b'hello')
1462-
self.assertEqual(c, b'hee')
1463-
c = b.translate(None, b'e')
1464-
self.assertEqual(c, b'hllo')
1465-
c = ba.translate(None, b'e')
1466-
self.assertEqual(c, b'hllo')
1467-
self.assertRaises(TypeError, b.translate, None, None)
1468-
self.assertRaises(TypeError, ba.translate, None, None)
1469-
14701483
def test_split_bytearray(self):
14711484
self.assertEqual(b'a b'.split(memoryview(b' ')), [b'a', b'b'])
14721485

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ What's New in Python 3.6.0 beta 1
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #27506: Support passing the bytes/bytearray.translate() "delete"
14+
argument by keyword.
15+
1316
- Issue #27587: Fix another issue found by PVS-Studio: Null pointer check
1417
after use of 'def' in _PyState_AddModule().
1518
Initial patch by Christian Heimes.

Objects/bytearrayobject.c

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,21 +1175,19 @@ bytearray.translate
11751175
11761176
table: object
11771177
Translation table, which must be a bytes object of length 256.
1178-
[
1179-
deletechars: object
1180-
]
11811178
/
1179+
delete as deletechars: object(c_default="NULL") = b''
11821180
11831181
Return a copy with each character mapped by the given translation table.
11841182
1185-
All characters occurring in the optional argument deletechars are removed.
1183+
All characters occurring in the optional argument delete are removed.
11861184
The remaining characters are mapped through the given translation table.
11871185
[clinic start generated code]*/
11881186

11891187
static PyObject *
11901188
bytearray_translate_impl(PyByteArrayObject *self, PyObject *table,
1191-
int group_right_1, PyObject *deletechars)
1192-
/*[clinic end generated code: output=2bebc86a9a1ff083 input=846a01671bccc1c5]*/
1189+
PyObject *deletechars)
1190+
/*[clinic end generated code: output=b6a8f01c2a74e446 input=cfff956d4d127a9b]*/
11931191
{
11941192
char *input, *output;
11951193
const char *table_chars;
@@ -1258,8 +1256,7 @@ bytearray_translate_impl(PyByteArrayObject *self, PyObject *table,
12581256
for (i = inlen; --i >= 0; ) {
12591257
c = Py_CHARMASK(*input++);
12601258
if (trans_table[c] != -1)
1261-
if (Py_CHARMASK(*output++ = (char)trans_table[c]) == c)
1262-
continue;
1259+
*output++ = (char)trans_table[c];
12631260
}
12641261
/* Fix the size of the resulting string */
12651262
if (inlen > 0)

Objects/bytesobject.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2045,21 +2045,19 @@ bytes.translate
20452045
20462046
table: object
20472047
Translation table, which must be a bytes object of length 256.
2048-
[
2049-
deletechars: object
2050-
]
20512048
/
2049+
delete as deletechars: object(c_default="NULL") = b''
20522050
20532051
Return a copy with each character mapped by the given translation table.
20542052
2055-
All characters occurring in the optional argument deletechars are removed.
2053+
All characters occurring in the optional argument delete are removed.
20562054
The remaining characters are mapped through the given translation table.
20572055
[clinic start generated code]*/
20582056

20592057
static PyObject *
2060-
bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1,
2058+
bytes_translate_impl(PyBytesObject *self, PyObject *table,
20612059
PyObject *deletechars)
2062-
/*[clinic end generated code: output=233df850eb50bf8d input=ca20edf39d780d49]*/
2060+
/*[clinic end generated code: output=43be3437f1956211 input=0ecdf159f654233c]*/
20632061
{
20642062
char *input, *output;
20652063
Py_buffer table_view = {NULL, NULL};

Objects/clinic/bytearrayobject.c.h

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,47 +39,38 @@ bytearray_copy(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored))
3939
}
4040

4141
PyDoc_STRVAR(bytearray_translate__doc__,
42-
"translate(table, [deletechars])\n"
42+
"translate($self, table, /, delete=b\'\')\n"
43+
"--\n"
44+
"\n"
4345
"Return a copy with each character mapped by the given translation table.\n"
4446
"\n"
4547
" table\n"
4648
" Translation table, which must be a bytes object of length 256.\n"
4749
"\n"
48-
"All characters occurring in the optional argument deletechars are removed.\n"
50+
"All characters occurring in the optional argument delete are removed.\n"
4951
"The remaining characters are mapped through the given translation table.");
5052

5153
#define BYTEARRAY_TRANSLATE_METHODDEF \
52-
{"translate", (PyCFunction)bytearray_translate, METH_VARARGS, bytearray_translate__doc__},
54+
{"translate", (PyCFunction)bytearray_translate, METH_VARARGS|METH_KEYWORDS, bytearray_translate__doc__},
5355

5456
static PyObject *
5557
bytearray_translate_impl(PyByteArrayObject *self, PyObject *table,
56-
int group_right_1, PyObject *deletechars);
58+
PyObject *deletechars);
5759

5860
static PyObject *
59-
bytearray_translate(PyByteArrayObject *self, PyObject *args)
61+
bytearray_translate(PyByteArrayObject *self, PyObject *args, PyObject *kwargs)
6062
{
6163
PyObject *return_value = NULL;
64+
static const char * const _keywords[] = {"", "delete", NULL};
65+
static _PyArg_Parser _parser = {"O|O:translate", _keywords, 0};
6266
PyObject *table;
63-
int group_right_1 = 0;
6467
PyObject *deletechars = NULL;
6568

66-
switch (PyTuple_GET_SIZE(args)) {
67-
case 1:
68-
if (!PyArg_ParseTuple(args, "O:translate", &table)) {
69-
goto exit;
70-
}
71-
break;
72-
case 2:
73-
if (!PyArg_ParseTuple(args, "OO:translate", &table, &deletechars)) {
74-
goto exit;
75-
}
76-
group_right_1 = 1;
77-
break;
78-
default:
79-
PyErr_SetString(PyExc_TypeError, "bytearray.translate requires 1 to 2 arguments");
80-
goto exit;
69+
if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
70+
&table, &deletechars)) {
71+
goto exit;
8172
}
82-
return_value = bytearray_translate_impl(self, table, group_right_1, deletechars);
73+
return_value = bytearray_translate_impl(self, table, deletechars);
8374

8475
exit:
8576
return return_value;
@@ -720,4 +711,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored))
720711
{
721712
return bytearray_sizeof_impl(self);
722713
}
723-
/*[clinic end generated code: output=0af30f8c0b1ecd76 input=a9049054013a1b77]*/
714+
/*[clinic end generated code: output=59a0c86b29ff06d1 input=a9049054013a1b77]*/

Objects/clinic/bytesobject.c.h

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -269,47 +269,38 @@ bytes_rstrip(PyBytesObject *self, PyObject *args)
269269
}
270270

271271
PyDoc_STRVAR(bytes_translate__doc__,
272-
"translate(table, [deletechars])\n"
272+
"translate($self, table, /, delete=b\'\')\n"
273+
"--\n"
274+
"\n"
273275
"Return a copy with each character mapped by the given translation table.\n"
274276
"\n"
275277
" table\n"
276278
" Translation table, which must be a bytes object of length 256.\n"
277279
"\n"
278-
"All characters occurring in the optional argument deletechars are removed.\n"
280+
"All characters occurring in the optional argument delete are removed.\n"
279281
"The remaining characters are mapped through the given translation table.");
280282

281283
#define BYTES_TRANSLATE_METHODDEF \
282-
{"translate", (PyCFunction)bytes_translate, METH_VARARGS, bytes_translate__doc__},
284+
{"translate", (PyCFunction)bytes_translate, METH_VARARGS|METH_KEYWORDS, bytes_translate__doc__},
283285

284286
static PyObject *
285-
bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1,
287+
bytes_translate_impl(PyBytesObject *self, PyObject *table,
286288
PyObject *deletechars);
287289

288290
static PyObject *
289-
bytes_translate(PyBytesObject *self, PyObject *args)
291+
bytes_translate(PyBytesObject *self, PyObject *args, PyObject *kwargs)
290292
{
291293
PyObject *return_value = NULL;
294+
static const char * const _keywords[] = {"", "delete", NULL};
295+
static _PyArg_Parser _parser = {"O|O:translate", _keywords, 0};
292296
PyObject *table;
293-
int group_right_1 = 0;
294297
PyObject *deletechars = NULL;
295298

296-
switch (PyTuple_GET_SIZE(args)) {
297-
case 1:
298-
if (!PyArg_ParseTuple(args, "O:translate", &table)) {
299-
goto exit;
300-
}
301-
break;
302-
case 2:
303-
if (!PyArg_ParseTuple(args, "OO:translate", &table, &deletechars)) {
304-
goto exit;
305-
}
306-
group_right_1 = 1;
307-
break;
308-
default:
309-
PyErr_SetString(PyExc_TypeError, "bytes.translate requires 1 to 2 arguments");
310-
goto exit;
299+
if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
300+
&table, &deletechars)) {
301+
goto exit;
311302
}
312-
return_value = bytes_translate_impl(self, table, group_right_1, deletechars);
303+
return_value = bytes_translate_impl(self, table, deletechars);
313304

314305
exit:
315306
return return_value;
@@ -508,4 +499,4 @@ bytes_fromhex(PyTypeObject *type, PyObject *arg)
508499
exit:
509500
return return_value;
510501
}
511-
/*[clinic end generated code: output=637c2c14610d3c8d input=a9049054013a1b77]*/
502+
/*[clinic end generated code: output=5618c05c24c1e617 input=a9049054013a1b77]*/

0 commit comments

Comments
 (0)