Ignore compressed statics.
[redakcja.git] / apps / sorl / thumbnail / tests / classes.py
1 # -*- coding: utf-8 -*-
2 import os
3 import time
4 from StringIO import StringIO
5
6 from PIL import Image
7 from django.conf import settings
8
9 from sorl.thumbnail.base import Thumbnail
10 from sorl.thumbnail.main import DjangoThumbnail, get_thumbnail_setting
11 from sorl.thumbnail.processors import dynamic_import, get_valid_options
12 from sorl.thumbnail.tests.base import BaseTest, RELATIVE_PIC_NAME, PIC_NAME,\
13     THUMB_NAME, PIC_SIZE
14
15
16 class ThumbnailTest(BaseTest):
17     def testThumbnails(self):
18         # Thumbnail
19         thumb = Thumbnail(source=PIC_NAME, dest=THUMB_NAME % 1,
20                           requested_size=(240, 240))
21         self.verify_thumbnail((240, 180), thumb)
22
23         # Cropped thumbnail
24         thumb = Thumbnail(source=PIC_NAME, dest=THUMB_NAME % 2,
25                           requested_size=(240, 240), opts=['crop'])
26         self.verify_thumbnail((240, 240), thumb)
27
28         # Thumbnail with altered JPEG quality
29         thumb = Thumbnail(source=PIC_NAME, dest=THUMB_NAME % 3,
30                           requested_size=(240, 240), quality=95)
31         self.verify_thumbnail((240, 180), thumb)
32
33     def testRegeneration(self):
34         # Create thumbnail
35         thumb_name = THUMB_NAME % 4
36         thumb_size = (240, 240)
37         Thumbnail(source=PIC_NAME, dest=thumb_name, requested_size=thumb_size)
38         self.images_to_delete.add(thumb_name)
39         thumb_mtime = os.path.getmtime(thumb_name)
40         time.sleep(1)
41
42         # Create another instance, shouldn't generate a new thumb
43         Thumbnail(source=PIC_NAME, dest=thumb_name, requested_size=thumb_size)
44         self.assertEqual(os.path.getmtime(thumb_name), thumb_mtime)
45
46         # Recreate the source image, then see if a new thumb is generated
47         Image.new('RGB', PIC_SIZE).save(PIC_NAME, 'JPEG')
48         Thumbnail(source=PIC_NAME, dest=thumb_name, requested_size=thumb_size)
49         self.assertNotEqual(os.path.getmtime(thumb_name), thumb_mtime)
50
51     def testFilelikeDest(self):
52         # Thumbnail
53         filelike_dest = StringIO()
54         thumb = Thumbnail(source=PIC_NAME, dest=filelike_dest,
55                           requested_size=(240, 240))
56         self.verify_thumbnail((240, 180), thumb)
57
58     def testRGBA(self):
59         # RGBA image
60         rgba_pic_name = os.path.join(settings.MEDIA_ROOT,
61                                      'sorl-thumbnail-test_rgba_source.png')
62         Image.new('RGBA', PIC_SIZE).save(rgba_pic_name)
63         self.images_to_delete.add(rgba_pic_name)
64         # Create thumb and verify it's still RGBA
65         rgba_thumb_name = os.path.join(settings.MEDIA_ROOT,
66                                        'sorl-thumbnail-test_rgba_dest.png')
67         thumb = Thumbnail(source=rgba_pic_name, dest=rgba_thumb_name,
68                           requested_size=(240, 240))
69         self.verify_thumbnail((240, 180), thumb, expected_mode='RGBA')
70
71
72 class DjangoThumbnailTest(BaseTest):
73     def setUp(self):
74         super(DjangoThumbnailTest, self).setUp()
75         # Add another source image in a sub-directory for testing subdir and
76         # basedir.
77         self.sub_dir = os.path.join(settings.MEDIA_ROOT, 'test_thumbnail')
78         try:
79             os.mkdir(self.sub_dir)
80         except OSError:
81             pass
82         self.pic_subdir = os.path.join(self.sub_dir, RELATIVE_PIC_NAME)
83         Image.new('RGB', PIC_SIZE).save(self.pic_subdir, 'JPEG')
84         self.images_to_delete.add(self.pic_subdir)
85
86     def testFilenameGeneration(self):
87         basename = RELATIVE_PIC_NAME.replace('.', '_')
88         # Basic filename
89         thumb = DjangoThumbnail(relative_source=RELATIVE_PIC_NAME,
90                                 requested_size=(240, 120))
91         expected = os.path.join(settings.MEDIA_ROOT, basename)
92         expected += '_240x120_q85.jpg'
93         self.verify_thumbnail((160, 120), thumb, expected_filename=expected)
94
95         # Changed quality and cropped
96         thumb = DjangoThumbnail(relative_source=RELATIVE_PIC_NAME,
97                                 requested_size=(240, 120), opts=['crop'],
98                                 quality=95)
99         expected = os.path.join(settings.MEDIA_ROOT, basename)
100         expected += '_240x120_crop_q95.jpg'
101         self.verify_thumbnail((240, 120), thumb, expected_filename=expected)
102
103         # All options on
104         processors = dynamic_import(get_thumbnail_setting('PROCESSORS'))
105         valid_options = get_valid_options(processors)
106
107         thumb = DjangoThumbnail(relative_source=RELATIVE_PIC_NAME,
108                                 requested_size=(240, 120), opts=valid_options)
109         expected = (os.path.join(settings.MEDIA_ROOT, basename) + '_240x120_'
110                     'autocrop_bw_crop_detail_max_sharpen_upscale_q85.jpg')
111         self.verify_thumbnail((240, 120), thumb, expected_filename=expected)
112
113         # Different basedir
114         basedir = 'sorl-thumbnail-test-basedir'
115         self.change_settings.change({'BASEDIR': basedir})
116         thumb = DjangoThumbnail(relative_source=self.pic_subdir,
117                                 requested_size=(240, 120))
118         expected = os.path.join(basedir, self.sub_dir, basename)
119         expected += '_240x120_q85.jpg'
120         self.verify_thumbnail((160, 120), thumb, expected_filename=expected)
121         # Different subdir
122         self.change_settings.change({'BASEDIR': '', 'SUBDIR': 'subdir'})
123         thumb = DjangoThumbnail(relative_source=self.pic_subdir,
124                                 requested_size=(240, 120))
125         expected = os.path.join(settings.MEDIA_ROOT,
126                                 os.path.basename(self.sub_dir), 'subdir',
127                                 basename)
128         expected += '_240x120_q85.jpg'
129         self.verify_thumbnail((160, 120), thumb, expected_filename=expected)
130         # Different prefix
131         self.change_settings.change({'SUBDIR': '', 'PREFIX': 'prefix-'})
132         thumb = DjangoThumbnail(relative_source=self.pic_subdir,
133                                 requested_size=(240, 120))
134         expected = os.path.join(self.sub_dir, 'prefix-' + basename)
135         expected += '_240x120_q85.jpg'
136         self.verify_thumbnail((160, 120), thumb, expected_filename=expected)
137
138     def testAlternateExtension(self):
139         basename = RELATIVE_PIC_NAME.replace('.', '_')
140         # Control JPG
141         thumb = DjangoThumbnail(relative_source=RELATIVE_PIC_NAME,
142                                 requested_size=(240, 120))
143         expected = os.path.join(settings.MEDIA_ROOT, basename)
144         expected += '_240x120_q85.jpg'
145         expected_jpg = expected
146         self.verify_thumbnail((160, 120), thumb, expected_filename=expected)
147         # Test PNG
148         thumb = DjangoThumbnail(relative_source=RELATIVE_PIC_NAME,
149                                 requested_size=(240, 120), extension='png')
150         expected = os.path.join(settings.MEDIA_ROOT, basename)
151         expected += '_240x120_q85.png'
152         self.verify_thumbnail((160, 120), thumb, expected_filename=expected)
153         # Compare the file size to make sure it's not just saving as a JPG with
154         # a different extension.
155         self.assertNotEqual(os.path.getsize(expected_jpg),
156                             os.path.getsize(expected))
157
158     def testUnicodeName(self):
159         unicode_name = 'sorl-thumbnail-ążśź_source.jpg'
160         unicode_path = os.path.join(settings.MEDIA_ROOT, unicode_name)
161         Image.new('RGB', PIC_SIZE).save(unicode_path)
162         self.images_to_delete.add(unicode_path)
163         thumb = DjangoThumbnail(relative_source=unicode_name,
164                                 requested_size=(240, 120))
165         base_name = unicode_name.replace('.', '_')
166         expected = os.path.join(settings.MEDIA_ROOT,
167                                 base_name + '_240x120_q85.jpg')
168         self.verify_thumbnail((160, 120), thumb, expected_filename=expected)
169
170     def tearDown(self):
171         super(DjangoThumbnailTest, self).tearDown()
172         subdir = os.path.join(self.sub_dir, 'subdir')
173         if os.path.exists(subdir):
174             os.rmdir(subdir)
175         os.rmdir(self.sub_dir)