SF patch# 1770008 by Christian Heimes (plus some extras).
Completely get rid of StringIO.py and cStringIO.c.

I had to fix a few tests and modules beyond what Christian did, and
invent a few conventions.  E.g. in elementtree, I chose to
write/return Unicode strings whe no encoding is given, but bytes when
an explicit encoding is given.  Also mimetools was made to always
assume binary files.
diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py
index 7bff76f..0ad1f48 100644
--- a/Lib/test/pickletester.py
+++ b/Lib/test/pickletester.py
@@ -406,7 +406,7 @@
     # is a mystery.  cPickle also suppresses PUT for objects with a refcount
     # of 1.
     def dont_test_disassembly(self):
-        from cStringIO import StringIO
+        from io import StringIO
         from pickletools import dis
 
         for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
@@ -951,8 +951,8 @@
         self.assertEqual(self.module.HIGHEST_PROTOCOL, 2)
 
     def test_callapi(self):
-        from cStringIO import StringIO
-        f = StringIO()
+        from io import BytesIO
+        f = BytesIO()
         # With and without keyword arguments
         self.module.dump(123, f, -1)
         self.module.dump(123, file=f, protocol=-1)
diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py
index 28b82ad..31e4eaf 100755
--- a/Lib/test/regrtest.py
+++ b/Lib/test/regrtest.py
@@ -125,7 +125,7 @@
 import random
 import warnings
 import re
-import StringIO
+import io
 import traceback
 
 # I see no other way to suppress these warnings;
@@ -537,7 +537,7 @@
     if verbose:
         cfp = None
     else:
-        cfp = StringIO.StringIO()  # XXX Should use io.StringIO()
+        cfp = io.StringIO()  # XXX Should use io.StringIO()
 
     try:
         save_stdout = sys.stdout
diff --git a/Lib/test/test_StringIO.py b/Lib/test/test_StringIO.py
index 2f4a221..4f3ce83 100644
--- a/Lib/test/test_StringIO.py
+++ b/Lib/test/test_StringIO.py
@@ -2,13 +2,13 @@
 
 import sys
 import unittest
-import StringIO
-import cStringIO
+import io
 from test import test_support
 
 
 class TestGenericStringIO:
-    # use a class variable MODULE to define which module is being tested
+    # use a class variable CLASS to define which class is being tested
+    CLASS = None
 
     # Line of data to test as string
     _line = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!'
@@ -20,7 +20,7 @@
     def setUp(self):
         self._line = self.constructor(self._line)
         self._lines = self.constructor((self._line + '\n') * 5)
-        self._fp = self.MODULE.StringIO(self._lines)
+        self._fp = self.CLASS(self._lines)
 
     def test_reads(self):
         eq = self.assertEqual
@@ -30,7 +30,7 @@
         eq(len(self._fp.readlines(60)), 2)
 
     def test_writes(self):
-        f = self.MODULE.StringIO()
+        f = self.CLASS()
         self.assertRaises(TypeError, f.seek)
         f.write(self._line[:6])
         f.seek(3)
@@ -39,7 +39,7 @@
         self.assertEqual(f.getvalue(), 'abcuvwxyz!')
 
     def test_writelines(self):
-        f = self.MODULE.StringIO()
+        f = self.CLASS()
         f.writelines([self._line[0], self._line[1], self._line[2]])
         f.seek(0)
         self.assertEqual(f.getvalue(), 'abc')
@@ -48,12 +48,12 @@
         def errorGen():
             yield 'a'
             raise KeyboardInterrupt()
-        f = self.MODULE.StringIO()
+        f = self.CLASS()
         self.assertRaises(KeyboardInterrupt, f.writelines, errorGen())
 
     def test_truncate(self):
         eq = self.assertEqual
-        f = self.MODULE.StringIO()
+        f = self.CLASS()
         f.write(self._lines)
         f.seek(10)
         f.truncate()
@@ -62,22 +62,22 @@
         eq(f.getvalue(), 'abcde')
         f.write('xyz')
         eq(f.getvalue(), 'abcdexyz')
-        self.assertRaises(IOError, f.truncate, -1)
+        self.assertRaises(ValueError, f.truncate, -1)
         f.close()
         self.assertRaises(ValueError, f.write, 'frobnitz')
 
     def test_closed_flag(self):
-        f = self.MODULE.StringIO()
+        f = self.CLASS()
         self.assertEqual(f.closed, False)
         f.close()
         self.assertEqual(f.closed, True)
-        f = self.MODULE.StringIO(self.constructor("abc"))
+        f = self.CLASS(self.constructor("abc"))
         self.assertEqual(f.closed, False)
         f.close()
         self.assertEqual(f.closed, True)
 
     def test_isatty(self):
-        f = self.MODULE.StringIO()
+        f = self.CLASS()
         self.assertRaises(TypeError, f.isatty, None)
         self.assertEqual(f.isatty(), False)
         f.close()
@@ -96,10 +96,10 @@
             i += 1
         eq(i, 5)
         self._fp.close()
-        self.assertRaises(ValueError, next, self._fp)
+        self.assertRaises(StopIteration, next, self._fp)
 
-class TestStringIO(TestGenericStringIO, unittest.TestCase):
-    MODULE = StringIO
+class TestioStringIO(TestGenericStringIO, unittest.TestCase):
+    CLASS = io.StringIO
 
     def test_unicode(self):
 
@@ -109,7 +109,7 @@
         # snippets to larger Unicode strings. This is tested by this
         # method. Note that cStringIO does not support this extension.
 
-        f = self.MODULE.StringIO()
+        f = self.CLASS()
         f.write(self._line[:6])
         f.seek(3)
         f.write(str(self._line[20:26]))
@@ -118,55 +118,10 @@
         self.assertEqual(s, str('abcuvwxyz!'))
         self.assertEqual(type(s), str)
 
-class TestcStringIO(TestGenericStringIO, unittest.TestCase):
-    MODULE = cStringIO
-    constructor = str8
-
-    def test_unicode(self):
-
-        if not test_support.have_unicode: return
-
-        # The cStringIO module converts Unicode strings to character
-        # strings when writing them to cStringIO objects.
-        # Check that this works.
-
-        f = self.MODULE.StringIO()
-        f.write(str(self._line[:5]))
-        s = f.getvalue()
-        self.assertEqual(s, 'abcde')
-        self.assertEqual(type(s), str8)
-
-        f = self.MODULE.StringIO(str(self._line[:5]))
-        s = f.getvalue()
-        self.assertEqual(s, 'abcde')
-        self.assertEqual(type(s), str8)
-
-        # XXX This no longer fails -- the default encoding is always UTF-8.
-        ##self.assertRaises(UnicodeDecodeError, self.MODULE.StringIO, '\xf4')
-
-class TestBufferStringIO(TestStringIO):
-
-    def constructor(self, s):
-        return buffer(str8(s))
-
-class TestBuffercStringIO(TestcStringIO):
-
-    def constructor(self, s):
-        return buffer(str8(s))
-
 
 def test_main():
-    classes = [
-        TestStringIO,
-        TestcStringIO,
-        ]
-    if not sys.platform.startswith('java'):
-        classes.extend([
-        TestBufferStringIO,
-        TestBuffercStringIO
-        ])
-    test_support.run_unittest(*classes)
+    test_support.run_unittest(TestioStringIO)
 
 
 if __name__ == '__main__':
-    unittest.main()
+    test_main()
diff --git a/Lib/test/test___all__.py b/Lib/test/test___all__.py
index 4cf2e25..99bc330 100644
--- a/Lib/test/test___all__.py
+++ b/Lib/test/test___all__.py
@@ -36,7 +36,6 @@
         self.check_all("Queue")
         self.check_all("SimpleHTTPServer")
         self.check_all("SocketServer")
-        self.check_all("StringIO")
         self.check_all("UserString")
         self.check_all("aifc")
         self.check_all("base64")
diff --git a/Lib/test/test_atexit.py b/Lib/test/test_atexit.py
index 142e543..76a5036 100644
--- a/Lib/test/test_atexit.py
+++ b/Lib/test/test_atexit.py
@@ -1,6 +1,6 @@
 import sys
 import unittest
-import StringIO
+import io
 import atexit
 from test import test_support
 
@@ -25,7 +25,7 @@
 
 class TestCase(unittest.TestCase):
     def setUp(self):
-        self.stream = StringIO.StringIO()
+        self.stream = io.StringIO()
         sys.stdout = sys.stderr = self.stream
         atexit._clear()
 
diff --git a/Lib/test/test_base64.py b/Lib/test/test_base64.py
index 2f592f1..6f88695 100644
--- a/Lib/test/test_base64.py
+++ b/Lib/test/test_base64.py
@@ -36,23 +36,23 @@
 
     def test_encode(self):
         eq = self.assertEqual
-        from cStringIO import StringIO
-        infp = StringIO('abcdefghijklmnopqrstuvwxyz'
-                        'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-                        '0123456789!@#0^&*();:<>,. []{}')
-        outfp = StringIO()
+        from io import BytesIO
+        infp = BytesIO(b'abcdefghijklmnopqrstuvwxyz'
+                       b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+                       b'0123456789!@#0^&*();:<>,. []{}')
+        outfp = BytesIO()
         base64.encode(infp, outfp)
         eq(outfp.getvalue(),
-           'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE'
-           'RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT'
-           'Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==\n')
+           b'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE'
+           b'RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT'
+           b'Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==\n')
 
     def test_decode(self):
-        from cStringIO import StringIO
-        infp = StringIO('d3d3LnB5dGhvbi5vcmc=')
-        outfp = StringIO()
+        from io import BytesIO
+        infp = BytesIO(b'd3d3LnB5dGhvbi5vcmc=')
+        outfp = BytesIO()
         base64.decode(infp, outfp)
-        self.assertEqual(outfp.getvalue(), 'www.python.org')
+        self.assertEqual(outfp.getvalue(), b'www.python.org')
 
 
 
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index 7e37c29..a4ae21a 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -5,7 +5,7 @@
                               run_with_locale
 from operator import neg
 
-import sys, warnings, cStringIO, random, UserDict
+import sys, warnings, random, UserDict, io
 warnings.filterwarnings("ignore", "hex../oct.. of negative int",
                         FutureWarning, __name__)
 warnings.filterwarnings("ignore", "integer argument expected",
@@ -1455,11 +1455,11 @@
             self.assertRaises(ValueError, input)
 
             sys.stdout = BitBucket()
-            sys.stdin = cStringIO.StringIO("NULL\0")
+            sys.stdin = io.StringIO("NULL\0")
             self.assertRaises(TypeError, input, 42, 42)
-            sys.stdin = cStringIO.StringIO("    'whitespace'")
+            sys.stdin = io.StringIO("    'whitespace'")
             self.assertEqual(input(), "    'whitespace'")
-            sys.stdin = cStringIO.StringIO()
+            sys.stdin = io.StringIO()
             self.assertRaises(EOFError, input)
 
             del sys.stdout
diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py
index 06293f5..32c9cef 100644
--- a/Lib/test/test_bz2.py
+++ b/Lib/test/test_bz2.py
@@ -3,7 +3,7 @@
 from test.test_support import TESTFN
 
 import unittest
-from cStringIO import StringIO
+from io import BytesIO
 import os
 import subprocess
 import sys
@@ -98,7 +98,7 @@
         self.createTempFile()
         bz2f = BZ2File(self.filename)
         self.assertRaises(TypeError, bz2f.readline, None)
-        sio = StringIO(self.TEXT)
+        sio = BytesIO(self.TEXT)
         for line in sio.readlines():
             self.assertEqual(bz2f.readline(), line)
         bz2f.close()
@@ -108,7 +108,7 @@
         self.createTempFile()
         bz2f = BZ2File(self.filename)
         self.assertRaises(TypeError, bz2f.readlines, None)
-        sio = StringIO(self.TEXT)
+        sio = BytesIO(self.TEXT)
         self.assertEqual(bz2f.readlines(), sio.readlines())
         bz2f.close()
 
@@ -116,7 +116,7 @@
         # "Test iter(BZ2File)"
         self.createTempFile()
         bz2f = BZ2File(self.filename)
-        sio = StringIO(self.TEXT)
+        sio = BytesIO(self.TEXT)
         self.assertEqual(list(iter(bz2f)), sio.readlines())
         bz2f.close()
 
@@ -149,7 +149,7 @@
         # "Test BZ2File.writelines()"
         bz2f = BZ2File(self.filename, "w")
         self.assertRaises(TypeError, bz2f.writelines)
-        sio = StringIO(self.TEXT)
+        sio = BytesIO(self.TEXT)
         bz2f.writelines(sio.readlines())
         bz2f.close()
         # patch #1535500
diff --git a/Lib/test/test_cfgparser.py b/Lib/test/test_cfgparser.py
index 076de4a..8822735 100644
--- a/Lib/test/test_cfgparser.py
+++ b/Lib/test/test_cfgparser.py
@@ -1,5 +1,5 @@
 import ConfigParser
-import StringIO
+import io
 import unittest
 import UserDict
 
@@ -30,7 +30,7 @@
 
     def fromstring(self, string, defaults=None):
         cf = self.newconfig(defaults)
-        sio = StringIO.StringIO(string)
+        sio = io.StringIO(string)
         cf.readfp(sio)
         return cf
 
@@ -156,7 +156,7 @@
                          "No Section!\n")
 
     def parse_error(self, exc, src):
-        sio = StringIO.StringIO(src)
+        sio = io.StringIO(src)
         self.assertRaises(exc, self.cf.readfp, sio)
 
     def test_query_errors(self):
@@ -222,7 +222,7 @@
             "foo: another very\n"
             " long line"
             )
-        output = StringIO.StringIO()
+        output = io.StringIO()
         cf.write(output)
         self.assertEqual(
             output.getvalue(),
@@ -449,7 +449,7 @@
                         "o1=4\n"
                         "[a]\n"
                         "k=v\n")
-        output = StringIO.StringIO()
+        output = io.StringIO()
         self.cf.write(output)
         self.assertEquals(output.getvalue(),
                           "[a]\n"
diff --git a/Lib/test/test_cgi.py b/Lib/test/test_cgi.py
index 6d5bfd6..652b36e 100644
--- a/Lib/test/test_cgi.py
+++ b/Lib/test/test_cgi.py
@@ -4,7 +4,7 @@
 import sys
 import tempfile
 import unittest
-from StringIO import StringIO
+from io import StringIO
 
 class HackedSysModule:
     # The regression test will have real values in sys.argv, which
@@ -15,9 +15,9 @@
 cgi.sys = HackedSysModule()
 
 try:
-    from cStringIO import StringIO
+    from io import StringIO
 except ImportError:
-    from StringIO import StringIO
+    from io import StringIO
 
 class ComparableException:
     def __init__(self, err):
diff --git a/Lib/test/test_codeop.py b/Lib/test/test_codeop.py
index b3fd18a..edea601 100644
--- a/Lib/test/test_codeop.py
+++ b/Lib/test/test_codeop.py
@@ -6,10 +6,10 @@
 from test.test_support import run_unittest, is_jython
 
 from codeop import compile_command, PyCF_DONT_IMPLY_DEDENT
+import io
 
 if is_jython:
     import sys
-    import cStringIO
 
     def unify_callables(d):
         for n,v in d.items():
@@ -27,7 +27,7 @@
             if symbol == "single":
                 d,r = {},{}
                 saved_stdout = sys.stdout
-                sys.stdout = cStringIO.StringIO()
+                sys.stdout = io.StringIO()
                 try:
                     exec(code, d)
                     exec(compile(str,"<input>","single"), r)
diff --git a/Lib/test/test_cookielib.py b/Lib/test/test_cookielib.py
index d72a3a8..87f118d 100644
--- a/Lib/test/test_cookielib.py
+++ b/Lib/test/test_cookielib.py
@@ -153,8 +153,8 @@
             try:
                 result = split_header_words([arg])
             except:
-                import traceback, StringIO
-                f = StringIO.StringIO()
+                import traceback, io
+                f = io.StringIO()
                 traceback.print_exc(None, f)
                 result = "(error -- traceback follows)\n\n%s" % f.getvalue()
             self.assertEquals(result,  expect, """
@@ -204,8 +204,8 @@
         """
         headers: list of RFC822-style 'Key: value' strings
         """
-        import mimetools, StringIO
-        f = StringIO.StringIO("\n".join(headers))
+        import mimetools, io
+        f = io.StringIO("\n".join(headers))
         self._headers = mimetools.Message(f)
         self._url = url
     def info(self): return self._headers
diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py
index 6098285..21cc408 100644
--- a/Lib/test/test_csv.py
+++ b/Lib/test/test_csv.py
@@ -5,7 +5,7 @@
 import sys
 import os
 import unittest
-from StringIO import StringIO
+from io import StringIO
 from tempfile import TemporaryFile
 import csv
 import gc
diff --git a/Lib/test/test_deque.py b/Lib/test/test_deque.py
index 63391af..d51a865 100644
--- a/Lib/test/test_deque.py
+++ b/Lib/test/test_deque.py
@@ -4,7 +4,7 @@
 from weakref import proxy
 import copy
 import pickle
-from cStringIO import StringIO
+from io import StringIO
 import random
 import os
 
diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py
index d98c607..c016681 100644
--- a/Lib/test/test_dict.py
+++ b/Lib/test/test_dict.py
@@ -1,7 +1,7 @@
 import unittest
 from test import test_support
 
-import sys, UserDict, cStringIO
+import sys, UserDict
 
 
 class DictTest(unittest.TestCase):
diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py
index f1bd3e7..f135780 100644
--- a/Lib/test/test_dis.py
+++ b/Lib/test/test_dis.py
@@ -4,7 +4,7 @@
 import unittest
 import sys
 import dis
-import StringIO
+import io
 
 
 def _f(a):
@@ -103,7 +103,7 @@
 
 class DisTests(unittest.TestCase):
     def do_disassembly_test(self, func, expected):
-        s = StringIO.StringIO()
+        s = io.StringIO()
         save_stdout = sys.stdout
         sys.stdout = s
         dis.dis(func)
diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py
index 5307395..dea03d3 100644
--- a/Lib/test/test_doctest.py
+++ b/Lib/test/test_doctest.py
@@ -2405,7 +2405,7 @@
     from test import test_doctest
     test_support.run_doctest(test_doctest, verbosity=True)
 
-import trace, sys, re, StringIO
+import trace, sys, re, io
 def test_coverage(coverdir):
     tracer = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix,],
                          trace=0, count=1)
diff --git a/Lib/test/test_fileinput.py b/Lib/test/test_fileinput.py
index e0b5818..a9d2fa6 100644
--- a/Lib/test/test_fileinput.py
+++ b/Lib/test/test_fileinput.py
@@ -7,7 +7,7 @@
 from test.test_support import verbose, TESTFN, run_unittest
 from test.test_support import unlink as safe_unlink
 import sys, os, re
-from StringIO import StringIO
+from io import StringIO
 from fileinput import FileInput, hook_encoded
 
 # The fileinput module has 2 interfaces: the FileInput class which does
diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py
index a1ab0f1..4710c8c 100644
--- a/Lib/test/test_generators.py
+++ b/Lib/test/test_generators.py
@@ -1685,8 +1685,8 @@
 
 Our ill-behaved code should be invoked during GC:
 
->>> import sys, StringIO
->>> old, sys.stderr = sys.stderr, StringIO.StringIO()
+>>> import sys, io
+>>> old, sys.stderr = sys.stderr, io.StringIO()
 >>> g = f()
 >>> next(g)
 >>> del g
@@ -1796,10 +1796,10 @@
 printing warnings and to doublecheck that we actually tested what we wanted
 to test.
 
->>> import sys, StringIO
+>>> import sys, io
 >>> old = sys.stderr
 >>> try:
-...     sys.stderr = StringIO.StringIO()
+...     sys.stderr = io.StringIO()
 ...     class Leaker:
 ...         def __del__(self):
 ...             raise RuntimeError
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
index 953acad..1073cdd 100644
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -25,7 +25,7 @@
 """
 
 import select
-import os, sys, struct, pickle, cStringIO
+import os, sys, struct, pickle, io
 import socket, tempfile, threading, time
 import logging, logging.handlers, logging.config
 from test.test_support import run_with_locale
@@ -606,7 +606,7 @@
     #Configure the logger for logrecv so events do not propagate beyond it.
     #The sockLogger output is buffered in memory until the end of the test,
     #and printed at the end.
-    sockOut = cStringIO.StringIO()
+    sockOut = io.StringIO()
     sockLogger = logging.getLogger("logrecv")
     sockLogger.setLevel(logging.DEBUG)
     sockhdlr = logging.StreamHandler(sockOut)
diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py
index 4761aa7..59def94 100644
--- a/Lib/test/test_mailbox.py
+++ b/Lib/test/test_mailbox.py
@@ -7,7 +7,7 @@
 import email.message
 import rfc822
 import re
-import StringIO
+import io
 from test import test_support
 import unittest
 import mailbox
@@ -69,7 +69,7 @@
         self.assertEqual(len(self._box), 2)
         keys.append(self._box.add(email.message_from_string(_sample_message)))
         self.assertEqual(len(self._box), 3)
-        keys.append(self._box.add(StringIO.StringIO(_sample_message)))
+        keys.append(self._box.add(io.StringIO(_sample_message)))
         self.assertEqual(len(self._box), 4)
         keys.append(self._box.add(_sample_message))
         self.assertEqual(len(self._box), 5)
@@ -400,12 +400,12 @@
     def test_dump_message(self):
         # Write message representations to disk
         for input in (email.message_from_string(_sample_message),
-                      _sample_message, StringIO.StringIO(_sample_message)):
-            output = StringIO.StringIO()
+                      _sample_message, io.StringIO(_sample_message)):
+            output = io.StringIO()
             self._box._dump_message(input, output)
             self.assert_(output.getvalue() ==
                          _sample_message.replace('\n', os.linesep))
-        output = StringIO.StringIO()
+        output = io.StringIO()
         self.assertRaises(TypeError,
                           lambda: self._box._dump_message(None, output))
 
diff --git a/Lib/test/test_mhlib.py b/Lib/test/test_mhlib.py
index 1b1af6a..ad66ede 100644
--- a/Lib/test/test_mhlib.py
+++ b/Lib/test/test_mhlib.py
@@ -8,7 +8,8 @@
 
 import unittest
 from test.test_support import run_unittest, TESTFN, TestSkipped
-import os, StringIO
+import os
+import io
 import sys
 import mhlib
 
@@ -262,7 +263,7 @@
         f = mh.openfolder('dummy1')
         def create(n):
             msg = "From: foo\nSubject: %s\n\nDummy Message %s\n" % (n,n)
-            f.createmessage(n, StringIO.StringIO(msg))
+            f.createmessage(n, io.StringIO(msg))
 
         create(7)
         create(8)
diff --git a/Lib/test/test_mimetools.py b/Lib/test/test_mimetools.py
index ad24776..cf0e191 100644
--- a/Lib/test/test_mimetools.py
+++ b/Lib/test/test_mimetools.py
@@ -1,28 +1,54 @@
 import unittest
 from test import test_support
 
-import string, StringIO, mimetools
+import string, mimetools
+import io
 
-msgtext1 = mimetools.Message(StringIO.StringIO(
+msgtext1 = mimetools.Message(io.StringIO(
 """Content-Type: text/plain; charset=iso-8859-1; format=flowed
 Content-Transfer-Encoding: 8bit
 
 Foo!
 """))
 
+sample = bytes(string.ascii_letters + "=" + string.digits + "\n", "ASCII")
+
 class MimeToolsTest(unittest.TestCase):
 
-    def test_decodeencode(self):
-        start = string.ascii_letters + "=" + string.digits + "\n"
-        for enc in ['7bit','8bit','base64','quoted-printable',
-                    'uuencode', 'x-uuencode', 'uue', 'x-uue']:
-            i = StringIO.StringIO(start)
-            o = StringIO.StringIO()
-            mimetools.encode(i, o, enc)
-            i = StringIO.StringIO(o.getvalue())
-            o = StringIO.StringIO()
-            mimetools.decode(i, o, enc)
-            self.assertEqual(o.getvalue(), start)
+    def decode_encode_test(self, enc):
+        i = io.BytesIO(sample)
+        o = io.BytesIO()
+        mimetools.encode(i, o, enc)
+        i = io.BytesIO(o.getvalue())
+        o = io.BytesIO()
+        mimetools.decode(i, o, enc)
+        self.assertEqual(o.getvalue(), sample)
+
+    # Separate tests for better diagnostics
+
+    def test_7bit(self):
+        self.decode_encode_test('7bit')
+
+    def test_8bit(self):
+        self.decode_encode_test('8bit')
+
+    def test_base64(self):
+        self.decode_encode_test('base64')
+
+    def test_quoted_printable(self):
+        self.decode_encode_test('quoted-printable')
+
+    def test_uuencode(self):
+        self.decode_encode_test('uuencode')
+
+    def test_x_uuencode(self):
+        self.decode_encode_test('x-uuencode')
+
+    def test_uue(self):
+        self.decode_encode_test('uue')
+
+    def test_x_uue(self):
+        self.decode_encode_test('x-uue')
 
     def test_boundary(self):
         s = set([""])
@@ -32,7 +58,7 @@
             s.add(nb)
 
     def test_message(self):
-        msg = mimetools.Message(StringIO.StringIO(msgtext1))
+        msg = mimetools.Message(io.StringIO(msgtext1))
         self.assertEqual(msg.gettype(), "text/plain")
         self.assertEqual(msg.getmaintype(), "text")
         self.assertEqual(msg.getsubtype(), "plain")
diff --git a/Lib/test/test_mimetypes.py b/Lib/test/test_mimetypes.py
index 0190c2f..53de072 100644
--- a/Lib/test/test_mimetypes.py
+++ b/Lib/test/test_mimetypes.py
@@ -1,5 +1,5 @@
 import mimetypes
-import StringIO
+import io
 import unittest
 
 from test import test_support
@@ -30,7 +30,7 @@
 
     def test_file_parsing(self):
         eq = self.assertEqual
-        sio = StringIO.StringIO("x-application/x-unittest pyunit\n")
+        sio = io.StringIO("x-application/x-unittest pyunit\n")
         self.db.readfp(sio)
         eq(self.db.guess_type("foo.pyunit"),
            ("x-application/x-unittest", None))
diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py
index cc637d0..fb3b098 100644
--- a/Lib/test/test_minidom.py
+++ b/Lib/test/test_minidom.py
@@ -4,7 +4,7 @@
 import sys
 import pickle
 import traceback
-from StringIO import StringIO
+from io import StringIO
 from test.test_support import verbose, run_unittest, TestSkipped
 import unittest
 
diff --git a/Lib/test/test_multifile.py b/Lib/test/test_multifile.py
index 437c394..b29137c 100644
--- a/Lib/test/test_multifile.py
+++ b/Lib/test/test_multifile.py
@@ -1,6 +1,6 @@
 import mimetools
 import multifile
-import cStringIO
+import io
 
 msg = """Mime-Version: 1.0
 Content-Type: multipart/mixed;
@@ -57,7 +57,7 @@
     global boundaries, linecount
     boundaries = 0
     linecount = 0
-    f = cStringIO.StringIO(msg)
+    f = io.StringIO(msg)
     getMIMEMsg(multifile.MultiFile(f))
     assert boundaries == 2
     assert linecount == 9
diff --git a/Lib/test/test_optparse.py b/Lib/test/test_optparse.py
index 2bae0a6..1cfdd50 100644
--- a/Lib/test/test_optparse.py
+++ b/Lib/test/test_optparse.py
@@ -14,7 +14,7 @@
 import copy
 import unittest
 
-from StringIO import StringIO
+from io import StringIO
 from pprint import pprint
 from test import test_support
 
@@ -157,12 +157,9 @@
                      expected_error=None):
         """Assert the parser prints the expected output on stdout."""
         save_stdout = sys.stdout
-        encoding = getattr(save_stdout, 'encoding', None)
         try:
             try:
                 sys.stdout = StringIO()
-                if encoding:
-                    sys.stdout.encoding = encoding
                 self.parser.parse_args(cmdline_args)
             finally:
                 output = sys.stdout.getvalue()
diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py
index 28ad055..faa5523 100644
--- a/Lib/test/test_peepholer.py
+++ b/Lib/test/test_peepholer.py
@@ -1,6 +1,6 @@
 import dis
 import sys
-from cStringIO import StringIO
+from io import StringIO
 import unittest
 
 def disassemble(func):
diff --git a/Lib/test/test_rfc822.py b/Lib/test/test_rfc822.py
index c355950..b563c9c 100644
--- a/Lib/test/test_rfc822.py
+++ b/Lib/test/test_rfc822.py
@@ -4,9 +4,9 @@
 from test import test_support
 
 try:
-    from cStringIO import StringIO
+    from io import StringIO
 except ImportError:
-    from StringIO import StringIO
+    from io import StringIO
 
 
 class MessageTestCase(unittest.TestCase):
diff --git a/Lib/test/test_robotparser.py b/Lib/test/test_robotparser.py
index 666d00a..e1e8055 100644
--- a/Lib/test/test_robotparser.py
+++ b/Lib/test/test_robotparser.py
@@ -1,4 +1,5 @@
-import unittest, StringIO, robotparser
+import unittest, robotparser
+import io
 from test import test_support
 
 class RobotTestCase(unittest.TestCase):
@@ -32,7 +33,7 @@
 def RobotTest(index, robots_txt, good_urls, bad_urls,
               agent="test_robotparser"):
 
-    lines = StringIO.StringIO(robots_txt).readlines()
+    lines = io.StringIO(robots_txt).readlines()
     parser = robotparser.RobotFileParser()
     parser.parse(lines)
     for url in good_urls:
diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py
index 0d76cbb..e2639fa 100644
--- a/Lib/test/test_sax.py
+++ b/Lib/test/test_sax.py
@@ -12,7 +12,7 @@
                              XMLFilterBase
 from xml.sax.expatreader import create_parser
 from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl
-from cStringIO import StringIO
+from io import StringIO
 from test.test_support import findfile, run_unittest
 import unittest
 import os
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index 7d7a09b..d9adf02 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -1,13 +1,13 @@
 # -*- coding: iso-8859-1 -*-
 import unittest, test.test_support
-import sys, cStringIO
+import sys, io
 
 class SysModuleTest(unittest.TestCase):
 
     def test_original_displayhook(self):
         import __builtin__
         savestdout = sys.stdout
-        out = cStringIO.StringIO()
+        out = io.StringIO()
         sys.stdout = out
 
         dh = sys.__displayhook__
@@ -46,7 +46,7 @@
 
     def test_original_excepthook(self):
         savestderr = sys.stderr
-        err = cStringIO.StringIO()
+        err = io.StringIO()
         sys.stderr = err
 
         eh = sys.__excepthook__
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
index ea32ef5..0585131 100644
--- a/Lib/test/test_tarfile.py
+++ b/Lib/test/test_tarfile.py
@@ -3,7 +3,7 @@
 import io
 import shutil
 import tempfile
-import StringIO
+import io
 from hashlib import md5
 import errno
 
@@ -897,15 +897,15 @@
         self._test()
 
     def test_empty_fileobj(self):
-        fobj = StringIO.StringIO()
+        fobj = io.BytesIO()
         self._add_testfile(fobj)
         fobj.seek(0)
         self._test(fileobj=fobj)
 
     def test_fileobj(self):
         self._create_testtar()
-        data = open(self.tarname).read()
-        fobj = StringIO.StringIO(data)
+        data = open(self.tarname, "rb").read()
+        fobj = io.BytesIO(data)
         self._add_testfile(fobj)
         fobj.seek(0)
         self._test(names=["foo", "bar"], fileobj=fobj)
diff --git a/Lib/test/test_threadedtempfile.py b/Lib/test/test_threadedtempfile.py
index 753f388..cde15b4 100644
--- a/Lib/test/test_threadedtempfile.py
+++ b/Lib/test/test_threadedtempfile.py
@@ -22,7 +22,7 @@
 
 from test.test_support import threading_setup, threading_cleanup, run_unittest
 import unittest
-import StringIO
+import io
 from traceback import print_exc
 
 startEvent = threading.Event()
@@ -32,7 +32,7 @@
     ok_count = 0
 
     def run(self):
-        self.errors = StringIO.StringIO()
+        self.errors = io.StringIO()
         startEvent.wait()
         for i in range(FILES_PER_THREAD):
             try:
diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py
index e3e6de2..91d6ba7 100644
--- a/Lib/test/test_urllib2.py
+++ b/Lib/test/test_urllib2.py
@@ -2,7 +2,7 @@
 from test import test_support
 
 import os, socket
-import StringIO
+import io
 
 import urllib2
 from urllib2 import Request, OpenerDirector
@@ -236,9 +236,9 @@
     def getheaders(self, name):
         return list(self.values())
 
-class MockResponse(StringIO.StringIO):
+class MockResponse(io.StringIO):
     def __init__(self, code, msg, headers, data, url=None):
-        StringIO.StringIO.__init__(self, data)
+        io.StringIO.__init__(self, data)
         self.code, self.msg, self.headers, self.url = code, msg, headers, url
     def info(self):
         return self.headers
@@ -353,7 +353,7 @@
         self.requests = []
     def http_open(self, req):
         import mimetools, httplib, copy
-        from StringIO import StringIO
+        from io import StringIO
         self.requests.append(copy.deepcopy(req))
         if self._count == 0:
             self._count = self._count + 1
@@ -546,7 +546,7 @@
             def __init__(self, data): self.data = data
             def retrfile(self, filename, filetype):
                 self.filename, self.filetype = filename, filetype
-                return StringIO.StringIO(self.data), len(self.data)
+                return io.StringIO(self.data), len(self.data)
 
         class NullFTPHandler(urllib2.FTPHandler):
             def __init__(self, data): self.data = data
diff --git a/Lib/test/test_uu.py b/Lib/test/test_uu.py
index 181e361..4723174 100644
--- a/Lib/test/test_uu.py
+++ b/Lib/test/test_uu.py
@@ -6,47 +6,50 @@
 import unittest
 from test import test_support
 
-import sys, os, uu, cStringIO
+import sys, os
 import uu
-from StringIO import StringIO
+from io import BytesIO
+import io
 
-plaintext = "The smooth-scaled python crept over the sleeping dog\n"
+plaintext = b"The smooth-scaled python crept over the sleeping dog\n"
 
-encodedtext = """\
+encodedtext = b"""\
 M5&AE('-M;V]T:\"US8V%L960@<'ET:&]N(&-R97!T(&]V97(@=&AE('-L965P
 (:6YG(&1O9PH """
 
-encodedtextwrapped = "begin %03o %s\n" + encodedtext.replace("%", "%%") + "\n \nend\n"
+def encodedtextwrapped(mode, filename):
+    return (bytes("begin %03o %s\n" % (mode, filename), "ascii") +
+            encodedtext + b"\n \nend\n")
 
 class UUTest(unittest.TestCase):
 
     def test_encode(self):
-        inp = cStringIO.StringIO(plaintext)
-        out = cStringIO.StringIO()
+        inp = io.BytesIO(plaintext)
+        out = io.BytesIO()
         uu.encode(inp, out, "t1")
-        self.assertEqual(out.getvalue(), encodedtextwrapped % (0o666, "t1"))
-        inp = cStringIO.StringIO(plaintext)
-        out = cStringIO.StringIO()
+        self.assertEqual(out.getvalue(), encodedtextwrapped(0o666, "t1"))
+        inp = io.BytesIO(plaintext)
+        out = io.BytesIO()
         uu.encode(inp, out, "t1", 0o644)
-        self.assertEqual(out.getvalue(), encodedtextwrapped % (0o644, "t1"))
+        self.assertEqual(out.getvalue(), encodedtextwrapped(0o644, "t1"))
 
     def test_decode(self):
-        inp = cStringIO.StringIO(encodedtextwrapped % (0o666, "t1"))
-        out = cStringIO.StringIO()
+        inp = io.BytesIO(encodedtextwrapped(0o666, "t1"))
+        out = io.BytesIO()
         uu.decode(inp, out)
         self.assertEqual(out.getvalue(), plaintext)
-        inp = cStringIO.StringIO(
-            "UUencoded files may contain many lines,\n" +
-            "even some that have 'begin' in them.\n" +
-            encodedtextwrapped % (0o666, "t1")
+        inp = io.BytesIO(
+            b"UUencoded files may contain many lines,\n" +
+            b"even some that have 'begin' in them.\n" +
+            encodedtextwrapped(0o666, "t1")
         )
-        out = cStringIO.StringIO()
+        out = io.BytesIO()
         uu.decode(inp, out)
         self.assertEqual(out.getvalue(), plaintext)
 
     def test_truncatedinput(self):
-        inp = cStringIO.StringIO("begin 644 t1\n" + encodedtext)
-        out = cStringIO.StringIO()
+        inp = io.BytesIO(b"begin 644 t1\n" + encodedtext)
+        out = io.BytesIO()
         try:
             uu.decode(inp, out)
             self.fail("No exception thrown")
@@ -54,8 +57,8 @@
             self.assertEqual(str(e), "Truncated input file")
 
     def test_missingbegin(self):
-        inp = cStringIO.StringIO("")
-        out = cStringIO.StringIO()
+        inp = io.BytesIO(b"")
+        out = io.BytesIO()
         try:
             uu.decode(inp, out)
             self.fail("No exception thrown")
@@ -73,24 +76,27 @@
         sys.stdout = self.stdout
 
     def test_encode(self):
-        sys.stdin = cStringIO.StringIO(plaintext)
-        sys.stdout = cStringIO.StringIO()
+        sys.stdin = io.StringIO(plaintext.decode("ascii"))
+        sys.stdout = io.StringIO()
         uu.encode("-", "-", "t1", 0o666)
-        self.assertEqual(
-            sys.stdout.getvalue(),
-            encodedtextwrapped % (0o666, "t1")
-        )
+        self.assertEqual(sys.stdout.getvalue(),
+                         encodedtextwrapped(0o666, "t1").decode("ascii"))
 
     def test_decode(self):
-        sys.stdin = cStringIO.StringIO(encodedtextwrapped % (0o666, "t1"))
-        sys.stdout = cStringIO.StringIO()
+        sys.stdin = io.StringIO(encodedtextwrapped(0o666, "t1").decode("ascii"))
+        sys.stdout = io.StringIO()
         uu.decode("-", "-")
-        self.assertEqual(sys.stdout.getvalue(), plaintext)
+        stdout = sys.stdout
+        sys.stdout = self.stdout
+        sys.stdin = self.stdin
+        self.assertEqual(stdout.getvalue(), plaintext.decode("ascii"))
 
 class UUFileTest(unittest.TestCase):
 
     def _kill(self, f):
         # close and remove file
+        if f is None:
+            return
         try:
             f.close()
         except (SystemExit, KeyboardInterrupt):
@@ -113,44 +119,46 @@
         del self.tmpout
 
     def test_encode(self):
+        fin = fout = None
         try:
             fin = open(self.tmpin, 'wb')
             fin.write(plaintext)
             fin.close()
 
             fin = open(self.tmpin, 'rb')
-            fout = open(self.tmpout, 'w')
+            fout = open(self.tmpout, 'wb')
             uu.encode(fin, fout, self.tmpin, mode=0o644)
             fin.close()
             fout.close()
 
-            fout = open(self.tmpout, 'r')
+            fout = open(self.tmpout, 'rb')
             s = fout.read()
             fout.close()
-            self.assertEqual(s, encodedtextwrapped % (0o644, self.tmpin))
+            self.assertEqual(s, encodedtextwrapped(0o644, self.tmpin))
 
             # in_file and out_file as filenames
             uu.encode(self.tmpin, self.tmpout, self.tmpin, mode=0o644)
-            fout = open(self.tmpout, 'r')
+            fout = open(self.tmpout, 'rb')
             s = fout.read()
             fout.close()
-            self.assertEqual(s, encodedtextwrapped % (0o644, self.tmpin))
+            self.assertEqual(s, encodedtextwrapped(0o644, self.tmpin))
 
         finally:
             self._kill(fin)
             self._kill(fout)
 
     def test_decode(self):
+        f = None
         try:
-            f = open(self.tmpin, 'w')
-            f.write(encodedtextwrapped % (0o644, self.tmpout))
+            f = open(self.tmpin, 'wb')
+            f.write(encodedtextwrapped(0o644, self.tmpout))
             f.close()
 
-            f = open(self.tmpin, 'r')
+            f = open(self.tmpin, 'rb')
             uu.decode(f)
             f.close()
 
-            f = open(self.tmpout, 'r')
+            f = open(self.tmpout, 'rb')
             s = f.read()
             f.close()
             self.assertEqual(s, plaintext)
@@ -160,21 +168,25 @@
 
     def test_decodetwice(self):
         # Verify that decode() will refuse to overwrite an existing file
+        f = None
         try:
-            f = cStringIO.StringIO(encodedtextwrapped % (0o644, self.tmpout))
+            f = io.BytesIO(encodedtextwrapped(0o644, self.tmpout))
 
-            f = open(self.tmpin, 'r')
+            f = open(self.tmpin, 'rb')
             uu.decode(f)
             f.close()
 
-            f = open(self.tmpin, 'r')
+            f = open(self.tmpin, 'rb')
             self.assertRaises(uu.Error, uu.decode, f)
             f.close()
         finally:
             self._kill(f)
 
 def test_main():
-    test_support.run_unittest(UUTest, UUStdIOTest, UUFileTest)
+    test_support.run_unittest(UUTest,
+                              UUStdIOTest,
+                              UUFileTest,
+                              )
 
 if __name__=="__main__":
     test_main()
diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
index 1c5edd0..c8dd344 100644
--- a/Lib/test/test_xml_etree.py
+++ b/Lib/test/test_xml_etree.py
@@ -39,14 +39,11 @@
     if not hasattr(method, '__call__'):
         print(method, "not callable")
 
-def serialize(ET, elem, encoding=None):
-    import StringIO
-    file = StringIO.StringIO()
+def serialize(ET, elem):
+    import io
     tree = ET.ElementTree(elem)
-    if encoding:
-        tree.write(file, encoding)
-    else:
-        tree.write(file)
+    file = io.StringIO()
+    tree.write(file)
     return file.getvalue()
 
 def summarize(elem):
diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py
index 49cdfde..22d2662 100644
--- a/Lib/test/test_xml_etree_c.py
+++ b/Lib/test/test_xml_etree_c.py
@@ -37,14 +37,11 @@
     if not hasattr(method, '__call__'):
         print(method, "not callable")
 
-def serialize(ET, elem, encoding=None):
-    import StringIO
-    file = StringIO.StringIO()
+def serialize(ET, elem):
+    import io
+    file = io.StringIO()
     tree = ET.ElementTree(elem)
-    if encoding:
-        tree.write(file, encoding)
-    else:
-        tree.write(file)
+    tree.write(file)
     return file.getvalue()
 
 def summarize(elem):
diff --git a/Lib/test/test_zipfile64.py b/Lib/test/test_zipfile64.py
index dedce4a..a008fd0 100644
--- a/Lib/test/test_zipfile64.py
+++ b/Lib/test/test_zipfile64.py
@@ -20,7 +20,7 @@
 import time
 import sys
 
-from StringIO import StringIO
+from io import StringIO
 from tempfile import TemporaryFile
 
 from test.test_support import TESTFN, run_unittest
diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py
index bae2172..f36cbf4 100644
--- a/Lib/test/test_zipimport.py
+++ b/Lib/test/test_zipimport.py
@@ -15,7 +15,7 @@
 import linecache
 import doctest
 import inspect
-import StringIO
+import io
 from traceback import extract_tb, extract_stack, print_tb
 raise_src = 'def do_raise(): raise TypeError\n'
 
@@ -314,7 +314,7 @@
             f,lno,n,line = extract_stack(tb.tb_frame, 1)[0]
             self.assertEqual(line, raise_src.strip())
 
-            s = StringIO.StringIO()
+            s = io.StringIO()
             print_tb(tb, 1, s)
             self.failUnless(s.getvalue().endswith(raise_src))
         else: