diff --git a/imagekit/specs/__init__.py b/imagekit/specs/__init__.py index 1ef298e..d9339f3 100644 --- a/imagekit/specs/__init__.py +++ b/imagekit/specs/__init__.py @@ -143,23 +143,26 @@ class ImageSpec(BaseImageSpec): raise MissingSource("The spec '%s' has no source file associated" " with it." % self) - file_opened_locally = False # TODO: Move into a generator base class # TODO: Factor out a generate_image function so you can create a generator and only override the PIL.Image creating part. (The tricky part is how to deal with original_format since generator base class won't have one.) + + closed = self.source.closed + if closed: + # Django file object should know how to reopen itself if it was closed + # https://code.djangoproject.com/ticket/13750 + self.source.open() + try: img = open_image(self.source) - except ValueError: - - # Re-open the file -- https://code.djangoproject.com/ticket/13750 - self.source.open() - file_opened_locally = True - img = open_image(self.source) - - new_image = process_image(img, processors=self.processors, - format=self.format, autoconvert=self.autoconvert, - options=self.options) - if file_opened_locally: - self.source.close() + new_image = process_image(img, + processors=self.processors, + format=self.format, + autoconvert=self.autoconvert, + options=self.options) + finally: + if closed: + # We need to close the file if it was opened by us + self.source.close() return new_image diff --git a/tests/test_closing_fieldfiles.py b/tests/test_closing_fieldfiles.py new file mode 100644 index 0000000..d8693c3 --- /dev/null +++ b/tests/test_closing_fieldfiles.py @@ -0,0 +1,25 @@ +from nose.tools import assert_false, assert_true + +from .models import Thumbnail +from .utils import create_photo + + +def test_do_not_leak_open_files(): + instance = create_photo('leak-test.jpg') + source_file = instance.original_image + # Ensure the FieldFile is closed before generation + source_file.close() + image_generator = Thumbnail(source=source_file) + image_generator.generate() + assert_true(source_file.closed) + + +def test_do_not_close_open_files_after_generate(): + instance = create_photo('do-not-close-test.jpg') + source_file = instance.original_image + # Ensure the FieldFile is opened before generation + source_file.open() + image_generator = Thumbnail(source=source_file) + image_generator.generate() + assert_false(source_file.closed) + source_file.close()