Add bytes/bytearray.maketrans() to mirror str.maketrans(), and deprecate
string.maketrans() which actually works on bytes. (Also closes #5675.)
This commit is contained in:
parent
78532baeab
commit
abc387747d
|
@ -479,7 +479,7 @@ debugging, and in numerical work.
|
||||||
exponent.
|
exponent.
|
||||||
|
|
||||||
|
|
||||||
.. method:: float.fromhex(s)
|
.. classmethod:: float.fromhex(s)
|
||||||
|
|
||||||
Class method to return the float represented by a hexadecimal
|
Class method to return the float represented by a hexadecimal
|
||||||
string *s*. The string *s* may have leading and trailing
|
string *s*. The string *s* may have leading and trailing
|
||||||
|
@ -967,7 +967,7 @@ functions based on regular expressions.
|
||||||
'example.com'
|
'example.com'
|
||||||
|
|
||||||
|
|
||||||
.. method:: str.maketrans(x[, y[, z]])
|
.. staticmethod:: str.maketrans(x[, y[, z]])
|
||||||
|
|
||||||
This static method returns a translation table usable for :meth:`str.translate`.
|
This static method returns a translation table usable for :meth:`str.translate`.
|
||||||
|
|
||||||
|
@ -1514,8 +1514,8 @@ Wherever one of these methods needs to interpret the bytes as characters
|
||||||
|
|
||||||
The bytes and bytearray types have an additional class method:
|
The bytes and bytearray types have an additional class method:
|
||||||
|
|
||||||
.. method:: bytes.fromhex(string)
|
.. classmethod:: bytes.fromhex(string)
|
||||||
bytearray.fromhex(string)
|
bytearray.fromhex(string)
|
||||||
|
|
||||||
This :class:`bytes` class method returns a bytes or bytearray object,
|
This :class:`bytes` class method returns a bytes or bytearray object,
|
||||||
decoding the given string object. The string must contain two hexadecimal
|
decoding the given string object. The string must contain two hexadecimal
|
||||||
|
@ -1524,7 +1524,9 @@ The bytes and bytearray types have an additional class method:
|
||||||
>>> bytes.fromhex('f0 f1f2 ')
|
>>> bytes.fromhex('f0 f1f2 ')
|
||||||
b'\xf0\xf1\xf2'
|
b'\xf0\xf1\xf2'
|
||||||
|
|
||||||
The translate method differs in semantics from the version available on strings:
|
|
||||||
|
The maketrans and translate methods differ in semantics from the versions
|
||||||
|
available on strings:
|
||||||
|
|
||||||
.. method:: bytes.translate(table[, delete])
|
.. method:: bytes.translate(table[, delete])
|
||||||
|
|
||||||
|
@ -1533,8 +1535,7 @@ The translate method differs in semantics from the version available on strings:
|
||||||
mapped through the given translation table, which must be a bytes object of
|
mapped through the given translation table, which must be a bytes object of
|
||||||
length 256.
|
length 256.
|
||||||
|
|
||||||
You can use the :func:`string.maketrans` helper function to create a
|
You can use the :func:`bytes.maketrans` method to create a translation table.
|
||||||
translation table.
|
|
||||||
|
|
||||||
Set the *table* argument to ``None`` for translations that only delete
|
Set the *table* argument to ``None`` for translations that only delete
|
||||||
characters::
|
characters::
|
||||||
|
@ -1543,6 +1544,16 @@ The translate method differs in semantics from the version available on strings:
|
||||||
b'rd ths shrt txt'
|
b'rd ths shrt txt'
|
||||||
|
|
||||||
|
|
||||||
|
.. staticmethod:: bytes.maketrans(from, to)
|
||||||
|
|
||||||
|
This static method returns a translation table usable for
|
||||||
|
:meth:`bytes.translate` that will map each character in *from* into the
|
||||||
|
character at the same position in *to*; *from* and *to* must be bytes objects
|
||||||
|
and have the same length.
|
||||||
|
|
||||||
|
.. versionadded:: 3.1
|
||||||
|
|
||||||
|
|
||||||
.. _types-set:
|
.. _types-set:
|
||||||
|
|
||||||
Set Types --- :class:`set`, :class:`frozenset`
|
Set Types --- :class:`set`, :class:`frozenset`
|
||||||
|
@ -1847,7 +1858,7 @@ pairs within braces, for example: ``{'jack': 4098, 'sjoerd': 4127}`` or ``{4098:
|
||||||
|
|
||||||
Return a shallow copy of the dictionary.
|
Return a shallow copy of the dictionary.
|
||||||
|
|
||||||
.. method:: fromkeys(seq[, value])
|
.. classmethod:: fromkeys(seq[, value])
|
||||||
|
|
||||||
Create a new dictionary with keys from *seq* and values set to *value*.
|
Create a new dictionary with keys from *seq* and values set to *value*.
|
||||||
|
|
||||||
|
|
|
@ -548,13 +548,9 @@ rule:
|
||||||
delimiter), and it should appear last in the regular expression.
|
delimiter), and it should appear last in the regular expression.
|
||||||
|
|
||||||
|
|
||||||
String functions
|
Helper functions
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
The following functions are available to operate on string objects.
|
|
||||||
They are not available as string methods.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: capwords(s)
|
.. function:: capwords(s)
|
||||||
|
|
||||||
Split the argument into words using :func:`split`, capitalize each word using
|
Split the argument into words using :func:`split`, capitalize each word using
|
||||||
|
@ -568,3 +564,6 @@ They are not available as string methods.
|
||||||
Return a translation table suitable for passing to :meth:`bytes.translate`,
|
Return a translation table suitable for passing to :meth:`bytes.translate`,
|
||||||
that will map each character in *from* into the character at the same
|
that will map each character in *from* into the character at the same
|
||||||
position in *to*; *from* and *to* must have the same length.
|
position in *to*; *from* and *to* must have the same length.
|
||||||
|
|
||||||
|
.. deprecated:: 3.1
|
||||||
|
Use the :meth:`bytes.maketrans` static method instead.
|
||||||
|
|
|
@ -20,6 +20,9 @@ extern void _Py_bytes_title(char *result, char *s, Py_ssize_t len);
|
||||||
extern void _Py_bytes_capitalize(char *result, char *s, Py_ssize_t len);
|
extern void _Py_bytes_capitalize(char *result, char *s, Py_ssize_t len);
|
||||||
extern void _Py_bytes_swapcase(char *result, char *s, Py_ssize_t len);
|
extern void _Py_bytes_swapcase(char *result, char *s, Py_ssize_t len);
|
||||||
|
|
||||||
|
/* This one gets the raw argument list. */
|
||||||
|
extern PyObject* _Py_bytes_maketrans(PyObject *args);
|
||||||
|
|
||||||
/* Shared __doc__ strings. */
|
/* Shared __doc__ strings. */
|
||||||
extern const char _Py_isspace__doc__[];
|
extern const char _Py_isspace__doc__[];
|
||||||
extern const char _Py_isalpha__doc__[];
|
extern const char _Py_isalpha__doc__[];
|
||||||
|
@ -33,6 +36,7 @@ extern const char _Py_upper__doc__[];
|
||||||
extern const char _Py_title__doc__[];
|
extern const char _Py_title__doc__[];
|
||||||
extern const char _Py_capitalize__doc__[];
|
extern const char _Py_capitalize__doc__[];
|
||||||
extern const char _Py_swapcase__doc__[];
|
extern const char _Py_swapcase__doc__[];
|
||||||
|
extern const char _Py_maketrans__doc__[];
|
||||||
|
|
||||||
#define FLAG_LOWER 0x01
|
#define FLAG_LOWER 0x01
|
||||||
#define FLAG_UPPER 0x02
|
#define FLAG_UPPER 0x02
|
||||||
|
|
|
@ -49,6 +49,9 @@ def maketrans(frm: bytes, to: bytes) -> bytes:
|
||||||
mapped to the byte at the same position in to.
|
mapped to the byte at the same position in to.
|
||||||
The strings frm and to must be of the same length.
|
The strings frm and to must be of the same length.
|
||||||
"""
|
"""
|
||||||
|
import warnings
|
||||||
|
warnings.warn("string.maketrans is deprecated, use bytes.maketrans instead",
|
||||||
|
DeprecationWarning)
|
||||||
if len(frm) != len(to):
|
if len(frm) != len(to):
|
||||||
raise ValueError("maketrans arguments must have same length")
|
raise ValueError("maketrans arguments must have same length")
|
||||||
if not (isinstance(frm, bytes) and isinstance(to, bytes)):
|
if not (isinstance(frm, bytes) and isinstance(to, bytes)):
|
||||||
|
|
|
@ -418,18 +418,15 @@ class BaseStrTest:
|
||||||
@bigmemtest(minsize=_2G, memuse=2)
|
@bigmemtest(minsize=_2G, memuse=2)
|
||||||
def test_translate(self, size):
|
def test_translate(self, size):
|
||||||
_ = self.from_latin1
|
_ = self.from_latin1
|
||||||
trans = {
|
|
||||||
ord(_('.')): _('-'),
|
|
||||||
ord(_('a')): _('!'),
|
|
||||||
ord(_('Z')): _('$'),
|
|
||||||
}
|
|
||||||
SUBSTR = _('aZz.z.Aaz.')
|
SUBSTR = _('aZz.z.Aaz.')
|
||||||
if not isinstance(SUBSTR, str):
|
if isinstance(SUBSTR, str):
|
||||||
# Workaround the inexistence of bytes.maketrans()
|
trans = {
|
||||||
chars = bytearray(range(256))
|
ord(_('.')): _('-'),
|
||||||
for k, v in trans.items():
|
ord(_('a')): _('!'),
|
||||||
chars[k] = ord(v)
|
ord(_('Z')): _('$'),
|
||||||
trans = chars
|
}
|
||||||
|
else:
|
||||||
|
trans = bytes.maketrans(b'.aZ', b'-!$')
|
||||||
sublen = len(SUBSTR)
|
sublen = len(SUBSTR)
|
||||||
repeats = size // sublen + 2
|
repeats = size // sublen + 2
|
||||||
s = SUBSTR * repeats
|
s = SUBSTR * repeats
|
||||||
|
|
|
@ -450,6 +450,13 @@ class BaseBytesTest(unittest.TestCase):
|
||||||
self.assertEqual([ord(b[i:i+1]) for i in range(len(b))],
|
self.assertEqual([ord(b[i:i+1]) for i in range(len(b))],
|
||||||
[0, 65, 127, 128, 255])
|
[0, 65, 127, 128, 255])
|
||||||
|
|
||||||
|
def test_maketrans(self):
|
||||||
|
transtable = b'\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`xyzdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377'
|
||||||
|
|
||||||
|
self.assertEqual(self.type2test.maketrans(b'abc', b'xyz'), transtable)
|
||||||
|
self.assertRaises(ValueError, self.type2test.maketrans, b'abc', b'xyzq')
|
||||||
|
self.assertRaises(TypeError, self.type2test.maketrans, 'abc', 'def')
|
||||||
|
|
||||||
|
|
||||||
class BytesTest(BaseBytesTest):
|
class BytesTest(BaseBytesTest):
|
||||||
type2test = bytes
|
type2test = bytes
|
||||||
|
|
|
@ -101,14 +101,6 @@ class ModuleTest(unittest.TestCase):
|
||||||
self.assertRaises(ValueError, fmt.format, "{0}", 10, 20, i=100)
|
self.assertRaises(ValueError, fmt.format, "{0}", 10, 20, i=100)
|
||||||
self.assertRaises(ValueError, fmt.format, "{i}", 10, 20, i=100)
|
self.assertRaises(ValueError, fmt.format, "{i}", 10, 20, i=100)
|
||||||
|
|
||||||
|
|
||||||
def test_maketrans(self):
|
|
||||||
transtable = b'\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`xyzdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377'
|
|
||||||
|
|
||||||
self.assertEqual(string.maketrans(b'abc', b'xyz'), transtable)
|
|
||||||
self.assertRaises(ValueError, string.maketrans, b'abc', b'xyzq')
|
|
||||||
self.assertRaises(TypeError, string.maketrans, 'abc', 'def')
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
support.run_unittest(ModuleTest)
|
support.run_unittest(ModuleTest)
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,11 @@ What's New in Python 3.1 beta 1?
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- The string.maketrans() function is deprecated; there is a new static method
|
||||||
|
maketrans() on the bytes and bytearray classes. This removes confusion about
|
||||||
|
the types string.maketrans() is supposed to work with, and mirrors the
|
||||||
|
methods available on the str class.
|
||||||
|
|
||||||
- Issue #2170: refactored xml.dom.minidom.normalize, increasing both
|
- Issue #2170: refactored xml.dom.minidom.normalize, increasing both
|
||||||
its clarity and its speed.
|
its clarity and its speed.
|
||||||
|
|
||||||
|
|
|
@ -1451,6 +1451,13 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
bytes_maketrans(PyObject *null, PyObject *args)
|
||||||
|
{
|
||||||
|
return _Py_bytes_maketrans(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define FORWARD 1
|
#define FORWARD 1
|
||||||
#define REVERSE -1
|
#define REVERSE -1
|
||||||
|
|
||||||
|
@ -3131,6 +3138,8 @@ bytes_methods[] = {
|
||||||
{"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, ljust__doc__},
|
{"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, ljust__doc__},
|
||||||
{"lower", (PyCFunction)stringlib_lower, METH_NOARGS, _Py_lower__doc__},
|
{"lower", (PyCFunction)stringlib_lower, METH_NOARGS, _Py_lower__doc__},
|
||||||
{"lstrip", (PyCFunction)bytes_lstrip, METH_VARARGS, lstrip__doc__},
|
{"lstrip", (PyCFunction)bytes_lstrip, METH_VARARGS, lstrip__doc__},
|
||||||
|
{"maketrans", (PyCFunction)bytes_maketrans, METH_VARARGS|METH_STATIC,
|
||||||
|
_Py_maketrans__doc__},
|
||||||
{"partition", (PyCFunction)bytes_partition, METH_O, partition__doc__},
|
{"partition", (PyCFunction)bytes_partition, METH_O, partition__doc__},
|
||||||
{"pop", (PyCFunction)bytes_pop, METH_VARARGS, pop__doc__},
|
{"pop", (PyCFunction)bytes_pop, METH_VARARGS, pop__doc__},
|
||||||
{"remove", (PyCFunction)bytes_remove, METH_O, remove__doc__},
|
{"remove", (PyCFunction)bytes_remove, METH_O, remove__doc__},
|
||||||
|
|
|
@ -608,3 +608,70 @@ _Py_bytes_swapcase(char *result, char *s, Py_ssize_t len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PyDoc_STRVAR_shared(_Py_maketrans__doc__,
|
||||||
|
"B.maketrans(frm, to) -> translation table\n\
|
||||||
|
\n\
|
||||||
|
Return a translation table (a bytes object of length 256)\n\
|
||||||
|
suitable for use in bytes.translate where each byte in frm is\n\
|
||||||
|
mapped to the byte at the same position in to.\n\
|
||||||
|
The strings frm and to must be of the same length.");
|
||||||
|
|
||||||
|
static Py_ssize_t
|
||||||
|
_getbuffer(PyObject *obj, Py_buffer *view)
|
||||||
|
{
|
||||||
|
PyBufferProcs *buffer = Py_TYPE(obj)->tp_as_buffer;
|
||||||
|
|
||||||
|
if (buffer == NULL || buffer->bf_getbuffer == NULL)
|
||||||
|
{
|
||||||
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
"Type %.100s doesn't support the buffer API",
|
||||||
|
Py_TYPE(obj)->tp_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer->bf_getbuffer(obj, view, PyBUF_SIMPLE) < 0)
|
||||||
|
return -1;
|
||||||
|
return view->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
_Py_bytes_maketrans(PyObject *args)
|
||||||
|
{
|
||||||
|
PyObject *frm, *to, *res = NULL;
|
||||||
|
Py_buffer bfrm, bto;
|
||||||
|
int i;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
bfrm.len = -1;
|
||||||
|
bto.len = -1;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "OO:maketrans", &frm, &to))
|
||||||
|
return NULL;
|
||||||
|
if (_getbuffer(frm, &bfrm) < 0)
|
||||||
|
return NULL;
|
||||||
|
if (_getbuffer(to, &bto) < 0)
|
||||||
|
goto done;
|
||||||
|
if (bfrm.len != bto.len) {
|
||||||
|
PyErr_Format(PyExc_ValueError,
|
||||||
|
"maketrans arguments must have same length");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
res = PyBytes_FromStringAndSize(NULL, 256);
|
||||||
|
if (!res) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
p = PyBytes_AS_STRING(res);
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
p[i] = i;
|
||||||
|
for (i = 0; i < bfrm.len; i++) {
|
||||||
|
p[(int)((char *)bfrm.buf)[i]] = ((char *)bto.buf)[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (bfrm.len != -1)
|
||||||
|
PyBuffer_Release(&bfrm);
|
||||||
|
if (bto.len != -1)
|
||||||
|
PyBuffer_Release(&bto);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
|
@ -1950,6 +1950,12 @@ string_translate(PyBytesObject *self, PyObject *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
string_maketrans(PyObject *null, PyObject *args)
|
||||||
|
{
|
||||||
|
return _Py_bytes_maketrans(args);
|
||||||
|
}
|
||||||
|
|
||||||
#define FORWARD 1
|
#define FORWARD 1
|
||||||
#define REVERSE -1
|
#define REVERSE -1
|
||||||
|
|
||||||
|
@ -2851,6 +2857,8 @@ string_methods[] = {
|
||||||
{"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, ljust__doc__},
|
{"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, ljust__doc__},
|
||||||
{"lower", (PyCFunction)stringlib_lower, METH_NOARGS, _Py_lower__doc__},
|
{"lower", (PyCFunction)stringlib_lower, METH_NOARGS, _Py_lower__doc__},
|
||||||
{"lstrip", (PyCFunction)string_lstrip, METH_VARARGS, lstrip__doc__},
|
{"lstrip", (PyCFunction)string_lstrip, METH_VARARGS, lstrip__doc__},
|
||||||
|
{"maketrans", (PyCFunction)string_maketrans, METH_VARARGS|METH_STATIC,
|
||||||
|
_Py_maketrans__doc__},
|
||||||
{"partition", (PyCFunction)string_partition, METH_O, partition__doc__},
|
{"partition", (PyCFunction)string_partition, METH_O, partition__doc__},
|
||||||
{"replace", (PyCFunction)string_replace, METH_VARARGS, replace__doc__},
|
{"replace", (PyCFunction)string_replace, METH_VARARGS, replace__doc__},
|
||||||
{"rfind", (PyCFunction)string_rfind, METH_VARARGS, rfind__doc__},
|
{"rfind", (PyCFunction)string_rfind, METH_VARARGS, rfind__doc__},
|
||||||
|
|
Loading…
Reference in New Issue