Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #15644 -- Improved Django File wrapper to support more file-lik…

…e 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
  • Loading branch information...
commit 5c954136eaef3d98d532368deec4c19cf892f664 1 parent 5e047ed
Claude Paroz authored April 05, 2012
17  django/core/files/base.py
@@ -36,8 +36,13 @@ def _get_size(self):
36 36
         if not hasattr(self, '_size'):
37 37
             if hasattr(self.file, 'size'):
38 38
                 self._size = self.file.size
39  
-            elif os.path.exists(self.file.name):
  39
+            elif hasattr(self.file, 'name') and os.path.exists(self.file.name):
40 40
                 self._size = os.path.getsize(self.file.name)
  41
+            elif hasattr(self.file, 'tell') and hasattr(self.file, 'seek'):
  42
+                pos = self.file.tell()
  43
+                self.file.seek(0, os.SEEK_END)
  44
+                self._size = self.file.tell()
  45
+                self.file.seek(pos)
41 46
             else:
42 47
                 raise AttributeError("Unable to determine the file's size.")
43 48
         return self._size
@@ -61,12 +66,12 @@ def chunks(self, chunk_size=None):
61 66
 
62 67
         if hasattr(self, 'seek'):
63 68
             self.seek(0)
64  
-        # Assume the pointer is at zero...
65  
-        counter = self.size
66 69
 
67  
-        while counter > 0:
68  
-            yield self.read(chunk_size)
69  
-            counter -= chunk_size
  70
+        while True:
  71
+            data = self.read(chunk_size)
  72
+            if not data:
  73
+                break
  74
+            yield data
70 75
 
71 76
     def multiple_chunks(self, chunk_size=None):
72 77
         """
43  tests/regressiontests/file_storage/tests.py
... ...
@@ -1,4 +1,6 @@
1 1
 # -*- coding: utf-8 -*-
  2
+from __future__ import absolute_import
  3
+
2 4
 import errno
3 5
 import os
4 6
 import shutil
@@ -17,12 +19,13 @@
17 19
 
18 20
 from django.conf import settings
19 21
 from django.core.exceptions import SuspiciousOperation, ImproperlyConfigured
20  
-from django.core.files.base import ContentFile
  22
+from django.core.files.base import File, ContentFile
21 23
 from django.core.files.images import get_image_dimensions
22 24
 from django.core.files.storage import FileSystemStorage, get_storage_class
23 25
 from django.core.files.uploadedfile import UploadedFile
24 26
 from django.test import SimpleTestCase
25 27
 from django.utils import unittest
  28
+from ..servers.tests import LiveServerBase
26 29
 
27 30
 # Try to import PIL in either of the two ways it can end up installed.
28 31
 # Checking for the existence of Image is enough for CPython, but
@@ -544,6 +547,42 @@ class ContentFileTestCase(unittest.TestCase):
544 547
     def test_content_file_default_name(self):
545 548
         self.assertEqual(ContentFile("content").name, None)
546 549
 
547  
-    def test_content_file_custome_name(self):
  550
+    def test_content_file_custom_name(self):
548 551
         name = "I can have a name too!"
549 552
         self.assertEqual(ContentFile("content", name=name).name, name)
  553
+
  554
+class NoNameFileTestCase(unittest.TestCase):
  555
+    """
  556
+    Other examples of unnamed files may be tempfile.SpooledTemporaryFile or
  557
+    urllib.urlopen()
  558
+    """
  559
+    def test_noname_file_default_name(self):
  560
+        self.assertEqual(File(StringIO('A file with no name')).name, None)
  561
+
  562
+    def test_noname_file_get_size(self):
  563
+        self.assertEqual(File(StringIO('A file with no name')).size, 19)
  564
+
  565
+class FileLikeObjectTestCase(LiveServerBase):
  566
+    """
  567
+    Test file-like objects (#15644).
  568
+    """
  569
+    def setUp(self):
  570
+        self.temp_dir = tempfile.mkdtemp()
  571
+        self.storage = FileSystemStorage(location=self.temp_dir)
  572
+
  573
+    def tearDown(self):
  574
+        shutil.rmtree(self.temp_dir)
  575
+
  576
+    def test_urllib2_urlopen(self):
  577
+        """
  578
+        Test the File storage API with a file like object coming from urllib2.urlopen()
  579
+        """
  580
+
  581
+        file_like_object = self.urlopen('/example_view/')
  582
+        f = File(file_like_object)
  583
+        stored_filename = self.storage.save("remote_file.html", f)
  584
+
  585
+        stored_file = self.storage.open(stored_filename)
  586
+        remote_file = self.urlopen('/example_view/')
  587
+
  588
+        self.assertEqual(stored_file.read(), remote_file.read())

0 notes on commit 5c95413

Please sign in to comment.
Something went wrong with that request. Please try again.