summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/stdtypes.rst7
-rw-r--r--Lib/test/test_bytes.py49
-rw-r--r--Misc/NEWS3
-rw-r--r--Objects/bytearrayobject.c13
-rw-r--r--Objects/bytesobject.c10
-rw-r--r--Objects/clinic/bytearrayobject.c.h37
-rw-r--r--Objects/clinic/bytesobject.c.h37
7 files changed, 76 insertions, 80 deletions
diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst
index 76ecd01..0c7249d 100644
--- a/Doc/library/stdtypes.rst
+++ b/Doc/library/stdtypes.rst
@@ -2631,8 +2631,8 @@ arbitrary binary data.
The prefix(es) to search for may be any :term:`bytes-like object`.
-.. method:: bytes.translate(table[, delete])
- bytearray.translate(table[, delete])
+.. method:: bytes.translate(table, delete=b'')
+ bytearray.translate(table, delete=b'')
Return a copy of the bytes or bytearray object where all bytes occurring in
the optional argument *delete* are removed, and the remaining bytes have
@@ -2648,6 +2648,9 @@ arbitrary binary data.
>>> b'read this short text'.translate(None, b'aeiou')
b'rd ths shrt txt'
+ .. versionchanged:: 3.6
+ *delete* is now supported as a keyword argument.
+
The following methods on bytes and bytearray objects have default behaviours
that assume the use of ASCII compatible binary formats, but can still be used
diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py
index 64644e7..8bbd669 100644
--- a/Lib/test/test_bytes.py
+++ b/Lib/test/test_bytes.py
@@ -689,6 +689,37 @@ class BaseBytesTest:
test.support.check_free_after_iterating(self, iter, self.type2test)
test.support.check_free_after_iterating(self, reversed, self.type2test)
+ def test_translate(self):
+ b = self.type2test(b'hello')
+ rosetta = bytearray(range(256))
+ rosetta[ord('o')] = ord('e')
+
+ self.assertRaises(TypeError, b.translate)
+ self.assertRaises(TypeError, b.translate, None, None)
+ self.assertRaises(ValueError, b.translate, bytes(range(255)))
+
+ c = b.translate(rosetta, b'hello')
+ self.assertEqual(b, b'hello')
+ self.assertIsInstance(c, self.type2test)
+
+ c = b.translate(rosetta)
+ d = b.translate(rosetta, b'')
+ self.assertEqual(c, d)
+ self.assertEqual(c, b'helle')
+
+ c = b.translate(rosetta, b'l')
+ self.assertEqual(c, b'hee')
+ c = b.translate(None, b'e')
+ self.assertEqual(c, b'hllo')
+
+ # test delete as a keyword argument
+ c = b.translate(rosetta, delete=b'')
+ self.assertEqual(c, b'helle')
+ c = b.translate(rosetta, delete=b'l')
+ self.assertEqual(c, b'hee')
+ c = b.translate(None, delete=b'e')
+ self.assertEqual(c, b'hllo')
+
class BytesTest(BaseBytesTest, unittest.TestCase):
type2test = bytes
@@ -1449,24 +1480,6 @@ class AssortedBytesTest(unittest.TestCase):
self.assertRaises(SyntaxError, eval,
'b"%s"' % chr(c))
- def test_translate(self):
- b = b'hello'
- ba = bytearray(b)
- rosetta = bytearray(range(0, 256))
- rosetta[ord('o')] = ord('e')
- c = b.translate(rosetta, b'l')
- self.assertEqual(b, b'hello')
- self.assertEqual(c, b'hee')
- c = ba.translate(rosetta, b'l')
- self.assertEqual(ba, b'hello')
- self.assertEqual(c, b'hee')
- c = b.translate(None, b'e')
- self.assertEqual(c, b'hllo')
- c = ba.translate(None, b'e')
- self.assertEqual(c, b'hllo')
- self.assertRaises(TypeError, b.translate, None, None)
- self.assertRaises(TypeError, ba.translate, None, None)
-
def test_split_bytearray(self):
self.assertEqual(b'a b'.split(memoryview(b' ')), [b'a', b'b'])
diff --git a/Misc/NEWS b/Misc/NEWS
index 37c4420..8ae30e2 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ What's New in Python 3.6.0 beta 1
Core and Builtins
-----------------
+- Issue #27506: Support passing the bytes/bytearray.translate() "delete"
+ argument by keyword.
+
- Issue #27587: Fix another issue found by PVS-Studio: Null pointer check
after use of 'def' in _PyState_AddModule().
Initial patch by Christian Heimes.
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index de2dca9..b6631f9 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -1175,21 +1175,19 @@ bytearray.translate
table: object
Translation table, which must be a bytes object of length 256.
- [
- deletechars: object
- ]
/
+ delete as deletechars: object(c_default="NULL") = b''
Return a copy with each character mapped by the given translation table.
-All characters occurring in the optional argument deletechars are removed.
+All characters occurring in the optional argument delete are removed.
The remaining characters are mapped through the given translation table.
[clinic start generated code]*/
static PyObject *
bytearray_translate_impl(PyByteArrayObject *self, PyObject *table,
- int group_right_1, PyObject *deletechars)
-/*[clinic end generated code: output=2bebc86a9a1ff083 input=846a01671bccc1c5]*/
+ PyObject *deletechars)
+/*[clinic end generated code: output=b6a8f01c2a74e446 input=cfff956d4d127a9b]*/
{
char *input, *output;
const char *table_chars;
@@ -1258,8 +1256,7 @@ bytearray_translate_impl(PyByteArrayObject *self, PyObject *table,
for (i = inlen; --i >= 0; ) {
c = Py_CHARMASK(*input++);
if (trans_table[c] != -1)
- if (Py_CHARMASK(*output++ = (char)trans_table[c]) == c)
- continue;
+ *output++ = (char)trans_table[c];
}
/* Fix the size of the resulting string */
if (inlen > 0)
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index ff87dfe..4fdaa52 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -2045,21 +2045,19 @@ bytes.translate
table: object
Translation table, which must be a bytes object of length 256.
- [
- deletechars: object
- ]
/
+ delete as deletechars: object(c_default="NULL") = b''
Return a copy with each character mapped by the given translation table.
-All characters occurring in the optional argument deletechars are removed.
+All characters occurring in the optional argument delete are removed.
The remaining characters are mapped through the given translation table.
[clinic start generated code]*/
static PyObject *
-bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1,
+bytes_translate_impl(PyBytesObject *self, PyObject *table,
PyObject *deletechars)
-/*[clinic end generated code: output=233df850eb50bf8d input=ca20edf39d780d49]*/
+/*[clinic end generated code: output=43be3437f1956211 input=0ecdf159f654233c]*/
{
char *input, *output;
Py_buffer table_view = {NULL, NULL};
diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h
index b49c26b..a60be76 100644
--- a/Objects/clinic/bytearrayobject.c.h
+++ b/Objects/clinic/bytearrayobject.c.h
@@ -39,47 +39,38 @@ bytearray_copy(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored))
}
PyDoc_STRVAR(bytearray_translate__doc__,
-"translate(table, [deletechars])\n"
+"translate($self, table, /, delete=b\'\')\n"
+"--\n"
+"\n"
"Return a copy with each character mapped by the given translation table.\n"
"\n"
" table\n"
" Translation table, which must be a bytes object of length 256.\n"
"\n"
-"All characters occurring in the optional argument deletechars are removed.\n"
+"All characters occurring in the optional argument delete are removed.\n"
"The remaining characters are mapped through the given translation table.");
#define BYTEARRAY_TRANSLATE_METHODDEF \
- {"translate", (PyCFunction)bytearray_translate, METH_VARARGS, bytearray_translate__doc__},
+ {"translate", (PyCFunction)bytearray_translate, METH_VARARGS|METH_KEYWORDS, bytearray_translate__doc__},
static PyObject *
bytearray_translate_impl(PyByteArrayObject *self, PyObject *table,
- int group_right_1, PyObject *deletechars);
+ PyObject *deletechars);
static PyObject *
-bytearray_translate(PyByteArrayObject *self, PyObject *args)
+bytearray_translate(PyByteArrayObject *self, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"", "delete", NULL};
+ static _PyArg_Parser _parser = {"O|O:translate", _keywords, 0};
PyObject *table;
- int group_right_1 = 0;
PyObject *deletechars = NULL;
- switch (PyTuple_GET_SIZE(args)) {
- case 1:
- if (!PyArg_ParseTuple(args, "O:translate", &table)) {
- goto exit;
- }
- break;
- case 2:
- if (!PyArg_ParseTuple(args, "OO:translate", &table, &deletechars)) {
- goto exit;
- }
- group_right_1 = 1;
- break;
- default:
- PyErr_SetString(PyExc_TypeError, "bytearray.translate requires 1 to 2 arguments");
- goto exit;
+ if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
+ &table, &deletechars)) {
+ goto exit;
}
- return_value = bytearray_translate_impl(self, table, group_right_1, deletechars);
+ return_value = bytearray_translate_impl(self, table, deletechars);
exit:
return return_value;
@@ -720,4 +711,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored))
{
return bytearray_sizeof_impl(self);
}
-/*[clinic end generated code: output=0af30f8c0b1ecd76 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=59a0c86b29ff06d1 input=a9049054013a1b77]*/
diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h
index a99ce48..f179ce6 100644
--- a/Objects/clinic/bytesobject.c.h
+++ b/Objects/clinic/bytesobject.c.h
@@ -269,47 +269,38 @@ exit:
}
PyDoc_STRVAR(bytes_translate__doc__,
-"translate(table, [deletechars])\n"
+"translate($self, table, /, delete=b\'\')\n"
+"--\n"
+"\n"
"Return a copy with each character mapped by the given translation table.\n"
"\n"
" table\n"
" Translation table, which must be a bytes object of length 256.\n"
"\n"
-"All characters occurring in the optional argument deletechars are removed.\n"
+"All characters occurring in the optional argument delete are removed.\n"
"The remaining characters are mapped through the given translation table.");
#define BYTES_TRANSLATE_METHODDEF \
- {"translate", (PyCFunction)bytes_translate, METH_VARARGS, bytes_translate__doc__},
+ {"translate", (PyCFunction)bytes_translate, METH_VARARGS|METH_KEYWORDS, bytes_translate__doc__},
static PyObject *
-bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1,
+bytes_translate_impl(PyBytesObject *self, PyObject *table,
PyObject *deletechars);
static PyObject *
-bytes_translate(PyBytesObject *self, PyObject *args)
+bytes_translate(PyBytesObject *self, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"", "delete", NULL};
+ static _PyArg_Parser _parser = {"O|O:translate", _keywords, 0};
PyObject *table;
- int group_right_1 = 0;
PyObject *deletechars = NULL;
- switch (PyTuple_GET_SIZE(args)) {
- case 1:
- if (!PyArg_ParseTuple(args, "O:translate", &table)) {
- goto exit;
- }
- break;
- case 2:
- if (!PyArg_ParseTuple(args, "OO:translate", &table, &deletechars)) {
- goto exit;
- }
- group_right_1 = 1;
- break;
- default:
- PyErr_SetString(PyExc_TypeError, "bytes.translate requires 1 to 2 arguments");
- goto exit;
+ if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
+ &table, &deletechars)) {
+ goto exit;
}
- return_value = bytes_translate_impl(self, table, group_right_1, deletechars);
+ return_value = bytes_translate_impl(self, table, deletechars);
exit:
return return_value;
@@ -508,4 +499,4 @@ bytes_fromhex(PyTypeObject *type, PyObject *arg)
exit:
return return_value;
}
-/*[clinic end generated code: output=637c2c14610d3c8d input=a9049054013a1b77]*/
+/*[clinic end generated code: output=5618c05c24c1e617 input=a9049054013a1b77]*/