]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Patch #1071: Improve unicode.translate() so that you can pass unicode
authorGeorg Brandl <georg@python.org>
Tue, 23 Oct 2007 06:52:59 +0000 (06:52 +0000)
committerGeorg Brandl <georg@python.org>
Tue, 23 Oct 2007 06:52:59 +0000 (06:52 +0000)
characters as mapping keys and invalid mapping keys are recognized
and raise an error.

Doc/library/stdtypes.rst
Lib/test/test_unicode.py
Objects/unicodeobject.c

index 61b589f3d9a917d47ef017020eb659c022269163..06eb1cfda078d19f8f3997cf253c7bb61756a317 100644 (file)
@@ -931,7 +931,7 @@ functions based on regular expressions.
    Return a copy of the *s* where all characters have been mapped through the
    *map* which must be a dictionary of characters (strings of length 1) or
    Unicode ordinals (integers) to Unicode ordinals, strings or ``None``.
-   Unmapped characters are left untouched. Characters mapped to ``None`` are
+   Unmapped characters are left untouched.  Characters mapped to ``None`` are
    deleted.
 
    .. note::
index 04dddaadd369b100cadbc4a8104a3932ae8f356f..9aad59a2b9df3a74809f3266eff5ba04fb5f1b54 100644 (file)
@@ -160,12 +160,14 @@ class UnicodeTest(
         self.checkequalnofix('bbbc', 'abababc', 'translate', {ord('a'):None})
         self.checkequalnofix('iiic', 'abababc', 'translate', {ord('a'):None, ord('b'):ord('i')})
         self.checkequalnofix('iiix', 'abababc', 'translate', {ord('a'):None, ord('b'):ord('i'), ord('c'):'x'})
-        self.checkequalnofix('<i><i><i>c', 'abababc', 'translate', {ord('a'):None, ord('b'):'<i>'})
+        self.checkequalnofix('<i><i><i>c', 'abababc', 'translate', {'a':None, 'b':'<i>'})
         self.checkequalnofix('c', 'abababc', 'translate', {ord('a'):None, ord('b'):''})
         self.checkequalnofix('xyyx', 'xzx', 'translate', {ord('z'):'yy'})
 
         self.assertRaises(TypeError, 'hello'.translate)
         self.assertRaises(TypeError, 'abababc'.translate, 'abc', 'xyz')
+        self.assertRaises(ValueError, 'abababc'.translate, {'xy':2})
+        self.assertRaises(TypeError, 'abababc'.translate, {(1,):2})
 
     def test_split(self):
         string_tests.CommonTest.test_split(self)
index 13644b0bc4c53bba2deda2304e763b540905c7e9..61a23202e8f2321fbabfdc17d016896b00d65562 100644 (file)
@@ -7810,10 +7810,54 @@ are deleted.");
 static PyObject*
 unicode_translate(PyUnicodeObject *self, PyObject *table)
 {
-    return PyUnicode_TranslateCharmap(self->str,
-                                     self->length,
-                                     table,
-                                     "ignore");
+    PyObject *newtable = NULL;
+    Py_ssize_t i = 0;
+    PyObject *key, *value, *result;
+
+    if (!PyDict_Check(table)) {
+        PyErr_SetString(PyExc_TypeError, "translate argument must be a dict");
+        return NULL;
+    }
+    /* fixup the table -- allow size-1 string keys instead of only int keys */
+    newtable = PyDict_Copy(table);
+    if (!newtable) return NULL;
+    while (PyDict_Next(table, &i, &key, &value)) {
+        if (PyUnicode_Check(key)) {
+            /* convert string keys to integer keys */
+            PyObject *newkey;
+            int res;
+            if (PyUnicode_GET_SIZE(key) != 1) {
+                PyErr_SetString(PyExc_ValueError, "string items in translate "
+                                "table must be 1 element long");
+                goto err;
+            }
+            newkey = PyInt_FromLong(PyUnicode_AS_UNICODE(key)[0]);
+            if (!newkey)
+                goto err;
+            res = PyDict_SetItem(newtable, newkey, value);
+            Py_DECREF(newkey);
+            if (res < 0)
+                goto err;
+        } else if (PyInt_Check(key)) {
+            /* just keep integer keys */
+            if (PyDict_SetItem(newtable, key, value) < 0)
+                goto err;
+        } else {
+            PyErr_SetString(PyExc_TypeError, "items in translate table must be "
+                            "strings or integers");
+            goto err;
+        }
+    }
+
+    result = PyUnicode_TranslateCharmap(self->str,
+                                        self->length,
+                                        newtable,
+                                        "ignore");
+    Py_DECREF(newtable);
+    return result;
+  err:
+    Py_DECREF(newtable);
+    return NULL;
 }
 
 PyDoc_STRVAR(upper__doc__,