From 70552845ca651256bdb656cda28307b111bce4f6 Mon Sep 17 00:00:00 2001 From: Adam Palay Date: Thu, 10 Dec 2015 15:20:00 -0500 Subject: [PATCH] fix translations for profile images (TNL-3901) --- .../core/djangoapps/profile_images/images.py | 40 +++++++++++++------ .../profile_images/tests/test_images.py | 28 ++++++++----- 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/openedx/core/djangoapps/profile_images/images.py b/openedx/core/djangoapps/profile_images/images.py index cf8e8b4d34..a60b138056 100644 --- a/openedx/core/djangoapps/profile_images/images.py +++ b/openedx/core/djangoapps/profile_images/images.py @@ -6,7 +6,7 @@ from collections import namedtuple from django.conf import settings from django.core.files.base import ContentFile -from django.utils.translation import ugettext as _, ugettext_noop as _noop +from django.utils.translation import ugettext as _ from PIL import Image from openedx.core.djangoapps.user_api.accounts.image_helpers import get_profile_image_storage @@ -58,13 +58,6 @@ def get_valid_file_types(): return ', '.join([', '.join(IMAGE_TYPES[ft].extensions) for ft in IMAGE_TYPES.keys()]) -FILE_UPLOAD_TOO_LARGE = _noop(u'The file must be smaller than {image_max_size} in size.'.format(image_max_size=user_friendly_size(settings.PROFILE_IMAGE_MAX_BYTES))) # pylint: disable=line-too-long -FILE_UPLOAD_TOO_SMALL = _noop(u'The file must be at least {image_min_size} in size.'.format(image_min_size=user_friendly_size(settings.PROFILE_IMAGE_MIN_BYTES))) # pylint: disable=line-too-long -FILE_UPLOAD_BAD_TYPE = _noop(u'The file must be one of the following types: {valid_file_types}.'.format(valid_file_types=get_valid_file_types())) # pylint: disable=line-too-long -FILE_UPLOAD_BAD_EXT = _noop(u'The file name extension for this file does not match the file data. The file may be corrupted.') # pylint: disable=line-too-long -FILE_UPLOAD_BAD_MIMETYPE = _noop(u'The Content-Type header for this file does not match the file data. The file may be corrupted.') # pylint: disable=line-too-long - - class ImageValidationError(Exception): """ Exception to use when the system rejects a user-supplied source image. @@ -90,25 +83,46 @@ def validate_uploaded_image(uploaded_file): # see also: http://en.wikipedia.org/wiki/Magic_number_%28programming%29 if uploaded_file.size > settings.PROFILE_IMAGE_MAX_BYTES: - raise ImageValidationError(FILE_UPLOAD_TOO_LARGE) + file_upload_too_large = _( + u'The file must be smaller than {image_max_size} in size.' + ).format( + image_max_size=user_friendly_size(settings.PROFILE_IMAGE_MAX_BYTES) + ) + raise ImageValidationError(file_upload_too_large) elif uploaded_file.size < settings.PROFILE_IMAGE_MIN_BYTES: - raise ImageValidationError(FILE_UPLOAD_TOO_SMALL) + file_upload_too_small = _( + u'The file must be at least {image_min_size} in size.' + ).format( + image_min_size=user_friendly_size(settings.PROFILE_IMAGE_MIN_BYTES) + ) + raise ImageValidationError(file_upload_too_small) # check the file extension looks acceptable filename = unicode(uploaded_file.name).lower() filetype = [ft for ft in IMAGE_TYPES if any(filename.endswith(ext) for ext in IMAGE_TYPES[ft].extensions)] if not filetype: - raise ImageValidationError(FILE_UPLOAD_BAD_TYPE) + file_upload_bad_type = _( + u'The file must be one of the following types: {valid_file_types}.' + ).format(valid_file_types=get_valid_file_types()) + raise ImageValidationError(file_upload_bad_type) filetype = filetype[0] # check mimetype matches expected file type if uploaded_file.content_type not in IMAGE_TYPES[filetype].mimetypes: - raise ImageValidationError(FILE_UPLOAD_BAD_MIMETYPE) + file_upload_bad_mimetype = _( + u'The Content-Type header for this file does not match ' + u'the file data. The file may be corrupted.' + ) + raise ImageValidationError(file_upload_bad_mimetype) # check magic number matches expected file type headers = IMAGE_TYPES[filetype].magic if uploaded_file.read(len(headers[0]) / 2).encode('hex') not in headers: - raise ImageValidationError(FILE_UPLOAD_BAD_EXT) + file_upload_bad_ext = _( + u'The file name extension for this file does not match ' + u'the file data. The file may be corrupted.' + ) + raise ImageValidationError(file_upload_bad_ext) # avoid unexpected errors from subsequent modules expecting the fp to be at 0 uploaded_file.seek(0) diff --git a/openedx/core/djangoapps/profile_images/tests/test_images.py b/openedx/core/djangoapps/profile_images/tests/test_images.py index 3e65bd06d0..52f877be77 100644 --- a/openedx/core/djangoapps/profile_images/tests/test_images.py +++ b/openedx/core/djangoapps/profile_images/tests/test_images.py @@ -16,15 +16,11 @@ import mock from PIL import Image from ..images import ( - FILE_UPLOAD_TOO_LARGE, - FILE_UPLOAD_TOO_SMALL, - FILE_UPLOAD_BAD_TYPE, - FILE_UPLOAD_BAD_EXT, - FILE_UPLOAD_BAD_MIMETYPE, create_profile_images, ImageValidationError, remove_profile_images, validate_uploaded_image, + get_valid_file_types, ) from .helpers import make_image_file, make_uploaded_file @@ -35,6 +31,12 @@ class TestValidateUploadedImage(TestCase): """ Test validate_uploaded_image """ + FILE_UPLOAD_BAD_TYPE = ( + u'The file must be one of the following types: {valid_file_types}.'.format( + valid_file_types=get_valid_file_types() + ) + ) + def check_validation_result(self, uploaded_file, expected_failure_message): """ Internal DRY helper. @@ -48,10 +50,10 @@ class TestValidateUploadedImage(TestCase): self.assertEqual(uploaded_file.tell(), 0) @ddt.data( - (99, FILE_UPLOAD_TOO_SMALL), + (99, u"The file must be at least 100 bytes in size."), (100, ), (1024, ), - (1025, FILE_UPLOAD_TOO_LARGE), + (1025, u"The file must be smaller than 1 KB in size."), ) @ddt.unpack @override_settings(PROFILE_IMAGE_MIN_BYTES=100, PROFILE_IMAGE_MAX_BYTES=1024) @@ -85,6 +87,10 @@ class TestValidateUploadedImage(TestCase): Ensure that validation fails when the file extension does not match the file data. """ + file_upload_bad_ext = ( + u'The file name extension for this file does not match ' + u'the file data. The file may be corrupted.' + ) # make a bmp, try to fool the function into thinking it's a jpeg with make_image_file(extension=".bmp") as bmp_file: with closing(NamedTemporaryFile(suffix=".jpeg")) as fake_jpeg_file: @@ -97,17 +103,21 @@ class TestValidateUploadedImage(TestCase): ) with self.assertRaises(ImageValidationError) as ctx: validate_uploaded_image(uploaded_file) - self.assertEqual(ctx.exception.message, FILE_UPLOAD_BAD_EXT) + self.assertEqual(ctx.exception.message, file_upload_bad_ext) def test_content_type(self): """ Ensure that validation fails when the content_type header and file extension do not match """ + file_upload_bad_mimetype = ( + u'The Content-Type header for this file does not match ' + u'the file data. The file may be corrupted.' + ) with make_uploaded_file(extension=".jpeg", content_type="image/gif") as uploaded_file: with self.assertRaises(ImageValidationError) as ctx: validate_uploaded_image(uploaded_file) - self.assertEqual(ctx.exception.message, FILE_UPLOAD_BAD_MIMETYPE) + self.assertEqual(ctx.exception.message, file_upload_bad_mimetype) @ddt.ddt