From f9cfbf027c174efdf4af35b938666095bd643734 Mon Sep 17 00:00:00 2001 From: usamasadiq <usama.sadiq@arbisoft.com> Date: Tue, 16 Feb 2021 17:19:59 +0500 Subject: [PATCH] Ran pyupgrade on lms/djangoapps Ran pyupgrade on lms/djangoapps/lms_xblock Ran pyupgrade on lms/djangoapps/lti_provider --- lms/djangoapps/lms_xblock/apps.py | 4 +- lms/djangoapps/lms_xblock/field_data.py | 2 +- .../lms_xblock/migrations/0001_initial.py | 5 +- lms/djangoapps/lms_xblock/mixin.py | 27 +++++----- lms/djangoapps/lms_xblock/models.py | 4 +- lms/djangoapps/lms_xblock/runtime.py | 23 ++++---- .../lms_xblock/test/test_runtime.py | 16 +++--- .../management/commands/resend_lti_scores.py | 9 ++-- .../commands/tests/test_resend_lti_scores.py | 32 ++++++------ .../lti_provider/migrations/0001_initial.py | 6 +-- .../migrations/0002_auto_20160325_0407.py | 3 -- .../migrations/0003_auto_20161118_1040.py | 3 -- lms/djangoapps/lti_provider/models.py | 4 +- lms/djangoapps/lti_provider/outcomes.py | 18 +++---- lms/djangoapps/lti_provider/signals.py | 8 +-- .../lti_provider/signature_validator.py | 5 +- lms/djangoapps/lti_provider/tasks.py | 2 +- .../lti_provider/tests/test_outcomes.py | 13 ++--- .../tests/test_signature_validator.py | 11 ++-- .../lti_provider/tests/test_tasks.py | 14 ++--- .../lti_provider/tests/test_users.py | 17 +++--- .../lti_provider/tests/test_views.py | 52 +++++++++---------- lms/djangoapps/lti_provider/users.py | 7 ++- lms/djangoapps/lti_provider/views.py | 7 ++- 24 files changed, 140 insertions(+), 152 deletions(-) diff --git a/lms/djangoapps/lms_xblock/apps.py b/lms/djangoapps/lms_xblock/apps.py index 9b919fa1a2b..5abbb4b151f 100644 --- a/lms/djangoapps/lms_xblock/apps.py +++ b/lms/djangoapps/lms_xblock/apps.py @@ -12,8 +12,8 @@ class LMSXBlockConfig(AppConfig): """ Default configuration for the "lms.djangoapps.lms_xblock" Django application. """ - name = u'lms.djangoapps.lms_xblock' - verbose_name = u'LMS XBlock' + name = 'lms.djangoapps.lms_xblock' + verbose_name = 'LMS XBlock' def ready(self): from .runtime import handler_url, local_resource_url diff --git a/lms/djangoapps/lms_xblock/field_data.py b/lms/djangoapps/lms_xblock/field_data.py index 3c485b0718b..b5665dba3d2 100644 --- a/lms/djangoapps/lms_xblock/field_data.py +++ b/lms/djangoapps/lms_xblock/field_data.py @@ -24,7 +24,7 @@ class LmsFieldData(SplitFieldData): self._authored_data = authored_data self._student_data = student_data - super(LmsFieldData, self).__init__({ # lint-amnesty, pylint: disable=super-with-arguments + super().__init__({ Scope.content: authored_data, Scope.settings: authored_data, Scope.parent: authored_data, diff --git a/lms/djangoapps/lms_xblock/migrations/0001_initial.py b/lms/djangoapps/lms_xblock/migrations/0001_initial.py index 5d65c5d218b..acf42bf26fc 100644 --- a/lms/djangoapps/lms_xblock/migrations/0001_initial.py +++ b/lms/djangoapps/lms_xblock/migrations/0001_initial.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- - - import django.db.models.deletion from django.conf import settings from django.db import migrations, models @@ -19,7 +16,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')), ('enabled', models.BooleanField(default=False, verbose_name='Enabled')), - ('disabled_blocks', models.TextField(default=u'about course_info static_tab', help_text=u'Space-separated list of XBlocks on which XBlockAsides should never render.')), + ('disabled_blocks', models.TextField(default='about course_info static_tab', help_text='Space-separated list of XBlocks on which XBlockAsides should never render.')), ('changed_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, editable=False, to=settings.AUTH_USER_MODEL, null=True, verbose_name='Changed by')), ], options={ diff --git a/lms/djangoapps/lms_xblock/mixin.py b/lms/djangoapps/lms_xblock/mixin.py index 2f02074a3b0..dff3ba680ec 100644 --- a/lms/djangoapps/lms_xblock/mixin.py +++ b/lms/djangoapps/lms_xblock/mixin.py @@ -5,7 +5,6 @@ Namespace that defines fields common to all blocks used in the LMS #from django.utils.translation import ugettext_noop as _ -import six from lazy import lazy from xblock.core import XBlock, XBlockMixin from xblock.exceptions import JsonHandlerError @@ -21,16 +20,16 @@ from xmodule.partitions.partitions import NoSuchUserPartitionError, NoSuchUserPa _ = lambda text: text INVALID_USER_PARTITION_VALIDATION_COMPONENT = _( - u"This component's access settings refer to deleted or invalid group configurations." + "This component's access settings refer to deleted or invalid group configurations." ) INVALID_USER_PARTITION_VALIDATION_UNIT = _( - u"This unit's access settings refer to deleted or invalid group configurations." + "This unit's access settings refer to deleted or invalid group configurations." ) INVALID_USER_PARTITION_GROUP_VALIDATION_COMPONENT = _( - u"This component's access settings refer to deleted or invalid groups." + "This component's access settings refer to deleted or invalid groups." ) -INVALID_USER_PARTITION_GROUP_VALIDATION_UNIT = _(u"This unit's access settings refer to deleted or invalid groups.") -NONSENSICAL_ACCESS_RESTRICTION = _(u"This component's access settings contradict its parent's access settings.") +INVALID_USER_PARTITION_GROUP_VALIDATION_UNIT = _("This unit's access settings refer to deleted or invalid groups.") +NONSENSICAL_ACCESS_RESTRICTION = _("This component's access settings contradict its parent's access settings.") class GroupAccessDict(Dict): @@ -43,7 +42,7 @@ class GroupAccessDict(Dict): def to_json(self, value): if value is not None: - return {six.text_type(k): value[k] for k in value} + return {str(k): value[k] for k in value} @XBlock.needs('partitions') @@ -158,7 +157,7 @@ class LmsBlockMixin(XBlockMixin): if user_partition.id == user_partition_id: return user_partition - raise NoSuchUserPartitionError(u"could not find a UserPartition with ID [{}]".format(user_partition_id)) + raise NoSuchUserPartitionError(f"could not find a UserPartition with ID [{user_partition_id}]") def _has_nonsensical_access_settings(self): """ @@ -185,7 +184,7 @@ class LmsBlockMixin(XBlockMixin): parent_group_access = parent.group_access component_group_access = self.group_access - for user_partition_id, parent_group_ids in six.iteritems(parent_group_access): + for user_partition_id, parent_group_ids in parent_group_access.items(): component_group_ids = component_group_access.get(user_partition_id) # pylint: disable=no-member if component_group_ids: return parent_group_ids and not set(component_group_ids).issubset(set(parent_group_ids)) @@ -198,12 +197,12 @@ class LmsBlockMixin(XBlockMixin): Validates the state of this xblock instance. """ _ = self.runtime.service(self, "i18n").ugettext - validation = super(LmsBlockMixin, self).validate() # lint-amnesty, pylint: disable=super-with-arguments + validation = super().validate() has_invalid_user_partitions = False has_invalid_groups = False block_is_unit = is_unit(self) - for user_partition_id, group_ids in six.iteritems(self.group_access): + for user_partition_id, group_ids in self.group_access.items(): # lint-amnesty, pylint:disable=no-member try: user_partition = self._get_user_partition(user_partition_id) except NoSuchUserPartitionError: @@ -254,10 +253,10 @@ class LmsBlockMixin(XBlockMixin): """ completion_service = self.runtime.service(self, 'completion') if completion_service is None: # lint-amnesty, pylint: disable=no-else-raise - raise JsonHandlerError(500, u"No completion service found") + raise JsonHandlerError(500, "No completion service found") elif not completion_service.completion_tracking_enabled(): - raise JsonHandlerError(404, u"Completion tracking is not enabled and API calls are unexpected") + raise JsonHandlerError(404, "Completion tracking is not enabled and API calls are unexpected") if not completion_service.can_mark_block_complete_on_view(self): - raise JsonHandlerError(400, u"Block not configured for completion on view.") + raise JsonHandlerError(400, "Block not configured for completion on view.") self.runtime.publish(self, "completion", data) return {'result': 'ok'} diff --git a/lms/djangoapps/lms_xblock/models.py b/lms/djangoapps/lms_xblock/models.py index efab9609e1e..13b7b2e05d9 100644 --- a/lms/djangoapps/lms_xblock/models.py +++ b/lms/djangoapps/lms_xblock/models.py @@ -23,8 +23,8 @@ class XBlockAsidesConfig(ConfigurationModel): app_label = "lms_xblock" disabled_blocks = TextField( - default=u"about course_info static_tab", - help_text=u"Space-separated list of XBlocks on which XBlockAsides should never render." + default="about course_info static_tab", + help_text="Space-separated list of XBlocks on which XBlockAsides should never render." ) @classmethod diff --git a/lms/djangoapps/lms_xblock/runtime.py b/lms/djangoapps/lms_xblock/runtime.py index 3e64229d636..57e048aca03 100644 --- a/lms/djangoapps/lms_xblock/runtime.py +++ b/lms/djangoapps/lms_xblock/runtime.py @@ -3,7 +3,6 @@ Module implementing `xblock.runtime.Runtime` functionality for the LMS """ -import six import xblock.reference.plugins from completion.services import CompletionService from django.conf import settings @@ -46,7 +45,7 @@ def handler_url(block, handler_name, suffix='', query='', thirdparty=False): # to ask for handler URLs without a student context. func = getattr(block.__class__, handler_name, None) if not func: - raise ValueError(u"{!r} is not a function name".format(handler_name)) + raise ValueError(f"{handler_name!r} is not a function name") # Is the following necessary? ProxyAttribute causes an UndefinedContext error # if trying this without the module system. @@ -58,8 +57,8 @@ def handler_url(block, handler_name, suffix='', query='', thirdparty=False): view_name = 'xblock_handler_noauth' url = reverse(view_name, kwargs={ - 'course_id': six.text_type(block.location.course_key), - 'usage_id': quote_slashes(six.text_type(block.scope_ids.usage_id)), + 'course_id': str(block.location.course_key), + 'usage_id': quote_slashes(str(block.scope_ids.usage_id)), 'handler': handler_name, 'suffix': suffix, }) @@ -91,7 +90,7 @@ def local_resource_url(block, uri): return xblock_local_resource_url(block, uri) -class UserTagsService(object): +class UserTagsService: """ A runtime class that provides an interface to the user service. It handles filling in the current course id and current user. @@ -115,7 +114,7 @@ class UserTagsService(object): key: the key for the value we want """ if scope != user_course_tag_api.COURSE_SCOPE: - raise ValueError(u"unexpected scope {0}".format(scope)) + raise ValueError(f"unexpected scope {scope}") return user_course_tag_api.get_course_tag( self._get_current_user(), @@ -131,7 +130,7 @@ class UserTagsService(object): value: the value to set """ if scope != user_course_tag_api.COURSE_SCOPE: - raise ValueError(u"unexpected scope {0}".format(scope)) + raise ValueError(f"unexpected scope {scope}") return user_course_tag_api.set_course_tag( self._get_current_user(), @@ -166,7 +165,7 @@ class LmsModuleSystem(ModuleSystem): # pylint: disable=abstract-method services['teams'] = TeamsService() services['teams_configuration'] = TeamsConfigurationService() services['call_to_action'] = CallToActionService() - super(LmsModuleSystem, self).__init__(**kwargs) # lint-amnesty, pylint: disable=super-with-arguments + super().__init__(**kwargs) def handler_url(self, *args, **kwargs): # lint-amnesty, pylint: disable=signature-differs """ @@ -205,8 +204,8 @@ class LmsModuleSystem(ModuleSystem): # pylint: disable=abstract-method runtime_class = 'LmsRuntime' extra_data = { - 'block-id': quote_slashes(six.text_type(block.scope_ids.usage_id)), - 'course-id': quote_slashes(six.text_type(block.course_id)), + 'block-id': quote_slashes(str(block.scope_ids.usage_id)), + 'course-id': quote_slashes(str(block.course_id)), 'url-selector': 'asideBaseUrl', 'runtime-class': runtime_class, } @@ -219,7 +218,7 @@ class LmsModuleSystem(ModuleSystem): # pylint: disable=abstract-method view, frag, context, - usage_id_serializer=six.text_type, + usage_id_serializer=str, request_token=self.request_token, extra_data=extra_data, ) @@ -244,6 +243,6 @@ class LmsModuleSystem(ModuleSystem): # pylint: disable=abstract-method # (see https://openedx.atlassian.net/browse/TE-811) return [ aside_type - for aside_type in super(LmsModuleSystem, self).applicable_aside_types(block) # lint-amnesty, pylint: disable=super-with-arguments + for aside_type in super().applicable_aside_types(block) if aside_type != 'acid_aside' ] diff --git a/lms/djangoapps/lms_xblock/test/test_runtime.py b/lms/djangoapps/lms_xblock/test/test_runtime.py index ada67de9e1d..67632e7e0cf 100644 --- a/lms/djangoapps/lms_xblock/test/test_runtime.py +++ b/lms/djangoapps/lms_xblock/test/test_runtime.py @@ -2,21 +2,23 @@ Tests of the LMS XBlock Runtime and associated utilities """ + +from unittest.mock import Mock, patch +from urllib.parse import urlparse + import pytest from ddt import data, ddt from django.conf import settings from django.test import TestCase -from mock import Mock, patch from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.locations import BlockUsageLocator, CourseLocator -from six.moves.urllib.parse import urlparse from xblock.exceptions import NoSuchServiceError from xblock.fields import ScopeIds +from common.djangoapps.student.tests.factories import UserFactory from lms.djangoapps.badges.tests.factories import BadgeClassFactory from lms.djangoapps.badges.tests.test_models import get_image from lms.djangoapps.lms_xblock.runtime import LmsModuleSystem -from common.djangoapps.student.tests.factories import UserFactory from xmodule.modulestore.django import ModuleI18nService from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory @@ -54,7 +56,7 @@ class TestHandlerUrl(TestCase): """Test the LMS handler_url""" def setUp(self): - super(TestHandlerUrl, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.block = BlockMock(name='block', scope_ids=ScopeIds(None, None, None, 'dummy')) self.course_key = CourseLocator("org", "course", "run") self.runtime = LmsModuleSystem( @@ -119,7 +121,7 @@ class TestUserServiceAPI(TestCase): """Test the user service interface""" def setUp(self): - super(TestUserServiceAPI, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.course_id = CourseLocator("org", "course", "run") self.user = UserFactory.create() @@ -169,7 +171,7 @@ class TestBadgingService(ModuleStoreTestCase): """Test the badging service interface""" def setUp(self): - super(TestBadgingService, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.course_id = CourseKey.from_string('course-v1:org+course+run') self.mock_block = Mock() @@ -235,7 +237,7 @@ class TestI18nService(ModuleStoreTestCase): def setUp(self): """ Setting up tests """ - super(TestI18nService, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.course = CourseFactory.create() self.test_language = 'dummy language' self.runtime = LmsModuleSystem( diff --git a/lms/djangoapps/lti_provider/management/commands/resend_lti_scores.py b/lms/djangoapps/lti_provider/management/commands/resend_lti_scores.py index 95b8a191650..3e44a201e13 100644 --- a/lms/djangoapps/lti_provider/management/commands/resend_lti_scores.py +++ b/lms/djangoapps/lti_provider/management/commands/resend_lti_scores.py @@ -5,7 +5,6 @@ Management command to resend all lti scores for the requested course. import textwrap -import six from django.core.management import BaseCommand from opaque_keys.edx.keys import CourseKey @@ -29,11 +28,11 @@ class Command(BaseCommand): help = textwrap.dedent(__doc__) def add_arguments(self, parser): - parser.add_argument(u'course_keys', type=CourseKey.from_string, nargs='*') + parser.add_argument('course_keys', type=CourseKey.from_string, nargs='*') def handle(self, *args, **options): - if options[u'course_keys']: - for course_key in options[u'course_keys']: + if options['course_keys']: + for course_key in options['course_keys']: for assignment in self._iter_course_assignments(course_key): self._send_score(assignment) else: @@ -46,7 +45,7 @@ class Command(BaseCommand): """ tasks.send_composite_outcome.delay( assignment.user_id, - six.text_type(assignment.course_key), + str(assignment.course_key), assignment.id, assignment.version_number, ) diff --git a/lms/djangoapps/lti_provider/management/commands/tests/test_resend_lti_scores.py b/lms/djangoapps/lti_provider/management/commands/tests/test_resend_lti_scores.py index 5f429ee5e57..200c7003ce9 100644 --- a/lms/djangoapps/lti_provider/management/commands/tests/test_resend_lti_scores.py +++ b/lms/djangoapps/lti_provider/management/commands/tests/test_resend_lti_scores.py @@ -3,14 +3,14 @@ Test lti_provider management commands. """ -import six +from unittest.mock import patch + from django.test import TestCase -from mock import patch from opaque_keys.edx.keys import CourseKey, UsageKey +from common.djangoapps.student.tests.factories import UserFactory from lms.djangoapps.lti_provider.management.commands import resend_lti_scores from lms.djangoapps.lti_provider.models import GradedAssignment, LtiConsumer, OutcomeService -from common.djangoapps.student.tests.factories import UserFactory from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.utils import TEST_DATA_DIR from xmodule.modulestore.xml_importer import import_course_from_xml @@ -34,7 +34,7 @@ class CommandArgsTestCase(TestCase): assert len(args.course_keys) == 2 key = args.course_keys[0] assert isinstance(key, CourseKey) - assert six.text_type(key) == 'course-v1:edX+test_course+2525_fall' + assert str(key) == 'course-v1:edX+test_course+2525_fall' def test_no_course_keys(self): parser = self._get_arg_parser() @@ -49,25 +49,25 @@ class CommandExecutionTestCase(SharedModuleStoreTestCase): @classmethod def setUpClass(cls): - super(CommandExecutionTestCase, cls).setUpClass() - cls.course_key = cls.store.make_course_key(u'edX', u'lti_provider', u'3000') + super().setUpClass() + cls.course_key = cls.store.make_course_key('edX', 'lti_provider', '3000') import_course_from_xml( cls.store, - u'test_user', + 'test_user', TEST_DATA_DIR, - source_dirs=[u'simple'], + source_dirs=['simple'], static_content_store=None, target_id=cls.course_key, raise_on_failure=True, create_if_not_present=True, ) - cls.lti_block = u'block-v1:edX+lti_provider+3000+type@chapter+block@chapter_2' + cls.lti_block = 'block-v1:edX+lti_provider+3000+type@chapter+block@chapter_2' def setUp(self): - super(CommandExecutionTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.user = UserFactory() - self.user2 = UserFactory(username=u'anotheruser') - self.client.login(username=self.user.username, password=u'test') + self.user2 = UserFactory(username='anotheruser') + self.client.login(username=self.user.username, password='test') def _configure_lti(self, usage_key): """ @@ -76,21 +76,21 @@ class CommandExecutionTestCase(SharedModuleStoreTestCase): consumer = LtiConsumer.objects.create() outcome_service = OutcomeService.objects.create( lti_consumer=consumer, - lis_outcome_service_url=u'https://lol.tools' + lis_outcome_service_url='https://lol.tools' ) GradedAssignment.objects.create( user=self.user, course_key=self.course_key, usage_key=usage_key, outcome_service=outcome_service, - lis_result_sourcedid=u'abc', + lis_result_sourcedid='abc', ) GradedAssignment.objects.create( user=self.user2, course_key=self.course_key, usage_key=usage_key, outcome_service=outcome_service, - lis_result_sourcedid=u'xyz', + lis_result_sourcedid='xyz', ) def _scores_sent_with_args(self, *args, **kwargs): @@ -111,5 +111,5 @@ class CommandExecutionTestCase(SharedModuleStoreTestCase): assert self._scores_sent_with_args(course_keys=[self.course_key]) def test_command_with_wrong_course_key(self): - fake_course_key = self.store.make_course_key(u'not', u'the', u'course') + fake_course_key = self.store.make_course_key('not', 'the', 'course') assert not self._scores_sent_with_args(course_keys=[fake_course_key]) diff --git a/lms/djangoapps/lti_provider/migrations/0001_initial.py b/lms/djangoapps/lti_provider/migrations/0001_initial.py index e4205c153cd..a61437e155d 100644 --- a/lms/djangoapps/lti_provider/migrations/0001_initial.py +++ b/lms/djangoapps/lti_provider/migrations/0001_initial.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - from openedx.core.lib.hash_utils import create_hash256, short_token from django.conf import settings @@ -63,10 +61,10 @@ class Migration(migrations.Migration): ), migrations.AlterUniqueTogether( name='ltiuser', - unique_together=set([('lti_consumer', 'lti_user_id')]), + unique_together={('lti_consumer', 'lti_user_id')}, ), migrations.AlterUniqueTogether( name='gradedassignment', - unique_together=set([('outcome_service', 'lis_result_sourcedid')]), + unique_together={('outcome_service', 'lis_result_sourcedid')}, ), ] diff --git a/lms/djangoapps/lti_provider/migrations/0002_auto_20160325_0407.py b/lms/djangoapps/lti_provider/migrations/0002_auto_20160325_0407.py index 10118670950..ab55f138937 100644 --- a/lms/djangoapps/lti_provider/migrations/0002_auto_20160325_0407.py +++ b/lms/djangoapps/lti_provider/migrations/0002_auto_20160325_0407.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- - - from openedx.core.lib.hash_utils import short_token from django.db import migrations, models diff --git a/lms/djangoapps/lti_provider/migrations/0003_auto_20161118_1040.py b/lms/djangoapps/lti_provider/migrations/0003_auto_20161118_1040.py index 44690ecb1ff..749ea8f75c5 100644 --- a/lms/djangoapps/lti_provider/migrations/0003_auto_20161118_1040.py +++ b/lms/djangoapps/lti_provider/migrations/0003_auto_20161118_1040.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- - - from django.db import migrations, models import openedx.core.djangolib.fields diff --git a/lms/djangoapps/lti_provider/models.py b/lms/djangoapps/lti_provider/models.py index a0969171029..0cb165eeef6 100644 --- a/lms/djangoapps/lti_provider/models.py +++ b/lms/djangoapps/lti_provider/models.py @@ -125,7 +125,7 @@ class GradedAssignment(models.Model): lis_result_sourcedid = models.CharField(max_length=255, db_index=True) version_number = models.IntegerField(default=0) - class Meta(object): + class Meta: unique_together = ('outcome_service', 'lis_result_sourcedid') @@ -142,5 +142,5 @@ class LtiUser(models.Model): lti_user_id = models.CharField(max_length=255) edx_user = models.OneToOneField(User, on_delete=models.CASCADE) - class Meta(object): + class Meta: unique_together = ('lti_consumer', 'lti_user_id') diff --git a/lms/djangoapps/lti_provider/outcomes.py b/lms/djangoapps/lti_provider/outcomes.py index 9463cbff94f..650c3ba77b0 100644 --- a/lms/djangoapps/lti_provider/outcomes.py +++ b/lms/djangoapps/lti_provider/outcomes.py @@ -38,9 +38,9 @@ def store_outcome_parameters(request_params, user, lti_consumer): # to figure out the result service URL. As it stands, though, this # is a badly-formed LTI request log.warning( - u"Outcome Service: lis_outcome_service_url parameter missing " - u"from scored assignment; we will be unable to return a score. " - u"Request parameters: %s", + "Outcome Service: lis_outcome_service_url parameter missing " + "from scored assignment; we will be unable to return a score. " + "Request parameters: %s", request_params ) return @@ -141,8 +141,8 @@ def send_score_update(assignment, score): # necessary. if not (response and check_replace_result_response(response)): log.error( - u"Outcome Service: Failed to update score on LTI consumer. " - u"User: %s, course: %s, usage: %s, score: %s, status: %s, body: %s", + "Outcome Service: Failed to update score on LTI consumer. " + "User: %s, course: %s, usage: %s, score: %s, status: %s, body: %s", assignment.user, assignment.course_key, assignment.usage_key, @@ -192,7 +192,7 @@ def check_replace_result_response(response): # Pylint doesn't recognize members in the LXML module if response.status_code != 200: log.error( - u"Outcome service response: Unexpected status code %s", + "Outcome service response: Unexpected status code %s", response.status_code ) return False @@ -201,7 +201,7 @@ def check_replace_result_response(response): xml = response.content root = etree.fromstring(xml) except etree.ParseError as ex: - log.error(u"Outcome service response: Failed to parse XML: %s\n %s", ex, xml) + log.error("Outcome service response: Failed to parse XML: %s\n %s", ex, xml) return False major_codes = root.xpath( @@ -209,14 +209,14 @@ def check_replace_result_response(response): namespaces={'ns': 'http://www.imsglobal.org/services/ltiv1p1/xsd/imsoms_v1p0'}) if len(major_codes) != 1: log.error( - u"Outcome service response: Expected exactly one imsx_codeMajor field in response. Received %s", + "Outcome service response: Expected exactly one imsx_codeMajor field in response. Received %s", major_codes ) return False if major_codes[0].text != 'success': log.error( - u"Outcome service response: Unexpected major code: %s.", + "Outcome service response: Unexpected major code: %s.", major_codes[0].text ) return False diff --git a/lms/djangoapps/lti_provider/signals.py b/lms/djangoapps/lti_provider/signals.py index 896932c6893..fd5657c08cc 100644 --- a/lms/djangoapps/lti_provider/signals.py +++ b/lms/djangoapps/lti_provider/signals.py @@ -10,9 +10,9 @@ from opaque_keys.edx.keys import LearningContextKey import lms.djangoapps.lti_provider.outcomes as outcomes from lms.djangoapps.grades.api import signals as grades_signals +from lms.djangoapps.lti_provider.tasks import send_composite_outcome, send_leaf_outcome from lms.djangoapps.lti_provider.views import parse_course_and_usage_keys from xmodule.modulestore.django import modulestore -from lms.djangoapps.lti_provider.tasks import send_composite_outcome, send_leaf_outcome log = logging.getLogger(__name__) @@ -70,8 +70,8 @@ def score_changed_handler(sender, **kwargs): # pylint: disable=unused-argument ) else: log.error( - u"Outcome Service: Required signal parameter is None. " - u"points_possible: %s, points_earned: %s, user_id: %s, " - u"course_id: %s, usage_id: %s", + "Outcome Service: Required signal parameter is None. " + "points_possible: %s, points_earned: %s, user_id: %s, " + "course_id: %s, usage_id: %s", points_possible, points_earned, user_id, course_id, usage_id ) diff --git a/lms/djangoapps/lti_provider/signature_validator.py b/lms/djangoapps/lti_provider/signature_validator.py index b48ca9615e2..a17bd41ffda 100644 --- a/lms/djangoapps/lti_provider/signature_validator.py +++ b/lms/djangoapps/lti_provider/signature_validator.py @@ -3,7 +3,6 @@ Subclass of oauthlib's RequestValidator that checks an OAuth signature. """ -import six from oauthlib.oauth1 import RequestValidator, SignatureOnlyEndpoint @@ -18,7 +17,7 @@ class SignatureValidator(RequestValidator): """ def __init__(self, lti_consumer): - super(SignatureValidator, self).__init__() # lint-amnesty, pylint: disable=super-with-arguments + super().__init__() self.endpoint = SignatureOnlyEndpoint(self) self.lti_consumer = lti_consumer @@ -99,7 +98,7 @@ class SignatureValidator(RequestValidator): :return: True if the signature matches, False if it does not. """ - method = six.text_type(request.method) + method = str(request.method) url = request.build_absolute_uri() body = request.body diff --git a/lms/djangoapps/lti_provider/tasks.py b/lms/djangoapps/lti_provider/tasks.py index 60c19b59232..7e9a803371b 100644 --- a/lms/djangoapps/lti_provider/tasks.py +++ b/lms/djangoapps/lti_provider/tasks.py @@ -46,7 +46,7 @@ def send_composite_outcome(user_id, course_id, assignment_id, version): assignment = GradedAssignment.objects.get(id=assignment_id) if version != assignment.version_number: log.info( - u"Score passback for GradedAssignment %s skipped. More recent score available.", + "Score passback for GradedAssignment %s skipped. More recent score available.", assignment.id ) return diff --git a/lms/djangoapps/lti_provider/tests/test_outcomes.py b/lms/djangoapps/lti_provider/tests/test_outcomes.py index bb6420e648d..58c98b9be47 100644 --- a/lms/djangoapps/lti_provider/tests/test_outcomes.py +++ b/lms/djangoapps/lti_provider/tests/test_outcomes.py @@ -3,14 +3,15 @@ Tests for the LTI outcome service handlers, both in outcomes.py and in tasks.py """ +from unittest.mock import ANY, MagicMock, patch + from django.test import TestCase from lxml import etree -from mock import ANY, MagicMock, patch from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator import lms.djangoapps.lti_provider.outcomes as outcomes -from lms.djangoapps.lti_provider.models import GradedAssignment, LtiConsumer, OutcomeService from common.djangoapps.student.tests.factories import UserFactory +from lms.djangoapps.lti_provider.models import GradedAssignment, LtiConsumer, OutcomeService from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, check_mongo_calls @@ -21,7 +22,7 @@ class StoreOutcomeParametersTest(TestCase): """ def setUp(self): - super(StoreOutcomeParametersTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.user = UserFactory.create() self.course_key = CourseLocator( org='some_org', @@ -135,7 +136,7 @@ class SignAndSendReplaceResultTest(TestCase): """ def setUp(self): - super(SignAndSendReplaceResultTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.course_key = CourseLocator( org='some_org', course='some_course', @@ -185,7 +186,7 @@ class XmlHandlingTest(TestCase): methods in outcomes.py """ - response_xml = u""" + response_xml = """ <imsx_POXEnvelopeResponse xmlns = "http://www.imsglobal.org/services/ltiv1p1/xsd/imsoms_v1p0"> <imsx_POXHeader> <imsx_POXResponseHeaderInfo> @@ -298,7 +299,7 @@ class TestAssignmentsForProblem(ModuleStoreTestCase): """ def setUp(self): - super(TestAssignmentsForProblem, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.user = UserFactory.create() self.user_id = self.user.id self.outcome_service = self.create_outcome_service('outcomes') diff --git a/lms/djangoapps/lti_provider/tests/test_signature_validator.py b/lms/djangoapps/lti_provider/tests/test_signature_validator.py index c66e572555d..2c92df8984a 100644 --- a/lms/djangoapps/lti_provider/tests/test_signature_validator.py +++ b/lms/djangoapps/lti_provider/tests/test_signature_validator.py @@ -3,10 +3,11 @@ Tests for the SignatureValidator class. """ +from unittest.mock import patch + import ddt from django.test import TestCase from django.test.client import RequestFactory -from mock import patch from lms.djangoapps.lti_provider.models import LtiConsumer from lms.djangoapps.lti_provider.signature_validator import SignatureValidator @@ -30,7 +31,7 @@ class ClientKeyValidatorTest(TestCase): """ def setUp(self): - super(ClientKeyValidatorTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.lti_consumer = get_lti_consumer() def test_valid_client_key(self): @@ -60,7 +61,7 @@ class NonceValidatorTest(TestCase): """ def setUp(self): - super(NonceValidatorTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.lti_consumer = get_lti_consumer() def test_valid_nonce(self): @@ -91,7 +92,7 @@ class SignatureValidatorTest(TestCase): """ def setUp(self): - super(SignatureValidatorTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.lti_consumer = get_lti_consumer() def test_get_existing_client_secret(self): @@ -110,7 +111,7 @@ class SignatureValidatorTest(TestCase): Verify that the signature validaton library method is called using the correct parameters derived from the HttpRequest. """ - body = u'oauth_signature_method=HMAC-SHA1&oauth_version=1.0' + body = 'oauth_signature_method=HMAC-SHA1&oauth_version=1.0' content_type = 'application/x-www-form-urlencoded' request = RequestFactory().post('/url', body, content_type=content_type) headers = {'Content-Type': content_type} diff --git a/lms/djangoapps/lti_provider/tests/test_tasks.py b/lms/djangoapps/lti_provider/tests/test_tasks.py index a8ca2fed049..f8c98cbdffe 100644 --- a/lms/djangoapps/lti_provider/tests/test_tasks.py +++ b/lms/djangoapps/lti_provider/tests/test_tasks.py @@ -3,15 +3,15 @@ Tests for the LTI outcome service handlers, both in outcomes.py and in tasks.py """ +from unittest.mock import MagicMock, patch + import ddt -import six from django.test import TestCase -from mock import MagicMock, patch from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator import lms.djangoapps.lti_provider.tasks as tasks -from lms.djangoapps.lti_provider.models import GradedAssignment, LtiConsumer, OutcomeService from common.djangoapps.student.tests.factories import UserFactory +from lms.djangoapps.lti_provider.models import GradedAssignment, LtiConsumer, OutcomeService class BaseOutcomeTest(TestCase): @@ -19,7 +19,7 @@ class BaseOutcomeTest(TestCase): Super type for tests of both the leaf and composite outcome celery tasks. """ def setUp(self): - super(BaseOutcomeTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.course_key = CourseLocator( org='some_org', course='some_course', @@ -96,7 +96,7 @@ class SendCompositeOutcomeTest(BaseOutcomeTest): """ def setUp(self): - super(SendCompositeOutcomeTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.descriptor = MagicMock() self.descriptor.location = BlockUsageLocator( course_key=self.course_key, @@ -123,7 +123,7 @@ class SendCompositeOutcomeTest(BaseOutcomeTest): def test_outcome_with_score_score(self, earned, possible, expected): self.course_grade.score_for_module = MagicMock(return_value=(earned, possible)) tasks.send_composite_outcome( - self.user.id, six.text_type(self.course_key), self.assignment.id, 1 + self.user.id, str(self.course_key), self.assignment.id, 1 ) self.send_score_update_mock.assert_called_once_with(self.assignment, expected) @@ -131,6 +131,6 @@ class SendCompositeOutcomeTest(BaseOutcomeTest): self.assignment.version_number = 2 self.assignment.save() tasks.send_composite_outcome( - self.user.id, six.text_type(self.course_key), self.assignment.id, 1 + self.user.id, str(self.course_key), self.assignment.id, 1 ) assert self.course_grade_mock.call_count == 0 diff --git a/lms/djangoapps/lti_provider/tests/test_users.py b/lms/djangoapps/lti_provider/tests/test_users.py index 31c0e27c3a6..867cdb31a83 100644 --- a/lms/djangoapps/lti_provider/tests/test_users.py +++ b/lms/djangoapps/lti_provider/tests/test_users.py @@ -4,17 +4,18 @@ Tests for the LTI user management functionality import string +from unittest.mock import MagicMock, PropertyMock, patch + import pytest from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user from django.core.exceptions import PermissionDenied from django.test import TestCase from django.test.client import RequestFactory -from mock import MagicMock, PropertyMock, patch -from six.moves import range + +from common.djangoapps.student.tests.factories import UserFactory from .. import users from ..models import LtiConsumer, LtiUser -from common.djangoapps.student.tests.factories import UserFactory # lint-amnesty, pylint: disable=wrong-import-order class UserManagementHelperTest(TestCase): @@ -23,7 +24,7 @@ class UserManagementHelperTest(TestCase): """ def setUp(self): - super(UserManagementHelperTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.request = RequestFactory().post('/') self.old_user = UserFactory.create() self.new_user = UserFactory.create() @@ -68,7 +69,7 @@ class UserManagementHelperTest(TestCase): # Check that the username contains only allowable characters for char in range(len(username)): # lint-amnesty, pylint: disable=consider-using-enumerate assert username[char] in (string.ascii_letters + string.digits), \ - u"Username has forbidden character '{}'".format(username[char]) + "Username has forbidden character '{}'".format(username[char]) @patch('lms.djangoapps.lti_provider.users.switch_user', autospec=True) @@ -79,7 +80,7 @@ class AuthenticateLtiUserTest(TestCase): """ def setUp(self): - super(AuthenticateLtiUserTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.lti_consumer = LtiConsumer( consumer_name='TestConsumer', consumer_key='TestKey', @@ -146,7 +147,7 @@ class CreateLtiUserTest(TestCase): """ def setUp(self): - super(CreateLtiUserTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.lti_consumer = LtiConsumer( consumer_name='TestConsumer', consumer_key='TestKey', @@ -183,7 +184,7 @@ class LtiBackendTest(TestCase): """ def setUp(self): - super(LtiBackendTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.edx_user = UserFactory.create() self.edx_user.save() self.lti_consumer = LtiConsumer( diff --git a/lms/djangoapps/lti_provider/tests/test_views.py b/lms/djangoapps/lti_provider/tests/test_views.py index abe72f4ceca..082b53a2bc0 100644 --- a/lms/djangoapps/lti_provider/tests/test_views.py +++ b/lms/djangoapps/lti_provider/tests/test_views.py @@ -3,36 +3,36 @@ Tests for the LTI provider views """ -import six +from unittest.mock import MagicMock, patch + from django.test import TestCase from django.test.client import RequestFactory from django.urls import reverse -from mock import MagicMock, patch from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator +from common.djangoapps.student.tests.factories import UserFactory from lms.djangoapps.courseware.testutils import RenderXBlockTestMixin from lms.djangoapps.lti_provider import models, views -from common.djangoapps.student.tests.factories import UserFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase LTI_DEFAULT_PARAMS = { - 'roles': u'Instructor,urn:lti:instrole:ims/lis/Administrator', - 'context_id': u'lti_launch_context_id', - 'oauth_version': u'1.0', - 'oauth_consumer_key': u'consumer_key', - 'oauth_signature': u'OAuth Signature', - 'oauth_signature_method': u'HMAC-SHA1', - 'oauth_timestamp': u'OAuth Timestamp', - 'oauth_nonce': u'OAuth Nonce', - 'user_id': u'LTI_User', + 'roles': 'Instructor,urn:lti:instrole:ims/lis/Administrator', + 'context_id': 'lti_launch_context_id', + 'oauth_version': '1.0', + 'oauth_consumer_key': 'consumer_key', + 'oauth_signature': 'OAuth Signature', + 'oauth_signature_method': 'HMAC-SHA1', + 'oauth_timestamp': 'OAuth Timestamp', + 'oauth_nonce': 'OAuth Nonce', + 'user_id': 'LTI_User', } LTI_OPTIONAL_PARAMS = { - 'context_title': u'context title', - 'context_label': u'context label', - 'lis_result_sourcedid': u'result sourcedid', - 'lis_outcome_service_url': u'outcome service URL', - 'tool_consumer_instance_guid': u'consumer instance guid' + 'context_title': 'context title', + 'context_label': 'context label', + 'lis_result_sourcedid': 'result sourcedid', + 'lis_outcome_service_url': 'outcome service URL', + 'tool_consumer_instance_guid': 'consumer instance guid' } COURSE_KEY = CourseLocator(org='some_org', course='some_course', run='some_run') @@ -62,13 +62,13 @@ def build_launch_request(extra_post_data=None, param_to_delete=None): return request -class LtiTestMixin(object): +class LtiTestMixin: """ Mixin for LTI tests """ @patch.dict('django.conf.settings.FEATURES', {'ENABLE_LTI_PROVIDER': True}) def setUp(self): - super(LtiTestMixin, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() # Always accept the OAuth signature self.mock_verify = MagicMock(return_value=True) patcher = patch('lms.djangoapps.lti_provider.signature_validator.SignatureValidator.verify', self.mock_verify) @@ -94,7 +94,7 @@ class LtiLaunchTest(LtiTestMixin, TestCase): Verifies that the LTI launch succeeds when passed a valid request. """ request = build_launch_request() - views.lti_launch(request, six.text_type(COURSE_KEY), six.text_type(USAGE_KEY)) + views.lti_launch(request, str(COURSE_KEY), str(USAGE_KEY)) render.assert_called_with(request, USAGE_KEY) @patch('lms.djangoapps.lti_provider.views.render_courseware') @@ -105,7 +105,7 @@ class LtiLaunchTest(LtiTestMixin, TestCase): Verifies that the LTI launch succeeds when passed a valid request. """ request = build_launch_request(extra_post_data=LTI_OPTIONAL_PARAMS) - views.lti_launch(request, six.text_type(COURSE_KEY), six.text_type(USAGE_KEY)) + views.lti_launch(request, str(COURSE_KEY), str(USAGE_KEY)) store_params.assert_called_with( dict(list(ALL_PARAMS.items()) + list(LTI_OPTIONAL_PARAMS.items())), request.user, @@ -122,8 +122,8 @@ class LtiLaunchTest(LtiTestMixin, TestCase): request = build_launch_request() views.lti_launch( request, - six.text_type(COURSE_PARAMS['course_key']), - six.text_type(COURSE_PARAMS['usage_key']) + str(COURSE_PARAMS['course_key']), + str(COURSE_PARAMS['usage_key']) ) store_params.assert_called_with(ALL_PARAMS, request.user, self.consumer) @@ -175,7 +175,7 @@ class LtiLaunchTest(LtiTestMixin, TestCase): consumer = models.LtiConsumer.objects.get( consumer_key=LTI_DEFAULT_PARAMS['oauth_consumer_key'] ) - assert consumer.instance_guid == u'consumer instance guid' + assert consumer.instance_guid == 'consumer instance guid' class LtiLaunchTestRender(LtiTestMixin, RenderXBlockTestMixin, ModuleStoreTestCase): @@ -192,8 +192,8 @@ class LtiLaunchTestRender(LtiTestMixin, RenderXBlockTestMixin, ModuleStoreTestCa lti_launch_url = reverse( 'lti_provider_launch', kwargs={ - 'course_id': six.text_type(self.course.id), - 'usage_id': six.text_type(usage_key) + 'course_id': str(self.course.id), + 'usage_id': str(usage_key) } ) if url_encoded_params: diff --git a/lms/djangoapps/lti_provider/users.py b/lms/djangoapps/lti_provider/users.py index 775c6832b00..eabf821065e 100644 --- a/lms/djangoapps/lti_provider/users.py +++ b/lms/djangoapps/lti_provider/users.py @@ -13,10 +13,9 @@ from django.contrib.auth import authenticate, login from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user from django.core.exceptions import PermissionDenied from django.db import IntegrityError, transaction -from six.moves import range -from lms.djangoapps.lti_provider.models import LtiUser from common.djangoapps.student.models import UserProfile +from lms.djangoapps.lti_provider.models import LtiUser def authenticate_lti_user(request, lti_user_id, lti_consumer): @@ -55,7 +54,7 @@ def create_lti_user(lti_user_id, lti_consumer): while not created: try: edx_user_id = generate_random_edx_username() - edx_email = "{}@{}".format(edx_user_id, settings.LTI_USER_EMAIL_DOMAIN) + edx_email = f"{edx_user_id}@{settings.LTI_USER_EMAIL_DOMAIN}" with transaction.atomic(): edx_user = User.objects.create_user( username=edx_user_id, @@ -112,7 +111,7 @@ def generate_random_edx_username(): return username -class LtiBackend(object): +class LtiBackend: """ A Django authentication backend that authenticates users via LTI. This backend will only return a User object if it is associated with an LTI diff --git a/lms/djangoapps/lti_provider/views.py b/lms/djangoapps/lti_provider/views.py index dfc01c9c8cb..261ccfe6e13 100644 --- a/lms/djangoapps/lti_provider/views.py +++ b/lms/djangoapps/lti_provider/views.py @@ -5,19 +5,18 @@ LTI Provider view functions import logging -import six from django.conf import settings from django.http import Http404, HttpResponseBadRequest, HttpResponseForbidden from django.views.decorators.csrf import csrf_exempt from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey, UsageKey +from common.djangoapps.util.views import add_p3p_header from lms.djangoapps.lti_provider.models import LtiConsumer from lms.djangoapps.lti_provider.outcomes import store_outcome_parameters from lms.djangoapps.lti_provider.signature_validator import SignatureValidator from lms.djangoapps.lti_provider.users import authenticate_lti_user from openedx.core.lib.url_utils import unquote_slashes -from common.djangoapps.util.views import add_p3p_header log = logging.getLogger("edx.lti_provider") @@ -78,7 +77,7 @@ def lti_launch(request, course_id, usage_id): course_key, usage_key = parse_course_and_usage_keys(course_id, usage_id) except InvalidKeyError: log.error( - u'Invalid course key %s or usage key %s from request %s', + 'Invalid course key %s or usage key %s from request %s', course_id, usage_id, request @@ -146,7 +145,7 @@ def render_courseware(request, usage_key): """ # return an HttpResponse object that contains the template and necessary context to render the courseware. from lms.djangoapps.courseware.views.views import render_xblock - return render_xblock(request, six.text_type(usage_key), check_if_enrolled=False) + return render_xblock(request, str(usage_key), check_if_enrolled=False) def parse_course_and_usage_keys(course_id, usage_id): -- GitLab