Add bytes/bytearray.maketrans() to mirror str.maketrans(), and deprecate
string.maketrans() which actually works on bytes.  (Also closes #5675.)
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index bc8f39e..ca597a2 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -1451,6 +1451,13 @@
 }
 
 
+static PyObject *
+bytes_maketrans(PyObject *null, PyObject *args)
+{
+	return _Py_bytes_maketrans(args);
+}
+
+
 #define FORWARD 1
 #define REVERSE -1
 
@@ -3131,6 +3138,8 @@
     {"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__},
diff --git a/Objects/bytes_methods.c b/Objects/bytes_methods.c
index 2d55601..403b131 100644
--- a/Objects/bytes_methods.c
+++ b/Objects/bytes_methods.c
@@ -608,3 +608,70 @@
 	}
 }
 
+
+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;
+}
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index d5c2bea..1239680 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -1950,6 +1950,12 @@
 }
 
 
+static PyObject *
+string_maketrans(PyObject *null, PyObject *args)
+{
+	return _Py_bytes_maketrans(args);
+}
+
 #define FORWARD 1
 #define REVERSE -1
 
@@ -2851,6 +2857,8 @@
 	{"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__},