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/xml/dom/pulldom.py b/Lib/xml/dom/pulldom.py
index c1463c91..c15618f 100644
--- a/Lib/xml/dom/pulldom.py
+++ b/Lib/xml/dom/pulldom.py
@@ -335,9 +335,9 @@
 
 def parseString(string, parser=None):
     try:
-        from cStringIO import StringIO
+        from io import StringIO
     except ImportError:
-        from StringIO import StringIO
+        from io import StringIO
 
     bufsize = len(string)
     buf = StringIO(string)
diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py
index 2fba177..782af81 100644
--- a/Lib/xml/etree/ElementTree.py
+++ b/Lib/xml/etree/ElementTree.py
@@ -625,15 +625,16 @@
     # Writes the element tree to a file, as XML.
     #
     # @param file A file name, or a file object opened for writing.
-    # @param encoding Optional output encoding (default is US-ASCII).
+    # @param encoding Optional output encoding (default is None)
 
-    def write(self, file, encoding="us-ascii"):
+    def write(self, file, encoding=None):
         assert self._root is not None
         if not hasattr(file, "write"):
-            file = open(file, "wb")
-        if not encoding:
-            encoding = "us-ascii"
-        elif encoding != "utf-8" and encoding != "us-ascii":
+            if encoding:
+                file = open(file, "wb")
+            else:
+                file = open(file, "w")
+        if encoding and encoding != "utf-8":
             file.write(_encode("<?xml version='1.0' encoding='%s'?>\n" % encoding, encoding))
         self._write(file, self._root, encoding, {})
 
@@ -720,10 +721,10 @@
         sys.stdout.write("\n")
 
 def _encode(s, encoding):
-    try:
+    if encoding:
         return s.encode(encoding)
-    except AttributeError:
-        return s # 1.5.2: assume the string uses the right encoding
+    else:
+        return s
 
 _escape = re.compile(r"[&<>\"\u0080-\uffff]+")
 
@@ -954,10 +955,11 @@
 
 ##
 # Generates a string representation of an XML element, including all
-# subelements.
+# subelements.  If encoding is None, the return type is a string;
+# otherwise it is a bytes array.
 #
 # @param element An Element instance.
-# @return An encoded string containing the XML data.
+# @return An (optionally) encoded string containing the XML data.
 # @defreturn string
 
 def tostring(element, encoding=None):
@@ -967,7 +969,10 @@
     file = dummy()
     file.write = data.append
     ElementTree(element).write(file, encoding)
-    return b"".join(data)
+    if encoding:
+        return b"".join(data)
+    else:
+        return "".join(data)
 
 ##
 # Generic element structure builder.  This builder converts a sequence
diff --git a/Lib/xml/sax/__init__.py b/Lib/xml/sax/__init__.py
index 242c689..b161b1f 100644
--- a/Lib/xml/sax/__init__.py
+++ b/Lib/xml/sax/__init__.py
@@ -33,10 +33,7 @@
     parser.parse(source)
 
 def parseString(string, handler, errorHandler=ErrorHandler()):
-    try:
-        from cStringIO import StringIO
-    except ImportError:
-        from StringIO import StringIO
+    from io import BytesIO
 
     if errorHandler is None:
         errorHandler = ErrorHandler()
@@ -45,7 +42,7 @@
     parser.setErrorHandler(errorHandler)
 
     inpsrc = InputSource()
-    inpsrc.setByteStream(StringIO(string))
+    inpsrc.setByteStream(BytesIO(string))
     parser.parse(inpsrc)
 
 # this is the parser list used by the make_parser function if no