Commit ae265345 authored by Russell Keith-Magee's avatar Russell Keith-Magee
Browse files

[1.2.X] Migrate the files doctests. Thanks to Alex Gaynor.

Backport of r13781 from trunk.

git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.2.X@13798 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 106600ed
Loading
Loading
Loading
Loading
+2 −122
Original line number Diff line number Diff line
@@ -7,10 +7,12 @@ and where files should be stored.

import random
import tempfile

from django.db import models
from django.core.files.base import ContentFile
from django.core.files.storage import FileSystemStorage


temp_storage_location = tempfile.mkdtemp()
temp_storage = FileSystemStorage(location=temp_storage_location)

@@ -30,125 +32,3 @@ class Storage(models.Model):
    custom = models.FileField(storage=temp_storage, upload_to=custom_upload_to)
    random = models.FileField(storage=temp_storage, upload_to=random_upload_to)
    default = models.FileField(storage=temp_storage, upload_to='tests', default='tests/default.txt')

__test__ = {'API_TESTS':"""
# Attempting to access a FileField from the class raises a descriptive error
>>> Storage.normal
Traceback (most recent call last):
...
AttributeError: The 'normal' attribute can only be accessed from Storage instances.

# An object without a file has limited functionality.

>>> obj1 = Storage()
>>> obj1.normal
<FieldFile: None>
>>> obj1.normal.size
Traceback (most recent call last):
...
ValueError: The 'normal' attribute has no file associated with it.

# Saving a file enables full functionality.

>>> obj1.normal.save('django_test.txt', ContentFile('content'))
>>> obj1.normal
<FieldFile: tests/django_test.txt>
>>> obj1.normal.size
7
>>> obj1.normal.read()
'content'

# File objects can be assigned to FileField attributes,  but shouldn't get
# committed until the model it's attached to is saved.

>>> from django.core.files.uploadedfile import SimpleUploadedFile
>>> obj1.normal = SimpleUploadedFile('assignment.txt', 'content')
>>> dirs, files = temp_storage.listdir('tests')
>>> dirs
[]
>>> files.sort()
>>> files == ['default.txt', 'django_test.txt']
True

>>> obj1.save()
>>> dirs, files = temp_storage.listdir('tests')
>>> files.sort()
>>> files == ['assignment.txt', 'default.txt', 'django_test.txt']
True

# Files can be read in a little at a time, if necessary.

>>> obj1.normal.open()
>>> obj1.normal.read(3)
'con'
>>> obj1.normal.read()
'tent'
>>> '-'.join(obj1.normal.chunks(chunk_size=2))
'co-nt-en-t'

# Save another file with the same name.

>>> obj2 = Storage()
>>> obj2.normal.save('django_test.txt', ContentFile('more content'))
>>> obj2.normal
<FieldFile: tests/django_test_1.txt>
>>> obj2.normal.size
12

# Push the objects into the cache to make sure they pickle properly

>>> from django.core.cache import cache
>>> cache.set('obj1', obj1)
>>> cache.set('obj2', obj2)
>>> cache.get('obj2').normal
<FieldFile: tests/django_test_1.txt>

# Deleting an object deletes the file it uses, if there are no other objects
# still using that file.

>>> obj2.delete()
>>> obj2.normal.save('django_test.txt', ContentFile('more content'))
>>> obj2.normal
<FieldFile: tests/django_test_1.txt>

# Multiple files with the same name get _N appended to them.

>>> objs = [Storage() for i in range(3)]
>>> for o in objs:
...     o.normal.save('multiple_files.txt', ContentFile('Same Content'))
>>> [o.normal for o in objs]
[<FieldFile: tests/multiple_files.txt>, <FieldFile: tests/multiple_files_1.txt>, <FieldFile: tests/multiple_files_2.txt>]
>>> for o in objs:
...     o.delete()

# Default values allow an object to access a single file.

>>> obj3 = Storage.objects.create()
>>> obj3.default
<FieldFile: tests/default.txt>
>>> obj3.default.read()
'default content'

# But it shouldn't be deleted, even if there are no more objects using it.

>>> obj3.delete()
>>> obj3 = Storage()
>>> obj3.default.read()
'default content'

# Verify the fix for #5655, making sure the directory is only determined once.

>>> obj4 = Storage()
>>> obj4.random.save('random_file', ContentFile('random content'))
>>> obj4.random
<FieldFile: .../random_file>

# Clean up the temporary files and dir.
>>> obj1.normal.delete()
>>> obj2.normal.delete()
>>> obj3.default.delete()
>>> obj4.random.delete()

>>> import shutil
>>> shutil.rmtree(temp_storage_location)
"""}
+100 −0
Original line number Diff line number Diff line
import shutil

from django.core.cache import cache
from django.core.files.base import ContentFile
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase

from models import Storage, temp_storage, temp_storage_location


class FileTests(TestCase):
    def tearDown(self):
        shutil.rmtree(temp_storage_location)

    def test_files(self):
        # Attempting to access a FileField from the class raises a descriptive
        # error
        self.assertRaises(AttributeError, lambda: Storage.normal)

        # An object without a file has limited functionality.
        obj1 = Storage()
        self.assertEqual(obj1.normal.name, "")
        self.assertRaises(ValueError, lambda: obj1.normal.size)

        # Saving a file enables full functionality.
        obj1.normal.save("django_test.txt", ContentFile("content"))
        self.assertEqual(obj1.normal.name, "tests/django_test.txt")
        self.assertEqual(obj1.normal.size, 7)
        self.assertEqual(obj1.normal.read(), "content")

        # File objects can be assigned to FileField attributes, but shouldn't
        # get committed until the model it's attached to is saved.
        obj1.normal = SimpleUploadedFile("assignment.txt", "content")
        dirs, files = temp_storage.listdir("tests")
        self.assertEqual(dirs, [])
        self.assertEqual(sorted(files), ["default.txt", "django_test.txt"])

        obj1.save()
        dirs, files = temp_storage.listdir("tests")
        self.assertEqual(
            sorted(files), ["assignment.txt", "default.txt", "django_test.txt"]
        )

        # Files can be read in a little at a time, if necessary.
        obj1.normal.open()
        self.assertEqual(obj1.normal.read(3), "con")
        self.assertEqual(obj1.normal.read(), "tent")
        self.assertEqual(list(obj1.normal.chunks(chunk_size=2)), ["co", "nt", "en", "t"])

        # Save another file with the same name.
        obj2 = Storage()
        obj2.normal.save("django_test.txt", ContentFile("more content"))
        self.assertEqual(obj2.normal.name, "tests/django_test_1.txt")
        self.assertEqual(obj2.normal.size, 12)

        # Push the objects into the cache to make sure they pickle properly
        cache.set("obj1", obj1)
        cache.set("obj2", obj2)
        self.assertEqual(cache.get("obj2").normal.name, "tests/django_test_1.txt")

        # Deleting an object deletes the file it uses, if there are no other
        # objects still using that file.
        obj2.delete()
        obj2.normal.save("django_test.txt", ContentFile("more content"))
        self.assertEqual(obj2.normal.name, "tests/django_test_1.txt")

        # Multiple files with the same name get _N appended to them.
        objs = [Storage() for i in range(3)]
        for o in objs:
            o.normal.save("multiple_files.txt", ContentFile("Same Content"))
        self.assertEqual(
            [o.normal.name for o in objs],
            ["tests/multiple_files.txt", "tests/multiple_files_1.txt", "tests/multiple_files_2.txt"]
        )
        for o in objs:
            o.delete()

        # Default values allow an object to access a single file.
        obj3 = Storage.objects.create()
        self.assertEqual(obj3.default.name, "tests/default.txt")
        self.assertEqual(obj3.default.read(), "default content")

        # But it shouldn't be deleted, even if there are no more objects using
        # it.
        obj3.delete()
        obj3 = Storage()
        self.assertEqual(obj3.default.read(), "default content")

        # Verify the fix for #5655, making sure the directory is only
        # determined once.
        obj4 = Storage()
        obj4.random.save("random_file", ContentFile("random content"))
        self.assertTrue(obj4.random.name.endswith("/random_file"))

        # Clean up the temporary files and dir.
        obj1.normal.delete()
        obj2.normal.delete()
        obj3.default.delete()
        obj4.random.delete()