Added 3rd optional argument to translate(), a string of characters to delete.
Added maketrans(), a utility to create a translation table.
diff --git a/Lib/string.py b/Lib/string.py
index edf24a4..afa0787 100644
--- a/Lib/string.py
+++ b/Lib/string.py
@@ -254,23 +254,37 @@
 	return res + line
 
 # Character translation through look-up table.
-def translate(s, table):
-    if type(table) != type('') or len(table) != 256:
-	raise TypeError, "translation table must be 256-char string"
-    res = ""
-    for c in s:
-	res = res + table[ord(c)]
-    return res
+def translate(s, table, deletions=""):
+	if type(table) != type('') or len(table) != 256:
+	    raise TypeError, "translation table must be 256 characters long"
+	res = ""
+	for c in s:
+		if c not in deletions:
+			res = res + table[ord(c)]
+	return res
 
 # Capitalize a string, e.g. "aBc  dEf" -> "Abc  def".
 def capitalize(s):
-    return upper(s[:1]) + lower(s[1:])
+	return upper(s[:1]) + lower(s[1:])
 
 # Capitalize the words in a string, e.g. " aBc  dEf " -> "Abc Def".
 # See also regsub.capwords().
 def capwords(s):
-    return join(map(capitalize, split(s)))
+	return join(map(capitalize, split(s)))
 
+# Construct a translation string
+_idmapL = None
+def maketrans(fromstr, tostr):
+	if len(fromstr) != len(tostr):
+		raise ValueError, "maketrans arguments must have same length"
+	global _idmapL
+	if not _idmapL:
+		_idmapL = map(None, _idmap)
+	L = _idmapL[:]
+	fromstr = map(ord, fromstr)
+	for i in range(len(fromstr)):
+		L[fromstr[i]] = tostr[i]
+	return joinfields(L, "")
 
 # Try importing optional built-in module "strop" -- if it exists,
 # it redefines some string operations that are 100-1000 times faster.
diff --git a/Lib/stringold.py b/Lib/stringold.py
index edf24a4..afa0787 100644
--- a/Lib/stringold.py
+++ b/Lib/stringold.py
@@ -254,23 +254,37 @@
 	return res + line
 
 # Character translation through look-up table.
-def translate(s, table):
-    if type(table) != type('') or len(table) != 256:
-	raise TypeError, "translation table must be 256-char string"
-    res = ""
-    for c in s:
-	res = res + table[ord(c)]
-    return res
+def translate(s, table, deletions=""):
+	if type(table) != type('') or len(table) != 256:
+	    raise TypeError, "translation table must be 256 characters long"
+	res = ""
+	for c in s:
+		if c not in deletions:
+			res = res + table[ord(c)]
+	return res
 
 # Capitalize a string, e.g. "aBc  dEf" -> "Abc  def".
 def capitalize(s):
-    return upper(s[:1]) + lower(s[1:])
+	return upper(s[:1]) + lower(s[1:])
 
 # Capitalize the words in a string, e.g. " aBc  dEf " -> "Abc Def".
 # See also regsub.capwords().
 def capwords(s):
-    return join(map(capitalize, split(s)))
+	return join(map(capitalize, split(s)))
 
+# Construct a translation string
+_idmapL = None
+def maketrans(fromstr, tostr):
+	if len(fromstr) != len(tostr):
+		raise ValueError, "maketrans arguments must have same length"
+	global _idmapL
+	if not _idmapL:
+		_idmapL = map(None, _idmap)
+	L = _idmapL[:]
+	fromstr = map(ord, fromstr)
+	for i in range(len(fromstr)):
+		L[fromstr[i]] = tostr[i]
+	return joinfields(L, "")
 
 # Try importing optional built-in module "strop" -- if it exists,
 # it redefines some string operations that are 100-1000 times faster.
diff --git a/Modules/stropmodule.c b/Modules/stropmodule.c
index 069d5f4..7e44e0e 100644
--- a/Modules/stropmodule.c
+++ b/Modules/stropmodule.c
@@ -547,30 +547,78 @@
 }
 
 
+static PyObject *
+strop_maketrans(self, args)
+	PyObject *self; /* Not used */
+	PyObject *args;
+{
+	unsigned char c[256], *from=NULL, *to=NULL;
+	int i, fromlen=0, tolen=0;
+
+	if (PyTuple_Size(args)!=0) {
+		if (!PyArg_ParseTuple(args, "s#s#", &from, &fromlen, 
+			         &to, &tolen)) 
+			return NULL;	
+	}
+
+	if (fromlen!=tolen) {
+		PyErr_SetString(ValueError,
+				"maketrans arguments must have same length");
+		return NULL;
+	}
+	for(i=0; i<256; i++)
+		c[i]=(unsigned char)i;
+	for(i=0; i<fromlen; i++) {
+		c[from[i]]=to[i];
+	}
+	return PyString_FromStringAndSize((char *)c, 256);
+}
+
+
 static object *
 strop_translate(self, args)
 	object *self;
 	object *args;
 {
-	char *input, *table, *output;
-	int inlen, tablen;
-	object *result;
-	int i;
+	char *input, *table, *output, *output_start, *delete=NULL;
+	int inlen, tablen, dellen;
+	PyObject *result;
+	int i, trans_table[256];
 
-	if (!newgetargs(args, "s#s#", &input, &inlen, &table, &tablen))
+	if (!PyArg_ParseTuple(args, "s#s#|s#", &input, &inlen,
+			      &table, &tablen, &delete, &dellen))
 		return NULL;
 	if (tablen != 256) {
-		err_setstr(ValueError,
+		PyErr_SetString(ValueError,
 			   "translation table must be 256 characters long");
 		return NULL;
 	}
-	result = newsizedstringobject((char *)NULL, inlen);
+	for(i=0; i<256; i++)
+		trans_table[i]=Py_CHARMASK(table[i]);
+	if (delete!=NULL) {
+		for(i=0; i<dellen; i++) 
+			trans_table[delete[i]]=-1;
+	}
+
+	result = PyString_FromStringAndSize((char *)NULL, inlen);
 	if (result == NULL)
 		return NULL;
-	output = getstringvalue(result);
-	for (i = 0; i < inlen; i++) {
-		int c = Py_CHARMASK(*input++);
-		*output++ = table[c];
+	output_start = output = PyString_AsString(result);
+        if (delete!=NULL && dellen!=0) {
+		for (i = 0; i < inlen; i++) {
+			int c = Py_CHARMASK(*input++);
+			if (trans_table[c]!=-1) 
+				*output++ = (char)trans_table[c];
+		}
+		/* Fix the size of the resulting string */
+		if (inlen > 0 &&_PyString_Resize(&result, output-output_start))
+			return NULL; 
+	} else {
+                /* If no deletions are required, use a faster loop */
+		for (i = 0; i < inlen; i++) {
+			int c = Py_CHARMASK(*input++);
+                        *output++ = (char)trans_table[c];
+                }
 	}
 	return result;
 }
@@ -592,6 +640,7 @@
 	{"splitfields",	strop_splitfields, 1},
 	{"strip",	strop_strip},
 	{"swapcase",	strop_swapcase},
+	{"maketrans",	strop_maketrans, 1},
 	{"translate",	strop_translate, 1},
 	{"upper",	strop_upper},
 	{NULL,		NULL}	/* sentinel */