Remove uses of the string and types modules:

x in string.whitespace => x.isspace()
type(x) in types.StringTypes => isinstance(x, basestring)
isinstance(x, types.StringTypes) => isinstance(x, basestring)
type(x) is types.StringType => isinstance(x, str)
type(x) == types.StringType => isinstance(x, str)
string.split(x, ...) => x.split(...)
string.join(x, y) => y.join(x)
string.zfill(x, ...) => x.zfill(...)
string.count(x, ...) => x.count(...)
hasattr(types, "UnicodeType") => try: unicode except NameError:
type(x) != types.TupleTuple => not isinstance(x, tuple)
isinstance(x, types.TupleType) => isinstance(x, tuple)
type(x) is types.IntType => isinstance(x, int)

Do not mention the string module in the rlcompleter docstring.

This partially applies SF patch http://www.python.org/sf/562373
(with basestring instead of string). (It excludes the changes to
unittest.py and does not change the os.stat stuff.)
diff --git a/Lib/ConfigParser.py b/Lib/ConfigParser.py
index 7e30f73..435e60d 100644
--- a/Lib/ConfigParser.py
+++ b/Lib/ConfigParser.py
@@ -83,7 +83,7 @@
         write the configuration state in .ini format
 """
 
-import string, types
+import types
 import re
 
 __all__ = ["NoSectionError","DuplicateSectionError","NoOptionError",
@@ -223,7 +223,7 @@
         configuration files in the list will be read.  A single
         filename may also be given.
         """
-        if type(filenames) in types.StringTypes:
+        if isinstance(filenames, basestring):
             filenames = [filenames]
         for filename in filenames:
             try:
@@ -454,7 +454,7 @@
                             # ';' is a comment delimiter only if it follows
                             # a spacing character
                             pos = optval.find(';')
-                            if pos and optval[pos-1] in string.whitespace:
+                            if pos and optval[pos-1].isspace():
                                 optval = optval[:pos]
                         optval = optval.strip()
                         # allow empty values
diff --git a/Lib/StringIO.py b/Lib/StringIO.py
index bdf11cc..7c4b6c7 100644
--- a/Lib/StringIO.py
+++ b/Lib/StringIO.py
@@ -28,7 +28,6 @@
   bytes that occupy space in the buffer.
 - There's a simple test set (see end of this file).
 """
-import types
 try:
     from errno import EINVAL
 except ImportError:
@@ -50,7 +49,7 @@
     """
     def __init__(self, buf = ''):
         # Force self.buf to be a string or unicode
-        if not isinstance(buf, types.StringTypes):
+        if not isinstance(buf, basestring):
             buf = str(buf)
         self.buf = buf
         self.len = len(buf)
@@ -151,7 +150,7 @@
             raise ValueError, "I/O operation on closed file"
         if not s: return
         # Force s to be a string or unicode
-        if not isinstance(s, types.StringTypes):
+        if not isinstance(s, basestring):
             s = str(s)
         if self.pos > self.len:
             self.buflist.append('\0'*(self.pos - self.len))
diff --git a/Lib/formatter.py b/Lib/formatter.py
index ccbbdf1..6ea5d9e 100644
--- a/Lib/formatter.py
+++ b/Lib/formatter.py
@@ -18,9 +18,7 @@
 manage and inserting data into the output.
 """
 
-import string
 import sys
-from types import StringType
 
 
 AS_IS = None
@@ -119,7 +117,7 @@
             self.writer.send_line_break()
         if not self.para_end:
             self.writer.send_paragraph((blankline and 1) or 0)
-        if type(format) is StringType:
+        if isinstance(format, str):
             self.writer.send_label_data(self.format_counter(format, counter))
         else:
             self.writer.send_label_data(format)
@@ -176,16 +174,13 @@
             return label.upper()
         return label
 
-    def add_flowing_data(self, data,
-                         # These are only here to load them into locals:
-                         whitespace = string.whitespace,
-                         join = string.join, split = string.split):
+    def add_flowing_data(self, data):
         if not data: return
         # The following looks a bit convoluted but is a great improvement over
         # data = regsub.gsub('[' + string.whitespace + ']+', ' ', data)
-        prespace = data[:1] in whitespace
-        postspace = data[-1:] in whitespace
-        data = join(split(data))
+        prespace = data[:1].isspace()
+        postspace = data[-1:].isspace()
+        data = " ".join(data.split())
         if self.nospace and not data:
             return
         elif prespace or self.softspace:
@@ -411,7 +406,7 @@
 
     def send_flowing_data(self, data):
         if not data: return
-        atbreak = self.atbreak or data[0] in string.whitespace
+        atbreak = self.atbreak or data[0].isspace()
         col = self.col
         maxcol = self.maxcol
         write = self.file.write
@@ -427,7 +422,7 @@
             col = col + len(word)
             atbreak = 1
         self.col = col
-        self.atbreak = data[-1] in string.whitespace
+        self.atbreak = data[-1].isspace()
 
 
 def test(file = None):
diff --git a/Lib/hmac.py b/Lib/hmac.py
index ba0a63c..db9b404 100644
--- a/Lib/hmac.py
+++ b/Lib/hmac.py
@@ -3,8 +3,6 @@
 Implements the HMAC algorithm as described by RFC 2104.
 """
 
-import string
-
 def _strxor(s1, s2):
     """Utility method. XOR the two strings s1 and s2 (must have same length).
     """
@@ -82,7 +80,7 @@
     def hexdigest(self):
         """Like digest(), but returns a string of hexadecimal digits instead.
         """
-        return "".join([string.zfill(hex(ord(x))[2:], 2)
+        return "".join([hex(ord(x))[2:].zfill(2)
                         for x in tuple(self.digest())])
 
 def new(key, msg = None, digestmod = None):
diff --git a/Lib/markupbase.py b/Lib/markupbase.py
index ae19869..acd0726 100644
--- a/Lib/markupbase.py
+++ b/Lib/markupbase.py
@@ -1,7 +1,6 @@
 """Shared support for scanning document type declarations in HTML and XHTML."""
 
 import re
-import string
 
 _declname_match = re.compile(r'[a-zA-Z][-_.a-zA-Z0-9]*\s*').match
 _declstringlit_match = re.compile(r'(\'[^\']*\'|"[^"]*")\s*').match
@@ -151,7 +150,7 @@
                     j = j + 1
             elif c == "]":
                 j = j + 1
-                while j < n and rawdata[j] in string.whitespace:
+                while j < n and rawdata[j].isspace():
                     j = j + 1
                 if j < n:
                     if rawdata[j] == ">":
@@ -160,7 +159,7 @@
                     self.error("unexpected char after internal subset")
                 else:
                     return -1
-            elif c in string.whitespace:
+            elif c.isspace():
                 j = j + 1
             else:
                 self.updatepos(declstartpos, j)
@@ -203,7 +202,7 @@
                     j = rawdata.find(")", j) + 1
                 else:
                     return -1
-                while rawdata[j:j+1] in string.whitespace:
+                while rawdata[j:j+1].isspace():
                     j = j + 1
                 if not rawdata[j:]:
                     # end of buffer, incomplete
@@ -268,7 +267,7 @@
                 c = rawdata[j:j+1]
                 if not c:
                     return -1
-                if c in string.whitespace:
+                if c.isspace():
                     j = j + 1
                 else:
                     break
diff --git a/Lib/nntplib.py b/Lib/nntplib.py
index 21faab1..f09c69a 100644
--- a/Lib/nntplib.py
+++ b/Lib/nntplib.py
@@ -31,7 +31,6 @@
 # Imports
 import re
 import socket
-import types
 
 __all__ = ["NNTP","NNTPReplyError","NNTPTemporaryError",
            "NNTPPermanentError","NNTPProtocolError","NNTPDataError",
@@ -218,7 +217,7 @@
         openedFile = None
         try:
             # If a string was passed then open a file with that name
-            if isinstance(file, types.StringType):
+            if isinstance(file, str):
                 openedFile = file = open(file, "w")
 
             resp = self.getresp()
diff --git a/Lib/popen2.py b/Lib/popen2.py
index f00cb83..d6ff002 100644
--- a/Lib/popen2.py
+++ b/Lib/popen2.py
@@ -8,7 +8,6 @@
 
 import os
 import sys
-import types
 
 __all__ = ["popen2", "popen3", "popen4"]
 
@@ -57,7 +56,7 @@
         _active.append(self)
 
     def _run_child(self, cmd):
-        if isinstance(cmd, types.StringTypes):
+        if isinstance(cmd, basestring):
             cmd = ['/bin/sh', '-c', cmd]
         for i in range(3, MAXFD):
             try:
diff --git a/Lib/pyclbr.py b/Lib/pyclbr.py
index fad46ad..9bc68c5 100644
--- a/Lib/pyclbr.py
+++ b/Lib/pyclbr.py
@@ -208,12 +208,10 @@
     f.close()
 
     # To avoid having to stop the regexp at each newline, instead
-    # when we need a line number we simply string.count the number of
+    # when we need a line number we simply count the number of
     # newlines in the string since the last time we did this; i.e.,
-    #    lineno = lineno + \
-    #             string.count(src, '\n', last_lineno_pos, here)
+    #    lineno += src.count('\n', last_lineno_pos, here)
     #    last_lineno_pos = here
-    countnl = string.count
     lineno, last_lineno_pos = 1, 0
     i = 0
     while 1:
@@ -226,9 +224,7 @@
             # found a method definition or function
             thisindent = _indent(m.group("MethodIndent"))
             meth_name = m.group("MethodName")
-            lineno = lineno + \
-                     countnl(src, '\n',
-                             last_lineno_pos, start)
+            lineno += src.count('\n', last_lineno_pos, start)
             last_lineno_pos = start
             # close all classes indented at least as much
             while classstack and \
@@ -254,8 +250,7 @@
             while classstack and \
                   classstack[-1][1] >= thisindent:
                 del classstack[-1]
-            lineno = lineno + \
-                     countnl(src, '\n', last_lineno_pos, start)
+            lineno += src.count('\n', last_lineno_pos, start)
             last_lineno_pos = start
             class_name = m.group("ClassName")
             inherit = m.group("ClassSupers")
diff --git a/Lib/rlcompleter.py b/Lib/rlcompleter.py
index 3075a14..de4c024 100644
--- a/Lib/rlcompleter.py
+++ b/Lib/rlcompleter.py
@@ -5,9 +5,9 @@
 defaults to __main__); when completing NAME.NAME..., it evaluates (!) the
 expression up to the last dot and completes its attributes.
 
-It's very cool to do "import string" type "string.", hit the
+It's very cool to do "import sys" type "sys.", hit the
 completion key (twice), and see the list of names defined by the
-string module!
+sys module!
 
 Tip: to use the tab key as the completion key, call
 
diff --git a/Lib/smtplib.py b/Lib/smtplib.py
index d840373..adbdcbc 100755
--- a/Lib/smtplib.py
+++ b/Lib/smtplib.py
@@ -44,7 +44,6 @@
 import socket
 import re
 import rfc822
-import types
 import base64
 import hmac
 
@@ -651,7 +650,7 @@
             self.rset()
             raise SMTPSenderRefused(code, resp, from_addr)
         senderrs={}
-        if isinstance(to_addrs, types.StringTypes):
+        if isinstance(to_addrs, basestring):
             to_addrs = [to_addrs]
         for each in to_addrs:
             (code,resp)=self.rcpt(each, rcpt_options)
diff --git a/Lib/string.py b/Lib/string.py
index cd9909e..1d452ed 100644
--- a/Lib/string.py
+++ b/Lib/string.py
@@ -190,10 +190,6 @@
 _float = float
 _int = int
 _long = long
-try:
-    _StringTypes = (str, unicode)
-except NameError:
-    _StringTypes = (str,)
 
 # Convert string to float
 def atof(s):
@@ -279,7 +275,7 @@
     of the specified width.  The string x is never truncated.
 
     """
-    if not isinstance(x, _StringTypes):
+    if not isinstance(x, basestring):
         x = repr(x)
     return x.zfill(width)
 
diff --git a/Lib/urllib.py b/Lib/urllib.py
index 0720125..381d54e 100644
--- a/Lib/urllib.py
+++ b/Lib/urllib.py
@@ -27,7 +27,6 @@
 import os
 import time
 import sys
-import types
 
 __all__ = ["urlopen", "URLopener", "FancyURLopener", "urlretrieve",
            "urlcleanup", "quote", "quote_plus", "unquote", "unquote_plus",
@@ -254,7 +253,7 @@
         """Use HTTP protocol."""
         import httplib
         user_passwd = None
-        if type(url) is types.StringType:
+        if isinstance(url, str):
             host, selector = splithost(url)
             if host:
                 user_passwd, host = splituser(host)
@@ -332,7 +331,7 @@
             """Use HTTPS protocol."""
             import httplib
             user_passwd = None
-            if type(url) is types.StringType:
+            if isinstance(url, str):
                 host, selector = splithost(url)
                 if host:
                     user_passwd, host = splituser(host)
@@ -906,12 +905,14 @@
 # unquote('abc%20def') -> 'abc def'
 # quote('abc def') -> 'abc%20def')
 
-if hasattr(types, "UnicodeType"):
-    def _is_unicode(x):
-        return isinstance(x, unicode)
-else:
+try:
+    unicode
+except NameError:
     def _is_unicode(x):
         return 0
+else:
+    def _is_unicode(x):
+        return isinstance(x, unicode)
 
 def toBytes(url):
     """toBytes(u"URL") --> 'URL'."""
@@ -1173,7 +1174,7 @@
         try:
             # non-sequence items should not work with len()
             # non-empty strings will fail this
-            if len(query) and type(query[0]) != types.TupleType:
+            if len(query) and not isinstance(query[0], tuple):
                 raise TypeError
             # zero-length sequences of all types will get here and succeed,
             # but that's a minor nit - since the original implementation
@@ -1193,7 +1194,7 @@
     else:
         for k, v in query:
             k = quote_plus(str(k))
-            if type(v) == types.StringType:
+            if isinstance(v, str):
                 v = quote_plus(v)
                 l.append(k + '=' + v)
             elif _is_unicode(v):
diff --git a/Lib/urllib2.py b/Lib/urllib2.py
index 898da7d..814a2df 100644
--- a/Lib/urllib2.py
+++ b/Lib/urllib2.py
@@ -92,7 +92,6 @@
 import inspect
 import re
 import base64
-import types
 import urlparse
 import md5
 import mimetypes
@@ -303,7 +302,7 @@
 
     def open(self, fullurl, data=None):
         # accept a URL or a Request object
-        if isinstance(fullurl, types.StringTypes):
+        if isinstance(fullurl, basestring):
             req = Request(fullurl, data)
         else:
             req = fullurl
@@ -516,7 +515,7 @@
 
     def add_password(self, realm, uri, user, passwd):
         # uri could be a single URI or a sequence
-        if isinstance(uri, types.StringTypes):
+        if isinstance(uri, basestring):
             uri = [uri]
         uri = tuple(map(self.reduce_uri, uri))
         if not realm in self.passwd:
@@ -1084,7 +1083,7 @@
     install_opener(build_opener(cfh, GopherHandler))
 
     for url in urls:
-        if isinstance(url, types.TupleType):
+        if isinstance(url, tuple):
             url, req = url
         else:
             req = None
diff --git a/Lib/warnings.py b/Lib/warnings.py
index dceddde..383e623 100644
--- a/Lib/warnings.py
+++ b/Lib/warnings.py
@@ -125,11 +125,11 @@
     Use assertions to check that all arguments have the right type."""
     assert action in ("error", "ignore", "always", "default", "module",
                       "once"), "invalid action: %s" % `action`
-    assert isinstance(message, types.StringType), "message must be a string"
+    assert isinstance(message, str), "message must be a string"
     assert isinstance(category, types.ClassType), "category must be a class"
     assert issubclass(category, Warning), "category must be a Warning subclass"
-    assert type(module) is types.StringType, "module must be a string"
-    assert type(lineno) is types.IntType and lineno >= 0, \
+    assert isinstance(module, str), "module must be a string"
+    assert isinstance(lineno, int) and lineno >= 0, \
            "lineno must be an int >= 0"
     item = (action, re.compile(message, re.I), category,
             re.compile(module), lineno)
diff --git a/Lib/zipfile.py b/Lib/zipfile.py
index c21be84..5c1c229 100644
--- a/Lib/zipfile.py
+++ b/Lib/zipfile.py
@@ -65,13 +65,6 @@
 _FH_FILENAME_LENGTH = 10
 _FH_EXTRA_FIELD_LENGTH = 11
 
-# Used to compare file passed to ZipFile
-import types
-_STRING_TYPES = (types.StringType,)
-if hasattr(types, "UnicodeType"):
-    _STRING_TYPES = _STRING_TYPES + (types.UnicodeType,)
-
-
 def is_zipfile(filename):
     """Quickly see if file is a ZIP file by checking the magic number.
 
@@ -175,7 +168,7 @@
         self.mode = key = mode[0]
 
         # Check if we were passed a file-like object
-        if type(file) in _STRING_TYPES:
+        if isinstance(file, basestring):
             self._filePassed = 0
             self.filename = file
             modeDict = {'r' : 'rb', 'w': 'wb', 'a' : 'r+b'}