From 34dcf51e06fc57fc5462bd40f6a4c8ee949521da Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Thu, 6 Dec 2012 17:14:44 +0100 Subject: [PATCH] Fixed #19367 -- Fixed saving ContentFile in filesystem storage This was not working properly when ContentFile was initialized with an unicode string. Thanks Alexey Boriskin for the report and the test. --- django/core/files/base.py | 9 ++++++--- tests/regressiontests/file_storage/tests.py | 20 +++++++++++++++++++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/django/core/files/base.py b/django/core/files/base.py index 71de5ab741..2d10100019 100644 --- a/django/core/files/base.py +++ b/django/core/files/base.py @@ -6,7 +6,7 @@ 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 +from django.utils.encoding import force_bytes, python_2_unicode_compatible @python_2_unicode_compatible class File(FileProxyMixin): @@ -134,8 +134,11 @@ class ContentFile(File): A File-like object that takes just raw content, rather than an actual file. """ def __init__(self, content, name=None): - content = content or b'' - stream_class = StringIO if isinstance(content, six.text_type) else BytesIO + if six.PY3: + stream_class = StringIO if isinstance(content, six.text_type) else BytesIO + else: + stream_class = BytesIO + content = force_bytes(content) super(ContentFile, self).__init__(stream_class(content), name=name) self.size = len(content) diff --git a/tests/regressiontests/file_storage/tests.py b/tests/regressiontests/file_storage/tests.py index 595b65d9f1..45c18ba14a 100644 --- a/tests/regressiontests/file_storage/tests.py +++ b/tests/regressiontests/file_storage/tests.py @@ -560,6 +560,13 @@ class InconsistentGetImageDimensionsBug(unittest.TestCase): class ContentFileTestCase(unittest.TestCase): + def setUp(self): + self.storage_dir = tempfile.mkdtemp() + self.storage = FileSystemStorage(self.storage_dir) + + def tearDown(self): + shutil.rmtree(self.storage_dir) + def test_content_file_default_name(self): self.assertEqual(ContentFile(b"content").name, None) @@ -576,7 +583,18 @@ class ContentFileTestCase(unittest.TestCase): 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)) + if six.PY3: + self.assertTrue(isinstance(ContentFile("español").read(), six.text_type)) + else: + self.assertTrue(isinstance(ContentFile("español").read(), bytes)) + + def test_content_saving(self): + """ + Test that ContentFile can be saved correctly with the filesystem storage, + both if it was initialized with string or unicode content""" + self.storage.save('bytes.txt', ContentFile(b"content")) + self.storage.save('unicode.txt', ContentFile("español")) + class NoNameFileTestCase(unittest.TestCase): """