From 4e70ad11d29bde54b846920ce0dcf8d10741d3ae Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Wed, 29 Aug 2012 15:13:20 +0200 Subject: [PATCH] Made FileSystemStorage accept both text and byte streams Thanks Alexey Boriskin for his help on the patch. --- django/core/files/storage.py | 11 +++++++++-- tests/regressiontests/file_storage/tests.py | 11 +++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/django/core/files/storage.py b/django/core/files/storage.py index 7542dcda46..0b300cd31e 100644 --- a/django/core/files/storage.py +++ b/django/core/files/storage.py @@ -195,11 +195,18 @@ class FileSystemStorage(Storage): fd = os.open(full_path, os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, 'O_BINARY', 0)) try: locks.lock(fd, locks.LOCK_EX) + _file = None for chunk in content.chunks(): - os.write(fd, chunk) + if _file is None: + mode = 'wb' if isinstance(chunk, bytes) else 'wt' + _file = os.fdopen(fd, mode) + _file.write(chunk) finally: locks.unlock(fd) - os.close(fd) + if _file is not None: + _file.close() + else: + os.close(fd) except OSError as e: if e.errno == errno.EEXIST: # Ooops, the file exists. We need a new file name. diff --git a/tests/regressiontests/file_storage/tests.py b/tests/regressiontests/file_storage/tests.py index 396e70f5e6..87b509e320 100644 --- a/tests/regressiontests/file_storage/tests.py +++ b/tests/regressiontests/file_storage/tests.py @@ -356,6 +356,17 @@ class FileStorageTests(unittest.TestCase): finally: os.remove = real_remove + def test_file_chunks_error(self): + """ + Test behaviour when file.chunks() is raising an error + """ + f1 = ContentFile('chunks fails') + def failing_chunks(): + raise IOError + f1.chunks = failing_chunks + with self.assertRaises(IOError): + self.storage.save('error.file', f1) + class CustomStorage(FileSystemStorage): def get_available_name(self, name):