Fixed #11739 -- Made ContentFile support Unicode input

This commit is contained in:
Claude Paroz 2012-08-29 09:45:02 +02:00
parent ebc773ada3
commit 361d6738f8
3 changed files with 25 additions and 9 deletions

View File

@ -1,10 +1,11 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import os import os
from io import BytesIO, UnsupportedOperation from io import BytesIO, StringIO, UnsupportedOperation
from django.utils.encoding import smart_text from django.utils.encoding import smart_text
from django.core.files.utils import FileProxyMixin from django.core.files.utils import FileProxyMixin
from django.utils import six
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
@python_2_unicode_compatible @python_2_unicode_compatible
@ -132,7 +133,8 @@ class ContentFile(File):
""" """
def __init__(self, content, name=None): def __init__(self, content, name=None):
content = content or b'' content = content or b''
super(ContentFile, self).__init__(BytesIO(content), name=name) stream_class = StringIO if isinstance(content, six.text_type) else BytesIO
super(ContentFile, self).__init__(stream_class(content), name=name)
self.size = len(content) self.size = len(content)
def __str__(self): def __str__(self):

View File

@ -91,14 +91,18 @@ The ``ContentFile`` Class
.. class:: ContentFile(File) .. class:: ContentFile(File)
The ``ContentFile`` class inherits from :class:`~django.core.files.File`, The ``ContentFile`` class inherits from :class:`~django.core.files.File`,
but unlike :class:`~django.core.files.File` it operates on string content, but unlike :class:`~django.core.files.File` it operates on string content
rather than an actual file. For example:: (bytes also supported), rather than an actual file. For example::
from __future__ import unicode_literals from __future__ import unicode_literals
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
f1 = ContentFile(b"my string content") f1 = ContentFile("esta sentencia está en español")
f2 = ContentFile("my unicode content encoded as UTF-8".encode('UTF-8')) f2 = ContentFile(b"these are bytes")
.. versionchanged:: 1.5
ContentFile also accepts Unicode strings.
.. currentmodule:: django.core.files.images .. currentmodule:: django.core.files.images

View File

@ -21,6 +21,7 @@ from django.core.files.images import get_image_dimensions
from django.core.files.storage import FileSystemStorage, get_storage_class from django.core.files.storage import FileSystemStorage, get_storage_class
from django.core.files.uploadedfile import UploadedFile from django.core.files.uploadedfile import UploadedFile
from django.test import SimpleTestCase from django.test import SimpleTestCase
from django.utils import six
from django.utils import unittest from django.utils import unittest
from ..servers.tests import LiveServerBase from ..servers.tests import LiveServerBase
@ -538,16 +539,25 @@ class InconsistentGetImageDimensionsBug(unittest.TestCase):
self.assertEqual(size_1, size_2) self.assertEqual(size_1, size_2)
class ContentFileTestCase(unittest.TestCase): class ContentFileTestCase(unittest.TestCase):
"""
Test that the constructor of ContentFile accepts 'name' (#16590).
"""
def test_content_file_default_name(self): def test_content_file_default_name(self):
self.assertEqual(ContentFile(b"content").name, None) self.assertEqual(ContentFile(b"content").name, None)
def test_content_file_custom_name(self): def test_content_file_custom_name(self):
"""
Test that the constructor of ContentFile accepts 'name' (#16590).
"""
name = "I can have a name too!" name = "I can have a name too!"
self.assertEqual(ContentFile(b"content", name=name).name, name) self.assertEqual(ContentFile(b"content", name=name).name, name)
def test_content_file_input_type(self):
"""
Test that ContentFile can accept both bytes and unicode and that the
retrieved content is of the same type.
"""
self.assertTrue(isinstance(ContentFile(b"content").read(), bytes))
self.assertTrue(isinstance(ContentFile("español").read(), six.text_type))
class NoNameFileTestCase(unittest.TestCase): class NoNameFileTestCase(unittest.TestCase):
""" """
Other examples of unnamed files may be tempfile.SpooledTemporaryFile or Other examples of unnamed files may be tempfile.SpooledTemporaryFile or