Browse Source

Replaced cStringIO.StringIO by io.BytesIO.

Also replaced StringIO.StringIO by BytesIO in some other appropriate
places. StringIO is not available in Python 3.
Claude Paroz 13 years ago
parent
commit
d7dfab59ea

+ 3 - 3
django/contrib/gis/geos/tests/test_geos.py

@@ -203,12 +203,12 @@ class GEOSTest(unittest.TestCase, TestDataMixin):
 
     def test01k_fromfile(self):
         "Testing the fromfile() factory."
-        from StringIO import StringIO
+        from io import BytesIO
         ref_pnt = GEOSGeometry('POINT(5 23)')
 
-        wkt_f = StringIO()
+        wkt_f = BytesIO()
         wkt_f.write(ref_pnt.wkt)
-        wkb_f = StringIO()
+        wkb_f = BytesIO()
         wkb_f.write(str(ref_pnt.wkb))
 
         # Other tests use `fromfile()` on string filenames so those

+ 2 - 5
django/contrib/gis/shortcuts.py

@@ -1,8 +1,5 @@
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from StringIO import StringIO
 import zipfile
+from io import BytesIO
 
 from django.conf import settings
 from django.http import HttpResponse
@@ -10,7 +7,7 @@ from django.template import loader
 
 def compress_kml(kml):
     "Returns compressed KMZ from the given KML string."
-    kmz = StringIO()
+    kmz = BytesIO()
     zf = zipfile.ZipFile(kmz, 'a', zipfile.ZIP_DEFLATED)
     zf.writestr('doc.kml', kml.encode(settings.DEFAULT_CHARSET))
     zf.close()

+ 2 - 5
django/contrib/gis/tests/geoapp/test_sitemaps.py

@@ -1,9 +1,6 @@
 from __future__ import absolute_import
 
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from StringIO import StringIO
+from io import BytesIO
 from xml.dom import minidom
 import zipfile
 
@@ -66,7 +63,7 @@ class GeoSitemapTest(TestCase):
                     kml_doc = minidom.parseString(self.client.get(kml_url).content)
                 elif kml_type == 'kmz':
                     # Have to decompress KMZ before parsing.
-                    buf = StringIO(self.client.get(kml_url).content)
+                    buf = BytesIO(self.client.get(kml_url).content)
                     zf = zipfile.ZipFile(buf)
                     self.assertEqual(1, len(zf.filelist))
                     self.assertEqual('doc.kml', zf.filelist[0].filename)

+ 2 - 5
django/core/files/base.py

@@ -1,8 +1,5 @@
 import os
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from StringIO import StringIO
+from io import BytesIO, StringIO
 
 from django.utils.encoding import smart_str, smart_unicode
 from django.core.files.utils import FileProxyMixin
@@ -89,7 +86,7 @@ class File(FileProxyMixin):
         # Iterate over this file-like object by newlines
         buffer_ = None
         for chunk in self.chunks():
-            chunk_buffer = StringIO(chunk)
+            chunk_buffer = BytesIO(chunk)
 
             for line in chunk_buffer:
                 if buffer_:

+ 3 - 6
django/core/files/uploadedfile.py

@@ -3,10 +3,7 @@ Classes representing uploaded files.
 """
 
 import os
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from StringIO import StringIO
+from io import BytesIO
 
 from django.conf import settings
 from django.core.files.base import File
@@ -110,8 +107,8 @@ class SimpleUploadedFile(InMemoryUploadedFile):
     A simple representation of a file, which just has content, size, and a name.
     """
     def __init__(self, name, content, content_type='text/plain'):
-        content = content or ''
-        super(SimpleUploadedFile, self).__init__(StringIO(content), None, name,
+        content = content or b''
+        super(SimpleUploadedFile, self).__init__(BytesIO(content), None, name,
                                                  content_type, len(content), None)
 
     def from_dict(cls, file_dict):

+ 3 - 6
django/core/files/uploadhandler.py

@@ -2,10 +2,7 @@
 Base file upload handler classes, and the built-in concrete subclasses
 """
 
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from StringIO import StringIO
+from io import BytesIO
 
 from django.conf import settings
 from django.core.exceptions import ImproperlyConfigured
@@ -161,12 +158,12 @@ class MemoryFileUploadHandler(FileUploadHandler):
     def new_file(self, *args, **kwargs):
         super(MemoryFileUploadHandler, self).new_file(*args, **kwargs)
         if self.activated:
-            self.file = StringIO()
+            self.file = BytesIO()
             raise StopFutureHandlers()
 
     def receive_data_chunk(self, raw_data, start):
         """
-        Add the data to the StringIO file.
+        Add the data to the BytesIO file.
         """
         if self.activated:
             self.file.write(raw_data)

+ 2 - 5
django/core/handlers/wsgi.py

@@ -1,9 +1,6 @@
 import sys
+from io import BytesIO
 from threading import Lock
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from StringIO import StringIO
 
 from django import http
 from django.core import signals
@@ -116,7 +113,7 @@ class LimitedStream(object):
             if not chunk:
                 break
             self.buffer += chunk
-        sio = StringIO(self.buffer)
+        sio = BytesIO(self.buffer)
         if size:
             line = sio.readline(size)
         else:

+ 3 - 6
django/core/mail/message.py

@@ -9,15 +9,12 @@ from email.mime.multipart import MIMEMultipart
 from email.mime.base import MIMEBase
 from email.header import Header
 from email.utils import formatdate, getaddresses, formataddr, parseaddr
+from io import BytesIO
 
 from django.conf import settings
 from django.core.mail.utils import DNS_NAME
 from django.utils.encoding import smart_str, force_unicode
 
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from StringIO import StringIO
 
 # Don't BASE64-encode UTF-8 messages so that we avoid unwanted attention from
 # some spam filters.
@@ -132,7 +129,7 @@ class SafeMIMEText(MIMEText):
         This overrides the default as_string() implementation to not mangle
         lines that begin with 'From '. See bug #13433 for details.
         """
-        fp = StringIO()
+        fp = BytesIO()
         g = Generator(fp, mangle_from_ = False)
         g.flatten(self, unixfrom=unixfrom)
         return fp.getvalue()
@@ -156,7 +153,7 @@ class SafeMIMEMultipart(MIMEMultipart):
         This overrides the default as_string() implementation to not mangle
         lines that begin with 'From '. See bug #13433 for details.
         """
-        fp = StringIO()
+        fp = BytesIO()
         g = Generator(fp, mangle_from_ = False)
         g.flatten(self, unixfrom=unixfrom)
         return fp.getvalue()

+ 2 - 5
django/core/management/base.py

@@ -6,6 +6,7 @@ be executed through ``django-admin.py`` or ``manage.py``).
 import os
 import sys
 
+from io import BytesIO
 from optparse import make_option, OptionParser
 import traceback
 
@@ -258,11 +259,7 @@ class BaseCommand(object):
 
         """
         from django.core.management.validation import get_validation_errors
-        try:
-            from cStringIO import StringIO
-        except ImportError:
-            from StringIO import StringIO
-        s = StringIO()
+        s = BytesIO()
         num_errors = get_validation_errors(s, app)
         if num_errors:
             s.seek(0)

+ 3 - 3
django/core/serializers/base.py

@@ -2,7 +2,7 @@
 Module for abstract serializer/unserializer base classes.
 """
 
-from StringIO import StringIO
+from io import BytesIO
 
 from django.db import models
 from django.utils.encoding import smart_unicode
@@ -34,7 +34,7 @@ class Serializer(object):
         """
         self.options = options
 
-        self.stream = options.pop("stream", StringIO())
+        self.stream = options.pop("stream", BytesIO())
         self.selected_fields = options.pop("fields", None)
         self.use_natural_keys = options.pop("use_natural_keys", False)
 
@@ -121,7 +121,7 @@ class Deserializer(object):
         """
         self.options = options
         if isinstance(stream_or_string, basestring):
-            self.stream = StringIO(stream_or_string)
+            self.stream = BytesIO(stream_or_string)
         else:
             self.stream = stream_or_string
         # hack to make sure that the models have all been loaded before

+ 2 - 2
django/core/serializers/json.py

@@ -8,7 +8,7 @@ from __future__ import absolute_import
 import datetime
 import decimal
 import json
-from StringIO import StringIO
+from io import BytesIO
 
 from django.core.serializers.base import DeserializationError
 from django.core.serializers.python import Serializer as PythonSerializer
@@ -37,7 +37,7 @@ def Deserializer(stream_or_string, **options):
     Deserialize a stream or string of JSON data.
     """
     if isinstance(stream_or_string, basestring):
-        stream = StringIO(stream_or_string)
+        stream = BytesIO(stream_or_string)
     else:
         stream = stream_or_string
     try:

+ 2 - 2
django/core/serializers/pyyaml.py

@@ -4,9 +4,9 @@ YAML serializer.
 Requires PyYaml (http://pyyaml.org/), but that's checked for in __init__.
 """
 
-from StringIO import StringIO
 import decimal
 import yaml
+from io import BytesIO
 
 from django.db import models
 from django.core.serializers.base import DeserializationError
@@ -49,7 +49,7 @@ def Deserializer(stream_or_string, **options):
     Deserialize a stream or string of YAML data.
     """
     if isinstance(stream_or_string, basestring):
-        stream = StringIO(stream_or_string)
+        stream = BytesIO(stream_or_string)
     else:
         stream = stream_or_string
     try:

+ 3 - 6
django/forms/fields.py

@@ -10,10 +10,7 @@ import os
 import re
 import urlparse
 from decimal import Decimal, DecimalException
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from StringIO import StringIO
+from io import BytesIO
 
 from django.core import validators
 from django.core.exceptions import ValidationError
@@ -554,9 +551,9 @@ class ImageField(FileField):
             file = data.temporary_file_path()
         else:
             if hasattr(data, 'read'):
-                file = StringIO(data.read())
+                file = BytesIO(data.read())
             else:
-                file = StringIO(data['content'])
+                file = BytesIO(data['content'])
 
         try:
             # load() is the only method that can spot a truncated JPEG,

+ 4 - 7
django/http/__init__.py

@@ -7,13 +7,10 @@ import sys
 import time
 import warnings
 
+from io import BytesIO
 from pprint import pformat
 from urllib import urlencode, quote
 from urlparse import urljoin, parse_qsl
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from StringIO import StringIO
 
 import Cookie
 # Some versions of Python 2.7 and later won't need this encoding bug fix:
@@ -292,7 +289,7 @@ class HttpRequest(object):
                 self._body = self.read()
             except IOError as e:
                 raise UnreadablePostError, e, sys.exc_traceback
-            self._stream = StringIO(self._body)
+            self._stream = BytesIO(self._body)
         return self._body
 
     @property
@@ -317,7 +314,7 @@ class HttpRequest(object):
         if self.META.get('CONTENT_TYPE', '').startswith('multipart'):
             if hasattr(self, '_body'):
                 # Use already read data
-                data = StringIO(self._body)
+                data = BytesIO(self._body)
             else:
                 data = self
             try:
@@ -340,7 +337,7 @@ class HttpRequest(object):
     ## Expects self._stream to be set to an appropriate source of bytes by
     ## a corresponding request subclass (e.g. WSGIRequest).
     ## Also when request data has already been read by request.POST or
-    ## request.body, self._stream points to a StringIO instance
+    ## request.body, self._stream points to a BytesIO instance
     ## containing that data.
 
     def read(self, *args, **kwargs):

+ 4 - 7
django/test/client.py

@@ -4,11 +4,8 @@ import os
 import re
 import mimetypes
 from copy import copy
+from io import BytesIO
 from urlparse import urlparse, urlsplit
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from StringIO import StringIO
 
 from django.conf import settings
 from django.contrib.auth import authenticate, login
@@ -35,13 +32,13 @@ CONTENT_TYPE_RE = re.compile('.*; charset=([\w\d-]+);?')
 
 class FakePayload(object):
     """
-    A wrapper around StringIO that restricts what can be read since data from
+    A wrapper around BytesIO that restricts what can be read since data from
     the network can't be seeked and cannot be read outside of its content
     length. This makes sure that views can't do anything under the test client
     that wouldn't work in Real Life.
     """
     def __init__(self, content):
-        self.__content = StringIO(content)
+        self.__content = BytesIO(content)
         self.__len = len(content)
 
     def read(self, num_bytes=None):
@@ -175,7 +172,7 @@ class RequestFactory(object):
     def __init__(self, **defaults):
         self.defaults = defaults
         self.cookies = SimpleCookie()
-        self.errors = StringIO()
+        self.errors = BytesIO()
 
     def _base_environ(self, **request):
         """

+ 2 - 2
django/utils/feedgenerator.py

@@ -174,8 +174,8 @@ class SyndicationFeed(object):
         """
         Returns the feed in the given encoding as a string.
         """
-        from StringIO import StringIO
-        s = StringIO()
+        from io import BytesIO
+        s = BytesIO()
         self.write(s, encoding)
         return s.getvalue()
 

+ 2 - 6
django/utils/text.py

@@ -3,11 +3,7 @@ import unicodedata
 import warnings
 from gzip import GzipFile
 from htmlentitydefs import name2codepoint
-
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from StringIO import StringIO
+from io import BytesIO
 
 from django.utils.encoding import force_unicode
 from django.utils.functional import allow_lazy, SimpleLazyObject
@@ -277,7 +273,7 @@ phone2numeric = allow_lazy(phone2numeric)
 # From http://www.xhaus.com/alan/python/httpcomp.html#gzip
 # Used with permission.
 def compress_string(s):
-    zbuf = StringIO()
+    zbuf = BytesIO()
     zfile = GzipFile(mode='wb', compresslevel=6, fileobj=zbuf)
     zfile.write(s)
     zfile.close()

+ 15 - 19
django/utils/translation/trans_real.py

@@ -5,13 +5,9 @@ import os
 import re
 import sys
 import gettext as gettext_module
+from io import BytesIO
 from threading import local
 
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from StringIO import StringIO
-
 from django.utils.importlib import import_module
 from django.utils.safestring import mark_safe, SafeData
 
@@ -442,7 +438,7 @@ def templatize(src, origin=None):
     """
     from django.template import (Lexer, TOKEN_TEXT, TOKEN_VAR, TOKEN_BLOCK,
             TOKEN_COMMENT, TRANSLATOR_COMMENT_MARK)
-    out = StringIO()
+    out = BytesIO()
     message_context = None
     intrans = False
     inplural = False
@@ -453,16 +449,16 @@ def templatize(src, origin=None):
     for t in Lexer(src, origin).tokenize():
         if incomment:
             if t.token_type == TOKEN_BLOCK and t.contents == 'endcomment':
-                content = ''.join(comment)
+                content = b''.join(comment)
                 translators_comment_start = None
                 for lineno, line in enumerate(content.splitlines(True)):
                     if line.lstrip().startswith(TRANSLATOR_COMMENT_MARK):
                         translators_comment_start = lineno
                 for lineno, line in enumerate(content.splitlines(True)):
                     if translators_comment_start is not None and lineno >= translators_comment_start:
-                        out.write(' # %s' % line)
+                        out.write(b' # %s' % line)
                     else:
-                        out.write(' #\n')
+                        out.write(b' #\n')
                 incomment = False
                 comment = []
             else:
@@ -474,18 +470,18 @@ def templatize(src, origin=None):
                 if endbmatch:
                     if inplural:
                         if message_context:
-                            out.write(' npgettext(%r, %r, %r,count) ' % (message_context, ''.join(singular), ''.join(plural)))
+                            out.write(b' npgettext(%r, %r, %r,count) ' % (message_context, ''.join(singular), ''.join(plural)))
                         else:
-                            out.write(' ngettext(%r, %r, count) ' % (''.join(singular), ''.join(plural)))
+                            out.write(b' ngettext(%r, %r, count) ' % (''.join(singular), ''.join(plural)))
                         for part in singular:
                             out.write(blankout(part, 'S'))
                         for part in plural:
                             out.write(blankout(part, 'P'))
                     else:
                         if message_context:
-                            out.write(' pgettext(%r, %r) ' % (message_context, ''.join(singular)))
+                            out.write(b' pgettext(%r, %r) ' % (message_context, ''.join(singular)))
                         else:
-                            out.write(' gettext(%r) ' % ''.join(singular))
+                            out.write(b' gettext(%r) ' % ''.join(singular))
                         for part in singular:
                             out.write(blankout(part, 'S'))
                     message_context = None
@@ -531,10 +527,10 @@ def templatize(src, origin=None):
                             message_context = message_context.strip('"')
                         elif message_context[0] == "'":
                             message_context = message_context.strip("'")
-                        out.write(' pgettext(%r, %r) ' % (message_context, g))
+                        out.write(b' pgettext(%r, %r) ' % (message_context, g))
                         message_context = None
                     else:
-                        out.write(' gettext(%r) ' % g)
+                        out.write(b' gettext(%r) ' % g)
                 elif bmatch:
                     for fmatch in constant_re.findall(t.contents):
                         out.write(' _(%s) ' % fmatch)
@@ -552,7 +548,7 @@ def templatize(src, origin=None):
                     plural = []
                 elif cmatches:
                     for cmatch in cmatches:
-                        out.write(' _(%s) ' % cmatch)
+                        out.write(b' _(%s) ' % cmatch)
                 elif t.contents == 'comment':
                     incomment = True
                 else:
@@ -561,14 +557,14 @@ def templatize(src, origin=None):
                 parts = t.contents.split('|')
                 cmatch = constant_re.match(parts[0])
                 if cmatch:
-                    out.write(' _(%s) ' % cmatch.group(1))
+                    out.write(b' _(%s) ' % cmatch.group(1))
                 for p in parts[1:]:
                     if p.find(':_(') >= 0:
-                        out.write(' %s ' % p.split(':',1)[1])
+                        out.write(b' %s ' % p.split(':',1)[1])
                     else:
                         out.write(blankout(p, 'F'))
             elif t.token_type == TOKEN_COMMENT:
-                out.write(' # %s' % t.contents)
+                out.write(b' # %s' % t.contents)
             else:
                 out.write(blankout(t.contents, 'X'))
     return out.getvalue()

+ 6 - 10
docs/howto/outputting-pdf.txt

@@ -104,15 +104,11 @@ Complex PDFs
 ============
 
 If you're creating a complex PDF document with ReportLab, consider using the
-:mod:`cStringIO` library as a temporary holding place for your PDF file. This
+:mod:`io` library as a temporary holding place for your PDF file. This
 library provides a file-like object interface that is particularly efficient.
-Here's the above "Hello World" example rewritten to use :mod:`cStringIO`::
+Here's the above "Hello World" example rewritten to use :mod:`io`::
 
-    # Fall back to StringIO in environments where cStringIO is not available
-    try:
-        from cStringIO import StringIO
-    except ImportError:
-        from StringIO import StringIO
+    from io import BytesIO
     from reportlab.pdfgen import canvas
     from django.http import HttpResponse
 
@@ -121,9 +117,9 @@ Here's the above "Hello World" example rewritten to use :mod:`cStringIO`::
         response = HttpResponse(mimetype='application/pdf')
         response['Content-Disposition'] = 'attachment; filename=somefilename.pdf'
 
-        buffer = StringIO()
+        buffer = BytesIO()
 
-        # Create the PDF object, using the StringIO object as its "file."
+        # Create the PDF object, using the BytesIO object as its "file."
         p = canvas.Canvas(buffer)
 
         # Draw things on the PDF. Here's where the PDF generation happens.
@@ -134,7 +130,7 @@ Here's the above "Hello World" example rewritten to use :mod:`cStringIO`::
         p.showPage()
         p.save()
 
-        # Get the value of the StringIO buffer and write it to the response.
+        # Get the value of the BytesIO buffer and write it to the response.
         pdf = buffer.getvalue()
         buffer.close()
         response.write(pdf)

+ 2 - 2
tests/modeltests/invalid_models/tests.py

@@ -1,6 +1,6 @@
 import copy
 import sys
-from cStringIO import StringIO
+from io import BytesIO
 
 from django.core.management.validation import get_validation_errors
 from django.db.models.loading import cache, load_app
@@ -16,7 +16,7 @@ class InvalidModelTestCase(unittest.TestCase):
         # coloring attached (makes matching the results easier). We restore
         # sys.stderr afterwards.
         self.old_stdout = sys.stdout
-        self.stdout = StringIO()
+        self.stdout = BytesIO()
         sys.stdout = self.stdout
 
         # This test adds dummy applications to the app cache. These

+ 0 - 13
tests/modeltests/model_forms/tests.py

@@ -1372,19 +1372,6 @@ class OldFormForXTests(TestCase):
         self.assertEqual(instance.image.name, 'foo/test4.png')
         instance.delete()
 
-        # Test image field when cStringIO is not available
-        from django.forms import fields
-        from StringIO import StringIO
-        old_StringIO = fields.StringIO
-        fields.StringIO = StringIO
-        try:
-            f = ImageFileForm(
-                data={'description': u'An image'},
-                files={'image': SimpleUploadedFile('test.png', image_data)})
-            self.assertEqual(f.is_valid(), True)
-        finally:
-            fields.StringIO = old_StringIO
-
     def test_media_on_modelform(self):
         # Similar to a regular Form class you can define custom media to be used on
         # the ModelForm.

+ 4 - 7
tests/regressiontests/file_storage/tests.py

@@ -7,10 +7,7 @@ import shutil
 import tempfile
 import time
 from datetime import datetime, timedelta
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from StringIO import StringIO
+from io import BytesIO
 
 try:
     import threading
@@ -483,7 +480,7 @@ class DimensionClosingBug(unittest.TestCase):
         """
         Open files passed into get_image_dimensions() should stay opened.
         """
-        empty_io = StringIO()
+        empty_io = BytesIO()
         try:
             get_image_dimensions(empty_io)
         finally:
@@ -557,10 +554,10 @@ class NoNameFileTestCase(unittest.TestCase):
     urllib.urlopen()
     """
     def test_noname_file_default_name(self):
-        self.assertEqual(File(StringIO('A file with no name')).name, None)
+        self.assertEqual(File(BytesIO(b'A file with no name')).name, None)
 
     def test_noname_file_get_size(self):
-        self.assertEqual(File(StringIO('A file with no name')).size, 19)
+        self.assertEqual(File(BytesIO(b'A file with no name')).size, 19)
 
 class FileLikeObjectTestCase(LiveServerBase):
     """

+ 13 - 16
tests/regressiontests/fixtures_regress/tests.py

@@ -4,10 +4,7 @@ from __future__ import absolute_import
 
 import os
 import re
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from StringIO import StringIO
+from io import BytesIO
 
 from django.core import management
 from django.core.management.base import CommandError
@@ -119,7 +116,7 @@ class TestFixtures(TestCase):
         Test for ticket #4371 -- Loading data of an unknown format should fail
         Validate that error conditions are caught correctly
         """
-        stderr = StringIO()
+        stderr = BytesIO()
         management.call_command(
             'loaddata',
             'bad_fixture1.unkn',
@@ -138,7 +135,7 @@ class TestFixtures(TestCase):
         using explicit filename.
         Validate that error conditions are caught correctly
         """
-        stderr = StringIO()
+        stderr = BytesIO()
         management.call_command(
             'loaddata',
             'bad_fixture2.xml',
@@ -157,7 +154,7 @@ class TestFixtures(TestCase):
         without file extension.
         Validate that error conditions are caught correctly
         """
-        stderr = StringIO()
+        stderr = BytesIO()
         management.call_command(
             'loaddata',
             'bad_fixture2',
@@ -175,7 +172,7 @@ class TestFixtures(TestCase):
         Test for ticket #4371 -- Loading a fixture file with no data returns an error.
         Validate that error conditions are caught correctly
         """
-        stderr = StringIO()
+        stderr = BytesIO()
         management.call_command(
             'loaddata',
             'empty',
@@ -194,7 +191,7 @@ class TestFixtures(TestCase):
         loading is aborted.
         Validate that error conditions are caught correctly
         """
-        stderr = StringIO()
+        stderr = BytesIO()
         management.call_command(
             'loaddata',
             'empty',
@@ -211,7 +208,7 @@ class TestFixtures(TestCase):
         """
         (Regression for #9011 - error message is correct)
         """
-        stderr = StringIO()
+        stderr = BytesIO()
         management.call_command(
             'loaddata',
             'bad_fixture2',
@@ -317,7 +314,7 @@ class TestFixtures(TestCase):
         )
         animal.save()
 
-        stdout = StringIO()
+        stdout = BytesIO()
         management.call_command(
             'dumpdata',
             'fixtures_regress.animal',
@@ -346,7 +343,7 @@ class TestFixtures(TestCase):
         """
         Regression for #11428 - Proxy models aren't included when you dumpdata
         """
-        stdout = StringIO()
+        stdout = BytesIO()
         # Create an instance of the concrete class
         widget = Widget.objects.create(name='grommet')
         management.call_command(
@@ -379,7 +376,7 @@ class TestFixtures(TestCase):
         """
         Regression for #3615 - Ensure data with nonexistent child key references raises error
         """
-        stderr = StringIO()
+        stderr = BytesIO()
         management.call_command(
             'loaddata',
             'forward_ref_bad_data.json',
@@ -414,7 +411,7 @@ class TestFixtures(TestCase):
         """
         Regression for #7043 - Error is quickly reported when no fixtures is provided in the command line.
         """
-        stderr = StringIO()
+        stderr = BytesIO()
         management.call_command(
             'loaddata',
             verbosity=0,
@@ -426,7 +423,7 @@ class TestFixtures(TestCase):
         )
 
     def test_loaddata_not_existant_fixture_file(self):
-        stdout_output = StringIO()
+        stdout_output = BytesIO()
         management.call_command(
             'loaddata',
             'this_fixture_doesnt_exist',
@@ -511,7 +508,7 @@ class NaturalKeyFixtureTests(TestCase):
             commit=False
             )
 
-        stdout = StringIO()
+        stdout = BytesIO()
         management.call_command(
             'dumpdata',
             'fixtures_regress.book',

+ 4 - 7
tests/regressiontests/i18n/commands/compilation.py

@@ -1,8 +1,5 @@
 import os
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from StringIO import StringIO
+from io import BytesIO
 
 from django.core.management import CommandError
 from django.core.management.commands.compilemessages import compile_messages
@@ -31,7 +28,7 @@ class PoFileTests(MessageCompilationTests):
         # We don't use the django.core.management infrastructure (call_command()
         # et al) because CommandError's cause exit(1) there. We test the
         # underlying compile_messages function instead
-        out = StringIO()
+        out = BytesIO()
         self.assertRaises(CommandError, compile_messages, out, locale=self.LOCALE)
         self.assertFalse(os.path.exists(self.MO_FILE))
 
@@ -51,7 +48,7 @@ class PoFileContentsTests(MessageCompilationTests):
         # We don't use the django.core.management infrastructure (call_command()
         # et al) because CommandError's cause exit(1) there. We test the
         # underlying compile_messages function instead
-        out = StringIO()
+        out = BytesIO()
         compile_messages(out, locale=self.LOCALE)
         self.assertTrue(os.path.exists(self.MO_FILE))
 
@@ -70,7 +67,7 @@ class PercentRenderingTests(MessageCompilationTests):
         # We don't use the django.core.management infrastructure (call_command()
         # et al) because CommandError's cause exit(1) there. We test the
         # underlying compile_messages function instead
-        out = StringIO()
+        out = BytesIO()
         compile_messages(out, locale=self.LOCALE)
         with translation.override(self.LOCALE):
             t = Template('{% load i18n %}{% trans "Looks like a str fmt spec %% o but shouldn\'t be interpreted as such" %}')

+ 4 - 7
tests/regressiontests/m2m_through_regress/tests.py

@@ -1,9 +1,6 @@
 from __future__ import absolute_import
 
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from StringIO import StringIO
+from io import BytesIO
 
 from django.core import management
 from django.contrib.auth.models import User
@@ -73,11 +70,11 @@ class M2MThroughTestCase(TestCase):
 
         pks = {"p_pk": p.pk, "g_pk": g.pk, "m_pk": m.pk}
 
-        out = StringIO()
+        out = BytesIO()
         management.call_command("dumpdata", "m2m_through_regress", format="json", stdout=out)
         self.assertEqual(out.getvalue().strip(), """[{"pk": %(m_pk)s, "model": "m2m_through_regress.membership", "fields": {"person": %(p_pk)s, "price": 100, "group": %(g_pk)s}}, {"pk": %(p_pk)s, "model": "m2m_through_regress.person", "fields": {"name": "Bob"}}, {"pk": %(g_pk)s, "model": "m2m_through_regress.group", "fields": {"name": "Roll"}}]""" % pks)
 
-        out = StringIO()
+        out = BytesIO()
         management.call_command("dumpdata", "m2m_through_regress", format="xml",
             indent=2, stdout=out)
         self.assertEqual(out.getvalue().strip(), """
@@ -145,6 +142,6 @@ class ThroughLoadDataTestCase(TestCase):
 
     def test_sequence_creation(self):
         "Check that sequences on an m2m_through are created for the through model, not a phantom auto-generated m2m table. Refs #11107"
-        out = StringIO()
+        out = BytesIO()
         management.call_command("dumpdata", "m2m_through_regress", format="json", stdout=out)
         self.assertEqual(out.getvalue().strip(), """[{"pk": 1, "model": "m2m_through_regress.usermembership", "fields": {"price": 100, "group": 1, "user": 1}}, {"pk": 1, "model": "m2m_through_regress.person", "fields": {"name": "Guido"}}, {"pk": 1, "model": "m2m_through_regress.group", "fields": {"name": "Python Core Group"}}]""")

+ 2 - 5
tests/regressiontests/serializers_regress/tests.py

@@ -10,10 +10,7 @@ from __future__ import absolute_import
 
 import datetime
 import decimal
-try:
-    from cStringIO import StringIO
-except ImportError:
-    from StringIO import StringIO
+from io import BytesIO
 
 try:
     import yaml
@@ -504,7 +501,7 @@ def streamTest(format, self):
     obj.save_base(raw=True)
 
     # Serialize the test database to a stream
-    stream = StringIO()
+    stream = BytesIO()
     serializers.serialize(format, [obj], indent=2, stream=stream)
 
     # Serialize normally for a comparison