Add bytes/bytearray.maketrans() to mirror str.maketrans(), and deprecate
string.maketrans() which actually works on bytes.  (Also closes #5675.)
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;
+}