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.
|
||||
|
||||
|
||||
.. method:: float.fromhex(s)
|
||||
.. classmethod:: float.fromhex(s)
|
||||
|
||||
Class method to return the float represented by a hexadecimal
|
||||
string *s*. The string *s* may have leading and trailing
|
||||
|
@ -967,7 +967,7 @@ functions based on regular expressions.
|
|||
'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`.
|
||||
|
||||
|
@ -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:
|
||||
|
||||
.. method:: bytes.fromhex(string)
|
||||
bytearray.fromhex(string)
|
||||
.. classmethod:: bytes.fromhex(string)
|
||||
bytearray.fromhex(string)
|
||||
|
||||
This :class:`bytes` class method returns a bytes or bytearray object,
|
||||
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 ')
|
||||
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])
|
||||
|
||||
|
@ -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
|
||||
length 256.
|
||||
|
||||
You can use the :func:`string.maketrans` helper function to create a
|
||||
translation table.
|
||||
You can use the :func:`bytes.maketrans` method to create a translation table.
|
||||
|
||||
Set the *table* argument to ``None`` for translations that only delete
|
||||
characters::
|
||||
|
@ -1543,6 +1544,16 @@ The translate method differs in semantics from the version available on strings:
|
|||
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:
|
||||
|
||||
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.
|
||||
|
||||
.. method:: fromkeys(seq[, value])
|
||||
.. classmethod:: fromkeys(seq[, 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.
|
||||
|
||||
|
||||
String functions
|
||||
Helper functions
|
||||
----------------
|
||||
|
||||
The following functions are available to operate on string objects.
|
||||
They are not available as string methods.
|
||||
|
||||
|
||||
.. function:: capwords(s)
|
||||
|
||||
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`,
|
||||
that will map each character in *from* into the character at the same
|
||||
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_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. */
|
||||
extern const char _Py_isspace__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_capitalize__doc__[];
|
||||
extern const char _Py_swapcase__doc__[];
|
||||
extern const char _Py_maketrans__doc__[];
|
||||
|
||||
#define FLAG_LOWER 0x01
|
||||
#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.
|
||||
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):
|
||||
raise ValueError("maketrans arguments must have same length")
|
||||
if not (isinstance(frm, bytes) and isinstance(to, bytes)):
|
||||
|
|
|
@ -418,18 +418,15 @@ class BaseStrTest:
|
|||
@bigmemtest(minsize=_2G, memuse=2)
|
||||
def test_translate(self, size):
|
||||
_ = self.from_latin1
|
||||
trans = {
|
||||
ord(_('.')): _('-'),
|
||||
ord(_('a')): _('!'),
|
||||
ord(_('Z')): _('$'),
|
||||
}
|
||||
SUBSTR = _('aZz.z.Aaz.')
|
||||
if not isinstance(SUBSTR, str):
|
||||
# Workaround the inexistence of bytes.maketrans()
|
||||
chars = bytearray(range(256))
|
||||
for k, v in trans.items():
|
||||
chars[k] = ord(v)
|
||||
trans = chars
|
||||
if isinstance(SUBSTR, str):
|
||||
trans = {
|
||||
ord(_('.')): _('-'),
|
||||
ord(_('a')): _('!'),
|
||||
ord(_('Z')): _('$'),
|
||||
}
|
||||
else:
|
||||
trans = bytes.maketrans(b'.aZ', b'-!$')
|
||||
sublen = len(SUBSTR)
|
||||
repeats = size // sublen + 2
|
||||
s = SUBSTR * repeats
|
||||
|
|
|
@ -450,6 +450,13 @@ class BaseBytesTest(unittest.TestCase):
|
|||
self.assertEqual([ord(b[i:i+1]) for i in range(len(b))],
|
||||
[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):
|
||||
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, "{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():
|
||||
support.run_unittest(ModuleTest)
|
||||
|
||||
|
|
|
@ -12,6 +12,11 @@ What's New in Python 3.1 beta 1?
|
|||
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
|
||||
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 REVERSE -1
|
||||
|
||||
|
@ -3131,6 +3138,8 @@ bytes_methods[] = {
|
|||
{"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, ljust__doc__},
|
||||
{"lower", (PyCFunction)stringlib_lower, METH_NOARGS, _Py_lower__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__},
|
||||
{"pop", (PyCFunction)bytes_pop, METH_VARARGS, pop__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 REVERSE -1
|
||||
|
||||
|
@ -2851,6 +2857,8 @@ string_methods[] = {
|
|||
{"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, ljust__doc__},
|
||||
{"lower", (PyCFunction)stringlib_lower, METH_NOARGS, _Py_lower__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__},
|
||||
{"replace", (PyCFunction)string_replace, METH_VARARGS, replace__doc__},
|
||||
{"rfind", (PyCFunction)string_rfind, METH_VARARGS, rfind__doc__},
|
||||
|
|
Loading…
Reference in New Issue