From fbf0d9002c0c8f51ef34104c8e0534286d93e9ee Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Thu, 13 Nov 2014 16:02:36 +0000 Subject: [PATCH] Define a custom exception type for IO errors thrown when opening source images, and catch that in InageNode.render so that we're not masking unrelated IOErrors elsewhere in the get_rendition process --- wagtail/wagtailimages/models.py | 19 +++++++++++++++++-- .../templatetags/wagtailimages_tags.py | 6 +++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/wagtail/wagtailimages/models.py b/wagtail/wagtailimages/models.py index 163dfd676..9e19a03f4 100644 --- a/wagtail/wagtailimages/models.py +++ b/wagtail/wagtailimages/models.py @@ -1,7 +1,7 @@ import os.path import re -from six import BytesIO +from six import BytesIO, text_type from taggit.managers import TaggableManager @@ -28,6 +28,13 @@ from wagtail.wagtailimages.rect import Rect from wagtail.wagtailadmin.utils import get_object_usage +class SourceImageIOError(IOError): + """ + Custom exception to distinguish IOErrors that were thrown while opening the source image + """ + pass + + def get_upload_to(instance, filename): folder_name = 'original_images' filename = instance.file.field.storage.get_valid_name(filename) @@ -178,7 +185,15 @@ class AbstractImage(models.Model, TagSearchable): # If we have a backend attribute then pass it to process # image - else pass 'default' backend_name = getattr(self, 'backend', 'default') - generated_image = filter.process_image(file_field.file, backend_name=backend_name, focal_point=self.get_focal_point()) + + try: + image_file = file_field.file # triggers a call to self.storage.open, so IOErrors from missing files will be raised at this point + except IOError as e: + # re-throw this as a SourceImageIOError so that calling code can distinguish + # these from IOErrors elsewhere in the process + raise SourceImageIOError(text_type(e)) + + generated_image = filter.process_image(image_file, backend_name=backend_name, focal_point=self.get_focal_point()) # generate new filename derived from old one, inserting the filter spec and focal point key before the extension if self.has_focal_point(): diff --git a/wagtail/wagtailimages/templatetags/wagtailimages_tags.py b/wagtail/wagtailimages/templatetags/wagtailimages_tags.py index 5c7273417..c8f609c6b 100644 --- a/wagtail/wagtailimages/templatetags/wagtailimages_tags.py +++ b/wagtail/wagtailimages/templatetags/wagtailimages_tags.py @@ -1,6 +1,6 @@ from django import template -from wagtail.wagtailimages.models import Filter +from wagtail.wagtailimages.models import Filter, SourceImageIOError register = template.Library() @@ -53,10 +53,10 @@ class ImageNode(template.Node): try: rendition = image.get_rendition(self.filter) - except IOError: + except SourceImageIOError: # It's fairly routine for people to pull down remote databases to their # local dev versions without retrieving the corresponding image files. - # In such a case, we would get an IOError at the point where we try to + # In such a case, we would get a SourceImageIOError at the point where we try to # create the resized version of a non-existent image. Since this is a # bit catastrophic for a missing image, we'll substitute a dummy # Rendition object so that we just output a broken link instead.