#7475: add (un)transform method to bytes/bytearray and str, add back codecs that can be used with them from Python 2.
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index f419eee..6ca096a 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -2488,6 +2488,75 @@
return PyUnicode_FromEncodedObject(self, encoding, errors);
}
+PyDoc_STRVAR(transform__doc__,
+"B.transform(encoding, errors='strict') -> bytearray\n\
+\n\
+Transform B using the codec registered for encoding. errors may be given\n\
+to set a different error handling scheme.");
+
+static PyObject *
+bytearray_transform(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ const char *encoding = NULL;
+ const char *errors = NULL;
+ static char *kwlist[] = {"encoding", "errors", 0};
+ PyObject *v, *w;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|s:transform",
+ kwlist, &encoding, &errors))
+ return NULL;
+
+ v = PyCodec_Encode(self, encoding, errors);
+ if (v == NULL)
+ return NULL;
+ if (!PyBytes_Check(v)) {
+ PyErr_Format(PyExc_TypeError,
+ "encoder did not return a bytes object (type=%.400s)",
+ Py_TYPE(v)->tp_name);
+ Py_DECREF(v);
+ return NULL;
+ }
+ w = PyByteArray_FromStringAndSize(PyBytes_AS_STRING(v),
+ PyBytes_GET_SIZE(v));
+ Py_DECREF(v);
+ return w;
+}
+
+
+PyDoc_STRVAR(untransform__doc__,
+"B.untransform(encoding, errors='strict') -> bytearray\n\
+\n\
+Reverse-transform B using the codec registered for encoding. errors may\n\
+be given to set a different error handling scheme.");
+
+static PyObject *
+bytearray_untransform(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ const char *encoding = NULL;
+ const char *errors = NULL;
+ static char *kwlist[] = {"encoding", "errors", 0};
+ PyObject *v, *w;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|s:untransform",
+ kwlist, &encoding, &errors))
+ return NULL;
+
+ v = PyCodec_Decode(self, encoding, errors);
+ if (v == NULL)
+ return NULL;
+ if (!PyBytes_Check(v)) {
+ PyErr_Format(PyExc_TypeError,
+ "decoder did not return a bytes object (type=%.400s)",
+ Py_TYPE(v)->tp_name);
+ Py_DECREF(v);
+ return NULL;
+ }
+ w = PyByteArray_FromStringAndSize(PyBytes_AS_STRING(v),
+ PyBytes_GET_SIZE(v));
+ Py_DECREF(v);
+ return w;
+}
+
PyDoc_STRVAR(alloc_doc,
"B.__alloc__() -> int\n\
\n\
@@ -2782,8 +2851,12 @@
{"swapcase", (PyCFunction)stringlib_swapcase, METH_NOARGS,
_Py_swapcase__doc__},
{"title", (PyCFunction)stringlib_title, METH_NOARGS, _Py_title__doc__},
+ {"transform", (PyCFunction)bytearray_transform, METH_VARARGS | METH_KEYWORDS,
+ transform__doc__},
{"translate", (PyCFunction)bytearray_translate, METH_VARARGS,
translate__doc__},
+ {"untransform", (PyCFunction)bytearray_untransform, METH_VARARGS | METH_KEYWORDS,
+ untransform__doc__},
{"upper", (PyCFunction)stringlib_upper, METH_NOARGS, _Py_upper__doc__},
{"zfill", (PyCFunction)stringlib_zfill, METH_VARARGS, zfill__doc__},
{NULL}
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index 96134a3..d3b8a4f 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -2312,6 +2312,68 @@
return PyUnicode_FromEncodedObject(self, encoding, errors);
}
+PyDoc_STRVAR(transform__doc__,
+"B.transform(encoding, errors='strict') -> bytes\n\
+\n\
+Transform B using the codec registered for encoding. errors may be given\n\
+to set a different error handling scheme.");
+
+static PyObject *
+bytes_transform(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ const char *encoding = NULL;
+ const char *errors = NULL;
+ static char *kwlist[] = {"encoding", "errors", 0};
+ PyObject *v;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|s:transform",
+ kwlist, &encoding, &errors))
+ return NULL;
+
+ v = PyCodec_Encode(self, encoding, errors);
+ if (v == NULL)
+ return NULL;
+ if (!PyBytes_Check(v)) {
+ PyErr_Format(PyExc_TypeError,
+ "encoder did not return a bytes object (type=%.400s)",
+ Py_TYPE(v)->tp_name);
+ Py_DECREF(v);
+ return NULL;
+ }
+ return v;
+}
+
+
+PyDoc_STRVAR(untransform__doc__,
+"B.untransform(encoding, errors='strict') -> bytes\n\
+\n\
+Reverse-transform B using the codec registered for encoding. errors may\n\
+be given to set a different error handling scheme.");
+
+static PyObject *
+bytes_untransform(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ const char *encoding = NULL;
+ const char *errors = NULL;
+ static char *kwlist[] = {"encoding", "errors", 0};
+ PyObject *v;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|s:untransform",
+ kwlist, &encoding, &errors))
+ return NULL;
+
+ v = PyCodec_Decode(self, encoding, errors);
+ if (v == NULL)
+ return NULL;
+ if (!PyBytes_Check(v)) {
+ PyErr_Format(PyExc_TypeError,
+ "decoder did not return a bytes object (type=%.400s)",
+ Py_TYPE(v)->tp_name);
+ Py_DECREF(v);
+ return NULL;
+ }
+ return v;
+}
PyDoc_STRVAR(splitlines__doc__,
"B.splitlines([keepends]) -> list of lines\n\
@@ -2475,8 +2537,10 @@
{"swapcase", (PyCFunction)stringlib_swapcase, METH_NOARGS,
_Py_swapcase__doc__},
{"title", (PyCFunction)stringlib_title, METH_NOARGS, _Py_title__doc__},
+ {"transform", (PyCFunction)bytes_transform, METH_VARARGS | METH_KEYWORDS, transform__doc__},
{"translate", (PyCFunction)bytes_translate, METH_VARARGS,
translate__doc__},
+ {"untransform", (PyCFunction)bytes_untransform, METH_VARARGS | METH_KEYWORDS, untransform__doc__},
{"upper", (PyCFunction)stringlib_upper, METH_NOARGS, _Py_upper__doc__},
{"zfill", (PyCFunction)stringlib_zfill, METH_VARARGS, zfill__doc__},
{"__sizeof__", (PyCFunction)bytes_sizeof, METH_NOARGS,
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 89e3c8a..fd50882 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -7432,6 +7432,7 @@
v = PyUnicode_AsEncodedString((PyObject *)self, encoding, errors);
if (v == NULL)
goto onError;
+ /* XXX this check is redundant */
if (!PyBytes_Check(v)) {
PyErr_Format(PyExc_TypeError,
"encoder did not return a bytes object "
@@ -7446,6 +7447,44 @@
return NULL;
}
+PyDoc_STRVAR(transform__doc__,
+ "S.transform(encoding, errors='strict') -> str\n\
+\n\
+Transform S using the codec registered for encoding. errors may be given\n\
+to set a different error handling scheme.");
+
+static PyObject *
+unicode_transform(PyUnicodeObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = {"encoding", "errors", 0};
+ char *encoding = NULL;
+ char *errors = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|s:transform",
+ kwlist, &encoding, &errors))
+ return NULL;
+ return PyUnicode_AsEncodedUnicode((PyObject *)self, encoding, errors);
+}
+
+PyDoc_STRVAR(untransform__doc__,
+ "S.untransform(encoding, errors='strict') -> str\n\
+\n\
+Reverse-transform S using the codec registered for encoding. errors may be\n\
+given to set a different error handling scheme.");
+
+static PyObject *
+unicode_untransform(PyUnicodeObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = {"encoding", "errors", 0};
+ char *encoding = NULL;
+ char *errors = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|s:untransform",
+ kwlist, &encoding, &errors))
+ return NULL;
+ return PyUnicode_AsDecodedUnicode((PyObject *)self, encoding, errors);
+}
+
PyDoc_STRVAR(expandtabs__doc__,
"S.expandtabs([tabsize]) -> str\n\
\n\
@@ -9091,7 +9130,8 @@
/* Order is according to common usage: often used methods should
appear first, since lookup is done sequentially. */
- {"encode", (PyCFunction) unicode_encode, METH_VARARGS | METH_KEYWORDS, encode__doc__},
+ {"encode", (PyCFunction) unicode_encode, METH_VARARGS | METH_KEYWORDS,
+ encode__doc__},
{"replace", (PyCFunction) unicode_replace, METH_VARARGS, replace__doc__},
{"split", (PyCFunction) unicode_split, METH_VARARGS, split__doc__},
{"rsplit", (PyCFunction) unicode_rsplit, METH_VARARGS, rsplit__doc__},
@@ -9136,6 +9176,10 @@
{"__format__", (PyCFunction) unicode__format__, METH_VARARGS, p_format__doc__},
{"maketrans", (PyCFunction) unicode_maketrans,
METH_VARARGS | METH_STATIC, maketrans__doc__},
+ {"transform", (PyCFunction) unicode_transform, METH_VARARGS | METH_KEYWORDS,
+ transform__doc__},
+ {"untransform", (PyCFunction) unicode_untransform, METH_VARARGS | METH_KEYWORDS,
+ untransform__doc__},
{"__sizeof__", (PyCFunction) unicode__sizeof__, METH_NOARGS, sizeof__doc__},
#if 0
{"capwords", (PyCFunction) unicode_capwords, METH_NOARGS, capwords__doc__},