Permalink
Browse files

Replaced cStringIO.StringIO by io.BytesIO.

Also replaced StringIO.StringIO by BytesIO in some other appropriate
places. StringIO is not available in Python 3.
  • Loading branch information...
1 parent 1583d40 commit d7dfab59ead97b35c6f6786784225f377783e376 @claudep claudep committed May 5, 2012
@@ -203,12 +203,12 @@ def test01i_json(self):
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
@@ -1,16 +1,13 @@
-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
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()
@@ -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 @@ def test_geositemap_kml(self):
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)
@@ -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 @@ def __iter__(self):
# 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,10 +3,7 @@
"""
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):
@@ -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 @@ def handle_raw_input(self, input_data, META, content_length, boundary, encoding=
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)
@@ -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 @@ def readline(self, size=None):
if not chunk:
break
self.buffer += chunk
- sio = StringIO(self.buffer)
+ sio = BytesIO(self.buffer)
if size:
line = sio.readline(size)
else:
@@ -9,15 +9,12 @@
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 @@ def as_string(self, unixfrom=False):
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 @@ def as_string(self, unixfrom=False):
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()
@@ -6,6 +6,7 @@
import os
import sys
+from io import BytesIO
from optparse import make_option, OptionParser
import traceback
@@ -258,11 +259,7 @@ def validate(self, app=None, display_num_errors=False):
"""
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)
@@ -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 @@ def serialize(self, queryset, **options):
"""
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 @@ def __init__(self, stream_or_string, **options):
"""
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
@@ -8,7 +8,7 @@
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:
@@ -4,9 +4,9 @@
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:
@@ -10,10 +10,7 @@
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 @@ def to_python(self, data):
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,
@@ -7,13 +7,10 @@
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 @@ def body(self):
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 @@ def _load_post_and_files(self):
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 @@ def _load_post_and_files(self):
## 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):
View
@@ -4,11 +4,8 @@
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 @@
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)
@ondrowan
ondrowan Oct 9, 2012

Don't really want to open new ticket until I'm sure, but shouldn't this be StringIO in case content is unicode? Or will that be part of patch from ticket #11739 at some point?

@claudep
claudep Oct 9, 2012 Member

At first, I'd say that FakePayload would only expect a bytestring in the content argument. But your comment gave me an idea about a slightly better implementation which would also accept unicode content. Feel free to open a ticket, and I might upload a patch.

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):
"""
@@ -174,8 +174,8 @@ def writeString(self, encoding):
"""
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()
Oops, something went wrong.

2 comments on commit d7dfab5

@dswarbrick

Does this still pass tests? I would have thought that since Django liberally uses unicode, there would be TypeError exceptions where unicode strings were written to a BytesIO object without first being encode('utf_8') 'ed. The old StringIO.StringIO() supported unicode string assignment, whereas cStringIO.StringIO() did not. Since it appears that all of these files attempted to import cStringIO, I'm going to cautiously assume that there were no unicode writes happening. And yes, I do see the byte literal string prefixes, but since Django pulls strings out of DBs as unicode, I wonder if there are any situations where that string content could end up being written to a BytesIO object.

@claudep
Member
claudep commented on d7dfab5 May 6, 2012

See https://code.djangoproject.com/ticket/11739. Let's discuss it on the ticket (and yes, I should update the patch on this ticket).

Please sign in to comment.