Skip to content
Snippets Groups Projects
Unverified Commit 91d33611 authored by M. Zulqarnain's avatar M. Zulqarnain Committed by GitHub
Browse files

refactor: pyupgrade in profile_images, programs, safe_sessions (#26953)

parent 1c19fbf3
No related branches found
No related tags found
No related merge requests found
Showing
with 51 additions and 94 deletions
......@@ -3,9 +3,6 @@ Exceptions related to the handling of profile images.
"""
from six import text_type
class ImageValidationError(Exception):
"""
Exception to use when the system rejects a user-supplied source image.
......@@ -15,4 +12,4 @@ class ImageValidationError(Exception):
"""
Translate the developer-facing exception message for API clients.
"""
return text_type(self)
return str(self)
......@@ -9,7 +9,6 @@ from contextlib import closing
from io import BytesIO
import piexif
import six
from django.conf import settings
from django.core.files.base import ContentFile
from django.utils.translation import ugettext as _
......@@ -96,25 +95,25 @@ def validate_uploaded_image(uploaded_file):
if uploaded_file.size > settings.PROFILE_IMAGE_MAX_BYTES: # lint-amnesty, pylint: disable=no-else-raise
file_upload_too_large = _(
u'The file must be smaller than {image_max_size} in size.'
'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:
file_upload_too_small = _(
u'The file must be at least {image_min_size} in size.'
'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 = six.text_type(uploaded_file.name).lower()
filename = str(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:
file_upload_bad_type = _(
u'The file must be one of the following types: {valid_file_types}.'
'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]
......@@ -122,8 +121,8 @@ def validate_uploaded_image(uploaded_file):
# check mimetype matches expected file type
if uploaded_file.content_type not in IMAGE_TYPES[filetype].mimetypes:
file_upload_bad_mimetype = _(
u'The Content-Type header for this file does not match '
u'the file data. The file may be corrupted.'
'The Content-Type header for this file does not match '
'the file data. The file may be corrupted.'
)
raise ImageValidationError(file_upload_bad_mimetype)
......@@ -131,8 +130,8 @@ def validate_uploaded_image(uploaded_file):
headers = IMAGE_TYPES[filetype].magic
if binascii.hexlify(uploaded_file.read(len(headers[0]) // 2)).decode('utf-8') not in headers:
file_upload_bad_ext = _(
u'The file name extension for this file does not match '
u'the file data. The file may be corrupted.'
'The file name extension for this file does not match '
'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
......@@ -245,4 +244,4 @@ def _user_friendly_size(size):
while size >= 1024 and i < len(units):
size //= 1024
i += 1
return u'{} {}'.format(size, units[i])
return '{} {}'.format(size, units[i])
......@@ -9,7 +9,6 @@ from tempfile import NamedTemporaryFile
from django.core.files.uploadedfile import UploadedFile
import piexif
from PIL import Image
from six.moves import range
@contextmanager
......
"""
Test cases for image processing functions in the profile image package.
"""
from contextlib import closing
from unittest import mock
import pytest
from contextlib import closing
from itertools import product
import os
from tempfile import NamedTemporaryFile
......@@ -12,10 +13,8 @@ from django.core.files.uploadedfile import UploadedFile
from django.test import TestCase
from django.test.utils import override_settings
import ddt
import mock
import piexif
from PIL import Image
from six import text_type
from openedx.core.djangolib.testing.utils import skip_unless_lms
from ..exceptions import ImageValidationError
......@@ -37,7 +36,7 @@ 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(
'The file must be one of the following types: {valid_file_types}.'.format(
valid_file_types=_get_valid_file_types()
)
)
......@@ -49,16 +48,16 @@ class TestValidateUploadedImage(TestCase):
if expected_failure_message is not None:
with pytest.raises(ImageValidationError) as ctx:
validate_uploaded_image(uploaded_file)
assert text_type(ctx.value) == expected_failure_message
assert str(ctx.value) == expected_failure_message
else:
validate_uploaded_image(uploaded_file)
assert uploaded_file.tell() == 0
@ddt.data(
(99, u"The file must be at least 100 bytes in size."),
(99, "The file must be at least 100 bytes in size."),
(100, ),
(1024, ),
(1025, u"The file must be smaller than 1 KB in size."),
(1025, "The file must be smaller than 1 KB in size."),
)
@ddt.unpack
@override_settings(PROFILE_IMAGE_MIN_BYTES=100, PROFILE_IMAGE_MAX_BYTES=1024)
......@@ -93,8 +92,8 @@ class TestValidateUploadedImage(TestCase):
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.'
'The file name extension for this file does not match '
'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:
......@@ -108,7 +107,7 @@ class TestValidateUploadedImage(TestCase):
)
with pytest.raises(ImageValidationError) as ctx:
validate_uploaded_image(uploaded_file)
assert text_type(ctx.value) == file_upload_bad_ext
assert str(ctx.value) == file_upload_bad_ext
def test_content_type(self):
"""
......@@ -116,13 +115,13 @@ class TestValidateUploadedImage(TestCase):
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.'
'The Content-Type header for this file does not match '
'the file data. The file may be corrupted.'
)
with make_uploaded_file(extension=".jpeg", content_type="image/gif") as uploaded_file:
with pytest.raises(ImageValidationError) as ctx:
validate_uploaded_image(uploaded_file)
assert text_type(ctx.value) == file_upload_bad_mimetype
assert str(ctx.value) == file_upload_bad_mimetype
@ddt.ddt
......
"""
Test cases for the HTTP endpoints of the profile image api.
"""
from contextlib import closing
from unittest import mock
from unittest.mock import patch
import pytest
from contextlib import closing
import datetime
from pytz import UTC
......@@ -11,8 +13,6 @@ from django.urls import reverse
from django.http import HttpResponse
import ddt
import mock
from mock import patch
from PIL import Image
from rest_framework.test import APITestCase, APIClient
......@@ -44,7 +44,7 @@ class ProfileImageEndpointMixin(UserSettingsEventTestMixin):
_view_name = None
def setUp(self):
super(ProfileImageEndpointMixin, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
super().setUp()
self.user = UserFactory.create(password=TEST_PASSWORD)
# Ensure that parental controls don't apply to this user
self.user.profile.year_of_birth = 1980
......@@ -62,7 +62,7 @@ class ProfileImageEndpointMixin(UserSettingsEventTestMixin):
self.reset_tracker()
def tearDown(self):
super(ProfileImageEndpointMixin, self).tearDown() # lint-amnesty, pylint: disable=super-with-arguments
super().tearDown()
for name in get_profile_image_names(self.user.username).values():
self.storage.delete(name)
......@@ -212,7 +212,7 @@ class ProfileImageViewPostTestCase(ProfileImageEndpointMixin, APITestCase):
self.url,
data,
content_type=content_type,
HTTP_CONTENT_DISPOSITION='attachment;filename=filename{}'.format(extension),
HTTP_CONTENT_DISPOSITION=f'attachment;filename=filename{extension}',
)
self.check_response(response, 204)
self.check_images()
......@@ -297,8 +297,8 @@ class ProfileImageViewPostTestCase(ProfileImageEndpointMixin, APITestCase):
response = self.client.post(self.url, {}, format='multipart')
self.check_response(
response, 400,
expected_developer_message=u"No file provided for profile image",
expected_user_message=u"No file provided for profile image",
expected_developer_message="No file provided for profile image",
expected_user_message="No file provided for profile image",
)
self.check_images(False)
self.check_has_profile_image(False)
......@@ -313,8 +313,8 @@ class ProfileImageViewPostTestCase(ProfileImageEndpointMixin, APITestCase):
response = self.client.post(self.url, {'file': 'not a file'}, format='multipart')
self.check_response(
response, 400,
expected_developer_message=u"No file provided for profile image",
expected_user_message=u"No file provided for profile image",
expected_developer_message="No file provided for profile image",
expected_user_message="No file provided for profile image",
)
self.check_images(False)
self.check_has_profile_image(False)
......@@ -329,13 +329,13 @@ class ProfileImageViewPostTestCase(ProfileImageEndpointMixin, APITestCase):
with make_image_file() as image_file:
with mock.patch(
'openedx.core.djangoapps.profile_images.views.validate_uploaded_image',
side_effect=ImageValidationError(u"test error message")
side_effect=ImageValidationError("test error message")
):
response = self.client.post(self.url, {'file': image_file}, format='multipart')
self.check_response(
response, 400,
expected_developer_message=u"test error message",
expected_user_message=u"test error message",
expected_developer_message="test error message",
expected_user_message="test error message",
)
self.check_images(False)
self.check_has_profile_image(False)
......@@ -348,7 +348,7 @@ class ProfileImageViewPostTestCase(ProfileImageEndpointMixin, APITestCase):
Test that when upload validation fails, the proper HTTP response and
messages are returned.
"""
image_open.side_effect = [Exception(u"whoops"), None]
image_open.side_effect = [Exception("whoops"), None]
with make_image_file() as image_file:
with pytest.raises(Exception):
self.client.post(self.url, {'file': image_file}, format='multipart')
......@@ -367,7 +367,7 @@ class ProfileImageViewDeleteTestCase(ProfileImageEndpointMixin, APITestCase):
_view_name = "accounts_profile_image_api"
def setUp(self):
super(ProfileImageViewDeleteTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
super().setUp()
with make_image_file() as image_file:
create_profile_images(image_file, get_profile_image_names(self.user.username))
self.check_images()
......@@ -447,7 +447,7 @@ class ProfileImageViewDeleteTestCase(ProfileImageEndpointMixin, APITestCase):
Test that when remove validation fails, the proper HTTP response and
messages are returned.
"""
user_profile_save.side_effect = [Exception(u"whoops"), None]
user_profile_save.side_effect = [Exception("whoops"), None]
with pytest.raises(Exception):
self.client.delete(self.url)
self.check_images(True) # thumbnails should remain intact.
......
......@@ -16,7 +16,6 @@ from rest_framework import permissions, status
from rest_framework.parsers import FormParser, MultiPartParser
from rest_framework.response import Response
from rest_framework.views import APIView
from six import text_type
from openedx.core.djangoapps.user_api.accounts.image_helpers import get_profile_image_names, set_has_profile_image
from openedx.core.djangoapps.user_api.errors import UserNotFound
......@@ -30,8 +29,8 @@ from .images import IMAGE_TYPES, create_profile_images, remove_profile_images, v
log = logging.getLogger(__name__)
LOG_MESSAGE_CREATE = u'Generated and uploaded images %(image_names)s for user %(user_id)s'
LOG_MESSAGE_DELETE = u'Deleted images %(image_names)s for user %(user_id)s'
LOG_MESSAGE_CREATE = 'Generated and uploaded images %(image_names)s for user %(user_id)s'
LOG_MESSAGE_DELETE = 'Deleted images %(image_names)s for user %(user_id)s'
def _make_upload_dt():
......@@ -133,8 +132,8 @@ class ProfileImageView(DeveloperErrorViewMixin, APIView):
if 'file' not in request.FILES:
return Response(
{
"developer_message": u"No file provided for profile image",
"user_message": _(u"No file provided for profile image"),
"developer_message": "No file provided for profile image",
"user_message": _("No file provided for profile image"),
},
status=status.HTTP_400_BAD_REQUEST
......@@ -151,7 +150,7 @@ class ProfileImageView(DeveloperErrorViewMixin, APIView):
validate_uploaded_image(uploaded_file)
except ImageValidationError as error:
return Response(
{"developer_message": text_type(error), "user_message": error.user_message},
{"developer_message": str(error), "user_message": error.user_message},
status=status.HTTP_400_BAD_REQUEST,
)
......
......@@ -10,7 +10,7 @@ class ProgramsConfig(AppConfig):
"""
Default configuration for the "openedx.core.djangoapps.programs" Django application.
"""
name = u'openedx.core.djangoapps.programs'
name = 'openedx.core.djangoapps.programs'
def ready(self):
# noinspection PyUnresolvedReferences
......
......@@ -84,10 +84,10 @@ class Command(BaseCommand):
self._load_usernames(users=usernames)
if options.get('commit'):
logger.info(u'Enqueuing program certification tasks for %d candidates.', len(self.usernames))
logger.info('Enqueuing program certification tasks for %d candidates.', len(self.usernames))
else:
logger.info(
u'Found %d candidates. To enqueue program certification tasks, pass the -c or --commit flags.',
'Found %d candidates. To enqueue program certification tasks, pass the -c or --commit flags.',
len(self.usernames)
)
return
......@@ -98,14 +98,14 @@ class Command(BaseCommand):
award_program_certificates.delay(username)
except: # pylint: disable=bare-except
failed += 1
logger.exception(u'Failed to enqueue task for user [%s]', username)
logger.exception('Failed to enqueue task for user [%s]', username)
else:
succeeded += 1
logger.debug(u'Successfully enqueued task for user [%s]', username)
logger.debug('Successfully enqueued task for user [%s]', username)
logger.info(
u'Done. Successfully enqueued tasks for %d candidates. '
u'Failed to enqueue tasks for %d candidates.',
'Done. Successfully enqueued tasks for %d candidates. '
'Failed to enqueue tasks for %d candidates.',
succeeded,
failed
)
......@@ -117,7 +117,7 @@ class Command(BaseCommand):
programs.extend(get_programs(uuids=program_uuids))
else:
for site in Site.objects.all():
logger.info(u'Loading programs from the catalog for site %s.', site.domain)
logger.info('Loading programs from the catalog for site %s.', site.domain)
programs.extend(get_programs(site))
self.course_runs = self._flatten(programs)
......
# -*- coding: utf-8 -*-
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
......
# -*- coding: utf-8 -*-
from django.db import migrations, models
......
# -*- coding: utf-8 -*-
from django.db import migrations, models
......
# -*- coding: utf-8 -*-
from django.db import migrations, models
......
# -*- coding: utf-8 -*-
from django.db import migrations, models
......
# -*- coding: utf-8 -*-
from django.db import migrations, models
......
# -*- coding: utf-8 -*-
from django.db import migrations, models
......
# -*- coding: utf-8 -*-
from django.db import migrations, models
......
# -*- coding: utf-8 -*-
from django.db import migrations, models
......
# -*- coding: utf-8 -*-
from django.db import migrations, models
......
# -*- coding: utf-8 -*-
from django.db import migrations, models
......
# -*- coding: utf-8 -*-
from django.db import migrations, models
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment