Apply diff2.txt from SF patch http://www.python.org/sf/572113
(with one small bugfix in bgen/bgen/scantools.py)

This replaces string module functions with string methods
for the stuff in the Tools directory. Several uses of
string.letters etc. are still remaining.
diff --git a/Tools/audiopy/audiopy b/Tools/audiopy/audiopy
index f5a1021..b817c5c 100755
--- a/Tools/audiopy/audiopy
+++ b/Tools/audiopy/audiopy
@@ -47,7 +47,6 @@
 
 import sys
 import os
-import string
 import errno
 import sunaudiodev
 from SUNAUDIODEV import *
@@ -372,9 +371,9 @@
                 fp = open(readmefile)
                 contents = fp.read()
                 # wax the last page, it contains Emacs cruft
-                i = string.rfind(contents, '\f')
+                i = contents.rfind('\f')
                 if i > 0:
-                    contents = string.rstrip(contents[:i])
+                    contents = contents[:i].rstrip()
             finally:
                 if fp:
                     fp.close()
diff --git a/Tools/bgen/bgen/bgenGenerator.py b/Tools/bgen/bgen/bgenGenerator.py
index aa39668..1c19388 100644
--- a/Tools/bgen/bgen/bgenGenerator.py
+++ b/Tools/bgen/bgen/bgenGenerator.py
@@ -131,7 +131,6 @@
 			self.argumentList.append(arg)
 	
 	def docstring(self):
-		import string
 		input = []
 		output = []
 		for arg in self.argumentList:
@@ -156,11 +155,11 @@
 		if not input:
 			instr = "()"
 		else:
-			instr = "(%s)" % string.joinfields(input, ", ")
+			instr = "(%s)" % ", ".join(input)
 		if not output or output == ["void"]:
 			outstr = "None"
 		else:
-			outstr = "(%s)" % string.joinfields(output, ", ")
+			outstr = "(%s)" % ", ".join(output)
 		return instr + " -> " + outstr
 	
 	def functionbody(self):
diff --git a/Tools/bgen/bgen/bgenOutput.py b/Tools/bgen/bgen/bgenOutput.py
index a269585..c7e560c 100644
--- a/Tools/bgen/bgen/bgenOutput.py
+++ b/Tools/bgen/bgen/bgenOutput.py
@@ -69,12 +69,11 @@
 	text = format % args
 	if _Level > 0:
 		indent = '\t' * _Level
-		import string
-		lines = string.splitfields(text, '\n')
+		lines = text.split('\n')
 		for i in range(len(lines)):
 			if lines[i] and lines[i][0] != '#':
 				lines[i] = indent + lines[i]
-		text = string.joinfields(lines, '\n')
+		text = '\n'.join(lines)
 	_File.write(text + '\n')
 
 def IndentLevel(by = 1):
@@ -168,13 +167,12 @@
 	"""
 	# (Don't you love using triple quotes *inside* triple quotes? :-)
 	
-	import string
-	lines = string.splitfields(text, '\n')
+	lines = text.split('\n')
 	indent = ""
 	for line in lines:
-		if string.strip(line):
+		if line.strip():
 			for c in line:
-				if c not in string.whitespace:
+				if not c.isspace():
 					break
 				indent = indent + c
 			break
diff --git a/Tools/bgen/bgen/scantools.py b/Tools/bgen/bgen/scantools.py
index 205a1ce..61c2f37 100644
--- a/Tools/bgen/bgen/scantools.py
+++ b/Tools/bgen/bgen/scantools.py
@@ -15,7 +15,6 @@
 """
 
 import re
-import string
 import sys
 import os
 import fnmatch
@@ -67,8 +66,8 @@
 		for type in types:
 			modes = self.usedtypes[type].keys()
 			modes.sort()
-			self.report("%s %s", type, string.join(modes))
-			
+			self.report("%s %s", type, " ".join(modes))
+
 	def gentypetest(self, file):
 		fp = open(file, "w")
 		fp.write("types=[\n")
@@ -163,9 +162,9 @@
 			while line[-2:] == '\\\n':
 				line = line[:-2] + ' ' + f.readline()
 				lineno = lineno + 1
-			i = string.find(line, '#')
+			i = line.find('#')
 			if i >= 0: line = line[:i]
-			words = map(string.strip, string.splitfields(line, ':'))
+			words = [s.strip() for s in line.split(':')]
 			if words == ['']: continue
 			if len(words) <> 3:
 				print "Line", startlineno,
@@ -179,8 +178,8 @@
 				print "Empty pattern"
 				print `line`
 				continue
-			patparts = map(string.strip, string.splitfields(pat, ','))
-			repparts = map(string.strip, string.splitfields(rep, ','))
+			patparts = [s.strip() for s in pat.split(',')]
+			repparts = [s.strip() for s in rep.split(',')]
 			patterns = []
 			for p in patparts:
 				if not p:
@@ -188,7 +187,7 @@
 					print "Empty pattern part"
 					print `line`
 					continue
-				pattern = string.split(p)
+				pattern = p.split()
 				if len(pattern) > 3:
 					print "Line", startlineno,
 					print "Pattern part has > 3 words"
@@ -205,7 +204,7 @@
 					print "Empty replacement part"
 					print `line`
 					continue
-				replacement = string.split(p)
+				replacement = p.split()
 				if len(replacement) > 3:
 					print "Line", startlineno,
 					print "Pattern part has > 3 words"
@@ -502,10 +501,10 @@
 		self.generate(type, name, arglist)
 
 	def extractarglist(self, args):
-		args = string.strip(args)
+		args = args.strip()
 		if not args or args == "void":
 			return []
-		parts = map(string.strip, string.splitfields(args, ","))
+		parts = [s.strip() for s in args.split(",")]
 		arglist = []
 		for part in parts:
 			arg = self.extractarg(part)
@@ -524,7 +523,7 @@
 			# array matches an optional [] after the argument name
 			type = type + " ptr "
 		type = re.sub("\*", " ptr ", type)
-		type = string.strip(type)
+		type = type.strip()
 		type = re.sub("[ \t]+", "_", type)
 		return self.modifyarg(type, name, mode)
 	
@@ -581,7 +580,7 @@
 				if item[i] == '*':
 					newitem[i] = old[k][i]
 				elif item[i][:1] == '$':
-					index = string.atoi(item[i][1:]) - 1
+					index = int(item[i][1:]) - 1
 					newitem[i] = old[index][i]
 			new.append(tuple(newitem))
 		##self.report("old: %s", `old`)
diff --git a/Tools/faqwiz/faqwiz.py b/Tools/faqwiz/faqwiz.py
index 2e2a8b5..e91d4dc 100644
--- a/Tools/faqwiz/faqwiz.py
+++ b/Tools/faqwiz/faqwiz.py
@@ -11,7 +11,7 @@
 
 """
 
-import sys, string, time, os, stat, re, cgi, faqconf
+import sys, time, os, stat, re, cgi, faqconf
 from faqconf import *                   # This imports all uppercase names
 now = time.time()
 
@@ -33,14 +33,14 @@
         self.why = why
 
 def escape(s):
-    s = string.replace(s, '&', '&amp;')
-    s = string.replace(s, '<', '&lt;')
-    s = string.replace(s, '>', '&gt;')
+    s = s.replace('&', '&amp;')
+    s = s.replace('<', '&lt;')
+    s = s.replace('>', '&gt;')
     return s
 
 def escapeq(s):
     s = escape(s)
-    s = string.replace(s, '"', '&quot;')
+    s = s.replace('"', '&quot;')
     return s
 
 def _interpolate(format, args, kw):
@@ -95,7 +95,7 @@
         list.append(repl)
     j = len(text)
     list.append(escape(text[i:j]))
-    return string.join(list, '')
+    return ''.join(list)
 
 def emphasize(line):
     return re.sub(r'\*([a-zA-Z]+)\*', r'<I>\1</I>', line)
@@ -109,7 +109,7 @@
     m = revparse_prog.match(rev)
     if not m:
         return None
-    [major, minor] = map(string.atoi, m.group(1, 2))
+    [major, minor] = map(int, m.group(1, 2))
     return major, minor
 
 logon = 0
@@ -123,10 +123,10 @@
     if not os.environ.has_key('HTTP_COOKIE'):
         return {}
     raw = os.environ['HTTP_COOKIE']
-    words = map(string.strip, string.split(raw, ';'))
+    words = [s.strip() for s in raw.split(';')]
     cookies = {}
     for word in words:
-        i = string.find(word, '=')
+        i = word.find('=')
         if i >= 0:
             key, value = word[:i], word[i+1:]
             cookies[key] = value
@@ -140,10 +140,10 @@
         return {}
     import urllib
     value = urllib.unquote(value)
-    words = string.split(value, '/')
+    words = value.split('/')
     while len(words) < 3:
         words.append('')
-    author = string.join(words[:-2], '/')
+    author = '/'.join(words[:-2])
     email = words[-2]
     password = words[-1]
     return {'author': author,
@@ -194,7 +194,7 @@
         except (TypeError, KeyError):
             value = ''
         else:
-            value = string.strip(value)
+            value = value.strip()
         setattr(self, name, value)
         return value
 
@@ -209,7 +209,7 @@
         if fp:
             import rfc822
             self.__headers = rfc822.Message(fp)
-            self.body = string.strip(fp.read())
+            self.body = fp.read().strip()
         else:
             self.__headers = {'title': "%d.%d. " % sec_num}
             self.body = ''
@@ -217,7 +217,7 @@
     def __getattr__(self, name):
         if name[0] == '_':
             raise AttributeError
-        key = string.join(string.split(name, '_'), '-')
+        key = '-'.join(name.split('_'))
         try:
             value = self.__headers[key]
         except KeyError:
@@ -237,7 +237,7 @@
             if not line:
                 break
             if line[:5] == 'head:':
-                version = string.strip(line[5:])
+                version = line[5:].strip()
         p.close()
         self.version = version
 
@@ -262,10 +262,10 @@
         emit(ENTRY_HEADER2, self)
         pre = 0
         raw = 0
-        for line in string.split(self.body, '\n'):
+        for line in self.body.split('\n'):
             # Allow the user to insert raw html into a FAQ answer
             # (Skip Montanaro, with changes by Guido)
-            tag = string.lower(string.rstrip(line))
+            tag = line.rstrip().lower()
             if tag == '<html>':
                 raw = 1
                 continue
@@ -275,14 +275,14 @@
             if raw:
                 print line
                 continue
-            if not string.strip(line):
+            if not line.strip():
                 if pre:
                     print '</PRE>'
                     pre = 0
                 else:
                     print '<P>'
             else:
-                if line[0] not in string.whitespace:
+                if not line[0].isspace():
                     if pre:
                         print '</PRE>'
                         pre = 0
@@ -335,7 +335,7 @@
         if not m:
             return None
         sec, num = m.group(1, 2)
-        return string.atoi(sec), string.atoi(num)
+        return int(sec), int(num)
 
     def list(self):
         # XXX Caller shouldn't modify result
@@ -432,7 +432,7 @@
                 return
             words = map(lambda w: r'\b%s\b' % w, words)
             if self.ui.querytype[:3] == 'any':
-                queries = [string.join(words, '|')]
+                queries = ['|'.join(words)]
             else:
                 # Each of the individual queries must match
                 queries = words
@@ -551,7 +551,7 @@
         if not self.ui.days:
             days = 1
         else:
-            days = string.atof(self.ui.days)
+            days = float(self.ui.days)
         try:
             cutoff = now - days * 24 * 3600
         except OverflowError:
@@ -623,7 +623,7 @@
         output = os.popen(command).read()
         sys.stdout.write('<PRE>')
         athead = 0
-        lines = string.split(output, '\n')
+        lines = output.split('\n')
         while lines and not lines[-1]:
             del lines[-1]
         if lines:
@@ -634,7 +634,7 @@
         headrev = None
         for line in lines:
             if entry and athead and line[:9] == 'revision ':
-                rev = string.strip(line[9:])
+                rev = line[9:].split()
                 mami = revparse(rev)
                 if not mami:
                     print line
@@ -690,7 +690,7 @@
         print '</PRE>'
 
     def do_new(self):
-        entry = self.dir.new(section=string.atoi(self.ui.section))
+        entry = self.dir.new(section=int(self.ui.section))
         entry.version = '*new*'
         self.prologue(T_EDIT)
         emit(EDITHEAD)
@@ -723,7 +723,7 @@
             entry = self.dir.open(self.ui.file)
             entry.load_version()
         # Check that the FAQ entry number didn't change
-        if string.split(self.ui.title)[:1] != string.split(entry.title)[:1]:
+        if self.ui.title.split()[:1] != entry.title.split()[:1]:
             self.error("Don't change the entry number please!")
             return
         # Check that the edited version is the current version
@@ -779,7 +779,7 @@
         if '\r' in self.ui.body:
             self.ui.body = re.sub('\r\n?', '\n', self.ui.body)
         # Normalize whitespace in title
-        self.ui.title = string.join(string.split(self.ui.title))
+        self.ui.title = ' '.join(self.ui.title.split())
         # Check that there were any changes
         if self.ui.body == entry.body and self.ui.title == entry.title:
             self.error("You didn't make any changes!")
diff --git a/Tools/freeze/checkextensions.py b/Tools/freeze/checkextensions.py
index 8d597bf..584f8a6 100644
--- a/Tools/freeze/checkextensions.py
+++ b/Tools/freeze/checkextensions.py
@@ -3,7 +3,6 @@
 # and one or more .o files or a lib.a file.
 
 import os
-import string
 import parsesetup
 
 def checkextensions(unknown, extensions):
@@ -44,7 +43,7 @@
 		if not w:
 			continue
 		w = expandvars(w, vars)
-		for w in string.split(w):
+		for w in w.split():
 			if skipofiles and w[-2:] == '.o':
 				continue
 			# Assume $var expands to absolute pathname
@@ -73,14 +72,14 @@
 def expandvars(str, vars):
 	i = 0
 	while i < len(str):
-		i = k = string.find(str, '$', i)
+		i = k = str.find('$', i)
 		if i < 0:
 			break
 		i = i+1
 		var = str[i:i+1]
 		i = i+1
 		if var == '(':
-			j = string.find(str, ')', i)
+			j = str.find(')', i)
 			if j < 0:
 				break
 			var = str[i:j]
diff --git a/Tools/freeze/checkextensions_win32.py b/Tools/freeze/checkextensions_win32.py
index 85c3a3c..669a142 100644
--- a/Tools/freeze/checkextensions_win32.py
+++ b/Tools/freeze/checkextensions_win32.py
@@ -22,7 +22,7 @@
 but an obvious enhancement would be to provide command line options.
 """
 
-import os, string, sys
+import os, sys
 try:
 	import win32api
 except ImportError:
@@ -107,12 +107,12 @@
 		module.AddCompilerOption(win32api.ExpandEnvironmentStrings(cl_options))
 
 	exclude = win32api.GetProfileVal(moduleName, "exclude", "", mapFileName)
-	exclude = string.split(exclude)
+	exclude = exclude.split()
 
 	if win32api.GetProfileVal(moduleName, "Unicode", 0, mapFileName):
 		module.AddCompilerOption('/D UNICODE /D _UNICODE')
 
-	libs = string.split(win32api.GetProfileVal(moduleName, "libs", "", mapFileName))
+	libs = win32api.GetProfileVal(moduleName, "libs", "", mapFileName).split()
 	for lib in libs:
 		module.AddLinkerLib(win32api.ExpandEnvironmentStrings(lib))
 
@@ -135,9 +135,9 @@
 		sys.stderr.write("%s: %s\n" % (dsp, msg))
 		return None
 	for line in lines:
-		fields = string.split(string.strip(line), "=", 2)
+		fields = line.strip().split("=", 2)
 		if fields[0]=="SOURCE":
-			if string.lower(os.path.splitext(fields[1])[1]) in ['.cpp', '.c']:
+			if os.path.splitext(fields[1])[1].lower() in ['.cpp', '.c']:
 				ret.append( win32api.GetFullPathName(os.path.join(dsp_path, fields[1] ) ) )
 	return ret
 
@@ -148,12 +148,12 @@
 		# Write fn protos
 		for module in modules:
 			# bit of a hack for .pyd's as part of packages.
-			name = string.split(module.name,'.')[-1]
+			name = module.name.split('.')[-1]
 			fp.write('extern void init%s(void);\n' % (name) )
 		# Write the table
 		fp.write (ext_tab_header)
 		for module in modules:
-			name = string.split(module.name,'.')[-1]
+			name = module.name.split('.')[-1]
 			fp.write('\t{"%s", init%s},\n' % (name, name) )
 
 		fp.write (ext_tab_footer)
diff --git a/Tools/freeze/freeze.py b/Tools/freeze/freeze.py
index 0b9b206..2c59807 100755
--- a/Tools/freeze/freeze.py
+++ b/Tools/freeze/freeze.py
@@ -91,7 +91,6 @@
 
 import getopt
 import os
-import string
 import sys
 
 
@@ -148,7 +147,7 @@
         # last option can not be "-i", so this ensures "pos+1" is in range!
         if sys.argv[pos] == '-i':
             try:
-                options = string.split(open(sys.argv[pos+1]).read())
+                options = open(sys.argv[pos+1]).read().split()
             except IOError, why:
                 usage("File name '%s' specified with the -i option "
                       "can not be read - %s" % (sys.argv[pos+1], why) )
@@ -198,9 +197,9 @@
         if o == '-l':
             addn_link.append(a)
         if o == '-a':
-            apply(modulefinder.AddPackagePath, tuple(string.split(a,"=", 2)))
+            apply(modulefinder.AddPackagePath, tuple(a.split("=", 2)))
         if o == '-r':
-            f,r = string.split(a,"=", 2)
+            f,r = a.split("=", 2)
             replace_paths.append( (f,r) )
 
     # default prefix and exec_prefix
@@ -419,7 +418,7 @@
     # report unknown modules
     if unknown:
         sys.stderr.write('Warning: unknown modules remain: %s\n' %
-                         string.join(unknown))
+                         ' '.join(unknown))
 
     # windows gets different treatment
     if win:
@@ -462,8 +461,8 @@
     for key in makevars.keys():
         somevars[key] = makevars[key]
 
-    somevars['CFLAGS'] = string.join(cflags) # override
-    somevars['CPPFLAGS'] = string.join(cppflags) # override
+    somevars['CFLAGS'] = ' '.join(cflags) # override
+    somevars['CPPFLAGS'] = ' '.join(cppflags) # override
     files = [base_config_c, base_frozen_c] + \
             files + supp_sources +  addfiles + libs + \
             ['$(MODLIBS)', '$(LIBS)', '$(SYSLIBS)']
diff --git a/Tools/freeze/makefreeze.py b/Tools/freeze/makefreeze.py
index 3888050..29a6ad6 100644
--- a/Tools/freeze/makefreeze.py
+++ b/Tools/freeze/makefreeze.py
@@ -1,5 +1,4 @@
 import marshal
-import string
 import bkfile
 
 
@@ -38,7 +37,7 @@
     mods.sort()
     for mod in mods:
         m = dict[mod]
-        mangled = string.join(string.split(mod, "."), "__")
+        mangled = "__".join(mod.split("."))
         if m.__code__:
             file = 'M_' + mangled + '.c'
             outfp = bkfile.open(base + file, 'w')
@@ -88,4 +87,4 @@
 
 ## def writecode(outfp, mod, str):
 ##     outfp.write('unsigned char M_%s[%d] = "%s";\n' % (mod, len(str),
-##     string.join(map(lambda s: `s`[1:-1], string.split(str, '"')), '\\"')))
+##     '\\"'.join(map(lambda s: `s`[1:-1], str.split('"')))))
diff --git a/Tools/freeze/makemakefile.py b/Tools/freeze/makemakefile.py
index e33e32e..b8b99b8 100644
--- a/Tools/freeze/makemakefile.py
+++ b/Tools/freeze/makemakefile.py
@@ -1,7 +1,6 @@
 # Write the actual Makefile.
 
 import os
-import string
 
 def makemakefile(outfp, makevars, files, target):
     outfp.write("# Makefile generated by freeze.py script\n\n")
@@ -23,8 +22,8 @@
             files[i] = dest
             deps.append(dest)
 
-    outfp.write("\n%s: %s\n" % (target, string.join(deps)))
+    outfp.write("\n%s: %s\n" % (target, ' '.join(deps)))
     outfp.write("\t$(LINKCC) $(LDFLAGS) $(LINKFORSHARED) %s -o %s $(LDLAST)\n" % 
-                (string.join(files), target))
+                (' '.join(files), target))
 
     outfp.write("\nclean:\n\t-rm -f *.o %s\n" % target)
diff --git a/Tools/freeze/modulefinder.py b/Tools/freeze/modulefinder.py
index 741ef4d..e9c1140 100644
--- a/Tools/freeze/modulefinder.py
+++ b/Tools/freeze/modulefinder.py
@@ -5,7 +5,6 @@
 import marshal
 import os
 import re
-import string
 import sys
 import new
 
@@ -150,7 +149,7 @@
             self.msgout(4, "determine_parent ->", parent)
             return parent
         if '.' in pname:
-            i = string.rfind(pname, '.')
+            i = pname.rfind('.')
             pname = pname[:i]
             parent = self.modules[pname]
             assert parent.__name__ == pname
@@ -162,7 +161,7 @@
     def find_head_package(self, parent, name):
         self.msgin(4, "find_head_package", parent, name)
         if '.' in name:
-            i = string.find(name, '.')
+            i = name.find('.')
             head = name[:i]
             tail = name[i+1:]
         else:
@@ -190,7 +189,7 @@
         self.msgin(4, "load_tail", q, tail)
         m = q
         while tail:
-            i = string.find(tail, '.')
+            i = tail.find('.')
             if i < 0: i = len(tail)
             head, tail = tail[:i], tail[i+1:]
             mname = "%s.%s" % (m.__name__, head)
@@ -357,7 +356,7 @@
 
     def find_module(self, name, path):
         if path:
-            fullname = string.join(path, '.')+'.'+name
+            fullname = '.'.join(path)+'.'+name
         else:
             fullname = name
         if fullname in self.excludes:
@@ -399,7 +398,7 @@
             if key not in self.excludes:
                 mods = self.badmodules[key].keys()
                 mods.sort()
-                print "?", key, "from", string.join(mods, ', ')
+                print "?", key, "from", ', '.join(mods)
 
     def any_missing(self):
         keys = self.badmodules.keys()
@@ -457,7 +456,7 @@
         if o == '-m':
             domods = 1
         if o == '-p':
-            addpath = addpath + string.split(a, os.pathsep)
+            addpath = addpath + a.split(os.pathsep)
         if o == '-q':
             debug = 0
         if o == '-x':
diff --git a/Tools/freeze/parsesetup.py b/Tools/freeze/parsesetup.py
index 7a6b72e..2b9123e 100644
--- a/Tools/freeze/parsesetup.py
+++ b/Tools/freeze/parsesetup.py
@@ -1,7 +1,6 @@
 # Parse Makefiles and Python Setup(.in) files.
 
 import re
-import string
 
 
 # Extract variable definitions from a Makefile.
@@ -29,10 +28,10 @@
 				continue
 			(name, value) = matchobj.group(1, 2)
 			# Strip trailing comment
-			i = string.find(value, '#')
+			i = value.find('#')
 			if i >= 0:
 				value = value[:i]
-			value = string.strip(value)
+			value = value.strip()
 			variables[name] = value
 	finally:
 		fp.close()
@@ -60,7 +59,7 @@
 			if not line:
 				break
 			# Strip comments
-			i = string.find(line, '#')
+			i = line.find('#')
 			if i >= 0:
 				line = line[:i]
 			if line.endswith('\\\n'):
@@ -69,9 +68,9 @@
 			matchobj = setupvardef.match(line)
 			if matchobj:
 				(name, value) = matchobj.group(1, 2)
-				variables[name] = string.strip(value)
+				variables[name] = value.strip()
 			else:
-				words = string.split(line)
+				words = line.split()
 				if words:
 					modules[words[0]] = words[1:]
 	finally:
diff --git a/Tools/freeze/winmakemakefile.py b/Tools/freeze/winmakemakefile.py
index d668a6e8..763e820 100644
--- a/Tools/freeze/winmakemakefile.py
+++ b/Tools/freeze/winmakemakefile.py
@@ -1,4 +1,4 @@
-import sys, os, string
+import sys, os
 
 # Template used then the program is a GUI program
 WINMAINTEMPLATE = """
@@ -112,7 +112,7 @@
             print "\t\t$(cflags) $(cdebug) $(cinclude) \\"
             extra = moddefn.GetCompilerOptions()
             if extra:
-                print "\t\t%s \\" % (string.join(extra),)
+                print "\t\t%s \\" % (' '.join(extra),)
             print '\t\t"%s"' % file
             print
 
diff --git a/Tools/idle/AutoIndent.py b/Tools/idle/AutoIndent.py
index f8bb847..7bc195b 100644
--- a/Tools/idle/AutoIndent.py
+++ b/Tools/idle/AutoIndent.py
@@ -1,4 +1,3 @@
-import string
 #from Tkinter import TclError
 #import tkMessageBox
 #import tkSimpleDialog
@@ -168,15 +167,15 @@
             return "break"
         # Ick.  It may require *inserting* spaces if we back up over a
         # tab character!  This is written to be clear, not fast.
-        expand, tabwidth = string.expandtabs, self.tabwidth
-        have = len(expand(chars, tabwidth))
+        tabwidth = self.tabwidth
+        have = len(chars.expandtabs(tabwidth))
         assert have > 0
         want = ((have - 1) // self.indentwidth) * self.indentwidth
         ncharsdeleted = 0
         while 1:
             chars = chars[:-1]
             ncharsdeleted = ncharsdeleted + 1
-            have = len(expand(chars, tabwidth))
+            have = len(chars.expandtabs(tabwidth))
             if have <= want or chars[-1] not in " \t":
                 break
         text.undo_block_start()
@@ -210,8 +209,7 @@
                 if self.usetabs:
                     pad = '\t'
                 else:
-                    effective = len(string.expandtabs(prefix,
-                                                      self.tabwidth))
+                    effective = len(prefix.expandtabs(self.tabwidth))
                     n = self.indentwidth
                     pad = ' ' * (n - effective % n)
                 text.insert("insert", pad)
@@ -376,7 +374,7 @@
         head, tail, chars, lines = self.get_region()
         tabwidth = self._asktabwidth()
         for pos in range(len(lines)):
-            lines[pos] = string.expandtabs(lines[pos], tabwidth)
+            lines[pos] = lines[pos].expandtabs(tabwidth)
         self.set_region(head, tail, chars, lines)
 
     def toggle_tabs_event(self, event):
@@ -417,12 +415,12 @@
             head = text.index("insert linestart")
             tail = text.index("insert lineend +1c")
         chars = text.get(head, tail)
-        lines = string.split(chars, "\n")
+        lines = chars.split("\n")
         return head, tail, chars, lines
 
     def set_region(self, head, tail, chars, lines):
         text = self.text
-        newchars = string.join(lines, "\n")
+        newchars = "\n".join(lines)
         if newchars == chars:
             text.bell()
             return
diff --git a/Tools/idle/Bindings.py b/Tools/idle/Bindings.py
index 8bf0e70..a7d3802 100644
--- a/Tools/idle/Bindings.py
+++ b/Tools/idle/Bindings.py
@@ -6,7 +6,6 @@
 # Debug menu here, which is only present in the PythonShell window.
 
 import sys
-import string
 from keydefs import *
 
 menudefs = [
diff --git a/Tools/idle/CallTips.py b/Tools/idle/CallTips.py
index dc25083..d8445a4 100644
--- a/Tools/idle/CallTips.py
+++ b/Tools/idle/CallTips.py
@@ -141,7 +141,7 @@
                     items.append("...")
                 if fob.func_code.co_flags & 0x8:
                     items.append("***")
-                argText = string.join(items , ", ")
+                argText = ", ".join(items)
                 argText = "(%s)" % argText
             except:
                 pass
diff --git a/Tools/idle/ClassBrowser.py b/Tools/idle/ClassBrowser.py
index 19f3b7e..6e4b2a3 100644
--- a/Tools/idle/ClassBrowser.py
+++ b/Tools/idle/ClassBrowser.py
@@ -12,7 +12,6 @@
 
 import os
 import sys
-import string
 import pyclbr
 
 # XXX Patch pyclbr with dummies if it's vintage Python 1.5.2:
@@ -117,7 +116,7 @@
                             if sup.module != cl.module:
                                 sname = "%s.%s" % (sup.module, sname)
                         supers.append(sname)
-                    s = s + "(%s)" % string.join(supers, ", ")
+                    s = s + "(%s)" % ", ".join(supers)
                 items.append((cl.lineno, s))
                 self.classes[s] = cl
         items.sort()
diff --git a/Tools/idle/ColorDelegator.py b/Tools/idle/ColorDelegator.py
index 3d2ecef..059108f 100644
--- a/Tools/idle/ColorDelegator.py
+++ b/Tools/idle/ColorDelegator.py
@@ -1,5 +1,4 @@
 import time
-import string
 import re
 import keyword
 from Tkinter import *
@@ -14,7 +13,7 @@
 
 
 def any(name, list):
-    return "(?P<%s>" % name + string.join(list, "|") + ")"
+    return "(?P<%s>" % name + "|".join(list) + ")"
 
 def make_pat():
     kw = r"\b" + any("KEYWORD", keyword.kwlist) + r"\b"
diff --git a/Tools/idle/EditorWindow.py b/Tools/idle/EditorWindow.py
index e8b63ff..c0ae556 100644
--- a/Tools/idle/EditorWindow.py
+++ b/Tools/idle/EditorWindow.py
@@ -1,6 +1,5 @@
 import sys
 import os
-import string
 import re
 import imp
 from Tkinter import *
@@ -221,7 +220,7 @@
         self.text.after_idle(self.set_line_and_column)
 
     def set_line_and_column(self, event=None):
-        line, column = string.split(self.text.index(INSERT), '.')
+        line, column = self.text.index(INSERT).split('.')
         self.status_bar.set_label('column', 'Col: %s' % column)
         self.status_bar.set_label('line', 'Ln: %s' % line)
 
@@ -344,14 +343,14 @@
         except TclError:
             name = ""
         else:
-            name = string.strip(name)
+            name = name.strip()
         if not name:
             name = tkSimpleDialog.askstring("Module",
                      "Enter the name of a Python module\n"
                      "to search on sys.path and open:",
                      parent=self.text)
             if name:
-                name = string.strip(name)
+                name = name.strip()
             if not name:
                 return
         # XXX Ought to insert current file's directory in front of path
@@ -408,7 +407,7 @@
             f.close()
         except IOError:
             return False
-        return line[:2] == '#!' and string.find(line, 'python') >= 0
+        return line.startswith('#!') and 'python' in line
 
     def close_hook(self):
         if self.flist:
@@ -580,7 +579,7 @@
         if keydefs:
             self.apply_bindings(keydefs)
             for vevent in keydefs.keys():
-                methodname = string.replace(vevent, "-", "_")
+                methodname = vevent.replace("-", "_")
                 while methodname[:1] == '<':
                     methodname = methodname[1:]
                 while methodname[-1:] == '>':
@@ -700,7 +699,7 @@
 def prepstr(s):
     # Helper to extract the underscore from a string, e.g.
     # prepstr("Co_py") returns (2, "Copy").
-    i = string.find(s, '_')
+    i = s.find('_')
     if i >= 0:
         s = s[:i] + s[i+1:]
     return i, s
@@ -717,7 +716,7 @@
     if not keylist:
         return ""
     s = keylist[0]
-    s = re.sub(r"-[a-z]\b", lambda m: string.upper(m.group()), s)
+    s = re.sub(r"-[a-z]\b", lambda m: m.group().upper(), s)
     s = re.sub(r"\b\w+\b", lambda m: keynames.get(m.group(), m.group()), s)
     s = re.sub("Key-", "", s)
     s = re.sub("Control-", "Ctrl-", s)
diff --git a/Tools/idle/FormatParagraph.py b/Tools/idle/FormatParagraph.py
index ea18cc0..c1bc769 100644
--- a/Tools/idle/FormatParagraph.py
+++ b/Tools/idle/FormatParagraph.py
@@ -14,7 +14,6 @@
 #   spaces, they will not be considered part of the same block.
 # * Fancy comments, like this bulleted list, arent handled :-)
 
-import string
 import re
 
 class FormatParagraph:
@@ -50,14 +49,14 @@
                     find_paragraph(text, text.index("insert"))
         if comment_header:
             # Reformat the comment lines - convert to text sans header.
-            lines = string.split(data, "\n")
+            lines = data.split("\n")
             lines = map(lambda st, l=len(comment_header): st[l:], lines)
-            data = string.join(lines, "\n")
+            data = "\n".join(lines)
             # Reformat to 70 chars or a 20 char width, whichever is greater.
             format_width = max(70-len(comment_header), 20)
             newdata = reformat_paragraph(data, format_width)
             # re-split and re-insert the comment header.
-            newdata = string.split(newdata, "\n")
+            newdata = newdata.split("\n")
             # If the block ends in a \n, we dont want the comment
             # prefix inserted after it. (Im not sure it makes sense to
             # reformat a comment block that isnt made of complete
@@ -68,7 +67,7 @@
                 block_suffix = "\n"
                 newdata = newdata[:-1]
             builder = lambda item, prefix=comment_header: prefix+item
-            newdata = string.join(map(builder, newdata), '\n') + block_suffix
+            newdata = '\n'.join(map(builder, newdata)) + block_suffix
         else:
             # Just a normal text format
             newdata = reformat_paragraph(data)
@@ -84,7 +83,7 @@
         text.see("insert")
 
 def find_paragraph(text, mark):
-    lineno, col = map(int, string.split(mark, "."))
+    lineno, col = map(int, mark.split("."))
     line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno)
     while text.compare("%d.0" % lineno, "<", "end") and is_all_white(line):
         lineno = lineno + 1
@@ -109,7 +108,7 @@
     return first, last, comment_header, text.get(first, last)
 
 def reformat_paragraph(data, limit=70):
-    lines = string.split(data, "\n")
+    lines = data.split("\n")
     i = 0
     n = len(lines)
     while i < n and is_all_white(lines[i]):
@@ -130,18 +129,18 @@
             word = words[j]
             if not word:
                 continue # Can happen when line ends in whitespace
-            if len(string.expandtabs(partial + word)) > limit and \
+            if len((partial + word).expandtabs()) > limit and \
                partial != indent1:
-                new.append(string.rstrip(partial))
+                new.append(partial.rstrip())
                 partial = indent2
             partial = partial + word + " "
             if j+1 < len(words) and words[j+1] != " ":
                 partial = partial + " "
         i = i+1
-    new.append(string.rstrip(partial))
+    new.append(partial.rstrip())
     # XXX Should reformat remaining paragraphs as well
     new.extend(lines[i:])
-    return string.join(new, "\n")
+    return "\n".join(new)
 
 def is_all_white(line):
     return re.match(r"^\s*$", line) is not None
diff --git a/Tools/idle/GrepDialog.py b/Tools/idle/GrepDialog.py
index 61c77c3..ed5a979 100644
--- a/Tools/idle/GrepDialog.py
+++ b/Tools/idle/GrepDialog.py
@@ -1,4 +1,3 @@
-import string
 import os
 import re
 import fnmatch
diff --git a/Tools/idle/IdleHistory.py b/Tools/idle/IdleHistory.py
index b882c92..46e70e1 100644
--- a/Tools/idle/IdleHistory.py
+++ b/Tools/idle/IdleHistory.py
@@ -1,5 +1,3 @@
-import string
-
 class History:
 
     def __init__(self, text, output_sep = "\n"):
@@ -22,11 +20,11 @@
     def _get_source(self, start, end):
         # Get source code from start index to end index.  Lines in the
         # text control may be separated by sys.ps2 .
-        lines = string.split(self.text.get(start, end), self.output_sep)
-        return string.join(lines, "\n")
+        lines = self.text.get(start, end).split(self.output_sep)
+        return "\n".join(lines)
 
     def _put_source(self, where, source):
-        output = string.join(string.split(source, "\n"), self.output_sep)
+        output = self.output_sep.join(source.split("\n"))
         self.text.insert(where, output)
 
     def history_do(self, reverse):
@@ -68,7 +66,7 @@
         self.history_prefix = prefix
 
     def history_store(self, source):
-        source = string.strip(source)
+        source = source.strip()
         if len(source) > 2:
             # avoid duplicates
             try:
@@ -80,7 +78,7 @@
         self.history_prefix = None
 
     def recall(self, s):
-        s = string.strip(s)
+        s = s.strip()
         self.text.tag_remove("sel", "1.0", "end")
         self.text.delete("iomark", "end-1c")
         self.text.mark_set("insert", "end-1c")
diff --git a/Tools/idle/MultiScrolledLists.py b/Tools/idle/MultiScrolledLists.py
index 6c140df..6398b86 100644
--- a/Tools/idle/MultiScrolledLists.py
+++ b/Tools/idle/MultiScrolledLists.py
@@ -3,7 +3,6 @@
 # the right list displays the substructure of the selected item
 # in the left list.
 
-import string
 from Tkinter import *
 from WindowList import ListedToplevel
 from Separator import HSeparator
diff --git a/Tools/idle/OldStackViewer.py b/Tools/idle/OldStackViewer.py
index 2fa4127..4f295e8 100644
--- a/Tools/idle/OldStackViewer.py
+++ b/Tools/idle/OldStackViewer.py
@@ -1,4 +1,3 @@
-import string
 import sys
 import os
 from Tkinter import *
@@ -121,7 +120,7 @@
             filename = code.co_filename
             funcname = code.co_name
             sourceline = linecache.getline(filename, lineno)
-            sourceline = string.strip(sourceline)
+            sourceline = sourceline.strip()
             if funcname in ("?", "", None):
                 item = "%s, line %d: %s" % (modname, lineno, sourceline)
             else:
diff --git a/Tools/idle/ParenMatch.py b/Tools/idle/ParenMatch.py
index 17d76c2..1be60c0 100644
--- a/Tools/idle/ParenMatch.py
+++ b/Tools/idle/ParenMatch.py
@@ -10,8 +10,6 @@
 extensions what to capture the same event.
 """
 
-import string
-
 import PyParse
 from AutoIndent import AutoIndent, index2line
 from IdleConf import idleconf
@@ -177,10 +175,10 @@
         if i is None \
            or keysym_type(buf[i]) != right_keysym_type:
             return None
-        lines_back = string.count(buf[i:], "\n") - 1
+        lines_back = buf[i:].count("\n") - 1
         # subtract one for the "\n" added to please the parser
         upto_open = buf[:i]
-        j = string.rfind(upto_open, "\n") + 1 # offset of column 0 of line
+        j = upto_open.rfind("\n") + 1 # offset of column 0 of line
         offset = i - j
         return "%d.%d" % (lno - lines_back, offset)
 
diff --git a/Tools/idle/PyParse.py b/Tools/idle/PyParse.py
index c8212b2..422a86c 100644
--- a/Tools/idle/PyParse.py
+++ b/Tools/idle/PyParse.py
@@ -1,4 +1,3 @@
-import string
 import re
 import sys
 
@@ -7,7 +6,7 @@
 
 if 0:   # for throwaway debugging output
     def dump(*stuff):
-        sys.__stdout__.write(string.join(map(str, stuff), " ") + "\n")
+        sys.__stdout__.write(" ".join(map(str, stuff)) + "\n")
 
 # Find what looks like the start of a popular stmt.
 
@@ -103,7 +102,7 @@
     _tran[ord(ch)] = ')'
 for ch in "\"'\\\n#":
     _tran[ord(ch)] = ch
-_tran = string.join(_tran, '')
+_tran = ''.join(_tran)
 del ch
 
 try:
@@ -153,13 +152,12 @@
     # Python 1.5.2 (#0, Apr 13 1999, ...
 
     def find_good_parse_start(self, use_ps1, is_char_in_string=None,
-                              _rfind=string.rfind,
                               _synchre=_synchre):
         str, pos = self.str, None
         if use_ps1:
             # shell window
             ps1 = '\n' + sys.ps1
-            i = _rfind(str, ps1)
+            i = str.rfind(ps1)
             if i >= 0:
                 pos = i + len(ps1)
                 # make it look like there's a newline instead
@@ -178,10 +176,10 @@
         # bumped to a legitimate synch point.
         limit = len(str)
         for tries in range(5):
-            i = _rfind(str, ":\n", 0, limit)
+            i = str.rfind(":\n", 0, limit)
             if i < 0:
                 break
-            i = _rfind(str, '\n', 0, i) + 1  # start of colon line
+            i = str.rfind('\n', 0, i) + 1  # start of colon line
             m = _synchre(str, i, limit)
             if m and not is_char_in_string(m.start()):
                 pos = m.start()
@@ -226,7 +224,7 @@
     # based) of the non-continuation lines.
     # Creates self.{goodlines, continuation}.
 
-    def _study1(self, _replace=string.replace, _find=string.find):
+    def _study1(self):
         if self.study_level >= 1:
             return
         self.study_level = 1
@@ -236,12 +234,12 @@
         # uninteresting characters.  This can cut the number of chars
         # by a factor of 10-40, and so greatly speed the following loop.
         str = self.str
-        str = string.translate(str, _tran)
-        str = _replace(str, 'xxxxxxxx', 'x')
-        str = _replace(str, 'xxxx', 'x')
-        str = _replace(str, 'xx', 'x')
-        str = _replace(str, 'xx', 'x')
-        str = _replace(str, '\nx', '\n')
+        str = str.translate(_tran)
+        str = str.replace('xxxxxxxx', 'x')
+        str = str.replace('xxxx', 'x')
+        str = str.replace('xx', 'x')
+        str = str.replace('xx', 'x')
+        str = str.replace('\nx', '\n')
         # note that replacing x\n with \n would be incorrect, because
         # x may be preceded by a backslash
 
@@ -322,7 +320,7 @@
 
             if ch == '#':
                 # consume the comment
-                i = _find(str, '\n', i)
+                i = str.find('\n', i)
                 assert i >= 0
                 continue
 
@@ -363,8 +361,7 @@
     #     self.lastopenbracketpos
     #         if continuation is C_BRACKET, index of last open bracket
 
-    def _study2(self, _rfind=string.rfind, _find=string.find,
-                      _ws=string.whitespace):
+    def _study2(self):
         if self.study_level >= 2:
             return
         self._study1()
@@ -381,7 +378,7 @@
             q = p
             for nothing in range(goodlines[i-1], goodlines[i]):
                 # tricky: sets p to 0 if no preceding newline
-                p = _rfind(str, '\n', 0, p-1) + 1
+                p = str.rfind('\n', 0, p-1) + 1
             # The stmt str[p:q] isn't a continuation, but may be blank
             # or a non-indenting comment line.
             if  _junkre(str, p):
@@ -444,7 +441,7 @@
 
             if ch == '#':
                 # consume comment and trailing newline
-                p = _find(str, '\n', p, q) + 1
+                p = str.find('\n', p, q) + 1
                 assert p > 0
                 continue
 
@@ -465,13 +462,13 @@
     # Assuming continuation is C_BRACKET, return the number
     # of spaces the next line should be indented.
 
-    def compute_bracket_indent(self, _find=string.find):
+    def compute_bracket_indent(self):
         self._study2()
         assert self.continuation == C_BRACKET
         j = self.lastopenbracketpos
         str = self.str
         n = len(str)
-        origi = i = string.rfind(str, '\n', 0, j) + 1
+        origi = i = str.rfind('\n', 0, j) + 1
         j = j+1     # one beyond open bracket
         # find first list item; set i to start of its line
         while j < n:
@@ -482,7 +479,7 @@
                 break
             else:
                 # this line is junk; advance to next line
-                i = j = _find(str, '\n', j) + 1
+                i = j = str.find('\n', j) + 1
         else:
             # nothing interesting follows the bracket;
             # reproduce the bracket line's indentation + a level
@@ -490,8 +487,7 @@
             while str[j] in " \t":
                 j = j+1
             extra = self.indentwidth
-        return len(string.expandtabs(str[i:j],
-                                     self.tabwidth)) + extra
+        return len(str[i:j].expandtabs(self.tabwidth)) + extra
 
     # Return number of physical lines in last stmt (whether or not
     # it's an interesting stmt!  this is intended to be called when
@@ -517,7 +513,7 @@
 
         # See whether the initial line starts an assignment stmt; i.e.,
         # look for an = operator
-        endpos = string.find(str, '\n', startpos) + 1
+        endpos = str.find('\n', startpos) + 1
         found = level = 0
         while i < endpos:
             ch = str[i]
@@ -553,8 +549,7 @@
             while str[i] not in " \t\n":
                 i = i+1
 
-        return len(string.expandtabs(str[self.stmt_start :
-                                         i],
+        return len(str[self.stmt_start:i].expandtabs(\
                                      self.tabwidth)) + 1
 
     # Return the leading whitespace on the initial line of the last
diff --git a/Tools/idle/PyShell.py b/Tools/idle/PyShell.py
index e71a9a1..7fd28eb 100644
--- a/Tools/idle/PyShell.py
+++ b/Tools/idle/PyShell.py
@@ -208,7 +208,7 @@
         # Stuff source in the filename cache
         filename = "<pyshell#%d>" % self.gid
         self.gid = self.gid + 1
-        lines = string.split(source, "\n")
+        lines = source.split("\n")
         linecache.cache[filename] = len(source)+1, 0, lines, filename
         return filename
 
@@ -582,7 +582,7 @@
         # If we're in the current input and there's only whitespace
         # beyond the cursor, erase that whitespace first
         s = self.text.get("insert", "end-1c")
-        if s and not string.strip(s):
+        if s and not s.strip():
             self.text.delete("insert", "end-1c")
         # If we're in the current input before its last line,
         # insert a newline right at the insert point
diff --git a/Tools/idle/ReplaceDialog.py b/Tools/idle/ReplaceDialog.py
index 3d71703..cc8b1a6 100644
--- a/Tools/idle/ReplaceDialog.py
+++ b/Tools/idle/ReplaceDialog.py
@@ -1,4 +1,3 @@
-import string
 import os
 import re
 import fnmatch
diff --git a/Tools/idle/SearchDialogBase.py b/Tools/idle/SearchDialogBase.py
index faf5269..d5f13db 100644
--- a/Tools/idle/SearchDialogBase.py
+++ b/Tools/idle/SearchDialogBase.py
@@ -1,4 +1,3 @@
-import string
 from Tkinter import *
 
 class SearchDialogBase:
diff --git a/Tools/idle/SearchEngine.py b/Tools/idle/SearchEngine.py
index e379751..cc40a00 100644
--- a/Tools/idle/SearchEngine.py
+++ b/Tools/idle/SearchEngine.py
@@ -1,4 +1,3 @@
-import string
 import re
 from Tkinter import *
 import tkMessageBox
@@ -175,7 +174,7 @@
                 wrapped = 1
                 wrap = 0
                 pos = text.index("end-1c")
-                line, col = map(int, string.split(pos, "."))
+                line, col = map(int, pos.split("."))
             chars = text.get("%d.0" % line, "%d.0" % (line+1))
             col = len(chars) - 1
         return None
@@ -217,5 +216,5 @@
 # Helper to parse a text index into a (line, col) tuple.
 
 def get_line_col(index):
-    line, col = map(int, string.split(index, ".")) # Fails on invalid index
+    line, col = map(int, index.split(".")) # Fails on invalid index
     return line, col
diff --git a/Tools/idle/StackViewer.py b/Tools/idle/StackViewer.py
index d70658b..7f57c0d 100644
--- a/Tools/idle/StackViewer.py
+++ b/Tools/idle/StackViewer.py
@@ -1,6 +1,5 @@
 import os
 import sys
-import string
 import linecache
 
 from TreeWidget import TreeNode, TreeItem, ScrolledCanvas
@@ -50,7 +49,7 @@
         filename = code.co_filename
         funcname = code.co_name
         sourceline = linecache.getline(filename, lineno)
-        sourceline = string.strip(sourceline)
+        sourceline = sourceline.strip()
         if funcname in ("?", "", None):
             item = "%s, line %d: %s" % (modname, lineno, sourceline)
         else:
diff --git a/Tools/idle/TreeWidget.py b/Tools/idle/TreeWidget.py
index 37bc58f..d713264 100644
--- a/Tools/idle/TreeWidget.py
+++ b/Tools/idle/TreeWidget.py
@@ -16,7 +16,6 @@
 
 import os
 import sys
-import string
 from Tkinter import *
 import imp
 
diff --git a/Tools/idle/UndoDelegator.py b/Tools/idle/UndoDelegator.py
index 3ef14c3..54b0851 100644
--- a/Tools/idle/UndoDelegator.py
+++ b/Tools/idle/UndoDelegator.py
@@ -311,7 +311,7 @@
         strs = []
         for cmd in self.cmds:
             strs.append("    " + `cmd`)
-        return s + "(\n" + string.join(strs, ",\n") + "\n)"
+        return s + "(\n" + ",\n".join(strs) + "\n)"
 
     def __len__(self):
         return len(self.cmds)
diff --git a/Tools/idle/eventparse.py b/Tools/idle/eventparse.py
index cb2028d..784dc90 100644
--- a/Tools/idle/eventparse.py
+++ b/Tools/idle/eventparse.py
@@ -5,7 +5,6 @@
 import re
 import sys
 import os
-import string
 import getopt
 import glob
 import fileinput
@@ -25,7 +24,7 @@
             if not sublist:
                 sublist.append('file %s' % fileinput.filename())
                 sublist.append('line %d' % fileinput.lineno())
-            sublist.append(string.strip(line[2:-1]))
+            sublist.append(line[2:-1].strip())
         else:
             if sublist:
                 hits.append(sublist)
@@ -37,7 +36,7 @@
     for sublist in hits:
         d = {}
         for line in sublist:
-            words = string.split(line, None, 1)
+            words = line.split(None, 1)
             if len(words) != 2:
                 continue
             tag = words[0]
diff --git a/Tools/modulator/genmodule.py b/Tools/modulator/genmodule.py
index 1974502..5788b95 100755
--- a/Tools/modulator/genmodule.py
+++ b/Tools/modulator/genmodule.py
@@ -20,7 +20,6 @@
 import sys
 import os
 import varsubst
-import string
 
 error = 'genmodule.error'
 
@@ -43,7 +42,7 @@
         if not self._subst:
             if not self.__dict__.has_key('abbrev'):
                 self.abbrev = self.name
-            self.Abbrev = string.upper(self.abbrev[0])+self.abbrev[1:]
+            self.Abbrev = self.abbrev[0].upper()+self.abbrev[1:]
             subst = varsubst.Varsubst(self.__dict__)
             subst.useindent(1)
             self._subst = subst.subst
diff --git a/Tools/modulator/modulator.py b/Tools/modulator/modulator.py
index cdf6afe..df6d9ef 100755
--- a/Tools/modulator/modulator.py
+++ b/Tools/modulator/modulator.py
@@ -223,7 +223,7 @@
         rv = rv + (name+'.name = '+`self.name_entry.get()`+'\n')
         rv = rv + (name+'.abbrev = '+`self.abbrev_entry.get()`+'\n')
         rv = rv + (name+'.methodlist = '+`getlistlist(self.method_list)`+'\n')
-        rv = rv + (name+'.objects = ['+string.joinfields(onames, ',')+']\n')
+        rv = rv + (name+'.objects = ['+','.join(onames)+']\n')
         rv = rv + ('\n')
         return rv
         
diff --git a/Tools/modulator/varsubst.py b/Tools/modulator/varsubst.py
index 71a2b26..5516be2 100644
--- a/Tools/modulator/varsubst.py
+++ b/Tools/modulator/varsubst.py
@@ -1,7 +1,6 @@
 #
 # Variable substitution. Variables are $delimited$
 #
-import string
 import re
 
 error = 'varsubst.error'
@@ -37,7 +36,7 @@
             rv = rv + value
 
     def _modindent(self, value, old):
-        lastnl = string.rfind(old, '\n', 0) + 1
+        lastnl = old.rfind('\n', 0) + 1
         lastnl = len(old) - lastnl
         sub = '\n' + (' '*lastnl)
         return re.sub('\n', sub, value)
diff --git a/Tools/scripts/byteyears.py b/Tools/scripts/byteyears.py
index f67be70..2b0f9b2 100755
--- a/Tools/scripts/byteyears.py
+++ b/Tools/scripts/byteyears.py
@@ -7,7 +7,6 @@
 # Options -[amc] select atime, mtime (default) or ctime as age.
 
 import sys, os, time
-import string
 from stat import *
 
 # Use lstat() to stat files if it exists, else stat()
@@ -51,7 +50,7 @@
         size = st[ST_SIZE]
         age = now - anytime
         byteyears = float(size) * float(age) / secs_per_year
-        print string.ljust(file, maxlen),
-        print string.rjust(`int(byteyears)`, 8)
+        print file.ljust(maxlen),
+        print repr(int(byteyears)).rjust(8)
 
 sys.exit(status)
diff --git a/Tools/scripts/checkappend.py b/Tools/scripts/checkappend.py
index c1188e2..b3141df 100755
--- a/Tools/scripts/checkappend.py
+++ b/Tools/scripts/checkappend.py
@@ -35,14 +35,13 @@
 
 import os
 import sys
-import string
 import getopt
 import tokenize
 
 verbose = 0
 
 def errprint(*args):
-    msg = string.join(args)
+    msg = ' '.join(args)
     sys.stderr.write(msg)
     sys.stderr.write("\n")
 
diff --git a/Tools/scripts/classfix.py b/Tools/scripts/classfix.py
index 26aa599..7b86aa3 100755
--- a/Tools/scripts/classfix.py
+++ b/Tools/scripts/classfix.py
@@ -156,8 +156,6 @@
 baseexpr = '^ *\(.*\) *( *) *$'
 baseprog = regex.compile(baseexpr)
 
-import string
-
 def fixline(line):
     if classprog.match(line) < 0: # No 'class' keyword -- no change
         return line
@@ -176,7 +174,7 @@
     basepart = line[a2+1:b2]
 
     # Extract list of base expressions
-    bases = string.splitfields(basepart, ',')
+    bases = basepart.split(',')
 
     # Strip trailing '()' from each base expression
     for i in range(len(bases)):
@@ -185,7 +183,7 @@
             bases[i] = bases[i][x1:y1]
 
     # Join the bases back again and build the new line
-    basepart = string.joinfields(bases, ', ')
+    basepart = ', '.join(bases)
 
     return head + '(' + basepart + '):' + tail
 
diff --git a/Tools/scripts/cvsfiles.py b/Tools/scripts/cvsfiles.py
index d133a40..2168556 100755
--- a/Tools/scripts/cvsfiles.py
+++ b/Tools/scripts/cvsfiles.py
@@ -14,7 +14,6 @@
 import sys
 import stat
 import getopt
-import string
 
 cutofftime = 0
 
@@ -51,7 +50,7 @@
     if cvsdir:
         entries = os.path.join(cvsdir, "Entries")
         for e in open(entries).readlines():
-            words = string.split(e, '/')
+            words = e.split('/')
             if words[0] == '' and words[1:]:
                 name = words[1]
                 fullname = os.path.join(dir, name)
diff --git a/Tools/scripts/dutree.py b/Tools/scripts/dutree.py
index 7a32533..35b3916 100755
--- a/Tools/scripts/dutree.py
+++ b/Tools/scripts/dutree.py
@@ -1,10 +1,10 @@
 #! /usr/bin/env python
 # Format du output in a tree shape
 
-import os, string, sys, errno
+import os, sys, errno
 
 def main():
-    p = os.popen('du ' + string.join(sys.argv[1:]), 'r')
+    p = os.popen('du ' + ' '.join(sys.argv[1:]), 'r')
     total, d = None, {}
     for line in p.readlines():
         i = 0
@@ -12,7 +12,7 @@
         size = eval(line[:i])
         while line[i] in ' \t': i = i+1
         file = line[i:-1]
-        comps = string.splitfields(file, '/')
+        comps = file.split('/')
         if comps[0] == '': comps[0] = '/'
         if comps[len(comps)-1] == '': del comps[len(comps)-1]
         total, d = store(size, comps, total, d)
@@ -51,7 +51,7 @@
         if tsub is None:
             psub = prefix
         else:
-            print prefix + string.rjust(`tsub`, width) + ' ' + key
+            print prefix + repr(tsub).rjust(width) + ' ' + key
             psub = prefix + ' '*(width-1) + '|' + ' '*(len(key)+1)
         if d.has_key(key):
             show(tsub, d[key][1], psub)
diff --git a/Tools/scripts/fixcid.py b/Tools/scripts/fixcid.py
index 6f674c6..8bc1de0 100755
--- a/Tools/scripts/fixcid.py
+++ b/Tools/scripts/fixcid.py
@@ -36,7 +36,6 @@
 
 import sys
 import regex
-import string
 import os
 from stat import *
 import getopt
@@ -213,11 +212,11 @@
 # Anything else is an operator -- don't list this explicitly because of '/*'
 
 OutsideComment = (Identifier, Number, String, Char, CommentStart)
-OutsideCommentPattern = '\(' + string.joinfields(OutsideComment, '\|') + '\)'
+OutsideCommentPattern = '\(' + '\|'.join(OutsideComment) + '\)'
 OutsideCommentProgram = regex.compile(OutsideCommentPattern)
 
 InsideComment = (Identifier, Number, CommentEnd)
-InsideCommentPattern = '\(' + string.joinfields(InsideComment, '\|') + '\)'
+InsideCommentPattern = '\(' + '\|'.join(InsideComment) + '\)'
 InsideCommentProgram = regex.compile(InsideCommentPattern)
 
 def initfixline():
@@ -286,10 +285,10 @@
         if not line: break
         lineno = lineno + 1
         try:
-            i = string.index(line, '#')
-        except string.index_error:
+            i = line.index('#')
+        except ValueError:
             i = -1          # Happens to delete trailing \n
-        words = string.split(line[:i])
+        words = line[:i].split()
         if not words: continue
         if len(words) == 3 and words[0] == 'struct':
             words[:2] = [words[0] + ' ' + words[1]]
diff --git a/Tools/scripts/fixheader.py b/Tools/scripts/fixheader.py
index ba2e0c5..1f9c713 100755
--- a/Tools/scripts/fixheader.py
+++ b/Tools/scripts/fixheader.py
@@ -3,7 +3,6 @@
 # Add some standard cpp magic to a header file
 
 import sys
-import string
 
 def main():
     args = sys.argv[1:]
@@ -29,8 +28,8 @@
     sys.stderr.write('Processing %s ...\n' % file)
     magic = 'Py_'
     for c in file:
-        if c in string.ascii_letters + string.digits:
-            magic = magic + string.upper(c)
+        if ord(c)<=0x80 and c.isalnum():
+            magic = magic + c.upper()
         else: magic = magic + '_'
     sys.stdout = f
     print '#ifndef', magic
diff --git a/Tools/scripts/ftpmirror.py b/Tools/scripts/ftpmirror.py
index 38af9dc..c3469d0 100755
--- a/Tools/scripts/ftpmirror.py
+++ b/Tools/scripts/ftpmirror.py
@@ -22,7 +22,6 @@
 import sys
 import time
 import getopt
-import string
 import ftplib
 import netrc
 from fnmatch import fnmatch
@@ -127,7 +126,7 @@
         if mac:
             # Mac listing has just filenames;
             # trailing / means subdirectory
-            filename = string.strip(line)
+            filename = line.strip()
             mode = '-'
             if filename[-1:] == '/':
                 filename = filename[:-1]
@@ -135,12 +134,12 @@
             infostuff = ''
         else:
             # Parse, assuming a UNIX listing
-            words = string.split(line, None, 8)
+            words = line.split(None, 8)
             if len(words) < 6:
                 if verbose > 1: print 'Skipping short line'
                 continue
-            filename = string.lstrip(words[-1])
-            i = string.find(filename, " -> ")
+            filename = words[-1].lstrip()
+            i = filename.find(" -> ")
             if i >= 0:
                 # words[0] had better start with 'l'...
                 if verbose > 1:
@@ -360,7 +359,7 @@
 def askabout(filetype, filename, pwd):
     prompt = 'Retrieve %s %s from %s ? [ny] ' % (filetype, filename, pwd)
     while 1:
-        reply = string.lower(string.strip(raw_input(prompt)))
+        reply = raw_input(prompt).strip().lower()
         if reply in ['y', 'ye', 'yes']:
             return 1
         if reply in ['', 'n', 'no', 'nop', 'nope']:
diff --git a/Tools/scripts/gencodec.py b/Tools/scripts/gencodec.py
index 69b6ede..46563df 100644
--- a/Tools/scripts/gencodec.py
+++ b/Tools/scripts/gencodec.py
@@ -22,7 +22,7 @@
 
 """#"
 
-import string,re,os,time,marshal
+import re,os,time,marshal
 
 # Create numeric tables or character based ones ?
 numeric = 1
@@ -34,9 +34,7 @@
                    '(#.+)?')
 
 def parsecodes(codes,
-
-               split=string.split,atoi=string.atoi,len=len,
-               filter=filter,range=range):
+               len=len, filter=filter,range=range):
 
     """ Converts code combinations to either a single code integer
         or a tuple of integers.
@@ -49,12 +47,12 @@
     """
     if not codes:
         return None
-    l = split(codes,'+')
+    l = codes.split('+')
     if len(l) == 1:
-        return atoi(l[0],16)
+        return int(l[0],16)
     for i in range(len(l)):
         try:
-            l[i] = atoi(l[i],16)
+            l[i] = int(l[i],16)
         except ValueError:
             l[i] = None
     l = filter(lambda x: x is not None, l)
@@ -63,9 +61,7 @@
     else:
         return tuple(l)
 
-def readmap(filename,
-
-            strip=string.strip):
+def readmap(filename):
 
     f = open(filename,'r')
     lines = f.readlines()
@@ -76,7 +72,7 @@
     for i in range(256):
         unmapped[i] = i
     for line in lines:
-        line = strip(line)
+        line = line.strip()
         if not line or line[0] == '#':
             continue
         m = mapRE.match(line)
@@ -108,9 +104,7 @@
 
     return enc2uni
 
-def hexrepr(t,
-
-            join=string.join):
+def hexrepr(t):
 
     if t is None:
         return 'None'
@@ -118,11 +112,9 @@
         len(t)
     except:
         return '0x%04x' % t
-    return '(' + join(map(lambda t: '0x%04x' % t, t),', ') + ')'
+    return '(' + ', '.join(map(lambda t: '0x%04x' % t, t)) + ')'
 
-def unicoderepr(t,
-
-                join=string.join):
+def unicoderepr(t):
 
     if t is None:
         return 'None'
@@ -133,11 +125,9 @@
             len(t)
         except:
             return repr(unichr(t))
-        return repr(join(map(unichr, t),''))
+        return repr(''.join(map(unichr, t)))
 
-def keyrepr(t,
-
-            join=string.join):
+def keyrepr(t):
 
     if t is None:
         return 'None'
@@ -151,7 +141,7 @@
                 return repr(chr(t))
             else:
                 return repr(unichr(t))
-        return repr(join(map(chr, t),''))
+        return repr(''.join(map(chr, t)))
 
 def codegen(name,map,comments=1):
 
@@ -246,7 +236,7 @@
 
 encoding_map = codecs.make_encoding_map(decoding_map)
 ''')
-    return string.join(l,'\n')
+    return '\n'.join(l)
 
 def pymap(name,map,pyfile,comments=1):
 
@@ -269,9 +259,9 @@
     mapnames = os.listdir(dir)
     for mapname in mapnames:
         name = os.path.split(mapname)[1]
-        name = string.replace(name,'-','_')
-        name = string.split(name, '.')[0]
-        name = string.lower(name)
+        name = name.replace('-','_')
+        name = name.split('.')[0]
+        name = name.lower()
         codefile = name + '.py'
         marshalfile = name + '.mapping'
         print 'converting %s to %s and %s' % (mapname,
diff --git a/Tools/scripts/ifdef.py b/Tools/scripts/ifdef.py
index da14437..c0c1459 100755
--- a/Tools/scripts/ifdef.py
+++ b/Tools/scripts/ifdef.py
@@ -29,7 +29,6 @@
 import sys
 import regex
 import getopt
-import string
 
 defs = []
 undefs = []
@@ -62,12 +61,12 @@
             nextline = fpi.readline()
             if not nextline: break
             line = line + nextline
-        tmp = string.strip(line)
+        tmp = line.strip()
         if tmp[:1] != '#':
             if ok: fpo.write(line)
             continue
-        tmp = string.strip(tmp[1:])
-        words = string.split(tmp)
+        tmp = tmp[1:].strip()
+        words = tmp.split()
         keyword = words[0]
         if keyword not in keywords:
             if ok: fpo.write(line)
diff --git a/Tools/scripts/logmerge.py b/Tools/scripts/logmerge.py
index d036749..d4c2fe6 100755
--- a/Tools/scripts/logmerge.py
+++ b/Tools/scripts/logmerge.py
@@ -24,7 +24,7 @@
 
 """
 
-import os, sys, getopt, string, re
+import os, sys, getopt, re
 
 sep1 = '='*77 + '\n'                    # file separator
 sep2 = '-'*28 + '\n'                    # revision separator
@@ -84,7 +84,7 @@
     keylen = len(key)
     for line in lines:
         if line[:keylen] == key:
-            working_file = string.strip(line[keylen:])
+            working_file = line[keylen:].strip()
             break
     else:
         working_file = None
@@ -93,7 +93,7 @@
         revline = lines[0]
         dateline = lines[1]
         text = lines[2:]
-        words = string.split(dateline)
+        words = dateline.split()
         author = None
         if len(words) >= 3 and words[0] == 'date:':
             dateword = words[1]
@@ -108,7 +108,7 @@
         else:
             date = None
             text.insert(0, revline)
-        words = string.split(revline)
+        words = revline.split()
         if len(words) >= 2 and words[0] == 'revision':
             rev = words[1]
         else:
diff --git a/Tools/scripts/mailerdaemon.py b/Tools/scripts/mailerdaemon.py
index 113b376..85f90aa 100755
--- a/Tools/scripts/mailerdaemon.py
+++ b/Tools/scripts/mailerdaemon.py
@@ -1,6 +1,5 @@
 """mailerdaemon - classes to parse mailer-daemon messages"""
 
-import string
 import rfc822
 import calendar
 import re
@@ -18,9 +17,9 @@
         sub = self.getheader('Subject')
         if not sub:
             return 0
-        sub = string.lower(sub)
-        if sub[:12] == 'waiting mail': return 1
-        if string.find(sub, 'warning') >= 0: return 1
+        sub = sub.lower()
+        if sub.startswith('waiting mail'): return 1
+        if 'warning' in sub: return 1
         self.sub = sub
         return 0
 
@@ -132,10 +131,10 @@
             if type(regexp) is type(''):
                 for i in range(len(emails)-1,-1,-1):
                     email = emails[i]
-                    exp = re.compile(string.join(string.split(regexp, '<>'), re.escape(email)), re.MULTILINE)
+                    exp = re.compile(re.escape(email).join(regexp.split('<>')), re.MULTILINE)
                     res = exp.search(data)
                     if res is not None:
-                        errors.append(string.join(string.split(string.strip(email)+': '+res.group('reason'))))
+                        errors.append(' '.join((email.strip()+': '+res.group('reason')).split()))
                         del emails[i]
                 continue
             res = regexp.search(data)
@@ -143,14 +142,14 @@
                 reason = res.group('reason')
                 break
     for email in emails:
-        errors.append(string.join(string.split(string.strip(email)+': '+reason)))
+        errors.append(' '.join((email.strip()+': '+reason).split()))
     return errors
 
 EMPARSERS = [emparse_list, ]
 
 def sort_numeric(a, b):
-    a = string.atoi(a)
-    b = string.atoi(b)
+    a = int(a)
+    b = int(b)
     if a < b: return -1
     elif a > b: return 1
     else: return 0
diff --git a/Tools/scripts/methfix.py b/Tools/scripts/methfix.py
index cbbb964..9e69961 100755
--- a/Tools/scripts/methfix.py
+++ b/Tools/scripts/methfix.py
@@ -30,7 +30,6 @@
 import regex
 import os
 from stat import *
-import string
 
 err = sys.stderr.write
 dbg = err
@@ -101,7 +100,7 @@
             return 1
         if lineno == 1 and g is None and line[:2] == '#!':
             # Check for non-Python scripts
-            words = string.split(line[2:])
+            words = line[2:].split()
             if words and regex.search('[pP]ython', words[0]) < 0:
                 msg = filename + ': ' + words[0]
                 msg = msg + ' script; not fixed\n'
diff --git a/Tools/scripts/nm2def.py b/Tools/scripts/nm2def.py
index fc1022a..6887ee2 100755
--- a/Tools/scripts/nm2def.py
+++ b/Tools/scripts/nm2def.py
@@ -34,7 +34,7 @@
 option to produce this format (since it is the original v7 Unix format).
 
 """
-import os,re,string,sys
+import os,re,sys
 
 PYTHONLIB = 'libpython'+sys.version[:3]+'.a'
 PC_PYTHONLIB = 'Python'+sys.version[0]+sys.version[2]+'.dll'
@@ -43,12 +43,12 @@
 def symbols(lib=PYTHONLIB,types=('T','C','D')):
 
     lines = os.popen(NM % lib).readlines()
-    lines = map(string.strip,lines)
+    lines = [s.strip() for s in lines]
     symbols = {}
     for line in lines:
         if len(line) == 0 or ':' in line:
             continue
-        items = string.split(line)
+        items = line.split()
         if len(items) != 3:
             continue
         address, type, name = items
@@ -69,7 +69,7 @@
     data.sort()
     data.append('')
     code.sort()
-    return string.join(data,' DATA\n')+'\n'+string.join(code,'\n')
+    return ' DATA\n'.join(data)+'\n'+'\n'.join(code)
 
 # Definition file template
 DEF_TEMPLATE = """\
diff --git a/Tools/scripts/objgraph.py b/Tools/scripts/objgraph.py
index e25e5b8..3e040b9 100755
--- a/Tools/scripts/objgraph.py
+++ b/Tools/scripts/objgraph.py
@@ -20,7 +20,6 @@
 
 
 import sys
-import string
 import os
 import getopt
 import regex
diff --git a/Tools/scripts/pathfix.py b/Tools/scripts/pathfix.py
index e1c6e73..81c5a6e 100755
--- a/Tools/scripts/pathfix.py
+++ b/Tools/scripts/pathfix.py
@@ -23,7 +23,6 @@
 import regex
 import os
 from stat import *
-import string
 import getopt
 
 err = sys.stderr.write
@@ -140,9 +139,9 @@
     return 0
 
 def fixline(line):
-    if line[:2] != '#!':
+    if not line.startswith('#!'):
         return line
-    if string.find(line, "python") < 0:
+    if "python" not in line:
         return line
     return '#! %s\n' % new_interpreter
 
diff --git a/Tools/scripts/pdeps.py b/Tools/scripts/pdeps.py
index 18b582b..1589709 100755
--- a/Tools/scripts/pdeps.py
+++ b/Tools/scripts/pdeps.py
@@ -23,7 +23,6 @@
 import sys
 import regex
 import os
-import string
 
 
 # Main program
@@ -82,10 +81,10 @@
         elif m_from.match(line) >= 0:
             (a, b), (a1, b1) = m_from.regs[:2]
         else: continue
-        words = string.splitfields(line[a1:b1], ',')
+        words = line[a1:b1].split(',')
         # print '#', line, words
         for word in words:
-            word = string.strip(word)
+            word = word.strip()
             if word not in list:
                 list.append(word)
 
@@ -152,7 +151,7 @@
     for mod in modules:
         list = table[mod]
         list.sort()
-        print string.ljust(mod, maxlen), ':',
+        print mod.ljust(maxlen), ':',
         if mod in list:
             print '(*)',
         for ref in list:
diff --git a/Tools/scripts/pindent.py b/Tools/scripts/pindent.py
index 318c20e..75175dc 100755
--- a/Tools/scripts/pindent.py
+++ b/Tools/scripts/pindent.py
@@ -83,7 +83,6 @@
 
 import os
 import re
-import string
 import sys
 
 next = {}
@@ -119,7 +118,7 @@
 
     def write(self, line):
         if self.expandtabs:
-            self._write(string.expandtabs(line, self.tabsize))
+            self._write(line.expandtabs(self.tabsize))
         else:
             self._write(line)
         # end if
@@ -270,7 +269,7 @@
                     thiskw = ''
                 # end if
             # end if
-            indent = len(string.expandtabs(line[:i], self.tabsize))
+            indent = len(line[:i].expandtabs(self.tabsize))
             while indent < current:
                 if firstkw:
                     if topid:
@@ -370,7 +369,7 @@
         return r
     # end def read
     def readline(self):
-        i = string.find(self.buf, '\n', self.pos)
+        i = self.buf.find('\n', self.pos)
         return self.read(i + 1 - self.pos)
     # end def readline
     def readlines(self):
@@ -514,9 +513,9 @@
             # end if
             action = 'reformat'
         elif o == '-s':
-            stepsize = string.atoi(a)
+            stepsize = int(a)
         elif o == '-t':
-            tabsize = string.atoi(a)
+            tabsize = int(a)
         elif o == '-e':
             expandtabs = 1
         # end if
diff --git a/Tools/scripts/rgrep.py b/Tools/scripts/rgrep.py
index 0271242..b644206 100755
--- a/Tools/scripts/rgrep.py
+++ b/Tools/scripts/rgrep.py
@@ -7,7 +7,6 @@
 
 import sys
 import re
-import string
 import getopt
 
 def main():
@@ -38,7 +37,7 @@
         pos = pos - size
         f.seek(pos)
         buffer = f.read(size)
-        lines = string.split(buffer, "\n")
+        lines = buffer.split("\n")
         del buffer
         if leftover is None:
             if not lines[-1]:
diff --git a/Tools/scripts/sum5.py b/Tools/scripts/sum5.py
index 3efcc74..4250dde 100755
--- a/Tools/scripts/sum5.py
+++ b/Tools/scripts/sum5.py
@@ -16,7 +16,6 @@
 """ % bufsize
 
 import sys
-import string
 import os
 import md5
 import regsub
@@ -89,7 +88,7 @@
         if o == '-t':
             rmode = 'r'
         if o == '-s':
-            bufsize = string.atoi(a)
+            bufsize = int(a)
     if not args: args = ['-']
     return sum(args, out)
 
diff --git a/Tools/scripts/trace.py b/Tools/scripts/trace.py
index f96e04f..38e985e 100644
--- a/Tools/scripts/trace.py
+++ b/Tools/scripts/trace.py
@@ -83,7 +83,7 @@
    trace.print_results(show_missing=1)
 """
 
-import sys, os, string, tempfile, types, copy, operator, inspect, exceptions, marshal
+import sys, os, tempfile, types, copy, operator, inspect, exceptions, marshal
 try:
     import cPickle
     pickle = cPickle
@@ -177,7 +177,7 @@
             # or
             #  d = "/usr/local.py"
             #  filename = "/usr/local.py"
-            if string.find(filename, d + os.sep) == 0:
+            if filename.startswith(d + os.sep):
                 self._ignore[modulename] = 1
                 return 1
 
@@ -341,13 +341,12 @@
                     # '#pragma: NO COVER' (it is possible to embed this into
                     # the text as a non-comment; no easy fix)
                     if executable_linenos.has_key(i+1) and \
-                       string.find(lines[i],
-                                   string.join(['#pragma', 'NO COVER'])) == -1:
+                       lines[i].find(' '.join(['#pragma', 'NO COVER'])) == -1:
                         outfile.write('>>>>>> ')
                     else:
                         outfile.write(' '*7)
                     n_lines = n_lines + 1
-                outfile.write(string.expandtabs(lines[i], 8))
+                outfile.write(lines[i].expandtabs(8))
 
             outfile.close()
 
@@ -675,16 +674,16 @@
             continue
 
         if opt == "--ignore-dir":
-            for s in string.split(val, os.pathsep):
+            for s in val.split(os.pathsep):
                 s = os.path.expandvars(s)
                 # should I also call expanduser? (after all, could use $HOME)
 
-                s = string.replace(s, "$prefix",
-                                   os.path.join(sys.prefix, "lib",
-                                                "python" + sys.version[:3]))
-                s = string.replace(s, "$exec_prefix",
-                                   os.path.join(sys.exec_prefix, "lib",
-                                                "python" + sys.version[:3]))
+                s = s.replace("$prefix",
+                              os.path.join(sys.prefix, "lib",
+                                           "python" + sys.version[:3]))
+                s = s.replace("$exec_prefix",
+                              os.path.join(sys.exec_prefix, "lib",
+                                           "python" + sys.version[:3]))
                 s = os.path.normpath(s)
                 ignore_dirs.append(s)
             continue
diff --git a/Tools/scripts/treesync.py b/Tools/scripts/treesync.py
index 96beba0..1064ab7 100755
--- a/Tools/scripts/treesync.py
+++ b/Tools/scripts/treesync.py
@@ -23,7 +23,7 @@
 
 """
 
-import os, sys, stat, string, getopt
+import os, sys, stat, getopt
 
 # Interactivity options
 default_answer = "ask"
@@ -97,7 +97,7 @@
     if cvsdir:
         entries = os.path.join(cvsdir, "Entries")
         for e in open(entries).readlines():
-            words = string.split(e, '/')
+            words = e.split('/')
             if words[0] == '' and words[1:]:
                 name = words[1]
                 s = os.path.join(slave, name)
@@ -188,10 +188,10 @@
     g.close()
 
 def okay(prompt, answer='ask'):
-    answer = string.lower(string.strip(answer))
+    answer = answer.strip().lower()
     if not answer or answer[0] not in 'ny':
         answer = raw_input(prompt)
-        answer = string.lower(string.strip(answer))
+        answer = answer.strip().lower()
         if not answer:
             answer = default_answer
     if answer[:1] == 'y':
diff --git a/Tools/scripts/untabify.py b/Tools/scripts/untabify.py
index 7be9f38..5eaf50e 100755
--- a/Tools/scripts/untabify.py
+++ b/Tools/scripts/untabify.py
@@ -4,7 +4,6 @@
 
 import os
 import sys
-import string
 import getopt
 
 def main():
@@ -32,7 +31,7 @@
     except IOError, msg:
         print "%s: I/O error: %s" % (`file`, str(msg))
         return
-    newtext = string.expandtabs(text, tabsize)
+    newtext = text.expandtabs(tabsize)
     if newtext == text:
         return
     backup = file + "~"
diff --git a/Tools/scripts/which.py b/Tools/scripts/which.py
index 96e242c..19e3203 100755
--- a/Tools/scripts/which.py
+++ b/Tools/scripts/which.py
@@ -7,13 +7,13 @@
 import sys
 if sys.path[0] in (".", ""): del sys.path[0]
 
-import sys, os, string
+import sys, os
 from stat import *
 
 def msg(str):
     sys.stderr.write(str + '\n')
 
-pathlist = string.splitfields(os.environ['PATH'], ':')
+pathlist = os.environ['PATH'].split(':')
 
 sts = 0
 longlist = ''
diff --git a/Tools/scripts/xxci.py b/Tools/scripts/xxci.py
index 2567bc5..681ce0b 100755
--- a/Tools/scripts/xxci.py
+++ b/Tools/scripts/xxci.py
@@ -9,7 +9,6 @@
 from stat import *
 import commands
 import fnmatch
-import string
 
 EXECMAGIC = '\001\140\000\010'
 
@@ -57,7 +56,7 @@
         f = open('.xxcign', 'r')
     except IOError:
         return
-    ignore[:] = ignore + string.split(f.read())
+    ignore[:] = ignore + f.read().split()
 
 def skipfile(file):
     for p in ignore:
diff --git a/Tools/unicode/makeunicodedata.py b/Tools/unicode/makeunicodedata.py
index 0eeb335..a18e548 100644
--- a/Tools/unicode/makeunicodedata.py
+++ b/Tools/unicode/makeunicodedata.py
@@ -100,7 +100,7 @@
         record = unicode.table[char]
         if record:
             if record[5]:
-                decomp = string.split(record[5])
+                decomp = record[5].split()
                 # prefix
                 if decomp[0][0] == "<":
                     prefix = decomp.pop(0)
@@ -362,7 +362,7 @@
         # indicates the last character in an entire string)
         ww = w[:-1] + chr(ord(w[-1])+128)
         # reuse string tails, when possible
-        o = string.find(lexicon, ww)
+        o = lexicon.find(ww)
         if o < 0:
             o = offset
             lexicon = lexicon + ww
@@ -442,7 +442,7 @@
 
 # load a unicode-data file from disk
 
-import string, sys
+import sys
 
 class UnicodeData:
 
@@ -453,8 +453,8 @@
             s = file.readline()
             if not s:
                 break
-            s = string.split(string.strip(s), ";")
-            char = string.atoi(s[0], 16)
+            s = s.strip().split(";")
+            char = int(s[0], 16)
             table[char] = s
 
         # expand first-last ranges (ignore surrogates and private use)
@@ -490,7 +490,7 @@
 
 def myhash(s, magic):
     h = 0
-    for c in map(ord, string.upper(s)):
+    for c in map(ord, s.upper()):
         h = (h * magic) + c
         ix = h & 0xff000000
         if ix:
@@ -598,7 +598,7 @@
                     s = "    " + i
                 else:
                     s = s + i
-            if string.strip(s):
+            if s.strip():
                 file.write(s + "\n")
         file.write("};\n\n")
 
diff --git a/Tools/versioncheck/checkversions.py b/Tools/versioncheck/checkversions.py
index 2420611..dcc56d3 100644
--- a/Tools/versioncheck/checkversions.py
+++ b/Tools/versioncheck/checkversions.py
@@ -5,7 +5,6 @@
 import os
 import getopt
 import sys
-import string
 import pyversioncheck
 
 CHECKNAME="_checkversion.py"
@@ -43,7 +42,7 @@
 		sys.exit(1)
 	for o, a in options:
 		if o == '-v':
-			VERBOSE = string.atoi(a)
+			VERBOSE = int(a)
 	if not arguments:
 		arguments = [sys.prefix]
 	for dir in arguments:
diff --git a/Tools/versioncheck/pyversioncheck.py b/Tools/versioncheck/pyversioncheck.py
index b6e50d3..51bdd68 100644
--- a/Tools/versioncheck/pyversioncheck.py
+++ b/Tools/versioncheck/pyversioncheck.py
@@ -3,7 +3,6 @@
 import rfc822
 import urllib
 import sys
-import string
 
 # Verbose options
 VERBOSE_SILENT=0	# Single-line reports per package
@@ -60,8 +59,8 @@
         if verbose >= VERBOSE_EACHFILE:
             print '    No "Current-Version:" header in URL or URL not found'
         return -1, None, None
-    version = string.strip(string.lower(version))
-    newversion = string.strip(string.lower(newversion))
+    version = version.lower().strip()
+    newversion = newversion.lower().strip()
     if version == newversion:
         if verbose >= VERBOSE_EACHFILE:
             print '    Version identical (%s)'%newversion
diff --git a/Tools/webchecker/tktools.py b/Tools/webchecker/tktools.py
index 0db4d49..3a68f9a 100644
--- a/Tools/webchecker/tktools.py
+++ b/Tools/webchecker/tktools.py
@@ -1,7 +1,6 @@
 """Assorted Tk-related subroutines used in Grail."""
 
 
-import string
 from types import *
 from Tkinter import *
 
@@ -335,7 +334,7 @@
     """Turn a list or tuple into a single string -- recursively."""
     t = type(msg)
     if t in (ListType, TupleType):
-        msg = string.join(map(flatten, msg))
+        msg = ' '.join(map(flatten, msg))
     elif t is ClassType:
         msg = msg.__name__
     else:
@@ -345,7 +344,7 @@
 
 def boolean(s):
     """Test whether a string is a Tk boolean, without error checking."""
-    if string.lower(s) in ('', '0', 'no', 'off', 'false'): return 0
+    if s.lower() in ('', '0', 'no', 'off', 'false'): return 0
     else: return 1
 
 
diff --git a/Tools/webchecker/wcgui.py b/Tools/webchecker/wcgui.py
index ae012bf..e467d92 100755
--- a/Tools/webchecker/wcgui.py
+++ b/Tools/webchecker/wcgui.py
@@ -60,7 +60,6 @@
 
 import sys
 import getopt
-import string
 from Tkinter import *
 import tktools
 import webchecker
@@ -86,7 +85,7 @@
     extra_roots = []
     for o, a in opts:
         if o == '-m':
-            webchecker.maxpage = string.atoi(a)
+            webchecker.maxpage = int(a)
         if o == '-q':
             webchecker.verbose = 0
         if o == '-v':
@@ -169,7 +168,7 @@
         self.root_seed = None
         webchecker.Checker.__init__(self)
         if root:
-            root = string.strip(str(root))
+            root = str(root).strip()
             if root:
                 self.suggestroot(root)
         self.newstatus()
@@ -189,7 +188,7 @@
 
     def enterroot(self, event=None):
         root = self.__rootentry.get()
-        root = string.strip(root)
+        root = root.strip()
         if root:
             self.__checking.config(text="Adding root "+root)
             self.__checking.update_idletasks()
@@ -353,7 +352,7 @@
     def selectedindices(self):
         l = self.list.curselection()
         if not l: return []
-        return map(string.atoi, l)
+        return map(int, l)
 
     def insert(self, url):
         if url not in self.items:
diff --git a/Tools/webchecker/webchecker.py b/Tools/webchecker/webchecker.py
index fa70f65..fd7f578 100755
--- a/Tools/webchecker/webchecker.py
+++ b/Tools/webchecker/webchecker.py
@@ -109,7 +109,6 @@
 import sys
 import os
 from types import *
-import string
 import StringIO
 import getopt
 import pickle
@@ -124,7 +123,7 @@
 
 # Extract real version number if necessary
 if __version__[0] == '$':
-    _v = string.split(__version__)
+    _v = __version__.split()
     if len(_v) == 3:
         __version__ = _v[1]
 
@@ -170,13 +169,13 @@
         if o == '-d':
             dumpfile = a
         if o == '-m':
-            maxpage = string.atoi(a)
+            maxpage = int(a)
         if o == '-n':
             norun = 1
         if o == '-q':
             verbose = 0
         if o == '-r':
-            roundsize = string.atoi(a)
+            roundsize = int(a)
         if o == '-t':
             extra_roots.append(a)
         if o == '-a':
@@ -248,7 +247,7 @@
     f.close()
     if verbose > 0:
         print "Done."
-        print "Root:", string.join(c.roots, "\n      ")
+        print "Root:", "\n      ".join(c.roots)
     return c
 
 
@@ -316,7 +315,7 @@
             troot = root
             scheme, netloc, path, params, query, fragment = \
                     urlparse.urlparse(root)
-            i = string.rfind(path, "/") + 1
+            i = path.rfind("/") + 1
             if 0 < i < len(path):
                 path = path[:i]
                 troot = urlparse.urlunparse((scheme, netloc, path,
@@ -544,7 +543,7 @@
 
     def checkforhtml(self, info, url):
         if info.has_key('content-type'):
-            ctype = string.lower(cgi.parse_header(info['content-type'])[0])
+            ctype = cgi.parse_header(info['content-type'])[0].lower()
         else:
             if url[-1:] == "/":
                 return 1
@@ -809,7 +808,7 @@
     def do_link(self, attributes):
         for name, value in attributes:
             if name == "rel":
-                parts = string.split(string.lower(value))
+                parts = value.lower().split()
                 if (  parts == ["stylesheet"]
                       or parts == ["alternate", "stylesheet"]):
                     self.link_attr(attributes, "href")
@@ -836,13 +835,13 @@
     def link_attr(self, attributes, *args):
         for name, value in attributes:
             if name in args:
-                if value: value = string.strip(value)
+                if value: value = value.strip()
                 if value: self.links[value] = None
 
     def do_base(self, attributes):
         for name, value in attributes:
             if name == 'href':
-                if value: value = string.strip(value)
+                if value: value = value.strip()
                 if value:
                     if self.checker:
                         self.checker.note(1, "  Base %s", value)
diff --git a/Tools/webchecker/websucker.py b/Tools/webchecker/websucker.py
index 5f726b3..ef2fa44 100755
--- a/Tools/webchecker/websucker.py
+++ b/Tools/webchecker/websucker.py
@@ -6,7 +6,6 @@
 
 import os
 import sys
-import string
 import urllib
 import getopt
 
@@ -14,7 +13,7 @@
 
 # Extract real version number if necessary
 if __version__[0] == '$':
-    _v = string.split(__version__)
+    _v = __version__.split()
     if len(_v) == 3:
         __version__ = _v[1]
 
@@ -90,14 +89,14 @@
     def savefilename(self, url):
         type, rest = urllib.splittype(url)
         host, path = urllib.splithost(rest)
-        while path[:1] == "/": path = path[1:]
+        path = path.lstrip("/")
         user, host = urllib.splituser(host)
         host, port = urllib.splitnport(host)
-        host = string.lower(host)
+        host = host.lower()
         if not path or path[-1] == "/":
             path = path + "index.html"
         if os.sep != "/":
-            path = string.join(string.split(path, "/"), os.sep)
+            path = os.sep.join(path.split("/"))
             if os.name == "mac":
                 path = os.sep + path
         path = os.path.join(host, path)
diff --git a/Tools/webchecker/wsgui.py b/Tools/webchecker/wsgui.py
index c301c6f..e44c6cd 100755
--- a/Tools/webchecker/wsgui.py
+++ b/Tools/webchecker/wsgui.py
@@ -8,7 +8,6 @@
 
 from Tkinter import *
 import Tkinter
-import string
 import websucker
 import sys
 import os
@@ -150,13 +149,13 @@
             return
         self.url_entry.selection_range(0, END)
         url = self.url_entry.get()
-        url = string.strip(url)
+        url = url.strip()
         if not url:
             self.top.bell()
             self.message("[Error: No URL entered]")
             return
         self.rooturl = url
-        dir = string.strip(self.dir_entry.get())
+        dir = self.dir_entry.get().strip()
         if not dir:
             self.sucker.savedir = None
         else:
@@ -184,7 +183,7 @@
                 text = self.top.selection_get(selection=t)
             except TclError:
                 continue
-            text = string.strip(text)
+            text = text.strip()
             if text:
                 break
         if not text: