From 356f169a473d24910dc119c399e330c2a16cd97a Mon Sep 17 00:00:00 2001 From: Awais Qureshi Date: Thu, 18 Mar 2021 11:19:46 +0500 Subject: [PATCH] Pyupgrade in common/djangoapps/coursemodes. --- common/djangoapps/course_modes/admin.py | 10 +-- common/djangoapps/course_modes/helpers.py | 6 +- .../course_modes/migrations/0001_initial.py | 15 ++--- ...rsemode_expiration_datetime_is_explicit.py | 3 - .../migrations/0003_auto_20151113_1443.py | 3 - .../migrations/0004_auto_20151113_1457.py | 3 - .../migrations/0005_auto_20151217_0958.py | 5 +- .../migrations/0006_auto_20160208_1407.py | 3 - .../migrations/0007_coursemode_bulk_sku.py | 5 +- .../0008_course_key_field_to_foreign_key.py | 5 +- .../0009_suggested_prices_to_charfield.py | 5 +- ..._archived_suggested_prices_to_charfield.py | 5 +- ...1_change_regex_for_comma_separated_ints.py | 5 +- .../migrations/0012_historicalcoursemode.py | 11 ++-- .../migrations/0013_auto_20200115_2022.py | 1 - common/djangoapps/course_modes/models.py | 48 +++++++------- .../course_modes/rest_api/serializers.py | 2 +- .../rest_api/v1/tests/test_views.py | 20 +++--- .../course_modes/rest_api/v1/urls.py | 4 +- .../course_modes/rest_api/v1/views.py | 2 +- .../course_modes/tests/factories.py | 6 +- .../course_modes/tests/test_admin.py | 6 +- .../course_modes/tests/test_models.py | 35 +++++----- .../course_modes/tests/test_signals.py | 4 +- .../course_modes/tests/test_views.py | 66 +++++++++---------- common/djangoapps/course_modes/urls.py | 4 +- common/djangoapps/course_modes/views.py | 20 +++--- 27 files changed, 134 insertions(+), 168 deletions(-) diff --git a/common/djangoapps/course_modes/admin.py b/common/djangoapps/course_modes/admin.py index c6419d241b..74a9d2892e 100644 --- a/common/djangoapps/course_modes/admin.py +++ b/common/djangoapps/course_modes/admin.py @@ -26,7 +26,7 @@ from openedx.core.lib.courses import clean_course_id from common.djangoapps.util.date_utils import get_time_display COURSE_MODE_SLUG_CHOICES = [(key, enrollment_mode['display_name']) - for key, enrollment_mode in six.iteritems(settings.COURSE_ENROLLMENT_MODES)] + for key, enrollment_mode in settings.COURSE_ENROLLMENT_MODES.items()] class CourseModeForm(forms.ModelForm): @@ -34,7 +34,7 @@ class CourseModeForm(forms.ModelForm): Admin form for adding a course mode. """ - class Meta(object): + class Meta: model = CourseMode fields = '__all__' @@ -63,7 +63,7 @@ class CourseModeForm(forms.ModelForm): args_copy['course'] = CourseKey.from_string(args_copy['course']) args = [args_copy] - super(CourseModeForm, self).__init__(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments + super().__init__(*args, **kwargs) try: if self.data.get('course'): @@ -122,7 +122,7 @@ class CourseModeForm(forms.ModelForm): Clean the form fields. This is the place to perform checks that involve multiple form fields. """ - cleaned_data = super(CourseModeForm, self).clean() # lint-amnesty, pylint: disable=super-with-arguments + cleaned_data = super().clean() mode_slug = cleaned_data.get("mode_slug") upgrade_deadline = cleaned_data.get("_expiration_datetime") verification_deadline = cleaned_data.get("verification_deadline") @@ -173,7 +173,7 @@ class CourseModeForm(forms.ModelForm): verification_deadline ) - return super(CourseModeForm, self).save(commit=commit) # lint-amnesty, pylint: disable=super-with-arguments + return super().save(commit=commit) @admin.register(CourseMode) diff --git a/common/djangoapps/course_modes/helpers.py b/common/djangoapps/course_modes/helpers.py index c3f26bc19a..4511a32ffd 100644 --- a/common/djangoapps/course_modes/helpers.py +++ b/common/djangoapps/course_modes/helpers.py @@ -58,10 +58,10 @@ def enrollment_mode_display(mode, verification_status, course_id): enrollment_value = _("Professional Ed") return { - 'enrollment_title': six.text_type(enrollment_title), - 'enrollment_value': six.text_type(enrollment_value), + 'enrollment_title': str(enrollment_title), + 'enrollment_value': str(enrollment_value), 'show_image': show_image, - 'image_alt': six.text_type(image_alt), + 'image_alt': str(image_alt), 'display_mode': _enrollment_mode_display(mode, verification_status, course_id) } diff --git a/common/djangoapps/course_modes/migrations/0001_initial.py b/common/djangoapps/course_modes/migrations/0001_initial.py index 094f8a037b..6caeedc04a 100644 --- a/common/djangoapps/course_modes/migrations/0001_initial.py +++ b/common/djangoapps/course_modes/migrations/0001_initial.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- - - from django.db import migrations, models from opaque_keys.edx.django.models import CourseKeyField @@ -19,12 +16,12 @@ class Migration(migrations.Migration): ('mode_slug', models.CharField(max_length=100, verbose_name='Mode')), ('mode_display_name', models.CharField(max_length=255, verbose_name='Display Name')), ('min_price', models.IntegerField(default=0, verbose_name='Price')), - ('currency', models.CharField(default=u'usd', max_length=8)), + ('currency', models.CharField(default='usd', max_length=8)), ('expiration_datetime', models.DateTimeField(default=None, help_text='OPTIONAL: After this date/time, users will no longer be able to enroll in this mode. Leave this blank if users can enroll in this mode until enrollment closes for the course.', null=True, verbose_name='Upgrade Deadline', blank=True)), ('expiration_date', models.DateField(default=None, null=True, blank=True)), - ('suggested_prices', models.CommaSeparatedIntegerField(default=u'', max_length=255, blank=True)), + ('suggested_prices', models.CommaSeparatedIntegerField(default='', max_length=255, blank=True)), ('description', models.TextField(null=True, blank=True)), - ('sku', models.CharField(help_text='OPTIONAL: This is the SKU (stock keeping unit) of this mode in the external ecommerce service. Leave this blank if the course has not yet been migrated to the ecommerce service.', max_length=255, null=True, verbose_name=u'SKU', blank=True)), + ('sku', models.CharField(help_text='OPTIONAL: This is the SKU (stock keeping unit) of this mode in the external ecommerce service. Leave this blank if the course has not yet been migrated to the ecommerce service.', max_length=255, null=True, verbose_name='SKU', blank=True)), ], ), migrations.CreateModel( @@ -35,14 +32,14 @@ class Migration(migrations.Migration): ('mode_slug', models.CharField(max_length=100)), ('mode_display_name', models.CharField(max_length=255)), ('min_price', models.IntegerField(default=0)), - ('suggested_prices', models.CommaSeparatedIntegerField(default=u'', max_length=255, blank=True)), - ('currency', models.CharField(default=u'usd', max_length=8)), + ('suggested_prices', models.CommaSeparatedIntegerField(default='', max_length=255, blank=True)), + ('currency', models.CharField(default='usd', max_length=8)), ('expiration_date', models.DateField(default=None, null=True, blank=True)), ('expiration_datetime', models.DateTimeField(default=None, null=True, blank=True)), ], ), migrations.AlterUniqueTogether( name='coursemode', - unique_together=set([('course_id', 'mode_slug', 'currency')]), + unique_together={('course_id', 'mode_slug', 'currency')}, ), ] diff --git a/common/djangoapps/course_modes/migrations/0002_coursemode_expiration_datetime_is_explicit.py b/common/djangoapps/course_modes/migrations/0002_coursemode_expiration_datetime_is_explicit.py index 86124fc13c..46ba65c1f7 100644 --- a/common/djangoapps/course_modes/migrations/0002_coursemode_expiration_datetime_is_explicit.py +++ b/common/djangoapps/course_modes/migrations/0002_coursemode_expiration_datetime_is_explicit.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- - - from django.db import migrations, models diff --git a/common/djangoapps/course_modes/migrations/0003_auto_20151113_1443.py b/common/djangoapps/course_modes/migrations/0003_auto_20151113_1443.py index c65f5932dc..8a7bb9231c 100644 --- a/common/djangoapps/course_modes/migrations/0003_auto_20151113_1443.py +++ b/common/djangoapps/course_modes/migrations/0003_auto_20151113_1443.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- - - from django.db import migrations, models diff --git a/common/djangoapps/course_modes/migrations/0004_auto_20151113_1457.py b/common/djangoapps/course_modes/migrations/0004_auto_20151113_1457.py index 24e842eb7e..34d173fc19 100644 --- a/common/djangoapps/course_modes/migrations/0004_auto_20151113_1457.py +++ b/common/djangoapps/course_modes/migrations/0004_auto_20151113_1457.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- - - from datetime import timedelta import django.db.models.deletion diff --git a/common/djangoapps/course_modes/migrations/0005_auto_20151217_0958.py b/common/djangoapps/course_modes/migrations/0005_auto_20151217_0958.py index 2842c255b8..d30a951c6f 100644 --- a/common/djangoapps/course_modes/migrations/0005_auto_20151217_0958.py +++ b/common/djangoapps/course_modes/migrations/0005_auto_20151217_0958.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- - - from django.db import migrations, models @@ -21,7 +18,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='coursemode', name='_expiration_datetime', - field=models.DateTimeField(db_column=u'expiration_datetime', default=None, blank=True, help_text='OPTIONAL: After this date/time, users will no longer be able to enroll in this mode. Leave this blank if users can enroll in this mode until enrollment closes for the course.', null=True, verbose_name='Upgrade Deadline'), + field=models.DateTimeField(db_column='expiration_datetime', default=None, blank=True, help_text='OPTIONAL: After this date/time, users will no longer be able to enroll in this mode. Leave this blank if users can enroll in this mode until enrollment closes for the course.', null=True, verbose_name='Upgrade Deadline'), ), ] ) diff --git a/common/djangoapps/course_modes/migrations/0006_auto_20160208_1407.py b/common/djangoapps/course_modes/migrations/0006_auto_20160208_1407.py index 6cc63a3a6b..02f5f81baf 100644 --- a/common/djangoapps/course_modes/migrations/0006_auto_20160208_1407.py +++ b/common/djangoapps/course_modes/migrations/0006_auto_20160208_1407.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- - - from django.db import migrations, models diff --git a/common/djangoapps/course_modes/migrations/0007_coursemode_bulk_sku.py b/common/djangoapps/course_modes/migrations/0007_coursemode_bulk_sku.py index f82e852807..c36111c5cd 100644 --- a/common/djangoapps/course_modes/migrations/0007_coursemode_bulk_sku.py +++ b/common/djangoapps/course_modes/migrations/0007_coursemode_bulk_sku.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- - - from django.db import migrations, models @@ -14,6 +11,6 @@ class Migration(migrations.Migration): migrations.AddField( model_name='coursemode', name='bulk_sku', - field=models.CharField(default=None, max_length=255, blank=True, help_text='This is the bulk SKU (stock keeping unit) of this mode in the external ecommerce service.', null=True, verbose_name=u'Bulk SKU'), + field=models.CharField(default=None, max_length=255, blank=True, help_text='This is the bulk SKU (stock keeping unit) of this mode in the external ecommerce service.', null=True, verbose_name='Bulk SKU'), ), ] diff --git a/common/djangoapps/course_modes/migrations/0008_course_key_field_to_foreign_key.py b/common/djangoapps/course_modes/migrations/0008_course_key_field_to_foreign_key.py index b844e4009d..7c4734f995 100644 --- a/common/djangoapps/course_modes/migrations/0008_course_key_field_to_foreign_key.py +++ b/common/djangoapps/course_modes/migrations/0008_course_key_field_to_foreign_key.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- - - from django.db import migrations, models from opaque_keys.edx.django.models import CourseKeyField @@ -52,6 +49,6 @@ class Migration(migrations.Migration): # since the database column constraint already exists). migrations.AlterUniqueTogether( name='coursemode', - unique_together=set([('course', 'mode_slug', 'currency')]), + unique_together={('course', 'mode_slug', 'currency')}, ), ] diff --git a/common/djangoapps/course_modes/migrations/0009_suggested_prices_to_charfield.py b/common/djangoapps/course_modes/migrations/0009_suggested_prices_to_charfield.py index 66e5ef5391..628020196b 100644 --- a/common/djangoapps/course_modes/migrations/0009_suggested_prices_to_charfield.py +++ b/common/djangoapps/course_modes/migrations/0009_suggested_prices_to_charfield.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- - - import re import django.core.validators @@ -17,6 +14,6 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='coursemode', name='suggested_prices', - field=models.CharField(default=u'', max_length=255, blank=True, validators=[django.core.validators.RegexValidator(re.compile('^[\\d,]+\\Z'), 'Enter only digits separated by commas.', 'invalid')]), + field=models.CharField(default='', max_length=255, blank=True, validators=[django.core.validators.RegexValidator(re.compile('^[\\d,]+\\Z'), 'Enter only digits separated by commas.', 'invalid')]), ), ] diff --git a/common/djangoapps/course_modes/migrations/0010_archived_suggested_prices_to_charfield.py b/common/djangoapps/course_modes/migrations/0010_archived_suggested_prices_to_charfield.py index 979b75afb2..d534d90010 100644 --- a/common/djangoapps/course_modes/migrations/0010_archived_suggested_prices_to_charfield.py +++ b/common/djangoapps/course_modes/migrations/0010_archived_suggested_prices_to_charfield.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- - - import re import django.core.validators @@ -17,6 +14,6 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='coursemodesarchive', name='suggested_prices', - field=models.CharField(default=u'', max_length=255, blank=True, validators=[django.core.validators.RegexValidator(re.compile('^[\\d,]+\\Z'), 'Enter only digits separated by commas.', 'invalid')]), + field=models.CharField(default='', max_length=255, blank=True, validators=[django.core.validators.RegexValidator(re.compile('^[\\d,]+\\Z'), 'Enter only digits separated by commas.', 'invalid')]), ), ] diff --git a/common/djangoapps/course_modes/migrations/0011_change_regex_for_comma_separated_ints.py b/common/djangoapps/course_modes/migrations/0011_change_regex_for_comma_separated_ints.py index 6d3c9d2885..add4c00520 100644 --- a/common/djangoapps/course_modes/migrations/0011_change_regex_for_comma_separated_ints.py +++ b/common/djangoapps/course_modes/migrations/0011_change_regex_for_comma_separated_ints.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.11.8 on 2018-01-30 17:38 @@ -18,11 +17,11 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='coursemode', name='suggested_prices', - field=models.CharField(blank=True, default=u'', max_length=255, validators=[django.core.validators.RegexValidator(re.compile('^\d+(?:{escaped_comma}\d+)*\Z'.format(escaped_comma=re.escape(','))), code='invalid', message='Enter only digits separated by commas.')]), + field=models.CharField(blank=True, default='', max_length=255, validators=[django.core.validators.RegexValidator(re.compile(r'^\d+(?:{escaped_comma}\d+)*\Z'.format(escaped_comma=re.escape(','))), code='invalid', message='Enter only digits separated by commas.')]), ), migrations.AlterField( model_name='coursemodesarchive', name='suggested_prices', - field=models.CharField(blank=True, default=u'', max_length=255, validators=[django.core.validators.RegexValidator(re.compile('^\d+(?:{escaped_comma}\d+)*\Z'.format(escaped_comma=re.escape(','))), code='invalid', message='Enter only digits separated by commas.')]), + field=models.CharField(blank=True, default='', max_length=255, validators=[django.core.validators.RegexValidator(re.compile(r'^\d+(?:{escaped_comma}\d+)*\Z'.format(escaped_comma=re.escape(','))), code='invalid', message='Enter only digits separated by commas.')]), ), ] diff --git a/common/djangoapps/course_modes/migrations/0012_historicalcoursemode.py b/common/djangoapps/course_modes/migrations/0012_historicalcoursemode.py index e59956d944..48d0a39cf4 100644 --- a/common/djangoapps/course_modes/migrations/0012_historicalcoursemode.py +++ b/common/djangoapps/course_modes/migrations/0012_historicalcoursemode.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.11.21 on 2019-06-19 01:31 @@ -26,14 +25,14 @@ class Migration(migrations.Migration): ('mode_slug', models.CharField(max_length=100, verbose_name='Mode')), ('mode_display_name', models.CharField(max_length=255, verbose_name='Display Name')), ('min_price', models.IntegerField(default=0, verbose_name='Price')), - ('currency', models.CharField(default=u'usd', max_length=8)), - ('_expiration_datetime', models.DateTimeField(blank=True, db_column=u'expiration_datetime', default=None, help_text='OPTIONAL: After this date/time, users will no longer be able to enroll in this mode. Leave this blank if users can enroll in this mode until enrollment closes for the course.', null=True, verbose_name='Upgrade Deadline')), + ('currency', models.CharField(default='usd', max_length=8)), + ('_expiration_datetime', models.DateTimeField(blank=True, db_column='expiration_datetime', default=None, help_text='OPTIONAL: After this date/time, users will no longer be able to enroll in this mode. Leave this blank if users can enroll in this mode until enrollment closes for the course.', null=True, verbose_name='Upgrade Deadline')), ('expiration_datetime_is_explicit', models.BooleanField(default=False)), ('expiration_date', models.DateField(blank=True, default=None, null=True)), - ('suggested_prices', models.CharField(blank=True, default=u'', max_length=255, validators=[django.core.validators.RegexValidator(re.compile('^\\d+(?:{escaped_comma}\\d+)*\\Z'.format(escaped_comma=re.escape(','))), code='invalid', message='Enter only digits separated by commas.')])), + ('suggested_prices', models.CharField(blank=True, default='', max_length=255, validators=[django.core.validators.RegexValidator(re.compile('^\\d+(?:{escaped_comma}\\d+)*\\Z'.format(escaped_comma=re.escape(','))), code='invalid', message='Enter only digits separated by commas.')])), ('description', models.TextField(blank=True, null=True)), - ('sku', models.CharField(blank=True, help_text='OPTIONAL: This is the SKU (stock keeping unit) of this mode in the external ecommerce service. Leave this blank if the course has not yet been migrated to the ecommerce service.', max_length=255, null=True, verbose_name=u'SKU')), - ('bulk_sku', models.CharField(blank=True, default=None, help_text='This is the bulk SKU (stock keeping unit) of this mode in the external ecommerce service.', max_length=255, null=True, verbose_name=u'Bulk SKU')), + ('sku', models.CharField(blank=True, help_text='OPTIONAL: This is the SKU (stock keeping unit) of this mode in the external ecommerce service. Leave this blank if the course has not yet been migrated to the ecommerce service.', max_length=255, null=True, verbose_name='SKU')), + ('bulk_sku', models.CharField(blank=True, default=None, help_text='This is the bulk SKU (stock keeping unit) of this mode in the external ecommerce service.', max_length=255, null=True, verbose_name='Bulk SKU')), ('history_id', models.AutoField(primary_key=True, serialize=False)), ('history_date', models.DateTimeField()), ('history_change_reason', models.CharField(max_length=100, null=True)), diff --git a/common/djangoapps/course_modes/migrations/0013_auto_20200115_2022.py b/common/djangoapps/course_modes/migrations/0013_auto_20200115_2022.py index 3139133565..eb89c2a9bb 100644 --- a/common/djangoapps/course_modes/migrations/0013_auto_20200115_2022.py +++ b/common/djangoapps/course_modes/migrations/0013_auto_20200115_2022.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.11.27 on 2020-01-15 20:22 diff --git a/common/djangoapps/course_modes/models.py b/common/djangoapps/course_modes/models.py index 82552ed531..c9972cd93d 100644 --- a/common/djangoapps/course_modes/models.py +++ b/common/djangoapps/course_modes/models.py @@ -69,7 +69,7 @@ class CourseMode(models.Model): min_price = models.IntegerField(default=0, verbose_name=_("Price")) # the currency these prices are in, using lower case ISO currency codes - currency = models.CharField(default=u"usd", max_length=8) + currency = models.CharField(default="usd", max_length=8) # The datetime at which the course mode will expire. # This is used to implement "upgrade" deadlines. @@ -78,12 +78,12 @@ class CourseMode(models.Model): # Once the date passes, users will no longer be able to enroll as verified. _expiration_datetime = models.DateTimeField( default=None, null=True, blank=True, - verbose_name=_(u"Upgrade Deadline"), + verbose_name=_("Upgrade Deadline"), help_text=_( - u"OPTIONAL: After this date/time, users will no longer be able to enroll in this mode. " - u"Leave this blank if users can enroll in this mode until enrollment closes for the course." + "OPTIONAL: After this date/time, users will no longer be able to enroll in this mode. " + "Leave this blank if users can enroll in this mode until enrollment closes for the course." ), - db_column=u'expiration_datetime', + db_column='expiration_datetime', ) # The system prefers to set this automatically based on default settings. But @@ -97,7 +97,7 @@ class CourseMode(models.Model): # DEPRECATED: the suggested prices for this mode # We used to allow users to choose from a set of prices, but we now allow only # a single price. This field has been deprecated by `min_price` - suggested_prices = models.CharField(max_length=255, blank=True, default=u'', + suggested_prices = models.CharField(max_length=255, blank=True, default='', validators=[validate_comma_separated_integer_list]) # optional description override @@ -109,10 +109,10 @@ class CourseMode(models.Model): max_length=255, null=True, blank=True, - verbose_name=u"SKU", + verbose_name="SKU", help_text=_( - u"OPTIONAL: This is the SKU (stock keeping unit) of this mode in the external ecommerce service. " - u"Leave this blank if the course has not yet been migrated to the ecommerce service." + "OPTIONAL: This is the SKU (stock keeping unit) of this mode in the external ecommerce service. " + "Leave this blank if the course has not yet been migrated to the ecommerce service." ) ) @@ -122,9 +122,9 @@ class CourseMode(models.Model): null=True, blank=True, default=None, # Need this in order to set DEFAULT NULL on the database column - verbose_name=u"Bulk SKU", + verbose_name="Bulk SKU", help_text=_( - u"This is the bulk SKU (stock keeping unit) of this mode in the external ecommerce service." + "This is the bulk SKU (stock keeping unit) of this mode in the external ecommerce service." ) ) @@ -184,14 +184,14 @@ class CourseMode(models.Model): # Modes that are allowed to upsell UPSELL_TO_VERIFIED_MODES = [HONOR, AUDIT] - CACHE_NAMESPACE = u"course_modes.CourseMode.cache." + CACHE_NAMESPACE = "course_modes.CourseMode.cache." - class Meta(object): + class Meta: app_label = "course_modes" unique_together = ('course', 'mode_slug', 'currency') def __init__(self, *args, **kwargs): # lint-amnesty, pylint: disable=useless-super-delegation - super(CourseMode, self).__init__(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments + super().__init__(*args, **kwargs) def clean(self): """ @@ -200,7 +200,7 @@ class CourseMode(models.Model): """ if self.is_professional_slug(self.mode_slug) and self.expiration_datetime is not None: raise ValidationError( - _(u"Professional education modes are not allowed to have expiration_datetime set.") + _("Professional education modes are not allowed to have expiration_datetime set.") ) mode_config = settings.COURSE_ENROLLMENT_MODES.get(self.mode_slug, {}) @@ -209,7 +209,7 @@ class CourseMode(models.Model): mode_display_name = mode_config.get('display_name', self.mode_slug) raise ValidationError( _( # lint-amnesty, pylint: disable=translation-of-non-string - u"The {course_mode} course mode has a minimum price of {min_price}. You must set a price greater than or equal to {min_price}.".format( # lint-amnesty, pylint: disable=line-too-long + "The {course_mode} course mode has a minimum price of {min_price}. You must set a price greater than or equal to {min_price}.".format( # lint-amnesty, pylint: disable=line-too-long course_mode=mode_display_name, min_price=min_price_for_mode ) ) @@ -222,7 +222,7 @@ class CourseMode(models.Model): if self.id is None: # If this model has no primary key at save time, it needs to be force-inserted. force_insert = True - super(CourseMode, self).save(force_insert, force_update, using) # lint-amnesty, pylint: disable=super-with-arguments + super().save(force_insert, force_update, using) @property def slug(self): @@ -304,7 +304,7 @@ class CourseMode(models.Model): mode for mode in modes if mode.expiration_datetime is None or mode.expiration_datetime >= now_dt ] - for course_id, modes in six.iteritems(all_modes) + for course_id, modes in all_modes.items() } return (all_modes, unexpired_modes) @@ -807,7 +807,7 @@ class CourseMode(models.Model): ) def __str__(self): - return u"{} : {}, min={}".format( + return "{} : {}, min={}".format( self.course_id, self.mode_slug, self.min_price ) @@ -888,7 +888,7 @@ class CourseModesArchive(models.Model): .. no_pii: """ - class Meta(object): + class Meta: app_label = "course_modes" # the course that this mode is attached to @@ -905,11 +905,11 @@ class CourseModesArchive(models.Model): min_price = models.IntegerField(default=0) # the suggested prices for this mode - suggested_prices = models.CharField(max_length=255, blank=True, default=u'', + suggested_prices = models.CharField(max_length=255, blank=True, default='', validators=[validate_comma_separated_integer_list]) # the currency these prices are in, using lower case ISO currency codes - currency = models.CharField(default=u"usd", max_length=8) + currency = models.CharField(default="usd", max_length=8) # turn this mode off after the given expiration date expiration_date = models.DateField(default=None, null=True, blank=True) @@ -924,7 +924,7 @@ class CourseModeExpirationConfig(ConfigurationModel): .. no_pii: """ - class Meta(object): + class Meta: app_label = "course_modes" verification_window = models.DurationField( @@ -936,4 +936,4 @@ class CourseModeExpirationConfig(ConfigurationModel): def __str__(self): """ Returns the unicode date of the verification window. """ - return six.text_type(self.verification_window) + return str(self.verification_window) diff --git a/common/djangoapps/course_modes/rest_api/serializers.py b/common/djangoapps/course_modes/rest_api/serializers.py index f3c73657a2..a0746f90d7 100644 --- a/common/djangoapps/course_modes/rest_api/serializers.py +++ b/common/djangoapps/course_modes/rest_api/serializers.py @@ -29,7 +29,7 @@ class CourseModeSerializer(serializers.Serializer): sku = serializers.CharField(required=False) bulk_sku = serializers.CharField(required=False) - class Meta(object): + class Meta: # For disambiguating within the drf-yasg swagger schema ref_name = 'course_modes.CourseMode' diff --git a/common/djangoapps/course_modes/rest_api/v1/tests/test_views.py b/common/djangoapps/course_modes/rest_api/v1/tests/test_views.py index ecbf18360e..37aad86651 100644 --- a/common/djangoapps/course_modes/rest_api/v1/tests/test_views.py +++ b/common/djangoapps/course_modes/rest_api/v1/tests/test_views.py @@ -66,7 +66,7 @@ class CourseModesViewTestBase(AuthAndScopesTestMixin): cls.other_mode.delete() def setUp(self): - super(CourseModesViewTestBase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() # overwrite self.student to be a staff member, since only staff # should be able to access the course_modes API endpoints. # This is needed to make a handful of tests inherited from AuthAndScopesTestMixin pass. @@ -89,7 +89,7 @@ class CourseModesViewTestBase(AuthAndScopesTestMixin): jwt_token = self._create_jwt_token(self.student, auth_type, include_me_filter=True) # include_me_filter=True means a JWT filter will require the username # of the requesting user to be in the requested URL - url = self.get_url(self.student) + '?username={}'.format(self.student.username) + url = self.get_url(self.student) + f'?username={self.student.username}' resp = self.get_response(AuthType.jwt, token=jwt_token, url=url) assert status.HTTP_200_OK == resp.status_code @@ -108,7 +108,7 @@ class TestCourseModesListViews(CourseModesViewTestBase, ModuleStoreTestCase, API Required method to implement AuthAndScopesTestMixin. """ kwargs = { - 'course_id': text_type(course_id or self.course_key) + 'course_id': str(course_id or self.course_key) } return reverse(self.view_name, kwargs=kwargs) @@ -130,7 +130,7 @@ class TestCourseModesListViews(CourseModesViewTestBase, ModuleStoreTestCase, API actual_results = self._sorted_results(response) expected_results = [ { - 'course_id': text_type(self.course_key), + 'course_id': str(self.course_key), 'mode_slug': 'audit', 'mode_display_name': 'Audit', 'min_price': 0, @@ -142,7 +142,7 @@ class TestCourseModesListViews(CourseModesViewTestBase, ModuleStoreTestCase, API 'bulk_sku': None, }, { - 'course_id': text_type(self.course_key), + 'course_id': str(self.course_key), 'mode_slug': 'verified', 'mode_display_name': 'Verified', 'min_price': 25, @@ -165,7 +165,7 @@ class TestCourseModesListViews(CourseModesViewTestBase, ModuleStoreTestCase, API other_actual_results = self._sorted_results(other_response) other_expected_results = [ { - 'course_id': text_type(self.other_course_key), + 'course_id': str(self.other_course_key), 'mode_slug': 'other-audit', 'mode_display_name': 'Other Audit', 'min_price': 0, @@ -199,7 +199,7 @@ class TestCourseModesListViews(CourseModesViewTestBase, ModuleStoreTestCase, API url = self.get_url(course_id=self.course_key) request_payload = { - 'course_id': text_type(self.course_key), + 'course_id': str(self.course_key), 'mode_slug': 'masters', 'mode_display_name': 'Masters', 'currency': 'usd', @@ -220,7 +220,7 @@ class TestCourseModesListViews(CourseModesViewTestBase, ModuleStoreTestCase, API url = self.get_url(course_id=self.course_key) request_payload = { - 'course_id': text_type(self.course_key), + 'course_id': str(self.course_key), 'mode_slug': 'phd', } @@ -252,7 +252,7 @@ class TestCourseModesDetailViews(CourseModesViewTestBase, APITestCase): Required method to implement AuthAndScopesTestMixin. """ kwargs = { - 'course_id': text_type(course_id or self.course_key), + 'course_id': str(course_id or self.course_key), 'mode_slug': mode_slug or 'audit', } return reverse(self.view_name, kwargs=kwargs) @@ -282,7 +282,7 @@ class TestCourseModesDetailViews(CourseModesViewTestBase, APITestCase): assert status.HTTP_200_OK == response.status_code actual_data = dict(response.data) expected_data = { - 'course_id': text_type(self.course_key), + 'course_id': str(self.course_key), 'mode_slug': 'audit', 'mode_display_name': 'Audit', 'min_price': 0, diff --git a/common/djangoapps/course_modes/rest_api/v1/urls.py b/common/djangoapps/course_modes/rest_api/v1/urls.py index a95e5de5aa..6102699840 100644 --- a/common/djangoapps/course_modes/rest_api/v1/urls.py +++ b/common/djangoapps/course_modes/rest_api/v1/urls.py @@ -12,12 +12,12 @@ app_name = 'v1' urlpatterns = [ url( - r'^courses/{course_id}/$'.format(course_id=settings.COURSE_ID_PATTERN), + fr'^courses/{settings.COURSE_ID_PATTERN}/$', views.CourseModesView.as_view(), name='course_modes_list' ), url( - r'^courses/{course_id}/(?P.*)$'.format(course_id=settings.COURSE_ID_PATTERN), + fr'^courses/{settings.COURSE_ID_PATTERN}/(?P.*)$', views.CourseModesDetailView.as_view(), name='course_modes_detail' ), diff --git a/common/djangoapps/course_modes/rest_api/v1/views.py b/common/djangoapps/course_modes/rest_api/v1/views.py index caeebb7097..7c37d8596d 100644 --- a/common/djangoapps/course_modes/rest_api/v1/views.py +++ b/common/djangoapps/course_modes/rest_api/v1/views.py @@ -22,7 +22,7 @@ from openedx.core.lib.api.parsers import MergePatchParser log = logging.getLogger(__name__) -class CourseModesMixin(object): +class CourseModesMixin: """ A base class for course modes views that specifies authentication, permissions, serialization, pagination, and the base queryset. diff --git a/common/djangoapps/course_modes/tests/factories.py b/common/djangoapps/course_modes/tests/factories.py index c19e027d6b..624189690c 100644 --- a/common/djangoapps/course_modes/tests/factories.py +++ b/common/djangoapps/course_modes/tests/factories.py @@ -17,7 +17,7 @@ from openedx.core.djangoapps.content.course_overviews.tests.factories import Cou # Factories are self documenting class CourseModeFactory(DjangoModelFactory): # lint-amnesty, pylint: disable=missing-class-docstring - class Meta(object): + class Meta: model = CourseMode mode_slug = CourseMode.DEFAULT_MODE_SLUG @@ -38,7 +38,7 @@ class CourseModeFactory(DjangoModelFactory): # lint-amnesty, pylint: disable=mi course_overview = None course_kwargs.setdefault('id', course_id) if course_id is not None: - if isinstance(course_id, six.string_types): + if isinstance(course_id, str): course_id = CourseKey.from_string(course_id) course_kwargs['id'] = course_id try: @@ -63,4 +63,4 @@ class CourseModeFactory(DjangoModelFactory): # lint-amnesty, pylint: disable=mi @lazy_attribute def mode_display_name(self): - return '{0} course'.format(self.mode_slug) + return f'{self.mode_slug} course' diff --git a/common/djangoapps/course_modes/tests/test_admin.py b/common/djangoapps/course_modes/tests/test_admin.py index 2f42e4d93c..f04be6d51a 100644 --- a/common/djangoapps/course_modes/tests/test_admin.py +++ b/common/djangoapps/course_modes/tests/test_admin.py @@ -47,7 +47,7 @@ class AdminCourseModePageTest(ModuleStoreTestCase): CourseOverview.load_from_module_store(course.id) data = { - 'course': six.text_type(course.id), + 'course': str(course.id), 'mode_slug': 'verified', 'mode_display_name': 'verified', 'min_price': 10, @@ -91,7 +91,7 @@ class AdminCourseModeFormTest(ModuleStoreTestCase): """ Create a test course. """ - super(AdminCourseModeFormTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.course = CourseFactory.create() CourseOverview.load_from_module_store(self.course.id) @@ -199,7 +199,7 @@ class AdminCourseModeFormTest(ModuleStoreTestCase): mode_slug=mode, ) return CourseModeForm({ - "course": six.text_type(self.course.id), + "course": str(self.course.id), "mode_slug": mode, "mode_display_name": mode, "_expiration_datetime": upgrade_deadline, diff --git a/common/djangoapps/course_modes/tests/test_models.py b/common/djangoapps/course_modes/tests/test_models.py index f915f21866..9ae42c2821 100644 --- a/common/djangoapps/course_modes/tests/test_models.py +++ b/common/djangoapps/course_modes/tests/test_models.py @@ -13,10 +13,9 @@ import ddt from django.core.exceptions import ValidationError from django.test import TestCase, override_settings from django.utils.timezone import now -from mock import patch +from unittest.mock import patch from opaque_keys.edx.locator import CourseLocator import six -from six.moves import zip from common.djangoapps.course_modes.helpers import enrollment_mode_display from common.djangoapps.course_modes.models import CourseMode, Mode, get_cosmetic_display_price, invalidate_course_mode_cache # lint-amnesty, pylint: disable=line-too-long @@ -38,12 +37,12 @@ class CourseModeModelTest(TestCase): } def setUp(self): - super(CourseModeModelTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.course_key = CourseLocator('Test', 'TestCourse', 'TestCourseRun') CourseMode.objects.all().delete() def tearDown(self): - super(CourseModeModelTest, self).tearDown() # lint-amnesty, pylint: disable=super-with-arguments + super().tearDown() invalidate_course_mode_cache(sender=None) def create_mode( @@ -92,7 +91,7 @@ class CourseModeModelTest(TestCase): self.create_mode('verified', 'Verified Certificate', 10) modes = CourseMode.modes_for_course(self.course_key) - mode = Mode(u'verified', u'Verified Certificate', 10, '', 'usd', None, None, None, None) + mode = Mode('verified', 'Verified Certificate', 10, '', 'usd', None, None, None, None) assert [mode] == modes modes_dict = CourseMode.modes_for_course_dict(self.course_key) @@ -103,16 +102,16 @@ class CourseModeModelTest(TestCase): """ Finding the modes when there's multiple modes """ - mode1 = Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None, None, None) - mode2 = Mode(u'verified', u'Verified Certificate', 10, '', 'usd', None, None, None, None) + mode1 = Mode('honor', 'Honor Code Certificate', 0, '', 'usd', None, None, None, None) + mode2 = Mode('verified', 'Verified Certificate', 10, '', 'usd', None, None, None, None) set_modes = [mode1, mode2] for mode in set_modes: self.create_mode(mode.slug, mode.name, mode.min_price, mode.suggested_prices) modes = CourseMode.modes_for_course(self.course_key) assert modes == set_modes - assert mode1 == CourseMode.mode_for_course(self.course_key, u'honor') - assert mode2 == CourseMode.mode_for_course(self.course_key, u'verified') + assert mode1 == CourseMode.mode_for_course(self.course_key, 'honor') + assert mode2 == CourseMode.mode_for_course(self.course_key, 'verified') assert CourseMode.mode_for_course(self.course_key, 'DNE') is None def test_min_course_price_for_currency(self): @@ -123,9 +122,9 @@ class CourseModeModelTest(TestCase): assert 0 == CourseMode.min_course_price_for_currency(self.course_key, 'usd') # create some modes - mode1 = Mode(u'honor', u'Honor Code Certificate', 10, '', 'usd', None, None, None, None) - mode2 = Mode(u'verified', u'Verified Certificate', 20, '', 'usd', None, None, None, None) - mode3 = Mode(u'honor', u'Honor Code Certificate', 80, '', 'cny', None, None, None, None) + mode1 = Mode('honor', 'Honor Code Certificate', 10, '', 'usd', None, None, None, None) + mode2 = Mode('verified', 'Verified Certificate', 20, '', 'usd', None, None, None, None) + mode3 = Mode('honor', 'Honor Code Certificate', 80, '', 'cny', None, None, None, None) set_modes = [mode1, mode2, mode3] for mode in set_modes: self.create_mode(mode.slug, mode.name, mode.min_price, mode.suggested_prices, mode.currency) @@ -140,7 +139,7 @@ class CourseModeModelTest(TestCase): modes = CourseMode.modes_for_course(self.course_key) assert [CourseMode.DEFAULT_MODE] == modes - mode1 = Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None, None, None) + mode1 = Mode('honor', 'Honor Code Certificate', 0, '', 'usd', None, None, None, None) self.create_mode(mode1.slug, mode1.name, mode1.min_price, mode1.suggested_prices) modes = CourseMode.modes_for_course(self.course_key) assert [mode1] == modes @@ -149,8 +148,8 @@ class CourseModeModelTest(TestCase): expired_mode.expiration_datetime = expiration_datetime expired_mode.save() expired_mode_value = Mode( - u'verified', - u'Verified Certificate', + 'verified', + 'Verified Certificate', 10, '', 'usd', @@ -335,7 +334,7 @@ class CourseModeModelTest(TestCase): assert not is_error_expected, 'Expected a ValidationError to be thrown.' except ValidationError as exc: assert is_error_expected, 'Did not expect a ValidationError to be thrown.' - assert exc.messages == [u'Professional education modes are not allowed to have expiration_datetime set.'] + assert exc.messages == ['Professional education modes are not allowed to have expiration_datetime set.'] @ddt.data( ("verified", "verify_need_to_verify"), @@ -385,11 +384,11 @@ class CourseModeModelTest(TestCase): # Check the selectable modes, which should exclude credit selectable_modes = CourseMode.modes_for_course_dict(self.course_key) - six.assertCountEqual(self, list(selectable_modes.keys()), expected_selectable_modes) + self.assertCountEqual(list(selectable_modes.keys()), expected_selectable_modes) # When we get all unexpired modes, we should see credit as well all_modes = CourseMode.modes_for_course_dict(self.course_key, only_selectable=False) - six.assertCountEqual(self, list(all_modes.keys()), available_modes) + self.assertCountEqual(list(all_modes.keys()), available_modes) def _enrollment_display_modes_dicts(self, dict_type): """ diff --git a/common/djangoapps/course_modes/tests/test_signals.py b/common/djangoapps/course_modes/tests/test_signals.py index ff04065969..9c6ca5f9c4 100644 --- a/common/djangoapps/course_modes/tests/test_signals.py +++ b/common/djangoapps/course_modes/tests/test_signals.py @@ -7,7 +7,7 @@ from datetime import datetime, timedelta import ddt from django.conf import settings -from mock import patch +from unittest.mock import patch from pytz import UTC from common.djangoapps.course_modes.models import CourseMode @@ -25,7 +25,7 @@ class CourseModeSignalTest(ModuleStoreTestCase): """ def setUp(self): - super(CourseModeSignalTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() self.end = datetime.now(tz=UTC).replace(microsecond=0) + timedelta(days=7) self.course = CourseFactory.create(end=self.end) CourseMode.objects.all().delete() diff --git a/common/djangoapps/course_modes/tests/test_views.py b/common/djangoapps/course_modes/tests/test_views.py index 3eaaa46229..3603af4964 100644 --- a/common/djangoapps/course_modes/tests/test_views.py +++ b/common/djangoapps/course_modes/tests/test_views.py @@ -14,7 +14,7 @@ import pytz import six from django.conf import settings from django.urls import reverse -from mock import patch +from unittest.mock import patch from common.djangoapps.course_modes.models import CourseMode, Mode from common.djangoapps.course_modes.tests.factories import CourseModeFactory @@ -43,7 +43,7 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest @patch.dict(settings.FEATURES, {'MODE_CREATION_FOR_TESTING': True}) def setUp(self): - super(CourseModeViewTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() now = datetime.now(pytz.utc) day = timedelta(days=1) tomorrow = now + day @@ -88,7 +88,7 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest ) # Configure whether we're upgrading or not - url = reverse('course_modes_choose', args=[six.text_type(course.id)]) + url = reverse('course_modes_choose', args=[str(course.id)]) response = self.client.get(url) # Check whether we were correctly redirected @@ -115,7 +115,7 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest ) # Configure whether we're upgrading or not - url = reverse('course_modes_choose', args=[six.text_type(self.course.id)]) + url = reverse('course_modes_choose', args=[str(self.course.id)]) response = self.client.get(url) start_flow_url = IDVerificationService.get_verify_location(course_id=self.course.id) @@ -136,7 +136,7 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest user=self.user ) # Configure whether we're upgrading or not - url = reverse('course_modes_choose', args=[six.text_type(prof_course.id)]) + url = reverse('course_modes_choose', args=[str(prof_course.id)]) response = self.client.get(url) self.assertRedirects(response, '/test_basket/add/?sku=TEST', fetch_redirect_response=False) ecomm_test_utils.update_commerce_config(enabled=False) @@ -170,7 +170,7 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest # Verify that the prices render correctly response = self.client.get( - reverse('course_modes_choose', args=[six.text_type(self.course.id)]), + reverse('course_modes_choose', args=[str(self.course.id)]), follow=False, ) @@ -191,7 +191,7 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest # Check whether credit upsell is shown on the page # This should *only* be shown when a credit mode is available - url = reverse('course_modes_choose', args=[six.text_type(self.course.id)]) + url = reverse('course_modes_choose', args=[str(self.course.id)]) response = self.client.get(url) if show_upsell: @@ -247,7 +247,7 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest # Check whether congratulations message is shown on the page # This should *only* be shown when an enrollment exists - url = reverse('course_modes_choose', args=[six.text_type(self.course.id)]) + url = reverse('course_modes_choose', args=[str(self.course.id)]) response = self.client.get(url) if create_enrollment: @@ -261,7 +261,7 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest CourseModeFactory.create(mode_slug=mode, course_id=self.course.id, min_price=1) # Go to the "choose your track" page - choose_track_url = reverse('course_modes_choose', args=[six.text_type(self.course.id)]) + choose_track_url = reverse('course_modes_choose', args=[str(self.course.id)]) response = self.client.get(choose_track_url) # Since the only available track is professional ed, expect that @@ -274,7 +274,7 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest user=self.user, is_active=True, mode=mode, - course_id=six.text_type(self.course.id), + course_id=str(self.course.id), ) # Expect that this time we're redirected to the dashboard (since we're already registered) @@ -303,7 +303,7 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest CourseModeFactory.create(mode_slug=mode, course_id=self.course.id, min_price=min_price) # Choose the mode (POST request) - choose_track_url = reverse('course_modes_choose', args=[six.text_type(self.course.id)]) + choose_track_url = reverse('course_modes_choose', args=[str(self.course.id)]) response = self.client.post(choose_track_url, self.POST_PARAMS_FOR_COURSE_MODE[course_mode]) # Verify the redirect @@ -330,7 +330,7 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest assert is_active is None # Choose the audit mode (POST request) - choose_track_url = reverse('course_modes_choose', args=[six.text_type(self.course.id)]) + choose_track_url = reverse('course_modes_choose', args=[str(self.course.id)]) self.client.post(choose_track_url, self.POST_PARAMS_FOR_COURSE_MODE[audit_mode]) # Assert learner is enrolled in Audit track post-POST @@ -358,14 +358,14 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest CourseModeFactory.create(mode_slug='verified', course_id=self.course.id, min_price=1) # Choose the mode (POST request) - choose_track_url = reverse('course_modes_choose', args=[six.text_type(self.course.id)]) + choose_track_url = reverse('course_modes_choose', args=[str(self.course.id)]) self.client.post(choose_track_url, self.POST_PARAMS_FOR_COURSE_MODE['verified']) # Expect that the contribution amount is stored in the user's session assert 'donation_for_course' in self.client.session - assert six.text_type(self.course.id) in self.client.session['donation_for_course'] + assert str(self.course.id) in self.client.session['donation_for_course'] - actual_amount = self.client.session['donation_for_course'][six.text_type(self.course.id)] + actual_amount = self.client.session['donation_for_course'][str(self.course.id)] expected_amount = decimal.Decimal(self.POST_PARAMS_FOR_COURSE_MODE['verified']['contribution']) assert actual_amount == expected_amount @@ -378,12 +378,12 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest # automatic enrollment params = { 'enrollment_action': 'enroll', - 'course_id': six.text_type(self.course.id) + 'course_id': str(self.course.id) } self.client.post(reverse('change_enrollment'), params) # Explicitly select the honor mode (POST request) - choose_track_url = reverse('course_modes_choose', args=[six.text_type(self.course.id)]) + choose_track_url = reverse('course_modes_choose', args=[str(self.course.id)]) self.client.post(choose_track_url, self.POST_PARAMS_FOR_COURSE_MODE[CourseMode.DEFAULT_MODE_SLUG]) # Verify that the user's enrollment remains unchanged @@ -397,7 +397,7 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest CourseModeFactory.create(mode_slug=mode, course_id=self.course.id) # Choose an unsupported mode (POST request) - choose_track_url = reverse('course_modes_choose', args=[six.text_type(self.course.id)]) + choose_track_url = reverse('course_modes_choose', args=[str(self.course.id)]) response = self.client.post(choose_track_url, self.POST_PARAMS_FOR_COURSE_MODE['unsupported']) assert 400 == response.status_code @@ -405,20 +405,20 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_default_mode_creation(self): # Hit the mode creation endpoint with no querystring params, to create an honor mode - url = reverse('create_mode', args=[six.text_type(self.course.id)]) + url = reverse('create_mode', args=[str(self.course.id)]) response = self.client.get(url) assert response.status_code == 200 - expected_mode = [Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None, None, None)] + expected_mode = [Mode('honor', 'Honor Code Certificate', 0, '', 'usd', None, None, None, None)] course_mode = CourseMode.modes_for_course(self.course.id) assert course_mode == expected_mode @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @ddt.data( - (u'verified', u'Verified Certificate', 10, '10,20,30', 'usd'), - (u'professional', u'Professional Education', 100, '100,200', 'usd'), + ('verified', 'Verified Certificate', 10, '10,20,30', 'usd'), + ('professional', 'Professional Education', 100, '100,200', 'usd'), ) @ddt.unpack def test_verified_mode_creation(self, mode_slug, mode_display_name, min_price, suggested_prices, currency): @@ -429,7 +429,7 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest parameters['suggested_prices'] = suggested_prices parameters['currency'] = currency - url = reverse('create_mode', args=[six.text_type(self.course.id)]) + url = reverse('create_mode', args=[str(self.course.id)]) response = self.client.get(url, parameters) assert response.status_code == 200 @@ -454,23 +454,23 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_multiple_mode_creation(self): # Create an honor mode - base_url = reverse('create_mode', args=[six.text_type(self.course.id)]) + base_url = reverse('create_mode', args=[str(self.course.id)]) self.client.get(base_url) # Excluding the currency parameter implicitly tests the mode creation endpoint's ability to # use default values when parameters are partially missing. parameters = {} - parameters['mode_slug'] = u'verified' - parameters['mode_display_name'] = u'Verified Certificate' + parameters['mode_slug'] = 'verified' + parameters['mode_display_name'] = 'Verified Certificate' parameters['min_price'] = 10 parameters['suggested_prices'] = '10,20' # Create a verified mode - url = reverse('create_mode', args=[six.text_type(self.course.id)]) + url = reverse('create_mode', args=[str(self.course.id)]) self.client.get(url, parameters) - honor_mode = Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None, None, None) - verified_mode = Mode(u'verified', u'Verified Certificate', 10, '10,20', 'usd', None, None, None, None) + honor_mode = Mode('honor', 'Honor Code Certificate', 0, '', 'usd', None, None, None, None) + verified_mode = Mode('verified', 'Verified Certificate', 10, '10,20', 'usd', None, None, None, None) expected_modes = [honor_mode, verified_mode] course_modes = CourseMode.modes_for_course(self.course.id) @@ -485,7 +485,7 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest CourseModeFactory.create(mode_slug=mode, course_id=self.course.id) # Load the track selection page - url = reverse('course_modes_choose', args=[six.text_type(self.course.id)]) + url = reverse('course_modes_choose', args=[str(self.course.id)]) response = self.client.get(url) # Verify that the header navigation links are hidden for the edx.org version @@ -502,7 +502,7 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest self.course.enrollment_end = datetime(2015, 1, 1) modulestore().update_item(self.course, self.user.id) - url = reverse('course_modes_choose', args=[six.text_type(self.course.id)]) + url = reverse('course_modes_choose', args=[str(self.course.id)]) response = self.client.get(url) # URL-encoded version of 1/1/15, 12:00 AM redirect_url = reverse('dashboard') + '?course_closed=1%2F1%2F15%2C+12%3A00+AM' @@ -517,7 +517,7 @@ class TrackSelectionEmbargoTest(UrlResetMixin, ModuleStoreTestCase): @patch.dict(settings.FEATURES, {'EMBARGO': True}) def setUp(self): - super(TrackSelectionEmbargoTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments + super().setUp() # Create a course and course modes self.course = CourseFactory.create() @@ -529,7 +529,7 @@ class TrackSelectionEmbargoTest(UrlResetMixin, ModuleStoreTestCase): self.client.login(username=self.user.username, password="edx") # Construct the URL for the track selection page - self.url = reverse('course_modes_choose', args=[six.text_type(self.course.id)]) + self.url = reverse('course_modes_choose', args=[str(self.course.id)]) @patch.dict(settings.FEATURES, {'EMBARGO': True}) def test_embargo_restrict(self): diff --git a/common/djangoapps/course_modes/urls.py b/common/djangoapps/course_modes/urls.py index 8e3937ef14..6337f51943 100644 --- a/common/djangoapps/course_modes/urls.py +++ b/common/djangoapps/course_modes/urls.py @@ -7,13 +7,13 @@ from django.conf.urls import url from common.djangoapps.course_modes import views urlpatterns = [ - url(r'^choose/{}/$'.format(settings.COURSE_ID_PATTERN), views.ChooseModeView.as_view(), name='course_modes_choose'), + url(fr'^choose/{settings.COURSE_ID_PATTERN}/$', views.ChooseModeView.as_view(), name='course_modes_choose'), ] # Enable verified mode creation if settings.FEATURES.get('MODE_CREATION_FOR_TESTING'): urlpatterns.append( - url(r'^create_mode/{}/$'.format(settings.COURSE_ID_PATTERN), + url(fr'^create_mode/{settings.COURSE_ID_PATTERN}/$', views.create_mode, name='create_mode'), ) diff --git a/common/djangoapps/course_modes/views.py b/common/djangoapps/course_modes/views.py index 389c5a59f7..df7bd13bd5 100644 --- a/common/djangoapps/course_modes/views.py +++ b/common/djangoapps/course_modes/views.py @@ -64,7 +64,7 @@ class ChooseModeView(View): atomic() block is active, since that would break atomicity. """ - return super(ChooseModeView, self).dispatch(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments + return super().dispatch(*args, **kwargs) @method_decorator(login_required) @method_decorator(transaction.atomic) @@ -136,13 +136,13 @@ class ChooseModeView(View): return redirect(reverse('dashboard')) donation_for_course = request.session.get("donation_for_course", {}) - chosen_price = donation_for_course.get(six.text_type(course_key), None) + chosen_price = donation_for_course.get(str(course_key), None) if CourseEnrollment.is_enrollment_closed(request.user, course): locale = to_locale(get_language()) enrollment_end_date = format_datetime(course.enrollment_end, 'short', locale=locale) params = six.moves.urllib.parse.urlencode({'course_closed': enrollment_end_date}) - return redirect('{0}?{1}'.format(reverse('dashboard'), params)) + return redirect('{}?{}'.format(reverse('dashboard'), params)) # When a credit mode is available, students will be given the option # to upgrade from a verified mode to a credit mode at the end of the course. @@ -156,7 +156,7 @@ class ChooseModeView(View): CourseMode.is_credit_mode(mode) for mode in CourseMode.modes_for_course(course_key, only_selectable=False) ) - course_id = text_type(course_key) + course_id = str(course_key) context = { "course_modes_choose_url": reverse( @@ -307,7 +307,7 @@ class ChooseModeView(View): return self.get(request, course_id, error=error_msg) donation_for_course = request.session.get("donation_for_course", {}) - donation_for_course[six.text_type(course_key)] = amount_value + donation_for_course[str(course_key)] = amount_value request.session["donation_for_course"] = donation_for_course verify_url = IDVerificationService.get_verify_location(course_id=course_key) @@ -358,16 +358,16 @@ def create_mode(request, course_id): Response """ PARAMETERS = { - 'mode_slug': u'honor', - 'mode_display_name': u'Honor Code Certificate', + 'mode_slug': 'honor', + 'mode_display_name': 'Honor Code Certificate', 'min_price': 0, - 'suggested_prices': u'', - 'currency': u'usd', + 'suggested_prices': '', + 'currency': 'usd', 'sku': None, } # Try pulling querystring parameters out of the request - for parameter, default in six.iteritems(PARAMETERS): + for parameter, default in PARAMETERS.items(): PARAMETERS[parameter] = request.GET.get(parameter, default) # Attempt to create the new mode for the given course