Commit 361d6738 authored by Claude Paroz's avatar Claude Paroz
Browse files

Fixed #11739 -- Made ContentFile support Unicode input

parent ebc773ad
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
from __future__ import unicode_literals

import os
from io import BytesIO, UnsupportedOperation
from io import BytesIO, StringIO, UnsupportedOperation

from django.utils.encoding import smart_text
from django.core.files.utils import FileProxyMixin
from django.utils import six
from django.utils.encoding import python_2_unicode_compatible

@python_2_unicode_compatible
@@ -132,7 +133,8 @@ class ContentFile(File):
    """
    def __init__(self, content, name=None):
        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)

    def __str__(self):
+8 −4
Original line number Diff line number Diff line
@@ -91,14 +91,18 @@ The ``ContentFile`` Class
.. class:: ContentFile(File)

    The ``ContentFile`` class inherits from :class:`~django.core.files.File`,
    but unlike :class:`~django.core.files.File` it operates on string content,
    rather than an actual file. For example::
    but unlike :class:`~django.core.files.File` it operates on string content
    (bytes also supported), rather than an actual file. For example::

        from __future__ import unicode_literals
        from django.core.files.base import ContentFile

        f1 = ContentFile(b"my string content")
        f2 = ContentFile("my unicode content encoded as UTF-8".encode('UTF-8'))
        f1 = ContentFile("esta sentencia está en español")
        f2 = ContentFile(b"these are bytes")

    .. versionchanged:: 1.5

        ContentFile also accepts Unicode strings.

.. currentmodule:: django.core.files.images

+13 −3
Original line number Diff line number Diff line
@@ -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.uploadedfile import UploadedFile
from django.test import SimpleTestCase
from django.utils import six
from django.utils import unittest
from ..servers.tests import LiveServerBase

@@ -538,16 +539,25 @@ class InconsistentGetImageDimensionsBug(unittest.TestCase):
        self.assertEqual(size_1, size_2)

class ContentFileTestCase(unittest.TestCase):
    """
    Test that the constructor of ContentFile accepts 'name' (#16590).
    """

    def test_content_file_default_name(self):
        self.assertEqual(ContentFile(b"content").name, None)

    def test_content_file_custom_name(self):
        """
        Test that the constructor of ContentFile accepts 'name' (#16590).
        """
        name = "I can have a name too!"
        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):
    """
    Other examples of unnamed files may be tempfile.SpooledTemporaryFile or