diff --git a/cms/djangoapps/api/v1/serializers/course_runs.py b/cms/djangoapps/api/v1/serializers/course_runs.py
index 8bd97eac4f..3ba33f1a07 100644
--- a/cms/djangoapps/api/v1/serializers/course_runs.py
+++ b/cms/djangoapps/api/v1/serializers/course_runs.py
@@ -1,10 +1,6 @@
""" Course run serializers. """
-
-
import logging
-import time # pylint: disable=unused-import
-import six
from django.contrib.auth import get_user_model
from django.db import transaction
from django.utils.translation import ugettext_lazy as _
@@ -14,8 +10,8 @@ from rest_framework.fields import empty
from cms.djangoapps.contentstore.views.assets import update_course_run_asset
from cms.djangoapps.contentstore.views.course import create_new_course, get_course_and_check_access, rerun_course
-from openedx.core.lib.courses import course_image_url
from common.djangoapps.student.models import CourseAccessRole
+from openedx.core.lib.courses import course_image_url
from xmodule.modulestore.django import modulestore
IMAGE_TYPES = {
@@ -88,7 +84,7 @@ def image_is_jpeg_or_png(value):
content_type = value.content_type
if content_type not in list(IMAGE_TYPES.keys()):
raise serializers.ValidationError(
- u'Only JPEG and PNG image types are supported. {} is not valid'.format(content_type))
+ f'Only JPEG and PNG image types are supported. {content_type} is not valid')
class CourseRunImageField(serializers.ImageField): # lint-amnesty, pylint: disable=missing-class-docstring
@@ -143,7 +139,7 @@ class CourseRunSerializer(CourseRunSerializerCommonFieldsMixin, CourseRunTeamSer
with transaction.atomic():
self.update_team(instance, team)
- for attr, value in six.iteritems(validated_data):
+ for attr, value in validated_data.items():
setattr(instance, attr, value)
modulestore().update_item(instance, self.context['request'].user.id)
@@ -183,11 +179,11 @@ class CourseRunRerunSerializer(CourseRunSerializerCommonFieldsMixin, CourseRunTe
new_course_run_key = store.make_course_key(course_run_key.org, number, run)
except InvalidKeyError:
raise serializers.ValidationError( # lint-amnesty, pylint: disable=raise-missing-from
- u'Invalid key supplied. Ensure there are no special characters in the Course Number.'
+ 'Invalid key supplied. Ensure there are no special characters in the Course Number.'
)
if store.has_course(new_course_run_key, ignore_case=True):
raise serializers.ValidationError(
- {'run': u'Course run {key} already exists'.format(key=new_course_run_key)}
+ {'run': f'Course run {new_course_run_key} already exists'}
)
return attrs
diff --git a/cms/djangoapps/api/v1/tests/test_serializers/test_course_runs.py b/cms/djangoapps/api/v1/tests/test_serializers/test_course_runs.py
index 3a6dbb1f6f..fd2fa0682c 100644
--- a/cms/djangoapps/api/v1/tests/test_serializers/test_course_runs.py
+++ b/cms/djangoapps/api/v1/tests/test_serializers/test_course_runs.py
@@ -7,9 +7,9 @@ import ddt
import pytz
from django.test import RequestFactory
-from openedx.core.lib.courses import course_image_url
from common.djangoapps.student.roles import CourseInstructorRole, CourseStaffRole
from common.djangoapps.student.tests.factories import UserFactory
+from openedx.core.lib.courses import course_image_url
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
@@ -21,7 +21,7 @@ from ..utils import serialize_datetime
class CourseRunSerializerTests(ModuleStoreTestCase): # lint-amnesty, pylint: disable=missing-class-docstring
def setUp(self):
- super(CourseRunSerializerTests, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
+ super().setUp()
self.course_start = datetime.datetime.now(pytz.UTC)
self.course_end = self.course_start + datetime.timedelta(days=30)
diff --git a/cms/djangoapps/api/v1/tests/test_views/test_course_runs.py b/cms/djangoapps/api/v1/tests/test_views/test_course_runs.py
index 5d98818c04..7fccfcd5d8 100644
--- a/cms/djangoapps/api/v1/tests/test_views/test_course_runs.py
+++ b/cms/djangoapps/api/v1/tests/test_views/test_course_runs.py
@@ -2,20 +2,20 @@
import datetime
+from unittest.mock import patch # lint-amnesty, pylint: disable=unused-import
import ddt
import pytz
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import RequestFactory, override_settings
from django.urls import reverse
-from mock import patch # lint-amnesty, pylint: disable=unused-import
from opaque_keys.edx.keys import CourseKey
from organizations.api import add_organization, get_course_organizations
from rest_framework.test import APIClient
-from openedx.core.lib.courses import course_image_url
from common.djangoapps.student.models import CourseAccessRole
from common.djangoapps.student.tests.factories import TEST_PASSWORD, AdminFactory, UserFactory
+from openedx.core.lib.courses import course_image_url
from xmodule.contentstore.content import StaticContent
from xmodule.contentstore.django import contentstore
from xmodule.exceptions import NotFoundError
@@ -35,7 +35,7 @@ class CourseRunViewSetTests(ModuleStoreTestCase):
list_url = reverse('api:v1:course_run-list')
def setUp(self):
- super(CourseRunViewSetTests, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
+ super().setUp()
self.client = APIClient()
user = AdminFactory()
self.client.login(username=user.username, password=TEST_PASSWORD)
@@ -388,7 +388,7 @@ class CourseRunViewSetTests(ModuleStoreTestCase):
}
response = self.client.post(url, data, format='json')
assert response.status_code == 400
- assert response.data == {'run': [u'Course run {key} already exists'.format(key=course_run.id)]}
+ assert response.data == {'run': [f'Course run {course_run.id} already exists']}
def test_rerun_invalid_number(self):
course_run = ToyCourseFactory()
@@ -400,5 +400,5 @@ class CourseRunViewSetTests(ModuleStoreTestCase):
response = self.client.post(url, data, format='json')
assert response.status_code == 400
assert response.data == {'non_field_errors': [
- u'Invalid key supplied. Ensure there are no special characters in the Course Number.'
+ 'Invalid key supplied. Ensure there are no special characters in the Course Number.'
]}
diff --git a/cms/djangoapps/api/v1/views/course_runs.py b/cms/djangoapps/api/v1/views/course_runs.py
index ebe1b63777..a0415d4e06 100644
--- a/cms/djangoapps/api/v1/views/course_runs.py
+++ b/cms/djangoapps/api/v1/views/course_runs.py
@@ -30,8 +30,8 @@ class CourseRunViewSet(viewsets.GenericViewSet): # lint-amnesty, pylint: disabl
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
assert lookup_url_kwarg in self.kwargs, (
- u'Expected view %s to be called with a URL keyword argument '
- u'named "%s". Fix your URL conf, or set the `.lookup_field` '
+ 'Expected view %s to be called with a URL keyword argument '
+ 'named "%s". Fix your URL conf, or set the `.lookup_field` '
'attribute on the view correctly.' %
(self.__class__.__name__, lookup_url_kwarg)
)
diff --git a/cms/djangoapps/cms_user_tasks/apps.py b/cms/djangoapps/cms_user_tasks/apps.py
index c8b3edb899..c4ac938c6e 100644
--- a/cms/djangoapps/cms_user_tasks/apps.py
+++ b/cms/djangoapps/cms_user_tasks/apps.py
@@ -11,7 +11,7 @@ class CmsUserTasksConfig(AppConfig):
"""
Application Configuration for cms_user_tasks.
"""
- name = u'cms.djangoapps.cms_user_tasks'
+ name = 'cms.djangoapps.cms_user_tasks'
def ready(self):
"""
diff --git a/cms/djangoapps/cms_user_tasks/signals.py b/cms/djangoapps/cms_user_tasks/signals.py
index 2d36ec821d..815d69f664 100644
--- a/cms/djangoapps/cms_user_tasks/signals.py
+++ b/cms/djangoapps/cms_user_tasks/signals.py
@@ -4,10 +4,10 @@ Receivers of signals sent from django-user-tasks
import logging
+from urllib.parse import urljoin
from django.dispatch import receiver
from django.urls import reverse
-from six.moves.urllib.parse import urljoin
from user_tasks.models import UserTaskArtifact
from user_tasks.signals import user_task_stopped
diff --git a/cms/djangoapps/cms_user_tasks/tasks.py b/cms/djangoapps/cms_user_tasks/tasks.py
index cbb4171bac..01515182ac 100644
--- a/cms/djangoapps/cms_user_tasks/tasks.py
+++ b/cms/djangoapps/cms_user_tasks/tasks.py
@@ -4,8 +4,8 @@ Celery tasks used by cms_user_tasks
from boto.exception import NoAuthHandlerFound
-from celery.exceptions import MaxRetriesExceededError
from celery import shared_task
+from celery.exceptions import MaxRetriesExceededError
from celery.utils.log import get_task_logger
from django.conf import settings
from django.core import mail
@@ -45,10 +45,10 @@ def send_task_complete_email(self, task_name, task_state_text, dest_addr, detail
try:
mail.send_mail(subject, message, from_address, [dest_addr], fail_silently=False)
- LOGGER.info(u"Task complete email has been sent to User %s", dest_addr)
+ LOGGER.info("Task complete email has been sent to User %s", dest_addr)
except NoAuthHandlerFound:
LOGGER.info(
- u'Retrying sending email to user %s, attempt # %s of %s',
+ 'Retrying sending email to user %s, attempt # %s of %s',
dest_addr,
retries,
TASK_COMPLETE_EMAIL_MAX_RETRIES
@@ -57,14 +57,14 @@ def send_task_complete_email(self, task_name, task_state_text, dest_addr, detail
self.retry(countdown=TASK_COMPLETE_EMAIL_TIMEOUT, max_retries=TASK_COMPLETE_EMAIL_MAX_RETRIES)
except MaxRetriesExceededError:
LOGGER.error(
- u'Unable to send task completion email to user from "%s" to "%s"',
+ 'Unable to send task completion email to user from "%s" to "%s"',
from_address,
dest_addr,
exc_info=True
)
except Exception: # pylint: disable=broad-except
LOGGER.exception(
- u'Unable to send task completion email to user from "%s" to "%s"',
+ 'Unable to send task completion email to user from "%s" to "%s"',
from_address,
dest_addr,
exc_info=True
diff --git a/cms/djangoapps/cms_user_tasks/tests.py b/cms/djangoapps/cms_user_tasks/tests.py
index 7015b7b4e2..bbc6cd098b 100644
--- a/cms/djangoapps/cms_user_tasks/tests.py
+++ b/cms/djangoapps/cms_user_tasks/tests.py
@@ -4,9 +4,9 @@ Unit tests for integration of the django-user-tasks app and its REST API.
import logging
+from unittest import mock
from uuid import uuid4
-import mock
from boto.exception import NoAuthHandlerFound
from django.conf import settings
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
@@ -80,7 +80,7 @@ class TestUserTasks(APITestCase):
cls.artifact = UserTaskArtifact.objects.create(status=cls.status, text='Lorem ipsum')
def setUp(self):
- super(TestUserTasks, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
+ super().setUp()
self.status.refresh_from_db()
self.client.force_authenticate(self.user) # pylint: disable=no-member
@@ -152,7 +152,7 @@ class TestUserTaskStopped(APITestCase):
total_steps=5)
def setUp(self):
- super(TestUserTaskStopped, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
+ super().setUp()
self.status.refresh_from_db()
self.client.force_authenticate(self.user) # pylint: disable=no-member
@@ -169,7 +169,7 @@ class TestUserTaskStopped(APITestCase):
platform_name=settings.PLATFORM_NAME, studio_name=settings.STUDIO_NAME
)
body_fragments = [
- "Your {task_name} task has completed with the status".format(task_name=self.status.name.lower()),
+ f"Your {self.status.name.lower()} task has completed with the status",
"https://test.edx.org/",
reverse('usertaskstatus-detail', args=[self.status.uuid])
]
@@ -202,7 +202,7 @@ class TestUserTaskStopped(APITestCase):
platform_name=settings.PLATFORM_NAME, studio_name=settings.STUDIO_NAME
)
fragments = [
- "Your {task_name} task has completed with the status".format(task_name=self.status.name.lower()),
+ f"Your {self.status.name.lower()} task has completed with the status",
"Sign in to view the details of your task or download any files created."
]
@@ -234,4 +234,4 @@ class TestUserTaskStopped(APITestCase):
mock_delay.side_effect = NoAuthHandlerFound()
user_task_stopped.send(sender=UserTaskStatus, status=self.status)
self.assertTrue(mock_delay.called)
- self.assertEqual(hdlr.messages['error'][0], u'Unable to queue send_task_complete_email')
+ self.assertEqual(hdlr.messages['error'][0], 'Unable to queue send_task_complete_email')
diff --git a/cms/djangoapps/contentstore/api/tests/base.py b/cms/djangoapps/contentstore/api/tests/base.py
index b125ff704f..10dc8bce64 100644
--- a/cms/djangoapps/contentstore/api/tests/base.py
+++ b/cms/djangoapps/contentstore/api/tests/base.py
@@ -6,8 +6,8 @@ Base test case for the course API views.
from django.urls import reverse
from rest_framework.test import APITestCase
-from lms.djangoapps.courseware.tests.factories import StaffFactory
from common.djangoapps.student.tests.factories import UserFactory
+from lms.djangoapps.courseware.tests.factories import StaffFactory
from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
@@ -22,7 +22,7 @@ class BaseCourseViewTest(SharedModuleStoreTestCase, APITestCase):
@classmethod
def setUpClass(cls):
- super(BaseCourseViewTest, cls).setUpClass()
+ super().setUpClass()
cls.course = CourseFactory.create(display_name='test course', run="Testing_course")
cls.course_key = cls.course.id
diff --git a/cms/djangoapps/contentstore/api/tests/test_import.py b/cms/djangoapps/contentstore/api/tests/test_import.py
index a989993590..a7a8246868 100644
--- a/cms/djangoapps/contentstore/api/tests/test_import.py
+++ b/cms/djangoapps/contentstore/api/tests/test_import.py
@@ -13,8 +13,8 @@ from rest_framework import status
from rest_framework.test import APITestCase
from user_tasks.models import UserTaskStatus
-from lms.djangoapps.courseware.tests.factories import StaffFactory
from common.djangoapps.student.tests.factories import UserFactory
+from lms.djangoapps.courseware.tests.factories import StaffFactory
from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
@@ -27,7 +27,7 @@ class CourseImportViewTest(SharedModuleStoreTestCase, APITestCase):
@classmethod
def setUpClass(cls):
- super(CourseImportViewTest, cls).setUpClass()
+ super().setUpClass()
cls.course = CourseFactory.create(display_name='test course', run="Testing_course")
cls.course_key = cls.course.id
diff --git a/cms/djangoapps/contentstore/api/tests/test_validation.py b/cms/djangoapps/contentstore/api/tests/test_validation.py
index cf570c7fcf..a269eb2a59 100644
--- a/cms/djangoapps/contentstore/api/tests/test_validation.py
+++ b/cms/djangoapps/contentstore/api/tests/test_validation.py
@@ -9,8 +9,8 @@ from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase
-from lms.djangoapps.courseware.tests.factories import StaffFactory
from common.djangoapps.student.tests.factories import UserFactory
+from lms.djangoapps.courseware.tests.factories import StaffFactory
from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
@@ -23,7 +23,7 @@ class CourseValidationViewTest(SharedModuleStoreTestCase, APITestCase):
@classmethod
def setUpClass(cls):
- super(CourseValidationViewTest, cls).setUpClass()
+ super().setUpClass()
cls.course = CourseFactory.create(display_name='test course', run="Testing_course")
cls.course_key = cls.course.id
@@ -49,7 +49,7 @@ class CourseValidationViewTest(SharedModuleStoreTestCase, APITestCase):
update_key.course_key,
update_key.block_type,
block_id=update_key.block_id,
- fields=dict(data=u"
Date
Hello world!
"),
+ fields=dict(data="Date
Hello world!
"),
)
section = ItemFactory.create(
diff --git a/cms/djangoapps/contentstore/api/urls.py b/cms/djangoapps/contentstore/api/urls.py
index 21a60c0342..384b0b708e 100644
--- a/cms/djangoapps/contentstore/api/urls.py
+++ b/cms/djangoapps/contentstore/api/urls.py
@@ -9,10 +9,10 @@ from cms.djangoapps.contentstore.api.views import course_import, course_quality,
app_name = 'contentstore'
urlpatterns = [
- url(r'^v0/import/{course_id}/$'.format(course_id=settings.COURSE_ID_PATTERN,),
+ url(fr'^v0/import/{settings.COURSE_ID_PATTERN}/$',
course_import.CourseImportView.as_view(), name='course_import'),
- url(r'^v1/validation/{course_id}/$'.format(course_id=settings.COURSE_ID_PATTERN,),
+ url(fr'^v1/validation/{settings.COURSE_ID_PATTERN}/$',
course_validation.CourseValidationView.as_view(), name='course_validation'),
- url(r'^v1/quality/{course_id}/$'.format(course_id=settings.COURSE_ID_PATTERN,),
+ url(fr'^v1/quality/{settings.COURSE_ID_PATTERN}/$',
course_quality.CourseQualityView.as_view(), name='course_quality'),
]
diff --git a/cms/djangoapps/contentstore/api/views/course_import.py b/cms/djangoapps/contentstore/api/views/course_import.py
index 9430aee2cd..13106b1d36 100644
--- a/cms/djangoapps/contentstore/api/views/course_import.py
+++ b/cms/djangoapps/contentstore/api/views/course_import.py
@@ -14,7 +14,6 @@ from rest_framework import status
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
-from six import text_type
from user_tasks.models import UserTaskStatus
from cms.djangoapps.contentstore.storage import course_import_export_storage
@@ -35,7 +34,7 @@ class CourseImportExportViewMixin(DeveloperErrorViewMixin):
"""
Ensures that the user is authenticated (e.g. not an AnonymousUser)
"""
- super(CourseImportExportViewMixin, self).perform_authentication(request) # lint-amnesty, pylint: disable=super-with-arguments
+ super().perform_authentication(request)
if request.user.is_anonymous:
raise AuthenticationFailed
@@ -135,18 +134,18 @@ class CourseImportView(CourseImportExportViewMixin, GenericAPIView):
if not course_dir.isdir():
os.mkdir(course_dir)
- log.debug(u'importing course to {0}'.format(temp_filepath))
+ log.debug(f'importing course to {temp_filepath}')
with open(temp_filepath, "wb+") as temp_file:
for chunk in request.FILES['course_data'].chunks():
temp_file.write(chunk)
- log.info(u"Course import %s: Upload complete", course_key)
+ log.info("Course import %s: Upload complete", course_key)
with open(temp_filepath, 'rb') as local_file:
django_file = File(local_file)
- storage_path = course_import_export_storage.save(u'olx_import/' + filename, django_file)
+ storage_path = course_import_export_storage.save('olx_import/' + filename, django_file)
async_result = import_olx.delay(
- request.user.id, text_type(course_key), storage_path, filename, request.LANGUAGE_CODE)
+ request.user.id, str(course_key), storage_path, filename, request.LANGUAGE_CODE)
return Response({
'task_id': async_result.task_id
})
@@ -166,7 +165,7 @@ class CourseImportView(CourseImportExportViewMixin, GenericAPIView):
try:
task_id = request.GET['task_id']
filename = request.GET['filename']
- args = {u'course_key_string': str(course_key), u'archive_name': filename}
+ args = {'course_key_string': str(course_key), 'archive_name': filename}
name = CourseImportTask.generate_name(args)
task_status = UserTaskStatus.objects.filter(name=name, task_id=task_id).first()
return Response({
diff --git a/cms/djangoapps/contentstore/api/views/course_quality.py b/cms/djangoapps/contentstore/api/views/course_quality.py
index b0dab122f2..7b2585f50f 100644
--- a/cms/djangoapps/contentstore/api/views/course_quality.py
+++ b/cms/djangoapps/contentstore/api/views/course_quality.py
@@ -3,7 +3,6 @@ import logging
import time
import numpy as np
-import six
from edxval.api import get_videos_for_course
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
@@ -91,7 +90,7 @@ class CourseQualityView(DeveloperErrorViewMixin, GenericAPIView):
if log_time:
start_time = time.time()
output = func(*args)
- log.info(u'[%s] completed in [%f]', func.__name__, (time.time() - start_time))
+ log.info('[%s] completed in [%f]', func.__name__, (time.time() - start_time))
else:
output = func(*args)
return output
@@ -154,25 +153,25 @@ class CourseQualityView(DeveloperErrorViewMixin, GenericAPIView):
def _subsections_quality(self, course, request): # lint-amnesty, pylint: disable=missing-function-docstring
subsection_unit_dict = self._get_subsections_and_units(course, request)
num_block_types_per_subsection_dict = {}
- for subsection_key, unit_dict in six.iteritems(subsection_unit_dict):
+ for subsection_key, unit_dict in subsection_unit_dict.items():
leaf_block_types_in_subsection = (
unit_info['leaf_block_types']
- for unit_info in six.itervalues(unit_dict)
+ for unit_info in unit_dict.values()
)
num_block_types_per_subsection_dict[subsection_key] = len(set().union(*leaf_block_types_in_subsection))
return dict(
total_visible=len(num_block_types_per_subsection_dict),
- num_with_one_block_type=list(six.itervalues(num_block_types_per_subsection_dict)).count(1),
- num_block_types=self._stats_dict(list(six.itervalues(num_block_types_per_subsection_dict))),
+ num_with_one_block_type=list(num_block_types_per_subsection_dict.values()).count(1),
+ num_block_types=self._stats_dict(list(num_block_types_per_subsection_dict.values())),
)
def _units_quality(self, course, request): # lint-amnesty, pylint: disable=missing-function-docstring
subsection_unit_dict = self._get_subsections_and_units(course, request)
num_leaf_blocks_per_unit = [
unit_info['num_leaf_blocks']
- for unit_dict in six.itervalues(subsection_unit_dict)
- for unit_info in six.itervalues(unit_dict)
+ for unit_dict in subsection_unit_dict.values()
+ for unit_info in unit_dict.values()
]
return dict(
total_visible=len(num_leaf_blocks_per_unit),
@@ -215,7 +214,7 @@ class CourseQualityView(DeveloperErrorViewMixin, GenericAPIView):
leaf_blocks = cls._get_leaf_blocks(unit)
unit_dict[unit.location] = dict(
num_leaf_blocks=len(leaf_blocks),
- leaf_block_types=set(block.location.block_type for block in leaf_blocks),
+ leaf_block_types={block.location.block_type for block in leaf_blocks},
)
subsection_dict[subsection.location] = unit_dict
diff --git a/cms/djangoapps/contentstore/api/views/course_validation.py b/cms/djangoapps/contentstore/api/views/course_validation.py
index a04b022288..1ab4e218ee 100644
--- a/cms/djangoapps/contentstore/api/views/course_validation.py
+++ b/cms/djangoapps/contentstore/api/views/course_validation.py
@@ -2,7 +2,6 @@
import logging
import dateutil
-import six
from pytz import UTC
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
@@ -118,7 +117,7 @@ class CourseValidationView(DeveloperErrorViewMixin, GenericAPIView):
]
assignments_with_dates_before_start = (
[
- {'id': six.text_type(a.location), 'display_name': a.display_name}
+ {'id': str(a.location), 'display_name': a.display_name}
for a in assignments_with_dates
if a.due < course.start
]
@@ -128,7 +127,7 @@ class CourseValidationView(DeveloperErrorViewMixin, GenericAPIView):
assignments_with_dates_after_end = (
[
- {'id': six.text_type(a.location), 'display_name': a.display_name}
+ {'id': str(a.location), 'display_name': a.display_name}
for a in assignments_with_dates
if a.due > course.end
]
@@ -144,7 +143,7 @@ class CourseValidationView(DeveloperErrorViewMixin, GenericAPIView):
]
assignments_with_dates_before_start = (
[
- {'id': six.text_type(a.location), 'display_name': a.display_name}
+ {'id': str(a.location), 'display_name': a.display_name}
for a in assignments_with_dates
if a.due < course.start
]
@@ -154,7 +153,7 @@ class CourseValidationView(DeveloperErrorViewMixin, GenericAPIView):
assignments_with_dates_after_end = (
[
- {'id': six.text_type(a.location), 'display_name': a.display_name}
+ {'id': str(a.location), 'display_name': a.display_name}
for a in assignments_with_dates
if a.due > course.end
]
@@ -175,14 +174,14 @@ class CourseValidationView(DeveloperErrorViewMixin, GenericAPIView):
parent_unit = modulestore().get_item(ora.parent)
parent_assignment = modulestore().get_item(parent_unit.parent)
assignments_with_ora_dates_before_start.append({
- 'id': six.text_type(parent_assignment.location),
+ 'id': str(parent_assignment.location),
'display_name': parent_assignment.display_name
})
if course.end and self._has_date_after_end(ora, course.end):
parent_unit = modulestore().get_item(ora.parent)
parent_assignment = modulestore().get_item(parent_unit.parent)
assignments_with_ora_dates_after_end.append({
- 'id': six.text_type(parent_assignment.location),
+ 'id': str(parent_assignment.location),
'display_name': parent_assignment.display_name
})
diff --git a/cms/djangoapps/contentstore/api/views/utils.py b/cms/djangoapps/contentstore/api/views/utils.py
index 92e75ae1a2..36c83b211b 100644
--- a/cms/djangoapps/contentstore/api/views/utils.py
+++ b/cms/djangoapps/contentstore/api/views/utils.py
@@ -9,10 +9,10 @@ from opaque_keys.edx.keys import CourseKey
from rest_framework import status
from rest_framework.generics import GenericAPIView
+from common.djangoapps.student.auth import has_course_author_access
from openedx.core.djangoapps.util.forms import to_bool
from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin, view_auth_classes
from openedx.core.lib.cache_utils import request_cached
-from common.djangoapps.student.auth import has_course_author_access
from xmodule.modulestore.django import modulestore
diff --git a/cms/djangoapps/contentstore/apps.py b/cms/djangoapps/contentstore/apps.py
index d3a854f005..a1ff02e4ca 100644
--- a/cms/djangoapps/contentstore/apps.py
+++ b/cms/djangoapps/contentstore/apps.py
@@ -12,7 +12,7 @@ class ContentstoreConfig(AppConfig):
"""
Application Configuration for Contentstore.
"""
- name = u'cms.djangoapps.contentstore'
+ name = 'cms.djangoapps.contentstore'
def ready(self):
"""
diff --git a/cms/djangoapps/contentstore/config/waffle.py b/cms/djangoapps/contentstore/config/waffle.py
index f6947229be..24c13190b3 100644
--- a/cms/djangoapps/contentstore/config/waffle.py
+++ b/cms/djangoapps/contentstore/config/waffle.py
@@ -5,39 +5,40 @@ waffle switches for the contentstore app.
from edx_toggles.toggles import LegacyWaffleFlag, LegacyWaffleFlagNamespace, LegacyWaffleSwitchNamespace
+
from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag
# Namespace
-WAFFLE_NAMESPACE = u'studio'
+WAFFLE_NAMESPACE = 'studio'
# Switches
-ENABLE_ACCESSIBILITY_POLICY_PAGE = u'enable_policy_page'
+ENABLE_ACCESSIBILITY_POLICY_PAGE = 'enable_policy_page'
def waffle():
"""
Returns the namespaced, cached, audited Waffle Switch class for Studio pages.
"""
- return LegacyWaffleSwitchNamespace(name=WAFFLE_NAMESPACE, log_prefix=u'Studio: ')
+ return LegacyWaffleSwitchNamespace(name=WAFFLE_NAMESPACE, log_prefix='Studio: ')
def waffle_flags():
"""
Returns the namespaced, cached, audited Waffle Flag class for Studio pages.
"""
- return LegacyWaffleFlagNamespace(name=WAFFLE_NAMESPACE, log_prefix=u'Studio: ')
+ return LegacyWaffleFlagNamespace(name=WAFFLE_NAMESPACE, log_prefix='Studio: ')
# TODO: After removing this flag, add a migration to remove waffle flag in a follow-up deployment.
ENABLE_CHECKLISTS_QUALITY = CourseWaffleFlag(
waffle_namespace=waffle_flags(),
- flag_name=u'enable_checklists_quality',
+ flag_name='enable_checklists_quality',
module_name=__name__,
)
SHOW_REVIEW_RULES_FLAG = CourseWaffleFlag(
waffle_namespace=waffle_flags(),
- flag_name=u'show_review_rules',
+ flag_name='show_review_rules',
module_name=__name__,
)
diff --git a/cms/djangoapps/contentstore/course_group_config.py b/cms/djangoapps/contentstore/course_group_config.py
index a9ae47aecf..33ed74f722 100644
--- a/cms/djangoapps/contentstore/course_group_config.py
+++ b/cms/djangoapps/contentstore/course_group_config.py
@@ -10,9 +10,9 @@ from collections import defaultdict
from django.utils.translation import ugettext as _
from cms.djangoapps.contentstore.utils import reverse_usage_url
+from common.djangoapps.util.db import MYSQL_MAX_INT, generate_int_id
from lms.lib.utils import get_parent_unit
from openedx.core.djangoapps.course_groups.partition_scheme import get_cohorted_user_partition
-from common.djangoapps.util.db import MYSQL_MAX_INT, generate_int_id
from xmodule.partitions.partitions import MINIMUM_STATIC_PARTITION_ID, ReadOnlyUserPartitionError, UserPartition
from xmodule.partitions.partitions_service import get_all_partitions_for_course
from xmodule.split_test_module import get_split_user_partitions
@@ -39,7 +39,7 @@ class GroupConfigurationsValidationError(Exception):
pass # lint-amnesty, pylint: disable=unnecessary-pass
-class GroupConfiguration(object):
+class GroupConfiguration:
"""
Prepare Group Configuration for the course.
"""
@@ -102,7 +102,7 @@ class GroupConfiguration(object):
"""
Return a list of IDs that already in use.
"""
- return set([p.id for p in get_all_partitions_for_course(course)]) # lint-amnesty, pylint: disable=consider-using-set-comprehension
+ return {p.id for p in get_all_partitions_for_course(course)}
def get_user_partition(self):
"""
@@ -144,7 +144,7 @@ class GroupConfiguration(object):
course.location.course_key.make_usage_key(unit_for_url.location.block_type, unit_for_url.location.block_id)
)
- usage_dict = {'label': u"{} / {}".format(unit.display_name, item.display_name), 'url': unit_url}
+ usage_dict = {'label': f"{unit.display_name} / {item.display_name}", 'url': unit_url}
if scheme_name == RANDOM_SCHEME:
validation_summary = item.general_validation_message()
usage_dict.update({'validation': validation_summary.to_json() if validation_summary else None})
@@ -196,7 +196,7 @@ class GroupConfiguration(object):
for split_test in split_tests:
unit = split_test.get_parent()
if not unit:
- log.warning(u"Unable to find parent for split_test %s", split_test.location)
+ log.warning("Unable to find parent for split_test %s", split_test.location)
# Make sure that this user_partition appears in the output even though it has no content
usage_info[split_test.user_partition_id] = []
continue
@@ -236,7 +236,7 @@ class GroupConfiguration(object):
for item, partition_id, group_id in GroupConfiguration._iterate_items_and_group_ids(course, items):
unit = item.get_parent()
if not unit:
- log.warning(u"Unable to find parent for component %s", item.location)
+ log.warning("Unable to find parent for component %s", item.location)
continue
usage_info[partition_id][group_id].append(GroupConfiguration._get_usage_dict(
diff --git a/cms/djangoapps/contentstore/courseware_index.py b/cms/djangoapps/contentstore/courseware_index.py
index e6b465797a..8bffd64a1f 100644
--- a/cms/djangoapps/contentstore/courseware_index.py
+++ b/cms/djangoapps/contentstore/courseware_index.py
@@ -11,7 +11,6 @@ from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy
from eventtracking import tracker
from search.search_engine_base import SearchEngine
-from six import add_metaclass, string_types, text_type
from cms.djangoapps.contentstore.course_group_config import GroupConfiguration
from common.djangoapps.course_modes.models import CourseMode
@@ -57,12 +56,11 @@ class SearchIndexingError(Exception):
""" Indicates some error(s) occured during indexing """
def __init__(self, message, error_list):
- super(SearchIndexingError, self).__init__(message) # lint-amnesty, pylint: disable=super-with-arguments
+ super().__init__(message)
self.error_list = error_list
-@add_metaclass(ABCMeta)
-class SearchIndexerBase(object, metaclass=ABCMeta):
+class SearchIndexerBase(metaclass=ABCMeta):
"""
Base class to perform indexing for courseware or library search from different modulestores
"""
@@ -192,22 +190,22 @@ class SearchIndexerBase(object, metaclass=ABCMeta):
for split_test_child in item.get_children():
if split_partition:
for group in split_partition.groups:
- group_id = text_type(group.id)
+ group_id = str(group.id)
child_location = item.group_id_to_child.get(group_id, None)
if child_location == split_test_child.location:
groups_usage_info.update({
- text_type(get_item_location(split_test_child)): [group_id],
+ str(get_item_location(split_test_child)): [group_id],
})
for component in split_test_child.get_children():
groups_usage_info.update({
- text_type(get_item_location(component)): [group_id]
+ str(get_item_location(component)): [group_id]
})
if groups_usage_info:
item_location = get_item_location(item)
- item_content_groups = groups_usage_info.get(text_type(item_location), None)
+ item_content_groups = groups_usage_info.get(str(item_location), None)
- item_id = text_type(cls._id_modifier(item.scope_ids.usage_id))
+ item_id = str(cls._id_modifier(item.scope_ids.usage_id))
indexed_items.add(item_id)
if item.has_children:
# determine if it's okay to skip adding the children herein based upon how recently any may have changed
@@ -244,8 +242,8 @@ class SearchIndexerBase(object, metaclass=ABCMeta):
return item_content_groups
except Exception as err: # pylint: disable=broad-except
# broad exception so that index operation does not fail on one item of many
- log.warning(u'Could not index item: %s - %r', item.location, err)
- error_list.append(_(u'Could not index item: {}').format(item.location))
+ log.warning('Could not index item: %s - %r', item.location, err)
+ error_list.append(_('Could not index item: {}').format(item.location))
try:
with modulestore.branch_setting(ModuleStoreEnum.RevisionOption.published_only):
@@ -263,7 +261,7 @@ class SearchIndexerBase(object, metaclass=ABCMeta):
except Exception as err: # pylint: disable=broad-except
# broad exception so that index operation does not prevent the rest of the application from working
log.exception(
- u"Indexing error encountered, courseware index may be out of date %s - %r",
+ "Indexing error encountered, courseware index may be out of date %s - %r",
structure_key,
err
)
@@ -365,7 +363,7 @@ class CoursewareSearchIndexer(SearchIndexerBase):
@classmethod
def _get_location_info(cls, normalized_structure_key):
""" Builds location info dictionary """
- return {"course": text_type(normalized_structure_key), "org": normalized_structure_key.org}
+ return {"course": str(normalized_structure_key), "org": normalized_structure_key.org}
@classmethod
def do_course_reindex(cls, modulestore, course_key):
@@ -405,7 +403,7 @@ class CoursewareSearchIndexer(SearchIndexerBase):
for name, group in groups.items():
for module in group:
view, args, kwargs = resolve(module['url']) # pylint: disable=unused-variable
- usage_key_string = text_type(kwargs['usage_key_string'])
+ usage_key_string = str(kwargs['usage_key_string'])
if groups_usage_dict.get(usage_key_string, None):
groups_usage_dict[usage_key_string].append(name)
else:
@@ -434,7 +432,7 @@ class CoursewareSearchIndexer(SearchIndexerBase):
while parent is not None:
path_component_name = parent.display_name
if not path_component_name:
- path_component_name = text_type(cls.UNNAMED_MODULE_NAME)
+ path_component_name = str(cls.UNNAMED_MODULE_NAME)
location_path.append(path_component_name)
parent = parent.get_parent()
location_path.reverse()
@@ -469,7 +467,7 @@ class LibrarySearchIndexer(SearchIndexerBase):
@classmethod
def _get_location_info(cls, normalized_structure_key):
""" Builds location info dictionary """
- return {"library": text_type(normalized_structure_key)}
+ return {"library": str(normalized_structure_key)}
@classmethod
def _id_modifier(cls, usage_id):
@@ -484,7 +482,7 @@ class LibrarySearchIndexer(SearchIndexerBase):
return cls._do_reindex(modulestore, library_key)
-class AboutInfo(object):
+class AboutInfo:
""" About info structure to contain
1) Property name to use
2) Where to add in the index (using flags above)
@@ -605,7 +603,7 @@ class CourseAboutSearchIndexer(CoursewareSearchIndexer):
if not searcher:
return
- course_id = text_type(course.id)
+ course_id = str(course.id)
course_info = {
'id': course_id,
'course': course_id,
@@ -631,7 +629,7 @@ class CourseAboutSearchIndexer(CoursewareSearchIndexer):
except: # pylint: disable=bare-except
section_content = None
log.warning(
- u"Course discovery could not collect property %s for course %s",
+ "Course discovery could not collect property %s for course %s",
about_information.property_name,
course_id,
exc_info=True,
@@ -640,7 +638,7 @@ class CourseAboutSearchIndexer(CoursewareSearchIndexer):
if section_content:
if about_information.index_flags & AboutInfo.ANALYSE:
analyse_content = section_content
- if isinstance(section_content, string_types):
+ if isinstance(section_content, str):
analyse_content = strip_html_content_to_text(section_content)
course_info['content'][about_information.property_name] = analyse_content
if about_information.index_flags & AboutInfo.PROPERTY:
@@ -651,20 +649,20 @@ class CourseAboutSearchIndexer(CoursewareSearchIndexer):
searcher.index([course_info])
except:
log.exception(
- u"Course discovery indexing error encountered, course discovery index may be out of date %s",
+ "Course discovery indexing error encountered, course discovery index may be out of date %s",
course_id,
)
raise
log.debug(
- u"Successfully added %s course to the course discovery index",
+ "Successfully added %s course to the course discovery index",
course_id
)
@classmethod
def _get_location_info(cls, normalized_structure_key):
""" Builds location info dictionary """
- return {"course": text_type(normalized_structure_key), "org": normalized_structure_key.org}
+ return {"course": str(normalized_structure_key), "org": normalized_structure_key.org}
@classmethod
def remove_deleted_items(cls, structure_key): # lint-amnesty, pylint: disable=arguments-differ
diff --git a/cms/djangoapps/contentstore/debug_file_uploader.py b/cms/djangoapps/contentstore/debug_file_uploader.py
index 77cbc59b71..e9546abd24 100644
--- a/cms/djangoapps/contentstore/debug_file_uploader.py
+++ b/cms/djangoapps/contentstore/debug_file_uploader.py
@@ -8,7 +8,7 @@ from django.core.files.uploadhandler import FileUploadHandler
class DebugFileUploader(FileUploadHandler): # lint-amnesty, pylint: disable=missing-class-docstring
def __init__(self, request=None):
- super(DebugFileUploader, self).__init__(request) # lint-amnesty, pylint: disable=super-with-arguments
+ super().__init__(request)
self.count = 0
def receive_data_chunk(self, raw_data, start):
diff --git a/cms/djangoapps/contentstore/git_export_utils.py b/cms/djangoapps/contentstore/git_export_utils.py
index bf39bbb901..67ff7a9709 100644
--- a/cms/djangoapps/contentstore/git_export_utils.py
+++ b/cms/djangoapps/contentstore/git_export_utils.py
@@ -7,13 +7,12 @@ committing and pushing the changes.
import logging
import os
import subprocess
+from urllib.parse import urlparse
-import six
from django.conf import settings
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
-from six.moves.urllib.parse import urlparse
from xmodule.contentstore.django import contentstore
from xmodule.modulestore.django import modulestore
@@ -32,9 +31,9 @@ class GitExportError(Exception):
def __init__(self, message):
# Force the lazy i18n values to turn into actual unicode objects
- super().__init__(six.text_type(message))
+ super().__init__(str(message))
- NO_EXPORT_DIR = _(u"GIT_REPO_EXPORT_DIR not set or path {0} doesn't exist, "
+ NO_EXPORT_DIR = _("GIT_REPO_EXPORT_DIR not set or path {0} doesn't exist, "
"please create it, or configure a different path with "
"GIT_REPO_EXPORT_DIR").format(GIT_REPO_EXPORT_DIR)
URL_BAD = _('Non writable git url provided. Expecting something like:'
@@ -61,9 +60,9 @@ def cmd_log(cmd, cwd):
command doesn't return 0, and returns the command's output.
"""
output = subprocess.check_output(cmd, cwd=cwd, stderr=subprocess.STDOUT)
- log.debug(u'Command was: {0!r}. '
- u'Working directory was: {1!r}'.format(' '.join(cmd), cwd))
- log.debug(u'Command output was: {0!r}'.format(output))
+ log.debug('Command was: {!r}. '
+ 'Working directory was: {!r}'.format(' '.join(cmd), cwd))
+ log.debug(f'Command output was: {output!r}')
return output
@@ -92,11 +91,11 @@ def export_to_git(course_id, repo, user='', rdir=None):
else:
rdir = repo.rsplit('/', 1)[-1].rsplit('.git', 1)[0]
- log.debug(u"rdir = %s", rdir)
+ log.debug("rdir = %s", rdir)
# Pull or clone repo before exporting to xml
# and update url in case origin changed.
- rdirp = '{0}/{1}'.format(GIT_REPO_EXPORT_DIR, rdir)
+ rdirp = f'{GIT_REPO_EXPORT_DIR}/{rdir}'
branch = None
if os.path.exists(rdirp):
log.info('Directory already exists, doing a git reset and pull '
@@ -107,13 +106,13 @@ def export_to_git(course_id, repo, user='', rdir=None):
try:
branch = cmd_log(cmd, cwd).decode('utf-8').strip('\n')
except subprocess.CalledProcessError as ex:
- log.exception(u'Failed to get branch: %r', ex.output)
+ log.exception('Failed to get branch: %r', ex.output)
raise GitExportError(GitExportError.DETACHED_HEAD) from ex
cmds = [
['git', 'remote', 'set-url', 'origin', repo],
['git', 'fetch', 'origin'],
- ['git', 'reset', '--hard', 'origin/{0}'.format(branch)],
+ ['git', 'reset', '--hard', f'origin/{branch}'],
['git', 'pull'],
['git', 'clean', '-d', '-f'],
]
@@ -126,7 +125,7 @@ def export_to_git(course_id, repo, user='', rdir=None):
try:
cmd_log(cmd, cwd)
except subprocess.CalledProcessError as ex:
- log.exception(u'Failed to pull git repository: %r', ex.output)
+ log.exception('Failed to pull git repository: %r', ex.output)
raise GitExportError(GitExportError.CANNOT_PULL) from ex
# export course as xml before commiting and pushing
@@ -135,7 +134,7 @@ def export_to_git(course_id, repo, user='', rdir=None):
try:
export_course_to_xml(modulestore(), contentstore(), course_id,
root_dir, course_dir)
- except (EnvironmentError, AttributeError):
+ except (OSError, AttributeError):
log.exception('Failed export to xml')
raise GitExportError(GitExportError.XML_EXPORT_FAIL) # lint-amnesty, pylint: disable=raise-missing-from
@@ -145,7 +144,7 @@ def export_to_git(course_id, repo, user='', rdir=None):
try:
branch = cmd_log(cmd, os.path.abspath(rdirp)).decode('utf-8').strip('\n')
except subprocess.CalledProcessError as ex:
- log.exception(u'Failed to get branch from freshly cloned repo: %r',
+ log.exception('Failed to get branch from freshly cloned repo: %r',
ex.output)
raise GitExportError(GitExportError.MISSING_BRANCH) from ex
@@ -161,23 +160,23 @@ def export_to_git(course_id, repo, user='', rdir=None):
ident = GIT_EXPORT_DEFAULT_IDENT
time_stamp = timezone.now()
cwd = os.path.abspath(rdirp)
- commit_msg = u"Export from Studio at {time_stamp}".format(
+ commit_msg = "Export from Studio at {time_stamp}".format(
time_stamp=time_stamp,
)
try:
cmd_log(['git', 'config', 'user.email', ident['email']], cwd)
cmd_log(['git', 'config', 'user.name', ident['name']], cwd)
except subprocess.CalledProcessError as ex:
- log.exception(u'Error running git configure commands: %r', ex.output)
+ log.exception('Error running git configure commands: %r', ex.output)
raise GitExportError(GitExportError.CONFIG_ERROR) from ex
try:
cmd_log(['git', 'add', '.'], cwd)
cmd_log(['git', 'commit', '-a', '-m', commit_msg], cwd)
except subprocess.CalledProcessError as ex:
- log.exception(u'Unable to commit changes: %r', ex.output)
+ log.exception('Unable to commit changes: %r', ex.output)
raise GitExportError(GitExportError.CANNOT_COMMIT) from ex
try:
cmd_log(['git', 'push', '-q', 'origin', branch], cwd)
except subprocess.CalledProcessError as ex:
- log.exception(u'Error running git push command: %r', ex.output)
+ log.exception('Error running git push command: %r', ex.output)
raise GitExportError(GitExportError.CANNOT_PUSH) from ex
diff --git a/cms/djangoapps/contentstore/migrations/0001_initial.py b/cms/djangoapps/contentstore/migrations/0001_initial.py
index edae499bb9..af5aa387f1 100644
--- a/cms/djangoapps/contentstore/migrations/0001_initial.py
+++ b/cms/djangoapps/contentstore/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
@@ -32,7 +29,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')),
- ('profile_whitelist', models.TextField(help_text=u'A comma-separated list of names of profiles to include in video encoding downloads.', blank=True)),
+ ('profile_whitelist', models.TextField(help_text='A comma-separated list of names of profiles to include in video encoding downloads.', blank=True)),
('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/cms/djangoapps/contentstore/migrations/0002_add_assets_page_flag.py b/cms/djangoapps/contentstore/migrations/0002_add_assets_page_flag.py
index eec99e24d2..678349489d 100644
--- a/cms/djangoapps/contentstore/migrations/0002_add_assets_page_flag.py
+++ b/cms/djangoapps/contentstore/migrations/0002_add_assets_page_flag.py
@@ -1,6 +1,3 @@
-# -*- coding: utf-8 -*-
-
-
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
diff --git a/cms/djangoapps/contentstore/migrations/0003_remove_assets_page_flag.py b/cms/djangoapps/contentstore/migrations/0003_remove_assets_page_flag.py
index 08f8f73d3c..ffe5d183df 100644
--- a/cms/djangoapps/contentstore/migrations/0003_remove_assets_page_flag.py
+++ b/cms/djangoapps/contentstore/migrations/0003_remove_assets_page_flag.py
@@ -1,6 +1,3 @@
-# -*- coding: utf-8 -*-
-
-
from django.db import migrations, models
diff --git a/cms/djangoapps/contentstore/migrations/0004_remove_push_notification_configmodel_table.py b/cms/djangoapps/contentstore/migrations/0004_remove_push_notification_configmodel_table.py
index 28e17ab72e..bfec00f991 100644
--- a/cms/djangoapps/contentstore/migrations/0004_remove_push_notification_configmodel_table.py
+++ b/cms/djangoapps/contentstore/migrations/0004_remove_push_notification_configmodel_table.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
# Generated by Django 1.11.22 on 2019-07-26 20:12
diff --git a/cms/djangoapps/contentstore/migrations/0005_add_enable_checklists_quality_waffle_flag.py b/cms/djangoapps/contentstore/migrations/0005_add_enable_checklists_quality_waffle_flag.py
index 325a8ab70a..04dafec2d4 100644
--- a/cms/djangoapps/contentstore/migrations/0005_add_enable_checklists_quality_waffle_flag.py
+++ b/cms/djangoapps/contentstore/migrations/0005_add_enable_checklists_quality_waffle_flag.py
@@ -1,6 +1,3 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import, unicode_literals
-
from django.db import migrations
from cms.djangoapps.contentstore.config.waffle import ENABLE_CHECKLISTS_QUALITY
diff --git a/cms/djangoapps/contentstore/models.py b/cms/djangoapps/contentstore/models.py
index c69643d27e..f6817ac59f 100644
--- a/cms/djangoapps/contentstore/models.py
+++ b/cms/djangoapps/contentstore/models.py
@@ -15,7 +15,7 @@ class VideoUploadConfig(ConfigurationModel):
"""
profile_whitelist = TextField(
blank=True,
- help_text=u"A comma-separated list of names of profiles to include in video encoding downloads."
+ help_text="A comma-separated list of names of profiles to include in video encoding downloads."
)
@classmethod
diff --git a/cms/djangoapps/contentstore/outlines.py b/cms/djangoapps/contentstore/outlines.py
index 63fd53fa48..708afdf98c 100644
--- a/cms/djangoapps/contentstore/outlines.py
+++ b/cms/djangoapps/contentstore/outlines.py
@@ -14,7 +14,7 @@ from openedx.core.djangoapps.content.learning_sequences.data import (
CourseSectionData,
CourseVisibility,
ExamData,
- VisibilityData,
+ VisibilityData
)
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore
diff --git a/cms/djangoapps/contentstore/proctoring.py b/cms/djangoapps/contentstore/proctoring.py
index fc9ea55c97..cf0704259b 100644
--- a/cms/djangoapps/contentstore/proctoring.py
+++ b/cms/djangoapps/contentstore/proctoring.py
@@ -5,7 +5,6 @@ Code related to the handling of Proctored Exams in Studio
import logging
-import six
from django.conf import settings
from edx_proctoring.api import (
create_exam,
@@ -39,7 +38,7 @@ def register_special_exams(course_key):
course = modulestore().get_course(course_key)
if course is None:
- raise ItemNotFoundError(u"Course {} does not exist", six.text_type(course_key)) # lint-amnesty, pylint: disable=raising-format-tuple
+ raise ItemNotFoundError("Course {} does not exist", str(course_key)) # lint-amnesty, pylint: disable=raising-format-tuple
if not course.enable_proctored_exams and not course.enable_timed_exams:
# likewise if course does not have these features turned on
@@ -68,8 +67,8 @@ def register_special_exams(course_key):
# add/update any exam entries in edx-proctoring
for timed_exam in timed_exams:
msg = (
- u'Found {location} as a timed-exam in course structure. Inspecting...'.format(
- location=six.text_type(timed_exam.location)
+ 'Found {location} as a timed-exam in course structure. Inspecting...'.format(
+ location=str(timed_exam.location)
)
)
log.info(msg)
@@ -87,20 +86,20 @@ def register_special_exams(course_key):
}
try:
- exam = get_exam_by_content_id(six.text_type(course_key), six.text_type(timed_exam.location))
+ exam = get_exam_by_content_id(str(course_key), str(timed_exam.location))
# update case, make sure everything is synced
exam_metadata['exam_id'] = exam['id']
exam_id = update_exam(**exam_metadata)
- msg = u'Updated timed exam {exam_id}'.format(exam_id=exam['id'])
+ msg = 'Updated timed exam {exam_id}'.format(exam_id=exam['id'])
log.info(msg)
except ProctoredExamNotFoundException:
- exam_metadata['course_id'] = six.text_type(course_key)
- exam_metadata['content_id'] = six.text_type(timed_exam.location)
+ exam_metadata['course_id'] = str(course_key)
+ exam_metadata['content_id'] = str(timed_exam.location)
exam_id = create_exam(**exam_metadata)
- msg = u'Created new timed exam {exam_id}'.format(exam_id=exam_id)
+ msg = f'Created new timed exam {exam_id}'
log.info(msg)
exam_review_policy_metadata = {
@@ -116,7 +115,7 @@ def register_special_exams(course_key):
except ProctoredExamReviewPolicyNotFoundException:
if timed_exam.exam_review_rules: # won't save an empty rule.
create_exam_review_policy(**exam_review_policy_metadata)
- msg = u'Created new exam review policy with exam_id {exam_id}'.format(exam_id=exam_id)
+ msg = f'Created new exam review policy with exam_id {exam_id}'
log.info(msg)
else:
try:
@@ -135,12 +134,12 @@ def register_special_exams(course_key):
search = [
timed_exam for timed_exam in timed_exams if
- six.text_type(timed_exam.location) == exam['content_id']
+ str(timed_exam.location) == exam['content_id']
]
if not search:
# This means it was turned off in Studio, we need to mark
# the exam as inactive (we don't delete!)
- msg = u'Disabling timed exam {exam_id}'.format(exam_id=exam['id'])
+ msg = 'Disabling timed exam {exam_id}'.format(exam_id=exam['id'])
log.info(msg)
update_exam(
exam_id=exam['id'],
diff --git a/cms/djangoapps/contentstore/rest_api/v1/tests/test_views.py b/cms/djangoapps/contentstore/rest_api/v1/tests/test_views.py
index a17a4cf34b..c70327da1d 100644
--- a/cms/djangoapps/contentstore/rest_api/v1/tests/test_views.py
+++ b/cms/djangoapps/contentstore/rest_api/v1/tests/test_views.py
@@ -8,8 +8,8 @@ from opaque_keys.edx.keys import CourseKey
from rest_framework import status
from rest_framework.test import APITestCase
-from lms.djangoapps.courseware.tests.factories import GlobalStaffFactory, InstructorFactory
from common.djangoapps.student.tests.factories import UserFactory
+from lms.djangoapps.courseware.tests.factories import GlobalStaffFactory, InstructorFactory
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
@@ -77,7 +77,7 @@ class ProctoringExamSettingsTestMixin():
response = self.make_request(course_id=course_id)
assert response.status_code == status.HTTP_404_NOT_FOUND
assert response.data == {
- 'detail': 'Course with course_id {} does not exist.'.format(course_id)
+ 'detail': f'Course with course_id {course_id} does not exist.'
}
diff --git a/cms/djangoapps/contentstore/rest_api/v1/urls.py b/cms/djangoapps/contentstore/rest_api/v1/urls.py
index 75c13d78c3..83e03bcb73 100644
--- a/cms/djangoapps/contentstore/rest_api/v1/urls.py
+++ b/cms/djangoapps/contentstore/rest_api/v1/urls.py
@@ -10,7 +10,7 @@ app_name = 'v1'
urlpatterns = [
re_path(
- r'^proctored_exam_settings/{}$'.format(COURSE_ID_PATTERN),
+ fr'^proctored_exam_settings/{COURSE_ID_PATTERN}$',
views.ProctoredExamSettingsView.as_view(),
name="proctored_exam_settings"
),
diff --git a/cms/djangoapps/contentstore/rest_api/v1/views.py b/cms/djangoapps/contentstore/rest_api/v1/views.py
index 9ff8a19d1a..76ba4b359e 100644
--- a/cms/djangoapps/contentstore/rest_api/v1/views.py
+++ b/cms/djangoapps/contentstore/rest_api/v1/views.py
@@ -169,7 +169,7 @@ class ProctoredExamSettingsView(APIView):
if not course_module:
raise NotFound(
- 'Course with course_id {} does not exist.'.format(course_id)
+ f'Course with course_id {course_id} does not exist.'
)
return course_module
diff --git a/cms/djangoapps/contentstore/signals/handlers.py b/cms/djangoapps/contentstore/signals/handlers.py
index 69c1421df3..fb7ed333ad 100644
--- a/cms/djangoapps/contentstore/signals/handlers.py
+++ b/cms/djangoapps/contentstore/signals/handlers.py
@@ -5,22 +5,21 @@ import logging
from datetime import datetime
from functools import wraps
-import six
from django.core.cache import cache
from django.dispatch import receiver
from pytz import UTC
from cms.djangoapps.contentstore.courseware_index import (
- CoursewareSearchIndexer,
CourseAboutSearchIndexer,
+ CoursewareSearchIndexer,
LibrarySearchIndexer
)
from cms.djangoapps.contentstore.proctoring import register_special_exams
+from common.djangoapps.track.event_transaction_utils import get_event_transaction_id, get_event_transaction_type
+from common.djangoapps.util.module_utils import yield_dynamic_descriptor_descendants
from lms.djangoapps.grades.api import task_compute_all_grades_for_course
from openedx.core.djangoapps.credit.signals import on_course_publish
from openedx.core.lib.gating import api as gating_api
-from common.djangoapps.track.event_transaction_utils import get_event_transaction_id, get_event_transaction_type
-from common.djangoapps.util.module_utils import yield_dynamic_descriptor_descendants
from xmodule.modulestore.django import SignalHandler, modulestore
from .signals import GRADING_POLICY_CHANGED
@@ -36,7 +35,7 @@ def locked(expiry_seconds, key): # lint-amnesty, pylint: disable=missing-functi
def wrapper(*args, **kwargs):
cache_key = '{}-{}'.format(func.__name__, kwargs[key])
if cache.add(cache_key, "true", expiry_seconds):
- log.info(u'Locking task in cache with key: %s for %s seconds', cache_key, expiry_seconds)
+ log.info('Locking task in cache with key: %s for %s seconds', cache_key, expiry_seconds)
return func(*args, **kwargs)
else:
log.info('Task with key %s already exists in cache', cache_key)
@@ -84,7 +83,7 @@ def listen_for_library_update(sender, library_key, **kwargs): # pylint: disable
# import here, because signal is registered at startup, but items in tasks are not yet able to be loaded
from cms.djangoapps.contentstore.tasks import update_library_index
- update_library_index.delay(six.text_type(library_key), datetime.now(UTC).isoformat())
+ update_library_index.delay(str(library_key), datetime.now(UTC).isoformat())
@receiver(SignalHandler.item_deleted)
@@ -122,13 +121,13 @@ def handle_grading_policy_changed(sender, **kwargs):
Receives signal and kicks off celery task to recalculate grades
"""
kwargs = {
- 'course_key': six.text_type(kwargs.get('course_key')),
- 'grading_policy_hash': six.text_type(kwargs.get('grading_policy_hash')),
- 'event_transaction_id': six.text_type(get_event_transaction_id()),
- 'event_transaction_type': six.text_type(get_event_transaction_type()),
+ 'course_key': str(kwargs.get('course_key')),
+ 'grading_policy_hash': str(kwargs.get('grading_policy_hash')),
+ 'event_transaction_id': str(get_event_transaction_id()),
+ 'event_transaction_type': str(get_event_transaction_type()),
}
result = task_compute_all_grades_for_course.apply_async(kwargs=kwargs, countdown=GRADING_POLICY_COUNTDOWN_SECONDS)
- log.info(u"Grades: Created {task_name}[{task_id}] with arguments {kwargs}".format(
+ log.info("Grades: Created {task_name}[{task_id}] with arguments {kwargs}".format(
task_name=task_compute_all_grades_for_course.name,
task_id=result.task_id,
kwargs=kwargs,
diff --git a/cms/djangoapps/contentstore/storage.py b/cms/djangoapps/contentstore/storage.py
index 0757676676..f3a04fbd21 100644
--- a/cms/djangoapps/contentstore/storage.py
+++ b/cms/djangoapps/contentstore/storage.py
@@ -16,7 +16,7 @@ class ImportExportS3Storage(S3BotoStorage): # pylint: disable=abstract-method
def __init__(self):
bucket = setting('COURSE_IMPORT_EXPORT_BUCKET', settings.AWS_STORAGE_BUCKET_NAME)
- super(ImportExportS3Storage, self).__init__(bucket=bucket, custom_domain=None, querystring_auth=True) # lint-amnesty, pylint: disable=super-with-arguments
+ super().__init__(bucket=bucket, custom_domain=None, querystring_auth=True)
# pylint: disable=invalid-name
course_import_export_storage = get_storage_class(settings.COURSE_IMPORT_EXPORT_STORAGE)()
diff --git a/cms/djangoapps/contentstore/tasks.py b/cms/djangoapps/contentstore/tasks.py
index 2768a80525..1a2780fb93 100644
--- a/cms/djangoapps/contentstore/tasks.py
+++ b/cms/djangoapps/contentstore/tasks.py
@@ -29,7 +29,6 @@ from organizations.api import add_organization_course, ensure_organization
from organizations.models import OrganizationCourse
from path import Path as path
from pytz import UTC
-from six import iteritems, text_type
from user_tasks.models import UserTaskArtifact, UserTaskStatus
from user_tasks.tasks import UserTask
@@ -42,9 +41,9 @@ from cms.djangoapps.contentstore.storage import course_import_export_storage
from cms.djangoapps.contentstore.utils import initialize_permissions, reverse_usage_url, translation_language
from cms.djangoapps.models.settings.course_metadata import CourseMetadata
from common.djangoapps.course_action_state.models import CourseRerunState
+from common.djangoapps.student.auth import has_course_author_access
from openedx.core.djangoapps.embargo.models import CountryAccessRule, RestrictedCourse
from openedx.core.lib.extract_tar import safetar_extractall
-from common.djangoapps.student.auth import has_course_author_access
from xmodule.contentstore.django import contentstore
from xmodule.course_module import CourseFields
from xmodule.exceptions import SerializationError
@@ -53,6 +52,7 @@ from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import DuplicateCourseError, ItemNotFoundError
from xmodule.modulestore.xml_exporter import export_course_to_xml, export_library_to_xml
from xmodule.modulestore.xml_importer import import_course_from_xml, import_library_from_xml
+
from .outlines import update_outline_from_modulestore
User = get_user_model()
@@ -76,7 +76,7 @@ def clone_instance(instance, field_values):
"""
instance.pk = None
- for field, value in iteritems(field_values):
+ for field, value in field_values.items():
setattr(instance, field, value)
instance.save()
@@ -136,14 +136,14 @@ def rerun_course(source_course_key_string, destination_course_key_string, user_i
except DuplicateCourseError:
# do NOT delete the original course, only update the status
CourseRerunState.objects.failed(course_key=destination_course_key)
- LOGGER.exception(u'Course Rerun Error')
+ LOGGER.exception('Course Rerun Error')
return "duplicate course"
# catch all exceptions so we can update the state and properly cleanup the course.
except Exception as exc: # pylint: disable=broad-except
# update state: Failed
CourseRerunState.objects.failed(course_key=destination_course_key)
- LOGGER.exception(u'Course Rerun Error')
+ LOGGER.exception('Course Rerun Error')
try:
# cleanup any remnants of the course
@@ -152,12 +152,12 @@ def rerun_course(source_course_key_string, destination_course_key_string, user_i
# it's possible there was an error even before the course module was created
pass
- return u"exception: " + text_type(exc)
+ return "exception: " + str(exc)
def deserialize_fields(json_fields):
fields = json.loads(json_fields)
- for field_name, value in iteritems(fields):
+ for field_name, value in fields.items():
fields[field_name] = getattr(CourseFields, field_name).from_json(value)
return fields
@@ -183,7 +183,7 @@ def update_search_index(course_id, triggered_time_isoformat):
# expensive (sometimes hours-long for really complex courses).
if isinstance(course_key, CCXLocator):
LOGGER.warning(
- u'Search indexing skipped for CCX Course %s (this is currently too slow to run in production)',
+ 'Search indexing skipped for CCX Course %s (this is currently too slow to run in production)',
course_id
)
return
@@ -193,13 +193,13 @@ def update_search_index(course_id, triggered_time_isoformat):
except SearchIndexingError as exc:
error_list = exc.error_list
LOGGER.error(
- u"Search indexing error for complete course %s - %s - %s",
+ "Search indexing error for complete course %s - %s - %s",
course_id,
- text_type(exc),
+ str(exc),
error_list,
)
else:
- LOGGER.debug(u'Search indexing successful for complete course %s', course_id)
+ LOGGER.debug('Search indexing successful for complete course %s', course_id)
@shared_task
@@ -211,9 +211,9 @@ def update_library_index(library_id, triggered_time_isoformat):
LibrarySearchIndexer.index(modulestore(), library_key, triggered_at=(_parse_time(triggered_time_isoformat)))
except SearchIndexingError as exc:
- LOGGER.error(u'Search indexing error for library %s - %s', library_id, text_type(exc))
+ LOGGER.error('Search indexing error for library %s - %s', library_id, str(exc))
else:
- LOGGER.debug(u'Search indexing successful for library %s', library_id)
+ LOGGER.debug('Search indexing successful for library %s', library_id)
class CourseExportTask(UserTask): # pylint: disable=abstract-method
@@ -244,8 +244,8 @@ class CourseExportTask(UserTask): # pylint: disable=abstract-method
Returns:
text_type: The generated name
"""
- key = arguments_dict[u'course_key_string']
- return u'Export of {}'.format(key)
+ key = arguments_dict['course_key_string']
+ return f'Export of {key}'
@shared_task(base=CourseExportTask, bind=True)
@@ -262,11 +262,11 @@ def export_olx(self, user_id, course_key_string, language):
user = User.objects.get(pk=user_id)
except User.DoesNotExist:
with translation_language(language):
- self.status.fail(_(u'Unknown User ID: {0}').format(user_id))
+ self.status.fail(_('Unknown User ID: {0}').format(user_id))
return
if not has_course_author_access(user, courselike_key):
with translation_language(language):
- self.status.fail(_(u'Permission denied'))
+ self.status.fail(_('Permission denied'))
return
if isinstance(courselike_key, LibraryLocator):
@@ -275,16 +275,16 @@ def export_olx(self, user_id, course_key_string, language):
courselike_module = modulestore().get_course(courselike_key)
try:
- self.status.set_state(u'Exporting')
+ self.status.set_state('Exporting')
tarball = create_export_tarball(courselike_module, courselike_key, {}, self.status)
- artifact = UserTaskArtifact(status=self.status, name=u'Output')
+ artifact = UserTaskArtifact(status=self.status, name='Output')
artifact.file.save(name=os.path.basename(tarball.name), content=File(tarball))
artifact.save()
# catch all exceptions so we can record useful error messages
except Exception as exception: # pylint: disable=broad-except
- LOGGER.exception(u'Error exporting course %s', courselike_key, exc_info=True)
+ LOGGER.exception('Error exporting course %s', courselike_key, exc_info=True)
if self.status.state != UserTaskStatus.FAILED:
- self.status.fail({'raw_error_msg': text_type(exception)})
+ self.status.fail({'raw_error_msg': str(exception)})
return
@@ -305,14 +305,14 @@ def create_export_tarball(course_module, course_key, context, status=None):
export_course_to_xml(modulestore(), contentstore(), course_module.id, root_dir, name)
if status:
- status.set_state(u'Compressing')
+ status.set_state('Compressing')
status.increment_completed_steps()
- LOGGER.debug(u'tar file being generated at %s', export_file.name)
+ LOGGER.debug('tar file being generated at %s', export_file.name)
with tarfile.open(name=export_file.name, mode='w:gz') as tar_file:
tar_file.add(root_dir / name, arcname=name)
except SerializationError as exc:
- LOGGER.exception(u'There was an error exporting %s', course_key, exc_info=True)
+ LOGGER.exception('There was an error exporting %s', course_key, exc_info=True)
parent = None
try:
failed_item = modulestore().get_item(exc.location)
@@ -334,7 +334,7 @@ def create_export_tarball(course_module, course_key, context, status=None):
'edit_unit_url': context['edit_unit_url']}))
raise
except Exception as exc:
- LOGGER.exception(u'There was an error exporting %s', course_key, exc_info=True)
+ LOGGER.exception('There was an error exporting %s', course_key, exc_info=True)
context.update({
'in_err': True,
'edit_unit_url': None,
@@ -378,9 +378,9 @@ class CourseImportTask(UserTask): # pylint: disable=abstract-method
Returns:
text_type: The generated name
"""
- key = arguments_dict[u'course_key_string']
- filename = arguments_dict[u'archive_name']
- return u'Import of {} from {}'.format(key, filename)
+ key = arguments_dict['course_key_string']
+ filename = arguments_dict['archive_name']
+ return f'Import of {key} from {filename}'
@shared_task(base=CourseImportTask, bind=True)
@@ -396,11 +396,11 @@ def import_olx(self, user_id, course_key_string, archive_path, archive_name, lan
user = User.objects.get(pk=user_id)
except User.DoesNotExist:
with translation_language(language):
- self.status.fail(_(u'Unknown User ID: {0}').format(user_id))
+ self.status.fail(_('Unknown User ID: {0}').format(user_id))
return
if not has_course_author_access(user, courselike_key):
with translation_language(language):
- self.status.fail(_(u'Permission denied'))
+ self.status.fail(_('Permission denied'))
return
is_library = isinstance(courselike_key, LibraryLocator)
@@ -420,24 +420,24 @@ def import_olx(self, user_id, course_key_string, archive_path, archive_name, lan
subdir = base64.urlsafe_b64encode(repr(courselike_key).encode('utf-8')).decode('utf-8')
course_dir = data_root / subdir
try:
- self.status.set_state(u'Unpacking')
+ self.status.set_state('Unpacking')
- if not archive_name.endswith(u'.tar.gz'):
+ if not archive_name.endswith('.tar.gz'):
with translation_language(language):
- self.status.fail(_(u'We only support uploading a .tar.gz file.'))
+ self.status.fail(_('We only support uploading a .tar.gz file.'))
return
temp_filepath = course_dir / get_valid_filename(archive_name)
if not course_dir.isdir():
os.mkdir(course_dir)
- LOGGER.debug(u'importing course to {0}'.format(temp_filepath))
+ LOGGER.debug(f'importing course to {temp_filepath}')
# Copy the OLX archive from where it was uploaded to (S3, Swift, file system, etc.)
if not course_import_export_storage.exists(archive_path):
- LOGGER.info(u'Course import %s: Uploaded file %s not found', courselike_key, archive_path)
+ LOGGER.info('Course import %s: Uploaded file %s not found', courselike_key, archive_path)
with translation_language(language):
- self.status.fail(_(u'Tar file not found'))
+ self.status.fail(_('Tar file not found'))
return
with course_import_export_storage.open(archive_path, 'rb') as source:
with open(temp_filepath, 'wb') as destination:
@@ -448,7 +448,7 @@ def import_olx(self, user_id, course_key_string, archive_path, archive_name, lan
return source.read(FILE_READ_CHUNK)
for chunk in iter(read_chunk, b''):
destination.write(chunk)
- LOGGER.info(u'Course import %s: Download from storage complete', courselike_key)
+ LOGGER.info('Course import %s: Download from storage complete', courselike_key)
# Delete from source location
course_import_export_storage.delete(archive_path)
@@ -456,40 +456,40 @@ def import_olx(self, user_id, course_key_string, archive_path, archive_name, lan
# current course state before import.
if is_course:
if courselike_module.entrance_exam_enabled:
- fake_request = RequestFactory().get(u'/')
+ fake_request = RequestFactory().get('/')
fake_request.user = user
from .views.entrance_exam import remove_entrance_exam_milestone_reference
# TODO: Is this really ok? Seems dangerous for a live course
remove_entrance_exam_milestone_reference(fake_request, courselike_key)
LOGGER.info(
- u'entrance exam milestone content reference for course %s has been removed',
+ 'entrance exam milestone content reference for course %s has been removed',
courselike_module.id
)
# Send errors to client with stage at which error occurred.
except Exception as exception: # pylint: disable=broad-except
if course_dir.isdir():
shutil.rmtree(course_dir)
- LOGGER.info(u'Course import %s: Temp data cleared', courselike_key)
+ LOGGER.info('Course import %s: Temp data cleared', courselike_key)
- LOGGER.exception(u'Error importing course %s', courselike_key, exc_info=True)
- self.status.fail(text_type(exception))
+ LOGGER.exception('Error importing course %s', courselike_key, exc_info=True)
+ self.status.fail(str(exception))
return
# try-finally block for proper clean up after receiving file.
try:
tar_file = tarfile.open(temp_filepath)
try:
- safetar_extractall(tar_file, (course_dir + u'/'))
+ safetar_extractall(tar_file, (course_dir + '/'))
except SuspiciousOperation as exc:
- LOGGER.info(u'Course import %s: Unsafe tar file - %s', courselike_key, exc.args[0])
+ LOGGER.info('Course import %s: Unsafe tar file - %s', courselike_key, exc.args[0])
with translation_language(language):
- self.status.fail(_(u'Unsafe tar file. Aborting import.'))
+ self.status.fail(_('Unsafe tar file. Aborting import.'))
return
finally:
tar_file.close()
- LOGGER.info(u'Course import %s: Uploaded file extracted', courselike_key)
- self.status.set_state(u'Verifying')
+ LOGGER.info('Course import %s: Uploaded file extracted', courselike_key)
+ self.status.set_state('Verifying')
self.status.increment_completed_steps()
# find the 'course.xml' file
@@ -516,14 +516,14 @@ def import_olx(self, user_id, course_key_string, archive_path, archive_name, lan
dirpath = get_dir_for_filename(course_dir, root_name)
if not dirpath:
with translation_language(language):
- self.status.fail(_(u'Could not find the {0} file in the package.').format(root_name))
+ self.status.fail(_('Could not find the {0} file in the package.').format(root_name))
return
dirpath = os.path.relpath(dirpath, data_root)
- LOGGER.debug(u'found %s at %s', root_name, dirpath)
+ LOGGER.debug('found %s at %s', root_name, dirpath)
- LOGGER.info(u'Course import %s: Extracted file verified', courselike_key)
- self.status.set_state(u'Updating')
+ LOGGER.info('Course import %s: Extracted file verified', courselike_key)
+ self.status.set_state('Updating')
self.status.increment_completed_steps()
courselike_items = import_func(
@@ -535,32 +535,32 @@ def import_olx(self, user_id, course_key_string, archive_path, archive_name, lan
)
new_location = courselike_items[0].location
- LOGGER.debug(u'new course at %s', new_location)
+ LOGGER.debug('new course at %s', new_location)
- LOGGER.info(u'Course import %s: Course import successful', courselike_key)
+ LOGGER.info('Course import %s: Course import successful', courselike_key)
except Exception as exception: # pylint: disable=broad-except
- LOGGER.exception(u'error importing course', exc_info=True)
- self.status.fail(text_type(exception))
+ LOGGER.exception('error importing course', exc_info=True)
+ self.status.fail(str(exception))
finally:
if course_dir.isdir():
shutil.rmtree(course_dir)
- LOGGER.info(u'Course import %s: Temp data cleared', courselike_key)
+ LOGGER.info('Course import %s: Temp data cleared', courselike_key)
- if self.status.state == u'Updating' and is_course:
+ if self.status.state == 'Updating' and is_course:
# Reload the course so we have the latest state
course = modulestore().get_course(courselike_key)
if course.entrance_exam_enabled:
entrance_exam_chapter = modulestore().get_items(
course.id,
- qualifiers={u'category': u'chapter'},
- settings={u'is_entrance_exam': True}
+ qualifiers={'category': 'chapter'},
+ settings={'is_entrance_exam': True}
)[0]
- metadata = {u'entrance_exam_id': text_type(entrance_exam_chapter.location)}
+ metadata = {'entrance_exam_id': str(entrance_exam_chapter.location)}
CourseMetadata.update_from_dict(metadata, course, user)
from .views.entrance_exam import add_entrance_exam_milestone
add_entrance_exam_milestone(course.id, entrance_exam_chapter)
- LOGGER.info(u'Course %s Entrance exam imported', course.id)
+ LOGGER.info('Course %s Entrance exam imported', course.id)
@shared_task
diff --git a/cms/djangoapps/contentstore/toggles.py b/cms/djangoapps/contentstore/toggles.py
index fe18f19714..899ccabb52 100644
--- a/cms/djangoapps/contentstore/toggles.py
+++ b/cms/djangoapps/contentstore/toggles.py
@@ -1,7 +1,7 @@
"""
CMS feature toggles.
"""
-from edx_toggles.toggles import SettingDictToggle, LegacyWaffleFlag, LegacyWaffleFlagNamespace
+from edx_toggles.toggles import LegacyWaffleFlag, LegacyWaffleFlagNamespace, SettingDictToggle
# .. toggle_name: FEATURES['ENABLE_EXPORT_GIT']
# .. toggle_implementation: SettingDictToggle
@@ -20,7 +20,7 @@ EXPORT_GIT = SettingDictToggle(
# Namespace for studio dashboard waffle flags.
WAFFLE_NAMESPACE = 'contentstore'
-WAFFLE_FLAG_NAMESPACE = LegacyWaffleFlagNamespace(name=WAFFLE_NAMESPACE, log_prefix=u'Contentstore: ')
+WAFFLE_FLAG_NAMESPACE = LegacyWaffleFlagNamespace(name=WAFFLE_NAMESPACE, log_prefix='Contentstore: ')
# Waffle flag to split library to new view.
# .. toggle_name: split_library_on_studio_dashboard
diff --git a/cms/djangoapps/contentstore/utils.py b/cms/djangoapps/contentstore/utils.py
index 1091dda5cc..a12881f844 100644
--- a/cms/djangoapps/contentstore/utils.py
+++ b/cms/djangoapps/contentstore/utils.py
@@ -7,7 +7,6 @@ import logging
from contextlib import contextmanager
from datetime import datetime
-import six
from django.conf import settings
from django.urls import reverse
from django.utils import translation
@@ -15,17 +14,16 @@ from django.utils.translation import ugettext as _
from opaque_keys.edx.keys import CourseKey, UsageKey
from opaque_keys.edx.locator import LibraryLocator
from pytz import UTC
-from six import text_type
+from common.djangoapps.student import auth
+from common.djangoapps.student.models import CourseEnrollment
+from common.djangoapps.student.roles import CourseInstructorRole, CourseStaffRole
from openedx.core.djangoapps.django_comment_common.models import assign_default_role
from openedx.core.djangoapps.django_comment_common.utils import seed_permissions_roles
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from openedx.core.djangoapps.site_configuration.models import SiteConfiguration
from openedx.features.content_type_gating.models import ContentTypeGatingConfig
from openedx.features.content_type_gating.partitions import CONTENT_TYPE_GATING_SCHEME
-from common.djangoapps.student import auth
-from common.djangoapps.student.models import CourseEnrollment
-from common.djangoapps.student.roles import CourseInstructorRole, CourseStaffRole
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import ItemNotFoundError
@@ -100,7 +98,7 @@ def _remove_instructors(course_key):
try:
remove_all_instructors(course_key)
except Exception as err: # lint-amnesty, pylint: disable=broad-except
- log.error(u"Error in deleting course groups for {0}: {1}".format(course_key, err))
+ log.error(f"Error in deleting course groups for {course_key}: {err}")
def get_lms_link_for_item(location, preview=False):
@@ -132,10 +130,10 @@ def get_lms_link_for_item(location, preview=False):
settings.FEATURES.get('PREVIEW_LMS_BASE')
)
- return u"//{lms_base}/courses/{course_key}/jump_to/{location}".format(
+ return "//{lms_base}/courses/{course_key}/jump_to/{location}".format(
lms_base=lms_base,
- course_key=text_type(location.course_key),
- location=text_type(location),
+ course_key=str(location.course_key),
+ location=str(location),
)
@@ -151,9 +149,9 @@ def get_lms_link_for_certificate_web_view(course_key, mode):
if lms_base is None:
return None
- return u"//{certificate_web_base}/certificates/course/{course_id}?preview={mode}".format(
+ return "//{certificate_web_base}/certificates/course/{course_id}?preview={mode}".format(
certificate_web_base=lms_base,
- course_id=six.text_type(course_key),
+ course_id=str(course_key),
mode=mode
)
@@ -292,7 +290,7 @@ def reverse_url(handler_name, key_name=None, key_value=None, kwargs=None):
Creates the URL for the given handler.
The optional key_name and key_value are passed in as kwargs to the handler.
"""
- kwargs_for_reverse = {key_name: six.text_type(key_value)} if key_name else None
+ kwargs_for_reverse = {key_name: str(key_value)} if key_name else None
if kwargs:
kwargs_for_reverse.update(kwargs)
return reverse(handler_name, kwargs=kwargs_for_reverse)
@@ -332,7 +330,7 @@ def get_split_group_display_name(xblock, course):
"""
for user_partition in get_user_partition_info(xblock, schemes=['random'], course=course):
for group in user_partition['groups']:
- if u'Group ID {group_id}'.format(group_id=group['id']) == xblock.display_name_with_default:
+ if 'Group ID {group_id}'.format(group_id=group['id']) == xblock.display_name_with_default:
return group['name']
@@ -400,7 +398,7 @@ def get_user_partition_info(xblock, schemes=None, course=None):
if course is None:
log.warning(
- u"Could not find course %s to retrieve user partition information",
+ "Could not find course %s to retrieve user partition information",
xblock.location.course_key
)
return []
@@ -432,7 +430,7 @@ def get_user_partition_info(xblock, schemes=None, course=None):
})
# Next, add any groups set on the XBlock that have been deleted
- all_groups = set(g.id for g in p.groups)
+ all_groups = {g.id for g in p.groups}
missing_group_ids = selected_groups - all_groups
for gid in missing_group_ids:
groups.append({
@@ -445,7 +443,7 @@ def get_user_partition_info(xblock, schemes=None, course=None):
# Put together the entire partition dictionary
partitions.append({
"id": p.id,
- "name": six.text_type(p.name), # Convert into a string in case ugettext_lazy was used
+ "name": str(p.name), # Convert into a string in case ugettext_lazy was used
"scheme": p.scheme.name,
"groups": groups,
})
@@ -502,7 +500,7 @@ def get_visibility_partition_info(xblock, course=None):
else:
# Translators: This is building up a list of groups. It is marked for translation because of the
# comma, which is used as a separator between each group.
- selected_groups_label = _(u'{previous_groups}, {current_group}').format(
+ selected_groups_label = _('{previous_groups}, {current_group}').format(
previous_groups=selected_groups_label,
current_group=group['name']
)
@@ -527,7 +525,7 @@ def get_xblock_aside_instance(usage_key):
if aside.scope_ids.block_type == usage_key.aside_type:
return aside
except ItemNotFoundError:
- log.warning(u'Unable to load item %s', usage_key.usage_key)
+ log.warning('Unable to load item %s', usage_key.usage_key)
def is_self_paced(course):
@@ -567,7 +565,7 @@ def get_sibling_urls(subsection):
# section.get_parent SHOULD return the course, but for some reason, it might not
sections = section.get_parent().get_children()
except AttributeError:
- log.error(u"URL Retrieval Error # 1: subsection {subsection} included in section {section}".format(
+ log.error("URL Retrieval Error # 1: subsection {subsection} included in section {section}".format(
section=section.location,
subsection=subsection.location
))
@@ -583,7 +581,7 @@ def get_sibling_urls(subsection):
try:
sections = section.get_parent().get_children()
except AttributeError:
- log.error(u"URL Retrieval Error # 2: subsection {subsection} included in section {section}".format(
+ log.error("URL Retrieval Error # 2: subsection {subsection} included in section {section}".format(
section=section.location,
subsection=subsection.location
))
diff --git a/cms/djangoapps/contentstore/video_utils.py b/cms/djangoapps/contentstore/video_utils.py
index 887b9d2ac3..a0b382ebd1 100644
--- a/cms/djangoapps/contentstore/video_utils.py
+++ b/cms/djangoapps/contentstore/video_utils.py
@@ -1,19 +1,17 @@
-#-*- coding: utf-8 -*-
"""
Utils related to the videos.
"""
import logging
+from urllib.parse import urljoin
import requests
-import six
from django.conf import settings
from django.core.files.images import get_image_dimensions
from django.core.files.uploadedfile import SimpleUploadedFile
from django.utils.translation import ugettext as _
from edxval.api import get_course_video_image_url, update_video_image
-from six.moves.urllib.parse import urljoin
# Youtube thumbnail sizes.
# https://img.youtube.com/vi/{youtube_id}/{thumbnail_quality}.jpg
@@ -43,15 +41,15 @@ def validate_video_image(image_file, skip_aspect_ratio=False):
if not all(hasattr(image_file, attr) for attr in ['name', 'content_type', 'size']):
error = _('The image must have name, content type, and size information.')
elif image_file.content_type not in list(settings.VIDEO_IMAGE_SUPPORTED_FILE_FORMATS.values()):
- error = _(u'This image file type is not supported. Supported file types are {supported_file_formats}.').format(
+ error = _('This image file type is not supported. Supported file types are {supported_file_formats}.').format(
supported_file_formats=list(settings.VIDEO_IMAGE_SUPPORTED_FILE_FORMATS.keys())
)
elif image_file.size > settings.VIDEO_IMAGE_SETTINGS['VIDEO_IMAGE_MAX_BYTES']:
- error = _(u'This image file must be smaller than {image_max_size}.').format(
+ error = _('This image file must be smaller than {image_max_size}.').format(
image_max_size=settings.VIDEO_IMAGE_MAX_FILE_SIZE_MB
)
elif image_file.size < settings.VIDEO_IMAGE_SETTINGS['VIDEO_IMAGE_MIN_BYTES']:
- error = _(u'This image file must be larger than {image_min_size}.').format(
+ error = _('This image file must be larger than {image_min_size}.').format(
image_min_size=settings.VIDEO_IMAGE_MIN_FILE_SIZE_KB
)
else:
@@ -63,15 +61,15 @@ def validate_video_image(image_file, skip_aspect_ratio=False):
return _('There is a problem with this image file. Try to upload a different file.')
image_file_aspect_ratio = abs(image_file_width / float(image_file_height) - settings.VIDEO_IMAGE_ASPECT_RATIO)
if image_file_width < settings.VIDEO_IMAGE_MIN_WIDTH or image_file_height < settings.VIDEO_IMAGE_MIN_HEIGHT:
- error = _(u'Recommended image resolution is {image_file_max_width}x{image_file_max_height}. '
- u'The minimum resolution is {image_file_min_width}x{image_file_min_height}.').format(
+ error = _('Recommended image resolution is {image_file_max_width}x{image_file_max_height}. '
+ 'The minimum resolution is {image_file_min_width}x{image_file_min_height}.').format(
image_file_max_width=settings.VIDEO_IMAGE_MAX_WIDTH,
image_file_max_height=settings.VIDEO_IMAGE_MAX_HEIGHT,
image_file_min_width=settings.VIDEO_IMAGE_MIN_WIDTH,
image_file_min_height=settings.VIDEO_IMAGE_MIN_HEIGHT
)
elif not skip_aspect_ratio and image_file_aspect_ratio > settings.VIDEO_IMAGE_ASPECT_RATIO_ERROR_MARGIN:
- error = _(u'This image file must have an aspect ratio of {video_image_aspect_ratio_text}.').format(
+ error = _('This image file must have an aspect ratio of {video_image_aspect_ratio_text}.').format(
video_image_aspect_ratio_text=settings.VIDEO_IMAGE_ASPECT_RATIO_TEXT
)
else:
@@ -108,7 +106,7 @@ def validate_and_update_video_image(course_key_string, edx_video_id, image_file,
error = validate_video_image(image_file, skip_aspect_ratio=True)
if error:
LOGGER.info(
- u'VIDEOS: Scraping youtube video thumbnail failed for edx_video_id [%s] in course [%s] with error: %s',
+ 'VIDEOS: Scraping youtube video thumbnail failed for edx_video_id [%s] in course [%s] with error: %s',
edx_video_id,
course_key_string,
error
@@ -117,7 +115,7 @@ def validate_and_update_video_image(course_key_string, edx_video_id, image_file,
update_video_image(edx_video_id, course_key_string, image_file, image_filename)
LOGGER.info(
- u'VIDEOS: Scraping youtube video thumbnail for edx_video_id [%s] in course [%s]', edx_video_id, course_key_string # lint-amnesty, pylint: disable=line-too-long
+ 'VIDEOS: Scraping youtube video thumbnail for edx_video_id [%s] in course [%s]', edx_video_id, course_key_string # lint-amnesty, pylint: disable=line-too-long
)
@@ -128,7 +126,7 @@ def scrape_youtube_thumbnail(course_id, edx_video_id, youtube_id):
# Scrape when course video image does not exist for edx_video_id.
if not get_course_video_image_url(course_id, edx_video_id):
thumbnail_content, thumbnail_content_type = download_youtube_video_thumbnail(youtube_id)
- supported_content_types = {v: k for k, v in six.iteritems(settings.VIDEO_IMAGE_SUPPORTED_FILE_FORMATS)}
+ supported_content_types = {v: k for k, v in settings.VIDEO_IMAGE_SUPPORTED_FILE_FORMATS.items()}
image_filename = '{youtube_id}{image_extention}'.format(
youtube_id=youtube_id,
image_extention=supported_content_types.get(