diff --git a/lms/djangoapps/instructor/settings/common.py b/lms/djangoapps/instructor/settings/common.py index d9a8ad60d1..8f44daaf27 100644 --- a/lms/djangoapps/instructor/settings/common.py +++ b/lms/djangoapps/instructor/settings/common.py @@ -1,7 +1,7 @@ """Common environment variables unique to the instructor plugin.""" -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ def plugin_settings(settings): diff --git a/lms/djangoapps/instructor/tests/test_api.py b/lms/djangoapps/instructor/tests/test_api.py index d8e97d9c93..044f84ff66 100644 --- a/lms/djangoapps/instructor/tests/test_api.py +++ b/lms/djangoapps/instructor/tests/test_api.py @@ -21,7 +21,7 @@ from django.http import HttpRequest, HttpResponse from django.test import RequestFactory, TestCase from django.test.client import MULTIPART_CONTENT from django.urls import reverse as django_reverse -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from edx_when.api import get_dates_for_course, get_overrides_for_user, set_date_for_block from edx_toggles.toggles.testutils import override_waffle_flag from opaque_keys.edx.keys import CourseKey diff --git a/lms/djangoapps/instructor/urls.py b/lms/djangoapps/instructor/urls.py index 17db7f600e..23a8430745 100644 --- a/lms/djangoapps/instructor/urls.py +++ b/lms/djangoapps/instructor/urls.py @@ -2,16 +2,16 @@ Instructor API endpoint urls. """ -from django.conf.urls import url, include +from django.urls import include, path, re_path from openedx.core.constants import COURSE_ID_PATTERN from .views import api_urls urlpatterns = [ - url(rf'^courses/{COURSE_ID_PATTERN}/instructor/api/', include(api_urls.urlpatterns)), - url( - r'^api/instructor/v1/', + re_path(rf'^courses/{COURSE_ID_PATTERN}/instructor/api/', include(api_urls.urlpatterns)), + path( + 'api/instructor/v1/', include((api_urls.v1_api_urls, 'lms.djangoapps.instructor'), namespace='instructor_api_v1'), ), ] diff --git a/lms/djangoapps/instructor/views/api.py b/lms/djangoapps/instructor/views/api.py index 0def090902..6385adf00a 100644 --- a/lms/djangoapps/instructor/views/api.py +++ b/lms/djangoapps/instructor/views/api.py @@ -24,7 +24,7 @@ from django.shortcuts import redirect from django.urls import reverse from django.utils.decorators import method_decorator from django.utils.html import strip_tags -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django.views.decorators.cache import cache_control from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.http import require_POST, require_http_methods diff --git a/lms/djangoapps/instructor/views/api_urls.py b/lms/djangoapps/instructor/views/api_urls.py index abf8712e43..0b4a88d1b7 100644 --- a/lms/djangoapps/instructor/views/api_urls.py +++ b/lms/djangoapps/instructor/views/api_urls.py @@ -2,7 +2,7 @@ Instructor API endpoint urls. """ -from django.conf.urls import url +from django.urls import path, re_path from lms.djangoapps.instructor.views import api, gradebook_api from openedx.core.constants import COURSE_ID_PATTERN @@ -13,79 +13,79 @@ from openedx.core.constants import COURSE_ID_PATTERN # in incompatible ways. If they do need incompatible changes for use via MFEs # then new v2 endpoints can be introduced. v1_api_urls = [ - url(rf'^tasks/{COURSE_ID_PATTERN}$', api.InstructorTasks.as_view(), name='list_instructor_tasks', ), - url(rf'^reports/{COURSE_ID_PATTERN}$', api.ReportDownloads.as_view(), name='list_report_downloads', ), - url(rf'^reports/{COURSE_ID_PATTERN}/generate/problem_responses$', api.ProblemResponseReportInitiate.as_view(), - name='generate_problem_responses', ), + re_path(rf'^tasks/{COURSE_ID_PATTERN}$', api.InstructorTasks.as_view(), name='list_instructor_tasks', ), + re_path(rf'^reports/{COURSE_ID_PATTERN}$', api.ReportDownloads.as_view(), name='list_report_downloads', ), + re_path(rf'^reports/{COURSE_ID_PATTERN}/generate/problem_responses$', api.ProblemResponseReportInitiate.as_view(), + name='generate_problem_responses', ), ] urlpatterns = [ - url(r'^students_update_enrollment$', api.students_update_enrollment, name='students_update_enrollment'), - url(r'^register_and_enroll_students$', api.register_and_enroll_students, name='register_and_enroll_students'), - url(r'^list_course_role_members$', api.list_course_role_members, name='list_course_role_members'), - url(r'^modify_access$', api.modify_access, name='modify_access'), - url(r'^bulk_beta_modify_access$', api.bulk_beta_modify_access, name='bulk_beta_modify_access'), - url(r'^get_problem_responses$', api.get_problem_responses, name='get_problem_responses'), - url(r'^get_grading_config$', api.get_grading_config, name='get_grading_config'), - url(r'^get_students_features(?P/csv)?$', api.get_students_features, name='get_students_features'), - url(r'^get_issued_certificates/$', api.get_issued_certificates, name='get_issued_certificates'), - url(r'^get_students_who_may_enroll$', api.get_students_who_may_enroll, name='get_students_who_may_enroll'), - url(r'^get_anon_ids$', api.get_anon_ids, name='get_anon_ids'), - url(r'^get_student_enrollment_status$', api.get_student_enrollment_status, name="get_student_enrollment_status"), - url(r'^get_student_progress_url$', api.get_student_progress_url, name='get_student_progress_url'), - url(r'^reset_student_attempts$', api.reset_student_attempts, name='reset_student_attempts'), - url(r'^rescore_problem$', api.rescore_problem, name='rescore_problem'), - url(r'^override_problem_score$', api.override_problem_score, name='override_problem_score'), - url(r'^reset_student_attempts_for_entrance_exam$', api.reset_student_attempts_for_entrance_exam, - name='reset_student_attempts_for_entrance_exam'), - url(r'^rescore_entrance_exam$', api.rescore_entrance_exam, name='rescore_entrance_exam'), - url(r'^list_entrance_exam_instructor_tasks', api.list_entrance_exam_instructor_tasks, - name='list_entrance_exam_instructor_tasks'), - url(r'^mark_student_can_skip_entrance_exam', api.mark_student_can_skip_entrance_exam, - name='mark_student_can_skip_entrance_exam'), - url(r'^list_instructor_tasks$', api.list_instructor_tasks, name='list_instructor_tasks'), - url(r'^list_background_email_tasks$', api.list_background_email_tasks, name='list_background_email_tasks'), - url(r'^list_email_content$', api.list_email_content, name='list_email_content'), - url(r'^list_forum_members$', api.list_forum_members, name='list_forum_members'), - url(r'^update_forum_role_membership$', api.update_forum_role_membership, name='update_forum_role_membership'), - url(r'^send_email$', api.send_email, name='send_email'), - url(r'^change_due_date$', api.change_due_date, name='change_due_date'), - url(r'^reset_due_date$', api.reset_due_date, name='reset_due_date'), - url(r'^show_unit_extensions$', api.show_unit_extensions, name='show_unit_extensions'), - url(r'^show_student_extensions$', api.show_student_extensions, name='show_student_extensions'), + path('students_update_enrollment', api.students_update_enrollment, name='students_update_enrollment'), + path('register_and_enroll_students', api.register_and_enroll_students, name='register_and_enroll_students'), + path('list_course_role_members', api.list_course_role_members, name='list_course_role_members'), + path('modify_access', api.modify_access, name='modify_access'), + path('bulk_beta_modify_access', api.bulk_beta_modify_access, name='bulk_beta_modify_access'), + path('get_problem_responses', api.get_problem_responses, name='get_problem_responses'), + path('get_grading_config', api.get_grading_config, name='get_grading_config'), + re_path(r'^get_students_features(?P/csv)?$', api.get_students_features, name='get_students_features'), + path('get_issued_certificates/', api.get_issued_certificates, name='get_issued_certificates'), + path('get_students_who_may_enroll', api.get_students_who_may_enroll, name='get_students_who_may_enroll'), + path('get_anon_ids', api.get_anon_ids, name='get_anon_ids'), + path('get_student_enrollment_status', api.get_student_enrollment_status, name="get_student_enrollment_status"), + path('get_student_progress_url', api.get_student_progress_url, name='get_student_progress_url'), + path('reset_student_attempts', api.reset_student_attempts, name='reset_student_attempts'), + path('rescore_problem', api.rescore_problem, name='rescore_problem'), + path('override_problem_score', api.override_problem_score, name='override_problem_score'), + path('reset_student_attempts_for_entrance_exam', api.reset_student_attempts_for_entrance_exam, + name='reset_student_attempts_for_entrance_exam'), + path('rescore_entrance_exam', api.rescore_entrance_exam, name='rescore_entrance_exam'), + path('list_entrance_exam_instructor_tasks', api.list_entrance_exam_instructor_tasks, + name='list_entrance_exam_instructor_tasks'), + path('mark_student_can_skip_entrance_exam', api.mark_student_can_skip_entrance_exam, + name='mark_student_can_skip_entrance_exam'), + path('list_instructor_tasks', api.list_instructor_tasks, name='list_instructor_tasks'), + path('list_background_email_tasks', api.list_background_email_tasks, name='list_background_email_tasks'), + path('list_email_content', api.list_email_content, name='list_email_content'), + path('list_forum_members', api.list_forum_members, name='list_forum_members'), + path('update_forum_role_membership', api.update_forum_role_membership, name='update_forum_role_membership'), + path('send_email', api.send_email, name='send_email'), + path('change_due_date', api.change_due_date, name='change_due_date'), + path('reset_due_date', api.reset_due_date, name='reset_due_date'), + path('show_unit_extensions', api.show_unit_extensions, name='show_unit_extensions'), + path('show_student_extensions', api.show_student_extensions, name='show_student_extensions'), # proctored exam downloads... - url(r'^get_proctored_exam_results$', api.get_proctored_exam_results, name='get_proctored_exam_results'), + path('get_proctored_exam_results', api.get_proctored_exam_results, name='get_proctored_exam_results'), # Grade downloads... - url(r'^list_report_downloads$', api.list_report_downloads, name='list_report_downloads'), - url(r'^calculate_grades_csv$', api.calculate_grades_csv, name='calculate_grades_csv'), - url(r'^problem_grade_report$', api.problem_grade_report, name='problem_grade_report'), + path('list_report_downloads', api.list_report_downloads, name='list_report_downloads'), + path('calculate_grades_csv', api.calculate_grades_csv, name='calculate_grades_csv'), + path('problem_grade_report', api.problem_grade_report, name='problem_grade_report'), # Reports.. - url(r'^get_course_survey_results$', api.get_course_survey_results, name='get_course_survey_results'), - url(r'^export_ora2_data', api.export_ora2_data, name='export_ora2_data'), - url(r'^export_ora2_summary', api.export_ora2_summary, name='export_ora2_summary'), + path('get_course_survey_results', api.get_course_survey_results, name='get_course_survey_results'), + path('export_ora2_data', api.export_ora2_data, name='export_ora2_data'), + path('export_ora2_summary', api.export_ora2_summary, name='export_ora2_summary'), - url(r'^export_ora2_submission_files', api.export_ora2_submission_files, - name='export_ora2_submission_files'), + path('export_ora2_submission_files', api.export_ora2_submission_files, + name='export_ora2_submission_files'), # spoc gradebook - url(r'^gradebook$', gradebook_api.spoc_gradebook, name='spoc_gradebook'), + path('gradebook', gradebook_api.spoc_gradebook, name='spoc_gradebook'), - url(r'^gradebook/(?P[0-9]+)$', gradebook_api.spoc_gradebook, name='spoc_gradebook'), + path('gradebook/', gradebook_api.spoc_gradebook, name='spoc_gradebook'), # Cohort management - url(r'^add_users_to_cohorts$', api.add_users_to_cohorts, name='add_users_to_cohorts'), + path('add_users_to_cohorts', api.add_users_to_cohorts, name='add_users_to_cohorts'), # Certificates - url(r'^enable_certificate_generation$', api.enable_certificate_generation, name='enable_certificate_generation'), - url(r'^start_certificate_generation', api.start_certificate_generation, name='start_certificate_generation'), - url(r'^start_certificate_regeneration', api.start_certificate_regeneration, name='start_certificate_regeneration'), - url(r'^certificate_exception_view/$', api.certificate_exception_view, name='certificate_exception_view'), - url(r'^generate_certificate_exceptions/(?P[^/]*)', api.generate_certificate_exceptions, - name='generate_certificate_exceptions'), - url(r'^generate_bulk_certificate_exceptions', api.generate_bulk_certificate_exceptions, - name='generate_bulk_certificate_exceptions'), - url(r'^certificate_invalidation_view/$', api.certificate_invalidation_view, name='certificate_invalidation_view'), + path('enable_certificate_generation', api.enable_certificate_generation, name='enable_certificate_generation'), + path('start_certificate_generation', api.start_certificate_generation, name='start_certificate_generation'), + path('start_certificate_regeneration', api.start_certificate_regeneration, name='start_certificate_regeneration'), + path('certificate_exception_view/', api.certificate_exception_view, name='certificate_exception_view'), + re_path(r'^generate_certificate_exceptions/(?P[^/]*)', api.generate_certificate_exceptions, + name='generate_certificate_exceptions'), + path('generate_bulk_certificate_exceptions', api.generate_bulk_certificate_exceptions, + name='generate_bulk_certificate_exceptions'), + path('certificate_invalidation_view/', api.certificate_invalidation_view, name='certificate_invalidation_view'), ] diff --git a/lms/djangoapps/instructor/views/instructor_dashboard.py b/lms/djangoapps/instructor/views/instructor_dashboard.py index b3ebc12699..52983f656c 100644 --- a/lms/djangoapps/instructor/views/instructor_dashboard.py +++ b/lms/djangoapps/instructor/views/instructor_dashboard.py @@ -15,8 +15,8 @@ from django.contrib.auth.decorators import login_required from django.http import Http404, HttpResponseServerError from django.urls import reverse from django.utils.html import escape -from django.utils.translation import ugettext as _ -from django.utils.translation import ugettext_noop +from django.utils.translation import gettext as _ +from django.utils.translation import gettext_noop from django.views.decorators.cache import cache_control from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.http import require_POST @@ -78,7 +78,7 @@ class InstructorDashboardTab(CourseTab): """ type = "instructor" - title = ugettext_noop('Instructor') + title = gettext_noop('Instructor') view_name = "instructor_dashboard" is_dynamic = True # The "Instructor" tab is instead dynamically added when it is enabled diff --git a/lms/djangoapps/instructor/views/instructor_task_helpers.py b/lms/djangoapps/instructor/views/instructor_task_helpers.py index 7ea28b10fd..d7354a821e 100644 --- a/lms/djangoapps/instructor/views/instructor_task_helpers.py +++ b/lms/djangoapps/instructor/views/instructor_task_helpers.py @@ -7,8 +7,8 @@ tasks. import json import logging -from django.utils.translation import ugettext as _ -from django.utils.translation import ungettext +from django.utils.translation import gettext as _ +from django.utils.translation import ngettext from common.djangoapps.util.date_utils import get_default_time_display from lms.djangoapps.bulk_email.models import CourseEmail @@ -80,7 +80,7 @@ def extract_email_features(email_task): else: if 'succeeded' in task_output and task_output['succeeded'] > 0: num_emails = task_output['succeeded'] - number_sent = ungettext( + number_sent = ngettext( "{num_emails} sent", "{num_emails} sent", num_emails @@ -89,7 +89,7 @@ def extract_email_features(email_task): if 'failed' in task_output and task_output['failed'] > 0: num_emails = task_output['failed'] number_sent += ", " - number_sent += ungettext( + number_sent += ngettext( "{num_emails} failed", "{num_emails} failed", num_emails diff --git a/lms/djangoapps/instructor/views/tools.py b/lms/djangoapps/instructor/views/tools.py index 62c95e1a71..06fdad5865 100644 --- a/lms/djangoapps/instructor/views/tools.py +++ b/lms/djangoapps/instructor/views/tools.py @@ -9,7 +9,7 @@ import operator import dateutil from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user from django.http import HttpResponseBadRequest -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from edx_when import api from opaque_keys.edx.keys import UsageKey from pytz import UTC diff --git a/lms/djangoapps/instructor_task/api_helper.py b/lms/djangoapps/instructor_task/api_helper.py index cb3dfa9c67..54345f1821 100644 --- a/lms/djangoapps/instructor_task/api_helper.py +++ b/lms/djangoapps/instructor_task/api_helper.py @@ -12,7 +12,7 @@ import logging from celery.result import AsyncResult from celery.states import FAILURE, READY_STATES, REVOKED, SUCCESS -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from opaque_keys.edx.keys import UsageKey from common.djangoapps.util.db import outer_atomic diff --git a/lms/djangoapps/instructor_task/models.py b/lms/djangoapps/instructor_task/models.py index 10f178a3b7..1309ac3283 100644 --- a/lms/djangoapps/instructor_task/models.py +++ b/lms/djangoapps/instructor_task/models.py @@ -25,7 +25,7 @@ from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imp from django.core.files.base import ContentFile from django.db import models, transaction -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from opaque_keys.edx.django.models import CourseKeyField from openedx.core.storage import get_storage diff --git a/lms/djangoapps/instructor_task/tasks.py b/lms/djangoapps/instructor_task/tasks.py index b97252daa0..61a933b5a6 100644 --- a/lms/djangoapps/instructor_task/tasks.py +++ b/lms/djangoapps/instructor_task/tasks.py @@ -24,7 +24,7 @@ import logging from functools import partial from celery import shared_task -from django.utils.translation import ugettext_noop +from django.utils.translation import gettext_noop from edx_django_utils.monitoring import set_code_owner_attribute from lms.djangoapps.bulk_email.tasks import perform_delegate_email_batches @@ -75,7 +75,7 @@ def rescore_problem(entry_id, xmodule_instance_args): to instantiate an xmodule instance. """ # Translators: This is a past-tense verb that is inserted into task progress messages as {action}. - action_name = ugettext_noop('rescored') + action_name = gettext_noop('rescored') update_fcn = partial(rescore_problem_module_state, xmodule_instance_args) visit_fcn = partial(perform_module_state_update, update_fcn, None) @@ -89,7 +89,7 @@ def override_problem_score(entry_id, xmodule_instance_args): Overrides a specific learner's score on a problem. """ # Translators: This is a past-tense verb that is inserted into task progress messages as {action}. - action_name = ugettext_noop('overridden') + action_name = gettext_noop('overridden') update_fcn = partial(override_score_module_state, xmodule_instance_args) visit_fcn = partial(perform_module_state_update, update_fcn, None) @@ -113,7 +113,7 @@ def reset_problem_attempts(entry_id, xmodule_instance_args): to instantiate an xmodule instance. """ # Translators: This is a past-tense verb that is inserted into task progress messages as {action}. - action_name = ugettext_noop('reset') + action_name = gettext_noop('reset') update_fcn = partial(reset_attempts_module_state, xmodule_instance_args) visit_fcn = partial(perform_module_state_update, update_fcn, None) return run_main_task(entry_id, visit_fcn, action_name) @@ -136,7 +136,7 @@ def delete_problem_state(entry_id, xmodule_instance_args): to instantiate an xmodule instance. """ # Translators: This is a past-tense verb that is inserted into task progress messages as {action}. - action_name = ugettext_noop('deleted') + action_name = gettext_noop('deleted') update_fcn = partial(delete_problem_module_state, xmodule_instance_args) visit_fcn = partial(perform_module_state_update, update_fcn, None) return run_main_task(entry_id, visit_fcn, action_name) @@ -159,7 +159,7 @@ def send_bulk_course_email(entry_id, _xmodule_instance_args): to instantiate an xmodule instance. This is unused here. """ # Translators: This is a past-tense verb that is inserted into task progress messages as {action}. - action_name = ugettext_noop('emailed') + action_name = gettext_noop('emailed') visit_fcn = perform_delegate_email_batches return run_main_task(entry_id, visit_fcn, action_name) @@ -175,7 +175,7 @@ def calculate_problem_responses_csv(entry_id, xmodule_instance_args): an S3 bucket for download. """ # Translators: This is a past-tense verb that is inserted into task progress messages as {action}. - action_name = ugettext_noop('generated') + action_name = gettext_noop('generated') task_fn = partial(ProblemResponses.generate, xmodule_instance_args) return run_main_task(entry_id, task_fn, action_name) @@ -187,7 +187,7 @@ def calculate_grades_csv(entry_id, xmodule_instance_args): Grade a course and push the results to an S3 bucket for download. """ # Translators: This is a past-tense verb that is inserted into task progress messages as {action}. - action_name = ugettext_noop('graded') + action_name = gettext_noop('graded') TASK_LOG.info( "Task: %s, InstructorTask ID: %s, Task type: %s, Preparing for task execution", xmodule_instance_args.get('task_id'), entry_id, action_name @@ -205,7 +205,7 @@ def calculate_problem_grade_report(entry_id, xmodule_instance_args): grades and push the results to an S3 bucket for download. """ # Translators: This is a past-tense phrase that is inserted into task progress messages as {action}. - action_name = ugettext_noop('problem distribution graded') + action_name = gettext_noop('problem distribution graded') TASK_LOG.info( "Task: %s, InstructorTask ID: %s, Task type: %s, Preparing for task execution", xmodule_instance_args.get('task_id'), entry_id, action_name @@ -223,7 +223,7 @@ def calculate_students_features_csv(entry_id, xmodule_instance_args): CSV to an S3 bucket for download. """ # Translators: This is a past-tense verb that is inserted into task progress messages as {action}. - action_name = ugettext_noop('generated') + action_name = gettext_noop('generated') task_fn = partial(upload_students_csv, xmodule_instance_args) return run_main_task(entry_id, task_fn, action_name) @@ -236,7 +236,7 @@ def course_survey_report_csv(entry_id, xmodule_instance_args): generated report to an S3 bucket for download. """ # Translators: This is a past-tense verb that is inserted into task progress messages as {action}. - action_name = ugettext_noop('generated') + action_name = gettext_noop('generated') task_fn = partial(upload_course_survey_report, xmodule_instance_args) return run_main_task(entry_id, task_fn, action_name) @@ -262,7 +262,7 @@ def calculate_may_enroll_csv(entry_id, xmodule_instance_args): download. """ # Translators: This is a past-tense verb that is inserted into task progress messages as {action}. - action_name = ugettext_noop('generated') + action_name = gettext_noop('generated') task_fn = partial(upload_may_enroll_csv, xmodule_instance_args) return run_main_task(entry_id, task_fn, action_name) @@ -274,7 +274,7 @@ def generate_certificates(entry_id, xmodule_instance_args): Grade students and generate certificates. """ # Translators: This is a past-tense verb that is inserted into task progress messages as {action}. - action_name = ugettext_noop('certificates generated') + action_name = gettext_noop('certificates generated') TASK_LOG.info( "Task: %s, InstructorTask ID: %s, Task type: %s, Preparing for task execution", xmodule_instance_args.get('task_id'), entry_id, action_name @@ -292,7 +292,7 @@ def cohort_students(entry_id, xmodule_instance_args): """ # Translators: This is a past-tense verb that is inserted into task progress messages as {action}. # An example of such a message is: "Progress: {action} {succeeded} of {attempted} so far" - action_name = ugettext_noop('cohorted') + action_name = gettext_noop('cohorted') task_fn = partial(cohort_students_and_upload, xmodule_instance_args) return run_main_task(entry_id, task_fn, action_name) @@ -305,7 +305,7 @@ def generate_anonymous_ids_for_course(entry_id, xmodule_instance_args): """ # Translators: This is a past-tense verb that is inserted into task progress messages as {action}. # An example of such a message is: "Progress: {action} {succeeded} of {attempted} so far" - action_name = ugettext_noop('generate_anonymized_id') + action_name = gettext_noop('generate_anonymized_id') task_fn = partial(generate_anonymous_ids, xmodule_instance_args) return run_main_task(entry_id, task_fn, action_name) @@ -316,7 +316,7 @@ def export_ora2_data(entry_id, xmodule_instance_args): """ Generate a CSV of ora2 responses and push it to S3. """ - action_name = ugettext_noop('generated') + action_name = gettext_noop('generated') task_fn = partial(upload_ora2_data, xmodule_instance_args) return run_main_task(entry_id, task_fn, action_name) @@ -328,7 +328,7 @@ def export_ora2_submission_files(entry_id, xmodule_instance_args): Download all submission files, generate csv downloads list, put all this into zip archive and push it to S3. """ - action_name = ugettext_noop('compressed') + action_name = gettext_noop('compressed') task_fn = partial(upload_ora2_submission_files, xmodule_instance_args) return run_main_task(entry_id, task_fn, action_name) @@ -339,6 +339,6 @@ def export_ora2_summary(entry_id, xmodule_instance_args): """ Generate a CSV of ora2/student summaries and push it to S3. """ - action_name = ugettext_noop('generated') + action_name = gettext_noop('generated') task_fn = partial(upload_ora2_summary, xmodule_instance_args) return run_main_task(entry_id, task_fn, action_name) diff --git a/lms/djangoapps/instructor_task/tasks_helper/module_state.py b/lms/djangoapps/instructor_task/tasks_helper/module_state.py index 7e7af2f00e..73c94af40b 100644 --- a/lms/djangoapps/instructor_task/tasks_helper/module_state.py +++ b/lms/djangoapps/instructor_task/tasks_helper/module_state.py @@ -7,7 +7,7 @@ import json import logging from time import time -from django.utils.translation import ugettext_noop +from django.utils.translation import gettext_noop from opaque_keys.edx.keys import UsageKey from xblock.runtime import KvsFieldData from xblock.scorable import Score @@ -65,7 +65,7 @@ def perform_module_state_update(update_fcn, filter_fcn, _entry_id, course_id, ta problem_url = task_input.get('problem_url') entrance_exam_url = task_input.get('entrance_exam_url') student_identifier = task_input.get('student') - override_score_task = action_name == ugettext_noop('overridden') + override_score_task = action_name == gettext_noop('overridden') problems = {} # if problem_url is present make a usage key from it diff --git a/lms/djangoapps/instructor_task/tests/test_tasks.py b/lms/djangoapps/instructor_task/tests/test_tasks.py index 86ab8ea334..ead71b5c7a 100644 --- a/lms/djangoapps/instructor_task/tests/test_tasks.py +++ b/lms/djangoapps/instructor_task/tests/test_tasks.py @@ -12,7 +12,7 @@ from uuid import uuid4 import pytest import ddt from celery.states import FAILURE, SUCCESS -from django.utils.translation import ugettext_noop +from django.utils.translation import gettext_noop from opaque_keys.edx.keys import i4xEncoder from common.djangoapps.course_modes.models import CourseMode @@ -676,7 +676,7 @@ class TestOra2ResponsesInstructorTask(TestInstructorTasks): with patch('lms.djangoapps.instructor_task.tasks.run_main_task') as mock_main_task: export_ora2_data(task_entry.id, task_xmodule_args) - action_name = ugettext_noop('generated') + action_name = gettext_noop('generated') assert mock_main_task.call_count == 1 args = mock_main_task.call_args[0] @@ -706,7 +706,7 @@ class TestOra2ExportSubmissionFilesInstructorTask(TestInstructorTasks): with patch('lms.djangoapps.instructor_task.tasks.run_main_task') as mock_main_task: export_ora2_submission_files(task_entry.id, task_xmodule_args) - action_name = ugettext_noop('compressed') + action_name = gettext_noop('compressed') assert mock_main_task.call_count == 1 args = mock_main_task.call_args[0] @@ -736,7 +736,7 @@ class TestOra2SummaryInstructorTask(TestInstructorTasks): with patch('lms.djangoapps.instructor_task.tasks.run_main_task') as mock_main_task: export_ora2_summary(task_entry.id, task_xmodule_args) - action_name = ugettext_noop('generated') + action_name = gettext_noop('generated') assert mock_main_task.call_count == 1 args = mock_main_task.call_args[0] diff --git a/lms/djangoapps/teams/api_urls.py b/lms/djangoapps/teams/api_urls.py index e36cb69a65..a210358a66 100644 --- a/lms/djangoapps/teams/api_urls.py +++ b/lms/djangoapps/teams/api_urls.py @@ -4,7 +4,7 @@ Defines the URL routes for the Team API. from django.conf import settings -from django.conf.urls import url +from django.urls import path, re_path from .views import ( MembershipBulkManagementView, @@ -21,31 +21,31 @@ TEAM_ID_PATTERN = r'(?P[a-z\d_-]+)' TOPIC_ID_PATTERN = r'(?P[A-Za-z\d_.-]+)' urlpatterns = [ - url( - r'^v0/teams/$', + path( + 'v0/teams/', TeamsListView.as_view(), name="teams_list" ), - url( + re_path( r'^v0/teams/{team_id_pattern}$'.format( team_id_pattern=TEAM_ID_PATTERN, ), TeamsDetailView.as_view(), name="teams_detail" ), - url( + re_path( r'^v0/teams/{team_id_pattern}/assignments$'.format( team_id_pattern=TEAM_ID_PATTERN, ), TeamsAssignmentsView.as_view(), name="teams_assignments_list" ), - url( - r'^v0/topics/$', + path( + 'v0/topics/', TopicListView.as_view(), name="topics_list" ), - url( + re_path( r'^v0/topics/{topic_id_pattern},{course_id_pattern}$'.format( topic_id_pattern=TOPIC_ID_PATTERN, course_id_pattern=settings.COURSE_ID_PATTERN, @@ -53,12 +53,12 @@ urlpatterns = [ TopicDetailView.as_view(), name="topics_detail" ), - url( - r'^v0/team_membership/$', + path( + 'v0/team_membership/', MembershipListView.as_view(), name="team_membership_list" ), - url( + re_path( r'^v0/team_membership/{team_id_pattern},{username_pattern}$'.format( team_id_pattern=TEAM_ID_PATTERN, username_pattern=settings.USERNAME_PATTERN, @@ -66,7 +66,7 @@ urlpatterns = [ MembershipDetailView.as_view(), name="team_membership_detail" ), - url( + re_path( r'^v0/bulk_team_membership/{course_id_pattern}$'.format( course_id_pattern=settings.COURSE_ID_PATTERN, ), diff --git a/lms/djangoapps/teams/models.py b/lms/djangoapps/teams/models.py index de76a5d30f..56de6f965a 100644 --- a/lms/djangoapps/teams/models.py +++ b/lms/djangoapps/teams/models.py @@ -13,7 +13,7 @@ from django.db import models from django.dispatch import receiver from django.utils.text import slugify -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext_lazy from django_countries.fields import CountryField from model_utils import FieldTracker from opaque_keys.edx.django.models import CourseKeyField @@ -138,7 +138,7 @@ class CourseTeam(models.Model): language = LanguageField( default='', blank=True, - help_text=ugettext_lazy("Optional language the team uses as ISO 639-1 code."), + help_text=gettext_lazy("Optional language the team uses as ISO 639-1 code."), ) # indexed for ordering last_activity_at = models.DateTimeField(default=utc_now, db_index=True) diff --git a/lms/djangoapps/teams/urls.py b/lms/djangoapps/teams/urls.py index 4c64eceb5f..5bdbc56c13 100644 --- a/lms/djangoapps/teams/urls.py +++ b/lms/djangoapps/teams/urls.py @@ -3,11 +3,11 @@ Defines the URL routes for this app. """ -from django.conf.urls import url +from django.urls import path from django.contrib.auth.decorators import login_required from .views import TeamsDashboardView urlpatterns = [ - url(r"^$", login_required(TeamsDashboardView.as_view()), name="teams_dashboard") + path('', login_required(TeamsDashboardView.as_view()), name="teams_dashboard") ] diff --git a/lms/djangoapps/teams/views.py b/lms/djangoapps/teams/views.py index b6ece3c3f0..582f61b7b2 100644 --- a/lms/djangoapps/teams/views.py +++ b/lms/djangoapps/teams/views.py @@ -14,8 +14,8 @@ from django.dispatch import receiver from django.http import Http404, HttpResponse, JsonResponse from django.shortcuts import get_object_or_404, render from django.utils.functional import cached_property -from django.utils.translation import ugettext as _ -from django.utils.translation import ugettext_noop +from django.utils.translation import gettext as _ +from django.utils.translation import gettext_noop from django_countries import countries from edx_rest_framework_extensions.paginators import DefaultPagination, paginate_search_results from opaque_keys import InvalidKeyError @@ -401,7 +401,7 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView): if 'course_id' not in request.query_params: return Response( - build_api_error(ugettext_noop("course_id must be provided")), + build_api_error(gettext_noop("course_id must be provided")), status=status.HTTP_400_BAD_REQUEST ) @@ -411,7 +411,7 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView): course_module = modulestore().get_course(course_key) except InvalidKeyError: error = build_api_error( - ugettext_noop("The supplied course id {course_id} is not valid."), + gettext_noop("The supplied course id {course_id} is not valid."), course_id=course_id_string, ) return Response(error, status=status.HTTP_400_BAD_REQUEST) @@ -427,7 +427,7 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView): text_search = request.query_params.get('text_search', None) if text_search and request.query_params.get('order_by', None): return Response( - build_api_error(ugettext_noop("text_search and order_by cannot be provided together")), + build_api_error(gettext_noop("text_search and order_by cannot be provided together")), status=status.HTTP_400_BAD_REQUEST ) @@ -438,7 +438,7 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView): if topic_id is not None: if topic_id not in course_module.teamsets_by_id: error = build_api_error( - ugettext_noop('The supplied topic id {topic_id} is not valid'), + gettext_noop('The supplied topic id {topic_id} is not valid'), topic_id=topic_id ) return Response(error, status=status.HTTP_400_BAD_REQUEST) @@ -458,7 +458,7 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView): search_engine = CourseTeamIndexer.engine() except ElasticSearchConnectionError: return Response( - build_api_error(ugettext_noop('Error connecting to elasticsearch')), + build_api_error(gettext_noop('Error connecting to elasticsearch')), status=status.HTTP_503_SERVICE_UNAVAILABLE ) @@ -547,7 +547,7 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView): return Response(status=status.HTTP_404_NOT_FOUND) except InvalidKeyError: field_errors['course_id'] = build_api_error( - ugettext_noop('The supplied course_id {course_id} is not valid.'), + gettext_noop('The supplied course_id {course_id} is not valid.'), course_id=course_id ) return Response({ @@ -557,7 +557,7 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView): topic_id = request.data.get('topic_id') if not topic_id: field_errors['topic_id'] = build_api_error( - ugettext_noop('topic_id is required'), + gettext_noop('topic_id is required'), course_id=course_id ) return Response({ @@ -576,7 +576,7 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView): # and not leak the existance of a private teamset if not can_user_create_team_in_topic(request.user, course_key, topic_id): return Response( - build_api_error(ugettext_noop("You can't create a team in an instructor managed topic.")), + build_api_error(gettext_noop("You can't create a team in an instructor managed topic.")), status=status.HTTP_403_FORBIDDEN ) @@ -588,7 +588,7 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView): CourseTeamMembership.user_in_team_for_teamset(request.user, course_key, topic_id=topic_id) ): error_message = build_api_error( - ugettext_noop('You are already in a team in this teamset.'), + gettext_noop('You are already in a team in this teamset.'), course_id=course_id, teamset_id=topic_id, ) @@ -982,7 +982,7 @@ class TopicListView(GenericAPIView): return Response({ 'field_errors': { 'course_id': build_api_error( - ugettext_noop("The supplied course id {course_id} is not valid."), + gettext_noop("The supplied course id {course_id} is not valid."), course_id=course_id_string ) } @@ -1319,7 +1319,7 @@ class MembershipListView(ExpandableFieldViewMixin, GenericAPIView): if 'team_id' in request.query_params and 'teamset_id' in request.query_params: return Response( - build_api_error(ugettext_noop("teamset_id and team_id are mutually exclusive options.")), + build_api_error(gettext_noop("teamset_id and team_id are mutually exclusive options.")), status=status.HTTP_400_BAD_REQUEST ) elif 'team_id' in request.query_params: @@ -1339,7 +1339,7 @@ class MembershipListView(ExpandableFieldViewMixin, GenericAPIView): elif 'teamset_id' in request.query_params: if 'course_id' not in request.query_params: return Response( - build_api_error(ugettext_noop("teamset_id requires course_id to also be provided.")), + build_api_error(gettext_noop("teamset_id requires course_id to also be provided.")), status=status.HTTP_400_BAD_REQUEST ) @@ -1355,7 +1355,7 @@ class MembershipListView(ExpandableFieldViewMixin, GenericAPIView): teamset = teamsets.get(teamset_id, None) if not teamset: return Response( - build_api_error(ugettext_noop("No teamset found in given course with given id")), + build_api_error(gettext_noop("No teamset found in given course with given id")), status=status.HTTP_404_NOT_FOUND ) teamset_teams = CourseTeam.objects.filter(course_id=requested_course_key, topic_id=teamset_id) @@ -1368,7 +1368,7 @@ class MembershipListView(ExpandableFieldViewMixin, GenericAPIView): ] if teamset.is_private_managed and not teams_with_access: return Response( - build_api_error(ugettext_noop("No teamset found in given course with given id")), + build_api_error(gettext_noop("No teamset found in given course with given id")), status=status.HTTP_404_NOT_FOUND ) team_ids = [team.team_id for team in teams_with_access] @@ -1389,7 +1389,7 @@ class MembershipListView(ExpandableFieldViewMixin, GenericAPIView): if not specified_username_or_team: return Response( - build_api_error(ugettext_noop("username or (team_id or teamset_id) must be specified.")), + build_api_error(gettext_noop("username or (team_id or teamset_id) must be specified.")), status=status.HTTP_400_BAD_REQUEST ) @@ -1410,10 +1410,10 @@ class MembershipListView(ExpandableFieldViewMixin, GenericAPIView): field_errors = {} if 'username' not in request.data: - field_errors['username'] = build_api_error(ugettext_noop("Username is required.")) + field_errors['username'] = build_api_error(gettext_noop("Username is required.")) if 'team_id' not in request.data: - field_errors['team_id'] = build_api_error(ugettext_noop("Team id is required.")) + field_errors['team_id'] = build_api_error(gettext_noop("Team id is required.")) if field_errors: return Response({ @@ -1442,13 +1442,13 @@ class MembershipListView(ExpandableFieldViewMixin, GenericAPIView): max_team_size = course_module.teams_configuration.default_max_team_size if max_team_size is not None and team.users.count() >= max_team_size: return Response( - build_api_error(ugettext_noop("This team is already full.")), + build_api_error(gettext_noop("This team is already full.")), status=status.HTTP_400_BAD_REQUEST ) if not can_user_modify_team(request.user, team): return Response( - build_api_error(ugettext_noop("You can't join an instructor managed team.")), + build_api_error(gettext_noop("You can't join an instructor managed team.")), status=status.HTTP_403_FORBIDDEN ) @@ -1466,7 +1466,7 @@ class MembershipListView(ExpandableFieldViewMixin, GenericAPIView): except AlreadyOnTeamInTeamset: return Response( build_api_error( - ugettext_noop("The user {username} is already a member of a team in this teamset."), + gettext_noop("The user {username} is already a member of a team in this teamset."), username=username ), status=status.HTTP_400_BAD_REQUEST @@ -1474,7 +1474,7 @@ class MembershipListView(ExpandableFieldViewMixin, GenericAPIView): except NotEnrolledInCourseForTeam: return Response( build_api_error( - ugettext_noop("The user {username} is not enrolled in the course associated with this team."), + gettext_noop("The user {username} is not enrolled in the course associated with this team."), username=username ), status=status.HTTP_400_BAD_REQUEST @@ -1597,7 +1597,7 @@ class MembershipDetailView(ExpandableFieldViewMixin, GenericAPIView): if not can_user_modify_team(request.user, team): return Response( - build_api_error(ugettext_noop("You can't leave an instructor managed team.")), + build_api_error(gettext_noop("You can't leave an instructor managed team.")), status=status.HTTP_403_FORBIDDEN ) diff --git a/lms/djangoapps/verify_student/models.py b/lms/djangoapps/verify_student/models.py index 063a501096..0e51593c31 100644 --- a/lms/djangoapps/verify_student/models.py +++ b/lms/djangoapps/verify_student/models.py @@ -28,7 +28,7 @@ from django.urls import reverse from django.utils.functional import cached_property from django.utils.timezone import now -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext_lazy from model_utils import Choices from model_utils.models import StatusModel, TimeStampedModel from opaque_keys.edx.django.models import CourseKeyField @@ -1086,11 +1086,11 @@ class VerificationDeadline(TimeStampedModel): max_length=255, db_index=True, unique=True, - help_text=ugettext_lazy("The course for which this deadline applies"), + help_text=gettext_lazy("The course for which this deadline applies"), ) deadline = models.DateTimeField( - help_text=ugettext_lazy( + help_text=gettext_lazy( "The datetime after which users are no longer allowed " "to submit photos for verification." ) diff --git a/lms/djangoapps/verify_student/services.py b/lms/djangoapps/verify_student/services.py index 06acd68eaf..69e1dbe9e3 100644 --- a/lms/djangoapps/verify_student/services.py +++ b/lms/djangoapps/verify_student/services.py @@ -9,7 +9,7 @@ from urllib.parse import quote from django.conf import settings from django.utils.timezone import now -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from common.djangoapps.course_modes.models import CourseMode from common.djangoapps.student.models import User diff --git a/lms/djangoapps/verify_student/signals.py b/lms/djangoapps/verify_student/signals.py index 2a53cfdb8d..686f4b07ce 100644 --- a/lms/djangoapps/verify_student/signals.py +++ b/lms/djangoapps/verify_student/signals.py @@ -18,7 +18,8 @@ log = logging.getLogger(__name__) # Signal for emitting IDV submission and review updates -idv_update_signal = Signal(providing_args=["attempt_id", "user_id", "status", "full_name", "profile_name"]) +# providing_args = ["attempt_id", "user_id", "status", "full_name", "profile_name"] +idv_update_signal = Signal() @receiver(SignalHandler.course_published) diff --git a/lms/djangoapps/verify_student/tests/test_services.py b/lms/djangoapps/verify_student/tests/test_services.py index bf83f1e9ef..2173c2c532 100644 --- a/lms/djangoapps/verify_student/tests/test_services.py +++ b/lms/djangoapps/verify_student/tests/test_services.py @@ -9,7 +9,7 @@ import ddt from django.conf import settings from django.test import TestCase from django.utils.timezone import now -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from freezegun import freeze_time from pytz import utc diff --git a/lms/djangoapps/verify_student/urls.py b/lms/djangoapps/verify_student/urls.py index 7009a6ecd9..6438eea73e 100644 --- a/lms/djangoapps/verify_student/urls.py +++ b/lms/djangoapps/verify_student/urls.py @@ -4,7 +4,7 @@ URL definitions for the verify_student app. from django.conf import settings -from django.conf.urls import url +from django.urls import path, re_path from lms.djangoapps.verify_student import views @@ -14,7 +14,7 @@ urlpatterns = [ # The user is starting the verification / payment process, # most likely after enrolling in a course and selecting # a "verified" track. - url( + re_path( fr'^start-flow/{settings.COURSE_ID_PATTERN}/$', # Pylint seems to dislike the as_view() method because as_view() is # decorated with `classonlymethod` instead of `classmethod`. @@ -26,7 +26,7 @@ urlpatterns = [ ), # This is for A/B testing. - url( + re_path( fr'^begin-flow/{settings.COURSE_ID_PATTERN}/$', views.PayAndVerifyView.as_view(), name="verify_student_begin_flow", @@ -38,7 +38,7 @@ urlpatterns = [ # The user is enrolled in a non-paid mode and wants to upgrade. # This is the same as the "start verification" flow, # except with slight messaging changes. - url( + re_path( fr'^upgrade/{settings.COURSE_ID_PATTERN}/$', views.PayAndVerifyView.as_view(), name="verify_student_upgrade_and_verify", @@ -53,7 +53,7 @@ urlpatterns = [ # from the verification step. # Note that if the user has already verified, this will redirect # to the dashboard. - url( + re_path( fr'^verify-now/{settings.COURSE_ID_PATTERN}/$', views.PayAndVerifyView.as_view(), name="verify_student_verify_now", @@ -64,26 +64,26 @@ urlpatterns = [ } ), - url( - r'^create_order', + path( + 'create_order', views.create_order, name="verify_student_create_order" ), - url( - r'^results_callback$', + path( + 'results_callback', views.results_callback, name="verify_student_results_callback", ), - url( - r'^submit-photos/$', + path( + 'submit-photos/', views.SubmitPhotosView.as_view(), name="verify_student_submit_photos" ), - url( - r'^status/$', + path( + 'status/', views.VerificationStatusAPIView.as_view(), name="verification_status_api" ), @@ -95,25 +95,25 @@ urlpatterns = [ # new photos. This is different than *in-course* reverification, # in which a student submits only face photos, which are matched # against the ID photo from the user's initial verification attempt. - url( - r'^reverify$', + path( + 'reverify', views.ReverifyView.as_view(), name="verify_student_reverify" ), - url( + re_path( fr'^photo-urls/{IDV_RECEIPT_ID_PATTERN}$', views.PhotoUrlsView.as_view(), name="verification_photo_urls" ), - url( + re_path( fr'^decrypt-idv-images/face/{IDV_RECEIPT_ID_PATTERN}$', views.DecryptFaceImageView.as_view(), name="verification_decrypt_face_image" ), - url( + re_path( fr'^decrypt-idv-images/photo-id/{IDV_RECEIPT_ID_PATTERN}$', views.DecryptPhotoIDImageView.as_view(), name="verification_decrypt_photo_id_image" @@ -124,5 +124,5 @@ urlpatterns = [ if settings.FEATURES.get('ENABLE_SOFTWARE_SECURE_FAKE'): from lms.djangoapps.verify_student.tests.fake_software_secure import SoftwareSecureFakeView urlpatterns += [ - url(r'^software-secure-fake-response', SoftwareSecureFakeView.as_view()), + path('software-secure-fake-response', SoftwareSecureFakeView.as_view()), ] diff --git a/lms/djangoapps/verify_student/views.py b/lms/djangoapps/verify_student/views.py index 17f683cb75..7dfb1c229f 100644 --- a/lms/djangoapps/verify_student/views.py +++ b/lms/djangoapps/verify_student/views.py @@ -16,8 +16,8 @@ from django.shortcuts import redirect from django.urls import reverse from django.utils.decorators import method_decorator from django.utils.timezone import now -from django.utils.translation import ugettext as _ -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext as _ +from django.utils.translation import gettext_lazy from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_POST from django.views.generic.base import View @@ -139,12 +139,12 @@ class PayAndVerifyView(View): ] STEP_TITLES = { - INTRO_STEP: ugettext_lazy("Intro"), - MAKE_PAYMENT_STEP: ugettext_lazy("Make payment"), - FACE_PHOTO_STEP: ugettext_lazy("Take photo"), - ID_PHOTO_STEP: ugettext_lazy("Take a photo of your ID"), - REVIEW_PHOTOS_STEP: ugettext_lazy("Review your info"), - ENROLLMENT_CONFIRMATION_STEP: ugettext_lazy("Enrollment confirmation"), + INTRO_STEP: gettext_lazy("Intro"), + MAKE_PAYMENT_STEP: gettext_lazy("Make payment"), + FACE_PHOTO_STEP: gettext_lazy("Take photo"), + ID_PHOTO_STEP: gettext_lazy("Take a photo of your ID"), + REVIEW_PHOTOS_STEP: gettext_lazy("Review your info"), + ENROLLMENT_CONFIRMATION_STEP: gettext_lazy("Enrollment confirmation"), } # Messages diff --git a/lms/envs/bok_choy.py b/lms/envs/bok_choy.py index bfba37685b..431feb6e31 100644 --- a/lms/envs/bok_choy.py +++ b/lms/envs/bok_choy.py @@ -16,7 +16,7 @@ import logging import os from tempfile import mkdtemp -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext_lazy from path import Path as path from openedx.core.release import RELEASE_LINE @@ -57,8 +57,8 @@ update_module_store_settings( default_store=os.environ.get('DEFAULT_STORE', 'draft'), ) -PLATFORM_NAME = ugettext_lazy("édX") -PLATFORM_DESCRIPTION = ugettext_lazy("Open édX Platform") +PLATFORM_NAME = gettext_lazy("édX") +PLATFORM_DESCRIPTION = gettext_lazy("Open édX Platform") ############################ STATIC FILES ############################# diff --git a/lms/envs/common.py b/lms/envs/common.py index 5014f095ff..fa902bf7b2 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -35,7 +35,7 @@ import os import django from corsheaders.defaults import default_headers as corsheaders_default_headers from path import Path as path -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from enterprise.constants import ( ENTERPRISE_ADMIN_ROLE, ENTERPRISE_CATALOG_ADMIN_ROLE, diff --git a/lms/envs/test.py b/lms/envs/test.py index d43db2672c..8b788d1ef7 100644 --- a/lms/envs/test.py +++ b/lms/envs/test.py @@ -18,7 +18,7 @@ from collections import OrderedDict from uuid import uuid4 import openid.oidutil -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext_lazy from edx_django_utils.plugins import add_plugins from path import Path as path @@ -377,8 +377,8 @@ openid.oidutil.log = lambda message, level=0: None # Include a non-ascii character in PLATFORM_NAME and PLATFORM_DESCRIPTION to uncover possible # UnicodeEncodeErrors in tests. Also use lazy text to reveal possible json dumps errors -PLATFORM_NAME = ugettext_lazy("édX") -PLATFORM_DESCRIPTION = ugettext_lazy("Open édX Platform") +PLATFORM_NAME = gettext_lazy("édX") +PLATFORM_DESCRIPTION = gettext_lazy("Open édX Platform") SITE_NAME = "edx.org" diff --git a/lms/urls.py b/lms/urls.py index 01e1e87d14..62e5924be1 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -4,11 +4,11 @@ URLs for LMS from config_models.views import ConfigurationModelCurrentAPIView from django.conf import settings -from django.conf.urls import include, url +from django.urls import include, re_path from django.conf.urls.static import static from django.contrib.admin import autodiscover as django_autodiscover from django.urls import path -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django.views.generic.base import RedirectView from edx_api_doc_tools import make_docs_urls from edx_django_utils.plugins import get_plugin_url_patterns @@ -76,17 +76,17 @@ handler429 = static_template_view_views.render_429 handler500 = static_template_view_views.render_500 notification_prefs_urls = [ - url(r'^notification_prefs/enable/', notification_prefs_views.ajax_enable), - url(r'^notification_prefs/disable/', notification_prefs_views.ajax_disable), - url(r'^notification_prefs/status/', notification_prefs_views.ajax_status), + path('notification_prefs/enable/', notification_prefs_views.ajax_enable), + path('notification_prefs/disable/', notification_prefs_views.ajax_disable), + path('notification_prefs/status/', notification_prefs_views.ajax_status), - url( + re_path( r'^notification_prefs/unsubscribe/(?P[a-zA-Z0-9-_=]+)/', notification_prefs_views.set_subscription, {'subscribe': False}, name='unsubscribe_forum_update', ), - url( + re_path( r'^notification_prefs/resubscribe/(?P[a-zA-Z0-9-_=]+)/', notification_prefs_views.set_subscription, {'subscribe': True}, @@ -96,32 +96,32 @@ notification_prefs_urls = [ urlpatterns = [ - url(r'^$', branding_views.index, name='root'), # Main marketing page, or redirect to courseware + path('', branding_views.index, name='root'), # Main marketing page, or redirect to courseware - url(r'', include('common.djangoapps.student.urls')), + path('', include('common.djangoapps.student.urls')), # TODO: Move lms specific student views out of common code - url(r'^dashboard/?$', student_views.student_dashboard, name='dashboard'), - url(r'^change_enrollment$', student_views.change_enrollment, name='change_enrollment'), + re_path(r'^dashboard/?$', student_views.student_dashboard, name='dashboard'), + path('change_enrollment', student_views.change_enrollment, name='change_enrollment'), # Event tracking endpoints - url(r'', include('common.djangoapps.track.urls')), + path('', include('common.djangoapps.track.urls')), # Static template view endpoints like blog, faq, etc. - url(r'', include('lms.djangoapps.static_template_view.urls')), + path('', include('lms.djangoapps.static_template_view.urls')), - url(r'^heartbeat', include('openedx.core.djangoapps.heartbeat.urls')), + path('heartbeat', include('openedx.core.djangoapps.heartbeat.urls')), - url(r'^i18n/', include('django.conf.urls.i18n')), + path('i18n/', include('django.conf.urls.i18n')), # Enrollment API RESTful endpoints - url(r'^api/enrollment/v1/', include('openedx.core.djangoapps.enrollments.urls')), + path('api/enrollment/v1/', include('openedx.core.djangoapps.enrollments.urls')), # Agreements API RESTful endpoints - url(r'^api/agreements/v1/', include('openedx.core.djangoapps.agreements.urls')), + path('api/agreements/v1/', include('openedx.core.djangoapps.agreements.urls')), # Entitlement API RESTful endpoints - url( - r'^api/entitlements/', + path( + 'api/entitlements/', include( ('common.djangoapps.entitlements.rest_api.urls', 'common.djangoapps.entitlements'), namespace='entitlements_api', @@ -129,81 +129,81 @@ urlpatterns = [ ), # Demographics API RESTful endpoints - url(r'^api/demographics/', include('openedx.core.djangoapps.demographics.rest_api.urls')), + path('api/demographics/', include('openedx.core.djangoapps.demographics.rest_api.urls')), # Courseware search endpoints - url(r'^search/', include('search.urls')), + path('search/', include('search.urls')), # Course API - url(r'^api/courses/', include('lms.djangoapps.course_api.urls')), + path('api/courses/', include('lms.djangoapps.course_api.urls')), # User API endpoints - url(r'^api/user/', include('openedx.core.djangoapps.user_api.urls')), + path('api/user/', include('openedx.core.djangoapps.user_api.urls')), # Note: these are older versions of the User API that will eventually be # subsumed by api/user listed above. - url(r'', include('openedx.core.djangoapps.user_api.legacy_urls')), + path('', include('openedx.core.djangoapps.user_api.legacy_urls')), # Profile Images API endpoints - url(r'^api/profile_images/', include('openedx.core.djangoapps.profile_images.urls')), + path('api/profile_images/', include('openedx.core.djangoapps.profile_images.urls')), # Video Abstraction Layer used to allow video teams to manage video assets # independently of courseware. https://github.com/edx/edx-val - url(r'^api/val/v0/', include('edxval.urls')), + path('api/val/v0/', include('edxval.urls')), - url( - r'^api/commerce/', + path( + 'api/commerce/', include( ('lms.djangoapps.commerce.api.urls', 'lms.djangoapps.commerce'), namespace='commerce_api', ), ), - url(r'^api/credit/', include('openedx.core.djangoapps.credit.urls')), - url(r'^api/toggles/', include('openedx.core.djangoapps.waffle_utils.urls')), - url(r'^rss_proxy/', include('lms.djangoapps.rss_proxy.urls')), - url(r'^api/organizations/', include('organizations.urls', namespace='organizations')), + path('api/credit/', include('openedx.core.djangoapps.credit.urls')), + path('api/toggles/', include('openedx.core.djangoapps.waffle_utils.urls')), + path('rss_proxy/', include('lms.djangoapps.rss_proxy.urls')), + path('api/organizations/', include('organizations.urls', namespace='organizations')), - url(r'^catalog/', include(('openedx.core.djangoapps.catalog.urls', 'openedx.core.djangoapps.catalog'), - namespace='catalog')), + path('catalog/', include(('openedx.core.djangoapps.catalog.urls', 'openedx.core.djangoapps.catalog'), + namespace='catalog')), # Update session view - url(r'^lang_pref/session_language', lang_pref_views.update_session_language, name='session_language'), + path('lang_pref/session_language', lang_pref_views.update_session_language, name='session_language'), # Multiple course modes and identity verification - url( - r'^course_modes/', + path( + 'course_modes/', include('common.djangoapps.course_modes.urls'), ), - url( - r'^api/course_modes/', + path( + 'api/course_modes/', include( ('common.djangoapps.course_modes.rest_api.urls', 'common.djangoapps.course_mods'), namespace='course_modes_api', ) ), - url(r'^verify_student/', include('lms.djangoapps.verify_student.urls')), + path('verify_student/', include('lms.djangoapps.verify_student.urls')), # URLs for managing dark launches of languages - url(r'^update_lang/', include(('openedx.core.djangoapps.dark_lang.urls', 'openedx.core.djangoapps.dark_lang'), - namespace='dark_lang')), + path('update_lang/', include(('openedx.core.djangoapps.dark_lang.urls', 'openedx.core.djangoapps.dark_lang'), + namespace='dark_lang')), # For redirecting to help pages. - url(r'^help_token/', include('help_tokens.urls')), + path('help_token/', include('help_tokens.urls')), # URLs for API access management - url(r'^api-admin/', include(('openedx.core.djangoapps.api_admin.urls', 'openedx.core.djangoapps.api_admin'), - namespace='api_admin')), + path('api-admin/', include(('openedx.core.djangoapps.api_admin.urls', 'openedx.core.djangoapps.api_admin'), + namespace='api_admin')), - url(r'^dashboard/', include('lms.djangoapps.learner_dashboard.urls')), - url( - r'^api/experiments/', + path('dashboard/', include('lms.djangoapps.learner_dashboard.urls')), + path( + 'api/experiments/', include( ('lms.djangoapps.experiments.urls', 'lms.djangoapps.experiments'), namespace='api_experiments', ), ), - url(r'^api/discounts/', include(('openedx.features.discounts.urls', 'openedx.features.discounts'), - namespace='api_discounts')), + path('api/discounts/', include(('openedx.features.discounts.urls', 'openedx.features.discounts'), + namespace='api_discounts')), path('403', handler403), path('404', handler404), path('429', handler429), @@ -212,26 +212,26 @@ urlpatterns = [ if settings.FEATURES.get('ENABLE_MOBILE_REST_API'): urlpatterns += [ - url(r'^api/mobile/(?Pv(1|0.5))/', include('lms.djangoapps.mobile_api.urls')), + re_path(r'^api/mobile/(?Pv(1|0.5))/', include('lms.djangoapps.mobile_api.urls')), ] if settings.FEATURES.get('ENABLE_OPENBADGES'): urlpatterns += [ - url(r'^api/badges/v1/', include(('lms.djangoapps.badges.api.urls', 'badges'), namespace='badges_api')), + path('api/badges/v1/', include(('lms.djangoapps.badges.api.urls', 'badges'), namespace='badges_api')), ] urlpatterns += [ - url(r'^openassessment/fileupload/', include('openassessment.fileupload.urls')), + path('openassessment/fileupload/', include('openassessment.fileupload.urls')), ] urlpatterns += [ - url(r'^support/', include('lms.djangoapps.support.urls')), + path('support/', include('lms.djangoapps.support.urls')), ] # Favicon favicon_path = configuration_helpers.get_value('favicon_path', settings.FAVICON_PATH) # pylint: disable=invalid-name urlpatterns += [ - url(r'^favicon\.ico$', RedirectView.as_view(url=settings.STATIC_URL + favicon_path, permanent=True)), + re_path(r'^favicon\.ico$', RedirectView.as_view(url=settings.STATIC_URL + favicon_path, permanent=True)), ] # Multicourse wiki (Note: wiki urls must be above the courseware ones because of @@ -247,28 +247,28 @@ if settings.WIKI_ENABLED: urlpatterns += [ # First we include views from course_wiki that we use to override the default views. # They come first in the urlpatterns so they get resolved first - url('^wiki/create-root/$', course_wiki_views.root_create, name='root_create'), - url(r'^wiki/', include((wiki_url_patterns, wiki_app_name), namespace='wiki')), - url(r'^notify/', include((notify_url_patterns, notify_app_name), namespace='notify')), + path('wiki/create-root/', course_wiki_views.root_create, name='root_create'), + path('wiki/', include((wiki_url_patterns, wiki_app_name), namespace='wiki')), + path('notify/', include((notify_url_patterns, notify_app_name), namespace='notify')), # These urls are for viewing the wiki in the context of a course. They should # never be returned by a reverse() so they come after the other url patterns - url(fr'^courses/{settings.COURSE_ID_PATTERN}/course_wiki/?$', - course_wiki_views.course_wiki_redirect, name='course_wiki'), - url(fr'^courses/{settings.COURSE_KEY_REGEX}/wiki/', - include((wiki_url_patterns, 'course_wiki_do_not_reverse'), namespace='course_wiki_do_not_reverse')), + re_path(fr'^courses/{settings.COURSE_ID_PATTERN}/course_wiki/?$', + course_wiki_views.course_wiki_redirect, name='course_wiki'), + re_path(fr'^courses/{settings.COURSE_KEY_REGEX}/wiki/', + include((wiki_url_patterns, 'course_wiki_do_not_reverse'), namespace='course_wiki_do_not_reverse')), ] urlpatterns += [ # jump_to URLs for direct access to a location in the course - url( + re_path( r'^courses/{}/jump_to/(?P.*)$'.format( settings.COURSE_ID_PATTERN, ), courseware_views.jump_to, name='jump_to', ), - url( + re_path( r'^courses/{}/jump_to_id/(?P.*)$'.format( settings.COURSE_ID_PATTERN, ), @@ -277,7 +277,7 @@ urlpatterns += [ ), # xblock Handler APIs - url( + re_path( r'^courses/{course_key}/xblock/{usage_key}/handler/(?P[^/]*)(?:/(?P.*))?$'.format( course_key=settings.COURSE_ID_PATTERN, usage_key=settings.USAGE_ID_PATTERN, @@ -285,7 +285,7 @@ urlpatterns += [ handle_xblock_callback, name='xblock_handler', ), - url( + re_path( r'^courses/{course_key}/xblock/{usage_key}/handler_noauth/(?P[^/]*)(?:/(?P.*))?$'.format( course_key=settings.COURSE_ID_PATTERN, usage_key=settings.USAGE_ID_PATTERN, @@ -297,7 +297,7 @@ urlpatterns += [ # xblock View API # (unpublished) API that returns JSON with the HTML fragment and related resources # for the xBlock's requested view. - url( + re_path( r'^courses/{course_key}/xblock/{usage_key}/view/(?P[^/]*)$'.format( course_key=settings.COURSE_ID_PATTERN, usage_key=settings.USAGE_ID_PATTERN, @@ -310,24 +310,24 @@ urlpatterns += [ # URL to provide an HTML view of an xBlock. The view type (e.g., student_view) is # passed as a 'view' parameter to the URL. # Note: This is not an API. Compare this with the xblock_view API above. - url( + re_path( fr'^xblock/{settings.USAGE_KEY_PATTERN}$', courseware_views.render_xblock, name=RENDER_XBLOCK_NAME, ), # xblock Resource URL - url( + re_path( r'xblock/resource/(?P[^/]+)/(?P.*)$', xblock_resource, name='xblock_resource_url', ), # New (Blockstore-based) XBlock REST API - url(r'', include(('openedx.core.djangoapps.xblock.rest_api.urls', 'openedx.core.djangoapps.xblock'), + path('', include(('openedx.core.djangoapps.xblock.rest_api.urls', 'openedx.core.djangoapps.xblock'), namespace='xblock_api')), - url( + re_path( r'^courses/{}/xqueue/(?P[^/]*)/(?P.*?)/(?P[^/]*)$'.format( settings.COURSE_ID_PATTERN, ), @@ -336,30 +336,30 @@ urlpatterns += [ ), # TODO: These views need to be updated before they work - url(r'^calculate$', util_views.calculate), + path('calculate', util_views.calculate), - url( - r'^reset_deadlines$', + path( + 'reset_deadlines', util_views.reset_course_deadlines, name=RESET_COURSE_DEADLINES_NAME, ), - url(r'^courses/?$', branding_views.courses, name='courses'), + re_path(r'^courses/?$', branding_views.courses, name='courses'), # About the course - url( + re_path( r'^courses/{}/about$'.format( settings.COURSE_ID_PATTERN, ), courseware_views.course_about, name='about_course', ), - url( - r'^courses/yt_video_metadata$', + path( + 'courses/yt_video_metadata', courseware_views.yt_video_metadata, name='yt_video_metadata', ), - url( + re_path( r'^courses/{}/enroll_staff$'.format( settings.COURSE_ID_PATTERN, ), @@ -368,14 +368,14 @@ urlpatterns += [ ), # Inside the course - url( + re_path( r'^courses/{}/$'.format( settings.COURSE_ID_PATTERN, ), courseware_views.course_info, name='course_root', ), - url( + re_path( r'^courses/{}/info$'.format( settings.COURSE_ID_PATTERN, ), @@ -383,7 +383,7 @@ urlpatterns += [ name='info', ), # TODO arjun remove when custom tabs in place, see courseware/courses.py - url( + re_path( r'^courses/{}/syllabus$'.format( settings.COURSE_ID_PATTERN, ), @@ -392,7 +392,7 @@ urlpatterns += [ ), # Survey associated with a course - url( + re_path( r'^courses/{}/survey$'.format( settings.COURSE_ID_PATTERN, ), @@ -400,14 +400,14 @@ urlpatterns += [ name='course_survey', ), - url( + re_path( r'^courses/{}/book/(?P\d+)/$'.format( settings.COURSE_ID_PATTERN, ), staticbook_views.index, name='book', ), - url( + re_path( r'^courses/{}/book/(?P\d+)/(?P\d+)$'.format( settings.COURSE_ID_PATTERN, ), @@ -415,14 +415,14 @@ urlpatterns += [ name='book', ), - url( + re_path( r'^courses/{}/pdfbook/(?P\d+)/$'.format( settings.COURSE_ID_PATTERN, ), staticbook_views.pdf_index, name='pdf_book', ), - url( + re_path( r'^courses/{}/pdfbook/(?P\d+)/(?P\d+)$'.format( settings.COURSE_ID_PATTERN, ), @@ -430,14 +430,14 @@ urlpatterns += [ name='pdf_book', ), - url( + re_path( r'^courses/{}/pdfbook/(?P\d+)/chapter/(?P\d+)/$'.format( settings.COURSE_ID_PATTERN, ), staticbook_views.pdf_index, name='pdf_book', ), - url( + re_path( r'^courses/{}/pdfbook/(?P\d+)/chapter/(?P\d+)/(?P\d+)$'.format( settings.COURSE_ID_PATTERN, ), @@ -445,14 +445,14 @@ urlpatterns += [ name='pdf_book', ), - url( + re_path( r'^courses/{}/htmlbook/(?P\d+)/$'.format( settings.COURSE_ID_PATTERN, ), staticbook_views.html_index, name='html_book', ), - url( + re_path( r'^courses/{}/htmlbook/(?P\d+)/chapter/(?P\d+)/$'.format( settings.COURSE_ID_PATTERN, ), @@ -460,28 +460,28 @@ urlpatterns += [ name='html_book', ), - url( + re_path( r'^courses/{}/courseware/?$'.format( settings.COURSE_ID_PATTERN, ), CoursewareIndex.as_view(), name='courseware', ), - url( + re_path( r'^courses/{}/courseware/(?P[^/]*)/$'.format( settings.COURSE_ID_PATTERN, ), CoursewareIndex.as_view(), name='courseware_chapter', ), - url( + re_path( r'^courses/{}/courseware/(?P[^/]*)/(?P
[^/]*)/$'.format( settings.COURSE_ID_PATTERN, ), CoursewareIndex.as_view(), name='courseware_section', ), - url( + re_path( r'^courses/{}/courseware/(?P[^/]*)/(?P
[^/]*)/(?P[^/]*)/?$'.format( settings.COURSE_ID_PATTERN, ), @@ -490,7 +490,7 @@ urlpatterns += [ ), # progress page - url( + re_path( r'^courses/{}/progress$'.format( settings.COURSE_ID_PATTERN, ), @@ -499,7 +499,7 @@ urlpatterns += [ ), # dates page - url( + re_path( r'^courses/{}/dates'.format( settings.COURSE_ID_PATTERN, ), @@ -508,7 +508,7 @@ urlpatterns += [ ), # Takes optional student_id for instructor use--shows profile as that student sees it. - url( + re_path( r'^courses/{}/progress/(?P[^/]*)/$'.format( settings.COURSE_ID_PATTERN, ), @@ -516,7 +516,7 @@ urlpatterns += [ name='student_progress', ), - url( + re_path( r'^programs/{}/about'.format( r'(?P[0-9a-f-]+)', ), @@ -525,7 +525,7 @@ urlpatterns += [ ), # For the instructor - url( + re_path( r'^courses/{}/instructor$'.format( settings.COURSE_ID_PATTERN, ), @@ -533,7 +533,7 @@ urlpatterns += [ name='instructor_dashboard', ), - url( + re_path( r'^courses/{}/set_course_mode_price$'.format( settings.COURSE_ID_PATTERN, ), @@ -542,7 +542,7 @@ urlpatterns += [ ), # Discussions Management - url( + re_path( r'^courses/{}/discussions/settings$'.format( settings.COURSE_KEY_PATTERN, ), @@ -551,61 +551,61 @@ urlpatterns += [ ), # Cohorts management API - url(r'^api/cohorts/', include( + path('api/cohorts/', include( ('openedx.core.djangoapps.course_groups.urls', 'openedx.core.djangoapps.course_groups'), namespace='api_cohorts')), # Cohorts management - url( + re_path( r'^courses/{}/cohorts/settings$'.format( settings.COURSE_KEY_PATTERN, ), course_groups_views.course_cohort_settings_handler, name='course_cohort_settings', ), - url( + re_path( r'^courses/{}/cohorts/(?P[0-9]+)?$'.format( settings.COURSE_KEY_PATTERN, ), course_groups_views.cohort_handler, name='cohorts', ), - url( + re_path( r'^courses/{}/cohorts/(?P[0-9]+)$'.format( settings.COURSE_KEY_PATTERN, ), course_groups_views.users_in_cohort, name='list_cohort', ), - url( + re_path( r'^courses/{}/cohorts/(?P[0-9]+)/add$'.format( settings.COURSE_KEY_PATTERN, ), course_groups_views.add_users_to_cohort, name='add_to_cohort', ), - url( + re_path( r'^courses/{}/cohorts/(?P[0-9]+)/delete$'.format( settings.COURSE_KEY_PATTERN, ), course_groups_views.remove_user_from_cohort, name='remove_from_cohort', ), - url( + re_path( r'^courses/{}/cohorts/debug$'.format( settings.COURSE_KEY_PATTERN, ), course_groups_views.debug_cohort_mgmt, name='debug_cohort_mgmt', ), - url( + re_path( r'^courses/{}/discussion/topics$'.format( settings.COURSE_KEY_PATTERN, ), discussion_views.discussion_topics, name='discussion_topics', ), - url( + re_path( r'^courses/{}/verified_track_content/settings'.format( settings.COURSE_KEY_PATTERN, ), @@ -614,7 +614,7 @@ urlpatterns += [ ), # LTI endpoints listing - url( + re_path( r'^courses/{}/lti_rest_endpoints/'.format( settings.COURSE_ID_PATTERN, ), @@ -623,7 +623,7 @@ urlpatterns += [ ), # Student Notes - url( + re_path( r'^courses/{}/edxnotes/'.format( settings.COURSE_ID_PATTERN, ), @@ -632,19 +632,19 @@ urlpatterns += [ ), # Student Notes API - url( - r'^api/edxnotes/v1/', + path( + 'api/edxnotes/v1/', include('lms.djangoapps.edxnotes.api_urls'), ), # Branding API - url( - r'^api/branding/v1/', + path( + 'api/branding/v1/', include('lms.djangoapps.branding.api_urls') ), # Course experience - url( + re_path( r'^courses/{}/course/'.format( settings.COURSE_ID_PATTERN, ), @@ -652,7 +652,7 @@ urlpatterns += [ ), # Course bookmarks UI in LMS - url( + re_path( r'^courses/{}/bookmarks/'.format( settings.COURSE_ID_PATTERN, ), @@ -660,13 +660,13 @@ urlpatterns += [ ), # Calendar Sync UI in LMS - url( + re_path( fr'^courses/{settings.COURSE_ID_PATTERN}/', include('openedx.features.calendar_sync.urls'), ), # Course search - url( + re_path( r'^courses/{}/search/'.format( settings.COURSE_ID_PATTERN, ), @@ -674,8 +674,8 @@ urlpatterns += [ ), # Learner profile - url( - r'^u/', + path( + 'u/', include('openedx.features.learner_profile.urls'), ), ] @@ -683,11 +683,11 @@ urlpatterns += [ if settings.FEATURES.get('ENABLE_TEAMS'): # Teams endpoints urlpatterns += [ - url( - r'^api/team/', + path( + 'api/team/', include('lms.djangoapps.teams.api_urls') ), - url( + re_path( r'^courses/{}/teams/'.format( settings.COURSE_ID_PATTERN, ), @@ -699,7 +699,7 @@ if settings.FEATURES.get('ENABLE_TEAMS'): # allow course staff to change to student view of courseware if settings.FEATURES.get('ENABLE_MASQUERADE'): urlpatterns += [ - url( + re_path( r'^courses/{}/masquerade$'.format( settings.COURSE_KEY_PATTERN, ), @@ -709,7 +709,7 @@ if settings.FEATURES.get('ENABLE_MASQUERADE'): ] urlpatterns += [ - url( + re_path( r'^courses/{}/generate_user_cert'.format( settings.COURSE_ID_PATTERN, ), @@ -721,11 +721,11 @@ urlpatterns += [ # discussion forums live within courseware, so courseware must be enabled first if settings.FEATURES.get('ENABLE_DISCUSSION_SERVICE'): urlpatterns += [ - url( - r'^api/discussion/', + path( + 'api/discussion/', include('lms.djangoapps.discussion.rest_api.urls') ), - url( + re_path( r'^courses/{}/discussion/'.format( settings.COURSE_ID_PATTERN, ), @@ -737,11 +737,11 @@ if is_forum_daily_digest_enabled(): urlpatterns += notification_prefs_urls urlpatterns += [ - url(r'^bulk_email/', include('lms.djangoapps.bulk_email.urls')), + path('bulk_email/', include('lms.djangoapps.bulk_email.urls')), ] urlpatterns += [ - url( + re_path( r'^courses/{}/tab/(?P[^/]+)/$'.format( settings.COURSE_ID_PATTERN, ), @@ -751,7 +751,7 @@ urlpatterns += [ ] urlpatterns += [ - url( + re_path( r'^courses/{}/lti_tab/(?P[^/]+)/$'.format( settings.COURSE_ID_PATTERN, ), @@ -763,7 +763,7 @@ urlpatterns += [ urlpatterns += [ # This MUST be the last view in the courseware--it's a catch-all for custom tabs. - url( + re_path( r'^courses/{}/(?P[^/]+)/$'.format( settings.COURSE_ID_PATTERN, ), @@ -774,7 +774,7 @@ urlpatterns += [ if settings.FEATURES.get('ENABLE_STUDENT_HISTORY_VIEW'): urlpatterns += [ - url( + re_path( r'^courses/{}/submission_history/(?P[^/]*)/(?P.*?)$'.format( settings.COURSE_ID_PATTERN ), @@ -792,61 +792,61 @@ if settings.DEBUG or settings.FEATURES.get('ENABLE_DJANGO_ADMIN_SITE'): # for backwards compatibility. if not settings.FEATURES.get('ENABLE_CHANGE_USER_PASSWORD_ADMIN'): urlpatterns += [ - url(r'^admin/auth/user/\d+/password/$', handler404), + re_path(r'^admin/auth/user/\d+/password/$', handler404), ] urlpatterns += [ - url(r'^admin/password_change/$', handler404), + path('admin/password_change/', handler404), # We are enforcing users to login through third party auth in site's # login page so we are disabling the admin panel's login page. - url(r'^admin/login/$', redirect_to_lms_login), - url(r'^admin/', admin.site.urls), + path('admin/login/', redirect_to_lms_login), + path('admin/', admin.site.urls), ] if configuration_helpers.get_value('ENABLE_BULK_ENROLLMENT_VIEW', settings.FEATURES.get('ENABLE_BULK_ENROLLMENT_VIEW')): urlpatterns += [ - url(r'^api/bulk_enroll/v1/', include('lms.djangoapps.bulk_enroll.urls')), + path('api/bulk_enroll/v1/', include('lms.djangoapps.bulk_enroll.urls')), ] # Course goals urlpatterns += [ - url(r'^api/course_goals/', include(('lms.djangoapps.course_goals.urls', 'lms.djangoapps.course_goals'), - namespace='course_goals_api')), + path('api/course_goals/', include(('lms.djangoapps.course_goals.urls', 'lms.djangoapps.course_goals'), + namespace='course_goals_api')), ] # Embargo if settings.FEATURES.get('EMBARGO'): urlpatterns += [ - url(r'^embargo/', include(('openedx.core.djangoapps.embargo.urls', 'openedx.core.djangoapps.embargo'), - namespace='embargo')), - url(r'^api/embargo/', include(('openedx.core.djangoapps.embargo.urls', 'openedx.core.djangoapps.embargo'), - namespace='api_embargo')), + path('embargo/', include(('openedx.core.djangoapps.embargo.urls', 'openedx.core.djangoapps.embargo'), + namespace='embargo')), + path('api/embargo/', include(('openedx.core.djangoapps.embargo.urls', 'openedx.core.djangoapps.embargo'), + namespace='api_embargo')), ] # Survey Djangoapp urlpatterns += [ - url(r'^survey/', include('lms.djangoapps.survey.urls')), + path('survey/', include('lms.djangoapps.survey.urls')), ] if settings.FEATURES.get('ENABLE_OAUTH2_PROVIDER'): urlpatterns += [ # These URLs dispatch to django-oauth-toolkit or django-oauth2-provider as appropriate. # Developers should use these routes, to maintain compatibility for existing client code - url(r'^oauth2/', include('openedx.core.djangoapps.oauth_dispatch.urls')), + path('oauth2/', include('openedx.core.djangoapps.oauth_dispatch.urls')), # The /_o/ prefix exists to provide a target for code in django-oauth-toolkit that # uses reverse() with the 'oauth2_provider' namespace. Developers should not access these # views directly, but should rather use the wrapped views at /oauth2/ - url(r'^_o/', include('oauth2_provider.urls', namespace='oauth2_provider')), + path('_o/', include('oauth2_provider.urls', namespace='oauth2_provider')), ] if settings.FEATURES.get('ENABLE_SERVICE_STATUS'): urlpatterns += [ - url(r'^status/', include('openedx.core.djangoapps.service_status.urls')), + path('status/', include('openedx.core.djangoapps.service_status.urls')), ] if settings.FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'): urlpatterns += [ - url( - r'^instructor_task_status/$', + path( + 'instructor_task_status/', instructor_task_views.instructor_task_status, name='instructor_task_status' ), @@ -854,31 +854,31 @@ if settings.FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'): if settings.FEATURES.get('ENABLE_DEBUG_RUN_PYTHON'): urlpatterns += [ - url(r'^debug/run_python$', debug_views.run_python), + path('debug/run_python', debug_views.run_python), ] urlpatterns += [ - url(r'^debug/show_parameters$', debug_views.show_parameters), + path('debug/show_parameters', debug_views.show_parameters), ] # Third-party auth. if settings.FEATURES.get('ENABLE_THIRD_PARTY_AUTH'): urlpatterns += [ - url(r'', include('common.djangoapps.third_party_auth.urls')), - url(r'^api/third_party_auth/', include('common.djangoapps.third_party_auth.api.urls')), + path('', include('common.djangoapps.third_party_auth.urls')), + path('api/third_party_auth/', include('common.djangoapps.third_party_auth.api.urls')), ] # Enterprise if enterprise_enabled(): urlpatterns += [ - url(r'', include('enterprise.urls')), + path('', include('enterprise.urls')), ] # OAuth token exchange if settings.FEATURES.get('ENABLE_OAUTH2_PROVIDER'): urlpatterns += [ - url( - r'^oauth2/login/$', + path( + 'oauth2/login/', LoginWithAccessTokenView.as_view(), name='login_with_access_token' ), @@ -886,38 +886,36 @@ if settings.FEATURES.get('ENABLE_OAUTH2_PROVIDER'): # Certificates urlpatterns += [ - url(r'^certificates/', include('lms.djangoapps.certificates.urls')), + path('certificates/', include('lms.djangoapps.certificates.urls')), # REST APIs - url(r'^api/certificates/', - include(('lms.djangoapps.certificates.apis.urls', 'lms.djangoapps.certificates'), - namespace='certificates_api')), + path('api/certificates/', include(('lms.djangoapps.certificates.apis.urls', 'lms.djangoapps.certificates'), + namespace='certificates_api')), ] # XDomain proxy urlpatterns += [ - url(r'^xdomain_proxy.html$', cors_csrf_views.xdomain_proxy, name='xdomain_proxy'), + re_path(r'^xdomain_proxy.html$', cors_csrf_views.xdomain_proxy, name='xdomain_proxy'), ] # Custom courses on edX (CCX) URLs if settings.FEATURES.get('CUSTOM_COURSES_EDX'): urlpatterns += [ - url(fr'^courses/{settings.COURSE_ID_PATTERN}/', - include('lms.djangoapps.ccx.urls')), - url(r'^api/ccx/', include(('lms.djangoapps.ccx.api.urls', 'lms.djangoapps.ccx'), namespace='ccx_api')), + re_path(fr'^courses/{settings.COURSE_ID_PATTERN}/', include('lms.djangoapps.ccx.urls')), + path('api/ccx/', include(('lms.djangoapps.ccx.api.urls', 'lms.djangoapps.ccx'), namespace='ccx_api')), ] # Access to courseware as an LTI provider if settings.FEATURES.get('ENABLE_LTI_PROVIDER'): urlpatterns += [ - url(r'^lti_provider/', include('lms.djangoapps.lti_provider.urls')), + path('lti_provider/', include('lms.djangoapps.lti_provider.urls')), ] urlpatterns += [ - url(r'^config/self_paced', ConfigurationModelCurrentAPIView.as_view(model=SelfPacedConfiguration)), - url(r'^config/programs', ConfigurationModelCurrentAPIView.as_view(model=ProgramsApiConfig)), - url(r'^config/catalog', ConfigurationModelCurrentAPIView.as_view(model=CatalogIntegration)), - url(r'^config/forums', ConfigurationModelCurrentAPIView.as_view(model=ForumsConfig)), + path('config/self_paced', ConfigurationModelCurrentAPIView.as_view(model=SelfPacedConfiguration)), + path('config/programs', ConfigurationModelCurrentAPIView.as_view(model=ProgramsApiConfig)), + path('config/catalog', ConfigurationModelCurrentAPIView.as_view(model=CatalogIntegration)), + path('config/forums', ConfigurationModelCurrentAPIView.as_view(model=ForumsConfig)), ] if settings.DEBUG: @@ -931,30 +929,30 @@ if settings.DEBUG: # UX reference templates urlpatterns += [ - url(r'^template/(?P