Fixed #15644 -- Improved Django File wrapper to support more file-like objects. Thanks nickname123 and Michael Palumbo for working on the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17871 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Claude Paroz 2012-04-05 15:44:04 +00:00
parent 5e047ed859
commit 5c954136ea
2 changed files with 52 additions and 8 deletions

View File

@ -36,8 +36,13 @@ class File(FileProxyMixin):
if not hasattr(self, '_size'):
if hasattr(self.file, 'size'):
self._size = self.file.size
elif os.path.exists(self.file.name):
elif hasattr(self.file, 'name') and os.path.exists(self.file.name):
self._size = os.path.getsize(self.file.name)
elif hasattr(self.file, 'tell') and hasattr(self.file, 'seek'):
pos = self.file.tell()
self.file.seek(0, os.SEEK_END)
self._size = self.file.tell()
self.file.seek(pos)
else:
raise AttributeError("Unable to determine the file's size.")
return self._size
@ -61,12 +66,12 @@ class File(FileProxyMixin):
if hasattr(self, 'seek'):
self.seek(0)
# Assume the pointer is at zero...
counter = self.size
while counter > 0:
yield self.read(chunk_size)
counter -= chunk_size
while True:
data = self.read(chunk_size)
if not data:
break
yield data
def multiple_chunks(self, chunk_size=None):
"""

View File

@ -1,4 +1,6 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
import errno
import os
import shutil
@ -17,12 +19,13 @@ except ImportError:
from django.conf import settings
from django.core.exceptions import SuspiciousOperation, ImproperlyConfigured
from django.core.files.base import ContentFile
from django.core.files.base import File, ContentFile
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 unittest
from ..servers.tests import LiveServerBase
# Try to import PIL in either of the two ways it can end up installed.
# Checking for the existence of Image is enough for CPython, but
@ -544,6 +547,42 @@ class ContentFileTestCase(unittest.TestCase):
def test_content_file_default_name(self):
self.assertEqual(ContentFile("content").name, None)
def test_content_file_custome_name(self):
def test_content_file_custom_name(self):
name = "I can have a name too!"
self.assertEqual(ContentFile("content", name=name).name, name)
class NoNameFileTestCase(unittest.TestCase):
"""
Other examples of unnamed files may be tempfile.SpooledTemporaryFile or
urllib.urlopen()
"""
def test_noname_file_default_name(self):
self.assertEqual(File(StringIO('A file with no name')).name, None)
def test_noname_file_get_size(self):
self.assertEqual(File(StringIO('A file with no name')).size, 19)
class FileLikeObjectTestCase(LiveServerBase):
"""
Test file-like objects (#15644).
"""
def setUp(self):
self.temp_dir = tempfile.mkdtemp()
self.storage = FileSystemStorage(location=self.temp_dir)
def tearDown(self):
shutil.rmtree(self.temp_dir)
def test_urllib2_urlopen(self):
"""
Test the File storage API with a file like object coming from urllib2.urlopen()
"""
file_like_object = self.urlopen('/example_view/')
f = File(file_like_object)
stored_filename = self.storage.save("remote_file.html", f)
stored_file = self.storage.open(stored_filename)
remote_file = self.urlopen('/example_view/')
self.assertEqual(stored_file.read(), remote_file.read())