From 764319d3e0cbaafa40d1d0b1758aeea843af0624 Mon Sep 17 00:00:00 2001 From: Matthew Piatetsky <mpiatetsky@edx.org> Date: Mon, 4 Feb 2019 14:18:57 -0500 Subject: [PATCH] fix unicode strings in lms/ part 2 --- lms/djangoapps/instructor/access.py | 6 +- lms/djangoapps/instructor/enrollment.py | 9 +- .../paidcourse_enrollment_report.py | 6 +- lms/djangoapps/instructor/services.py | 10 +- lms/djangoapps/instructor/tests/test_api.py | 124 +++++++++--------- .../instructor/tests/test_certificates.py | 6 +- .../instructor/tests/test_ecommerce.py | 24 ++-- .../instructor/tests/test_enrollment.py | 2 +- .../tests/test_registration_codes.py | 6 +- .../instructor/tests/test_services.py | 6 +- .../instructor/tests/test_spoc_gradebook.py | 8 +- .../tests/views/test_instructor_dashboard.py | 12 +- lms/djangoapps/instructor/views/api.py | 108 +++++++-------- lms/djangoapps/instructor/views/coupons.py | 22 ++-- .../instructor/views/instructor_dashboard.py | 14 +- .../views/instructor_task_helpers.py | 14 +- .../instructor/views/registration_codes.py | 8 +- lms/djangoapps/instructor/views/tools.py | 14 +- lms/djangoapps/instructor_analytics/basic.py | 21 +-- lms/djangoapps/instructor_analytics/csvs.py | 2 +- .../instructor_analytics/distributions.py | 4 +- .../instructor_analytics/tests/test_basic.py | 12 +- .../instructor_analytics/tests/test_csvs.py | 8 +- lms/djangoapps/instructor_task/api.py | 2 +- lms/djangoapps/instructor_task/api_helper.py | 16 +-- lms/djangoapps/instructor_task/models.py | 4 +- lms/djangoapps/instructor_task/subtasks.py | 28 ++-- lms/djangoapps/instructor_task/tasks_base.py | 2 +- .../tasks_helper/module_state.py | 8 +- .../instructor_task/tests/test_base.py | 2 +- .../instructor_task/tests/test_integration.py | 6 +- .../instructor_task/tests/test_tasks.py | 2 +- .../tests/test_tasks_helper.py | 14 +- .../instructor_task/tests/test_views.py | 4 +- lms/djangoapps/instructor_task/views.py | 42 +++--- .../learner_dashboard/tests/test_programs.py | 4 +- lms/djangoapps/lms_xblock/mixin.py | 2 +- lms/djangoapps/lms_xblock/runtime.py | 6 +- lms/djangoapps/lti_provider/outcomes.py | 18 +-- lms/djangoapps/lti_provider/signals.py | 2 +- lms/djangoapps/lti_provider/tasks.py | 2 +- .../lti_provider/tests/test_outcomes.py | 2 +- .../lti_provider/tests/test_users.py | 2 +- lms/djangoapps/lti_provider/views.py | 2 +- .../management/commands/mailchimp_id.py | 6 +- .../commands/mailchimp_sync_course.py | 6 +- .../mobile_api/video_outlines/views.py | 2 +- lms/djangoapps/notes/api.py | 12 +- lms/djangoapps/rss_proxy/views.py | 2 +- lms/djangoapps/shoppingcart/admin.py | 4 +- .../management/commands/retire_order.py | 4 +- lms/djangoapps/shoppingcart/models.py | 52 ++++---- lms/djangoapps/shoppingcart/pdf.py | 6 +- .../shoppingcart/processors/CyberSource2.py | 47 +++---- .../processors/tests/test_CyberSource2.py | 6 +- lms/djangoapps/shoppingcart/tests/test_pdf.py | 2 +- .../shoppingcart/tests/test_reports.py | 3 +- .../shoppingcart/tests/test_views.py | 67 ++++++---- lms/djangoapps/shoppingcart/views.py | 22 ++-- .../static_template_view/tests/test_views.py | 2 +- lms/djangoapps/staticbook/views.py | 6 +- lms/djangoapps/support/tests/test_refund.py | 4 +- lms/djangoapps/support/views/refund.py | 8 +- lms/djangoapps/survey/models.py | 7 +- .../tests/test_reindex_course_team.py | 2 +- lms/djangoapps/teams/models.py | 2 +- lms/djangoapps/teams/search_indexes.py | 2 +- lms/djangoapps/teams/tests/factories.py | 2 +- lms/djangoapps/teams/tests/test_views.py | 18 ++- lms/djangoapps/teams/views.py | 18 +-- .../commands/manual_verifications.py | 4 +- .../retry_failed_photo_verifications.py | 6 +- lms/djangoapps/verify_student/models.py | 20 +-- lms/djangoapps/verify_student/services.py | 2 +- lms/djangoapps/verify_student/ssencrypt.py | 6 +- lms/djangoapps/verify_student/tasks.py | 2 +- .../tests/fake_software_secure.py | 2 +- .../verify_student/tests/test_models.py | 2 +- .../verify_student/tests/test_views.py | 6 +- lms/djangoapps/verify_student/views.py | 42 +++--- lms/envs/aws.py | 2 +- lms/envs/common.py | 22 ++-- lms/envs/devstack.py | 3 +- lms/envs/production.py | 2 +- lms/envs/test.py | 4 +- lms/lib/comment_client/models.py | 12 +- lms/templates/shoppingcart/receipt.html | 35 ++--- 87 files changed, 560 insertions(+), 540 deletions(-) diff --git a/lms/djangoapps/instructor/access.py b/lms/djangoapps/instructor/access.py index f20a89ae204..eb38818e967 100644 --- a/lms/djangoapps/instructor/access.py +++ b/lms/djangoapps/instructor/access.py @@ -67,7 +67,7 @@ def _change_access(course, user, level, action, send_email=True): try: role = ROLES[level](course.id) except KeyError: - raise ValueError("unrecognized level '{}'".format(level)) + raise ValueError(u"unrecognized level '{}'".format(level)) if action == 'allow': if level == 'ccx_coach': @@ -83,7 +83,7 @@ def _change_access(course, user, level, action, send_email=True): elif action == 'revoke': role.remove_users(user) else: - raise ValueError("unrecognized action '{}'".format(action)) + raise ValueError(u"unrecognized action '{}'".format(action)) def update_forum_role(course_id, user, rolename, action): @@ -103,4 +103,4 @@ def update_forum_role(course_id, user, rolename, action): elif action == 'revoke': role.users.remove(user) else: - raise ValueError("unrecognized action '{}'".format(action)) + raise ValueError(u"unrecognized action '{}'".format(action)) diff --git a/lms/djangoapps/instructor/enrollment.py b/lms/djangoapps/instructor/enrollment.py index ed599886c51..4a62821c06f 100644 --- a/lms/djangoapps/instructor/enrollment.py +++ b/lms/djangoapps/instructor/enrollment.py @@ -44,6 +44,7 @@ from student.models import ( anonymous_id_for_user, is_email_retired, ) +from openedx.core.djangolib.markup import Text from submissions import api as sub_api # installed from the edx-submissions repository from submissions.models import score_set from track.event_transaction_utils import ( @@ -223,7 +224,7 @@ def send_beta_role_email(action, user, email_params): email_params['email_address'] = user.email email_params['full_name'] = user.profile.name else: - raise ValueError("Unexpected action received '{}' - expected 'add' or 'remove'".format(action)) + raise ValueError(u"Unexpected action received '{}' - expected 'add' or 'remove'".format(action)) trying_to_add_inactive_user = not user.is_active and action == 'add' if not trying_to_add_inactive_user: send_mail_to_student(user.email, email_params, language=get_user_email_language(user)) @@ -274,7 +275,7 @@ def reset_student_attempts(course_id, student, module_state_key, requesting_user submission_cleared = True except ItemNotFoundError: block = None - log.warning("Could not find %s in modulestore when attempting to reset attempts.", module_state_key) + log.warning(u"Could not find %s in modulestore when attempting to reset attempts.", module_state_key) # Reset the student's score in the submissions API, if xblock.clear_student_state has not done so already. # We need to do this before retrieving the `StudentModule` model, because a score may exist with no student module. @@ -375,7 +376,7 @@ def get_email_params(course, auto_enroll, secure=True, course_key=None, display_ protocol = 'https' if secure else 'http' course_key = course_key or text_type(course.id) - display_name = display_name or course.display_name_with_default_escaped + display_name = display_name or Text(course.display_name_with_default) stripped_site_name = configuration_helpers.get_value( 'SITE_NAME', @@ -449,7 +450,7 @@ def send_mail_to_student(student, param_dict, language=None): if 'display_name' in param_dict: param_dict['course_name'] = param_dict['display_name'] elif 'course' in param_dict: - param_dict['course_name'] = param_dict['course'].display_name_with_default + param_dict['course_name'] = Text(param_dict['course'].display_name_with_default) param_dict['site_name'] = configuration_helpers.get_value( 'SITE_NAME', diff --git a/lms/djangoapps/instructor/paidcourse_enrollment_report.py b/lms/djangoapps/instructor/paidcourse_enrollment_report.py index d9fae3ce15c..189946f2189 100644 --- a/lms/djangoapps/instructor/paidcourse_enrollment_report.py +++ b/lms/djangoapps/instructor/paidcourse_enrollment_report.py @@ -37,7 +37,7 @@ class PaidCourseEnrollmentReportProvider(BaseAbstractEnrollmentReportProvider): # check the user enrollment role if user.is_staff: platform_name = configuration_helpers.get_value('platform_name', settings.PLATFORM_NAME) - enrollment_role = _('{platform_name} Staff').format(platform_name=platform_name) + enrollment_role = _(u'{platform_name} Staff').format(platform_name=platform_name) elif is_course_staff: enrollment_role = _('Course Staff') else: @@ -67,14 +67,14 @@ class PaidCourseEnrollmentReportProvider(BaseAbstractEnrollmentReportProvider): manual_enrollment = ManualEnrollmentAudit.get_manual_enrollment(course_enrollment) if manual_enrollment is not None: enrollment_source = _( - 'manually enrolled by username: {username}' + u'manually enrolled by username: {username}' ).format(username=manual_enrollment.enrolled_by.username) manual_enrollment_reason = manual_enrollment.reason else: enrollment_source = _('Manually Enrolled') - enrollment_date = course_enrollment.created.strftime("%B %d, %Y") + enrollment_date = course_enrollment.created.strftime(u"%B %d, %Y") currently_enrolled = course_enrollment.is_active course_enrollment_data = collections.OrderedDict() diff --git a/lms/djangoapps/instructor/services.py b/lms/djangoapps/instructor/services.py index 8947cef23a6..b0b73841732 100644 --- a/lms/djangoapps/instructor/services.py +++ b/lms/djangoapps/instructor/services.py @@ -44,7 +44,7 @@ class InstructorService(object): except ObjectDoesNotExist: err_msg = ( 'Error occurred while attempting to reset student attempts for user ' - '{student_identifier} for content_id {content_id}. ' + u'{student_identifier} for content_id {content_id}. ' 'User does not exist!'.format( student_identifier=student_identifier, content_id=content_id @@ -57,7 +57,7 @@ class InstructorService(object): module_state_key = UsageKey.from_string(content_id) except InvalidKeyError: err_msg = ( - 'Invalid content_id {content_id}!'.format(content_id=content_id) + u'Invalid content_id {content_id}!'.format(content_id=content_id) ) log.error(err_msg) return @@ -74,7 +74,7 @@ class InstructorService(object): except (StudentModule.DoesNotExist, enrollment.sub_api.SubmissionError): err_msg = ( 'Error occurred while attempting to reset student attempts for user ' - '{student_identifier} for content_id {content_id}.'.format( + u'{student_identifier} for content_id {content_id}.'.format( student_identifier=student_identifier, content_id=content_id ) @@ -106,8 +106,8 @@ class InstructorService(object): subject = _(u"Proctored Exam Review: {review_status}").format(review_status=review_status) body = _( u"A proctored exam attempt for {exam_name} in {course_name} by username: {student_username} " - "was reviewed as {review_status} by the proctored exam review provider.\n" - "Review link: {review_url}" + u"was reviewed as {review_status} by the proctored exam review provider.\n" + u"Review link: {review_url}" ).format( exam_name=exam_name, course_name=course.display_name, diff --git a/lms/djangoapps/instructor/tests/test_api.py b/lms/djangoapps/instructor/tests/test_api.py index d43a3ca5fb6..e875c7e6629 100644 --- a/lms/djangoapps/instructor/tests/test_api.py +++ b/lms/djangoapps/instructor/tests/test_api.py @@ -234,7 +234,7 @@ def reverse(endpoint, args=None, kwargs=None, is_dashboard_endpoint=True): if is_dashboard_endpoint and is_endpoint_declared is False: # Verify that all endpoints are declared so we can ensure they are # properly validated elsewhere. - raise ValueError("The endpoint {} must be declared in ENDPOINTS before use.".format(endpoint)) + raise ValueError(u"The endpoint {} must be declared in ENDPOINTS before use.".format(endpoint)) return django_reverse(endpoint, args=args, kwargs=kwargs) @@ -359,7 +359,7 @@ class TestEndpointHttpMethods(SharedModuleStoreTestCase, LoginEnrollmentTestCase self.assertEqual( response.status_code, 405, - "Endpoint {} returned status code {} instead of a 405. It should not allow GET.".format( + u"Endpoint {} returned status code {} instead of a 405. It should not allow GET.".format( data, response.status_code ) ) @@ -374,7 +374,7 @@ class TestEndpointHttpMethods(SharedModuleStoreTestCase, LoginEnrollmentTestCase self.assertNotEqual( response.status_code, 405, - "Endpoint {} returned status code 405 where it shouldn't, since it should allow GET.".format( + u"Endpoint {} returned status code 405 where it shouldn't, since it should allow GET.".format( data ) ) @@ -690,7 +690,7 @@ class TestInstructorAPIBulkAccountCreationAndEnrollment(SharedModuleStoreTestCas self.assertEqual(manual_enrollments[0].state_transition, UNENROLLED_TO_ENROLLED) # test the log for email that's send to new created user. - info_log.assert_called_with('email sent to new created user at %s', 'test_student@example.com') + info_log.assert_called_with(u'email sent to new created user at %s', 'test_student@example.com') @patch('lms.djangoapps.instructor.views.api.log.info') def test_account_creation_and_enrollment_with_csv_with_blank_lines(self, info_log): @@ -711,7 +711,7 @@ class TestInstructorAPIBulkAccountCreationAndEnrollment(SharedModuleStoreTestCas self.assertEqual(manual_enrollments[0].state_transition, UNENROLLED_TO_ENROLLED) # test the log for email that's send to new created user. - info_log.assert_called_with('email sent to new created user at %s', 'test_student@example.com') + info_log.assert_called_with(u'email sent to new created user at %s', 'test_student@example.com') @patch('lms.djangoapps.instructor.views.api.log.info') def test_email_and_username_already_exist(self, info_log): @@ -798,7 +798,7 @@ class TestInstructorAPIBulkAccountCreationAndEnrollment(SharedModuleStoreTestCas self.assertNotEquals(len(data['row_errors']), 0) self.assertEquals(len(data['warnings']), 0) self.assertEquals(len(data['general_errors']), 0) - self.assertEquals(data['row_errors'][0]['response'], 'Invalid email {0}.'.format('test_student.example.com')) + self.assertEquals(data['row_errors'][0]['response'], u'Invalid email {0}.'.format('test_student.example.com')) manual_enrollments = ManualEnrollmentAudit.objects.all() self.assertEqual(manual_enrollments.count(), 0) @@ -835,8 +835,8 @@ class TestInstructorAPIBulkAccountCreationAndEnrollment(SharedModuleStoreTestCas response = self.client.post(self.url, {'students_list': uploaded_file}) self.assertEqual(response.status_code, 200) data = json.loads(response.content) - warning_message = 'An account with email {email} exists but the provided username {username} ' \ - 'is different. Enrolling anyway with {email}.'.format(email='test_student@example.com', username='test_student_2') + warning_message = u'An account with email {email} exists but the provided username {username} ' \ + u'is different. Enrolling anyway with {email}.'.format(email='test_student@example.com', username='test_student_2') self.assertNotEquals(len(data['warnings']), 0) self.assertEquals(data['warnings'][0]['response'], warning_message) user = User.objects.get(email='test_student@example.com') @@ -872,7 +872,7 @@ class TestInstructorAPIBulkAccountCreationAndEnrollment(SharedModuleStoreTestCas self.assertNotEquals(len(data['row_errors']), 0) self.assertEquals( data['row_errors'][0]['response'], - 'Invalid email {email}.'.format(email=conflicting_email) + u'Invalid email {email}.'.format(email=conflicting_email) ) self.assertFalse(User.objects.filter(email=conflicting_email).exists()) @@ -890,7 +890,7 @@ class TestInstructorAPIBulkAccountCreationAndEnrollment(SharedModuleStoreTestCas self.assertEqual(response.status_code, 200) data = json.loads(response.content) self.assertNotEquals(len(data['row_errors']), 0) - self.assertEquals(data['row_errors'][0]['response'], 'Username {user} already exists.'.format(user='test_student_1')) + self.assertEquals(data['row_errors'][0]['response'], u'Username {user} already exists.'.format(user='test_student_1')) def test_csv_file_not_attached(self): """ @@ -960,11 +960,11 @@ class TestInstructorAPIBulkAccountCreationAndEnrollment(SharedModuleStoreTestCas self.assertNotEquals(len(data['row_errors']), 0) self.assertEquals( data['row_errors'][0]['response'], - 'Username {user} already exists.'.format(user='test_student_1') + u'Username {user} already exists.'.format(user='test_student_1') ) self.assertEquals( data['row_errors'][1]['response'], - 'Invalid email {email}.'.format(email='test_student4@example.com') + u'Invalid email {email}.'.format(email='test_student4@example.com') ) self.assertTrue(User.objects.filter(username='test_student_1', email='test_student1@example.com').exists()) self.assertTrue(User.objects.filter(username='test_student_2', email='test_student2@example.com').exists()) @@ -1221,7 +1221,7 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest url = reverse('students_update_enrollment', kwargs={'course_id': text_type(self.course.id)}) response = self.client.post(url, {'identifiers': self.notenrolled_student.email, 'action': 'enroll', 'email_students': False}) - print("type(self.notenrolled_student.email): {}".format(type(self.notenrolled_student.email))) + print(u"type(self.notenrolled_student.email): {}".format(type(self.notenrolled_student.email))) self.assertEqual(response.status_code, 200) # test that the user is now enrolled @@ -1267,7 +1267,7 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest environ = {'wsgi.url_scheme': protocol} response = self.client.post(url, params, **environ) - print("type(self.notenrolled_student.email): {}".format(type(self.notenrolled_student.email))) + print(u"type(self.notenrolled_student.email): {}".format(type(self.notenrolled_student.email))) self.assertEqual(response.status_code, 200) # test that the user is now enrolled @@ -1313,7 +1313,7 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest assert text_body.startswith('Dear NotEnrolled Student\n\n') for body in [text_body, html_body]: - self.assertIn('You have been enrolled in {course_name} at edx.org by a member of the course staff.'.format( + self.assertIn(u'You have been enrolled in {course_name} at edx.org by a member of the course staff.'.format( course_name=self.course.display_name, ), body) @@ -1350,14 +1350,14 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest register_url = '{proto}://{site}/register'.format(proto=protocol, site=self.site_name) assert text_body.startswith('Dear student,') - assert 'To finish your registration, please visit {register_url}'.format( + assert u'To finish your registration, please visit {register_url}'.format( register_url=register_url, ) in text_body assert 'Please finish your registration and fill out' in html_body assert register_url in html_body for body in [text_body, html_body]: - assert 'You have been invited to join {course} at edx.org by a member of the course staff.'.format( + assert u'You have been invited to join {course} at edx.org by a member of the course staff.'.format( course=self.course.display_name ) in body @@ -1395,7 +1395,7 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest assert 'Please finish your registration and fill' in html_body for body in [text_body, html_body]: - assert 'You have been invited to join {display_name} at edx.org by a member of the course staff.'.format( + assert u'You have been invited to join {display_name} at edx.org by a member of the course staff.'.format( display_name=self.course.display_name ) in body @@ -1407,7 +1407,7 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest assert ('fill out the registration form making sure to use ' 'robot-not-an-email-yet@robot.org in the Email field') in body - assert 'You can then enroll in {display_name}.'.format( + assert u'You can then enroll in {display_name}.'.format( display_name=self.course.display_name ) in body @@ -1420,7 +1420,7 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest 'auto_enroll': True} environ = {'wsgi.url_scheme': protocol} response = self.client.post(url, params, **environ) - print("type(self.notregistered_email): {}".format(type(self.notregistered_email))) + print(u"type(self.notregistered_email): {}".format(type(self.notregistered_email))) self.assertEqual(response.status_code, 200) # Check the outbox @@ -1441,7 +1441,7 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest ) assert text_body.startswith('Dear student,') - assert 'To finish your registration, please visit {register_url}'.format( + assert u'To finish your registration, please visit {register_url}'.format( register_url=register_url, ) in text_body assert 'Please finish your registration and fill out the registration' in html_body @@ -1449,7 +1449,7 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest assert register_url in html_body for body in [text_body, html_body]: - assert 'You have been invited to join {display_name} at edx.org by a member of the course staff.'.format( + assert u'You have been invited to join {display_name} at edx.org by a member of the course staff.'.format( display_name=self.course.display_name ) in body @@ -1457,8 +1457,8 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest 'out the registration form making sure to use robot-not-an-email-yet@robot.org ' 'in the Email field') in body - assert ('Once you have registered and activated your account, ' - 'you will see {display_name} listed on your dashboard.').format( + assert (u'Once you have registered and activated your account, ' + u'you will see {display_name} listed on your dashboard.').format( display_name=self.course.display_name ) in body @@ -1468,7 +1468,7 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest url = reverse('students_update_enrollment', kwargs={'course_id': text_type(self.course.id)}) response = self.client.post(url, {'identifiers': self.enrolled_student.email, 'action': 'unenroll', 'email_students': False}) - print("type(self.enrolled_student.email): {}".format(type(self.enrolled_student.email))) + print(u"type(self.enrolled_student.email): {}".format(type(self.enrolled_student.email))) self.assertEqual(response.status_code, 200) # test that the user is now unenrolled @@ -1511,7 +1511,7 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest url = reverse('students_update_enrollment', kwargs={'course_id': text_type(self.course.id)}) response = self.client.post(url, {'identifiers': self.enrolled_student.email, 'action': 'unenroll', 'email_students': True}) - print("type(self.enrolled_student.email): {}".format(type(self.enrolled_student.email))) + print(u"type(self.enrolled_student.email): {}".format(type(self.enrolled_student.email))) self.assertEqual(response.status_code, 200) # test that the user is now unenrolled @@ -1551,7 +1551,7 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest self.assertEqual(len(mail.outbox), 1) self.assertEqual( mail.outbox[0].subject, - 'You have been unenrolled from {display_name}'.format(display_name=self.course.display_name,) + u'You have been unenrolled from {display_name}'.format(display_name=self.course.display_name,) ) text_body = mail.outbox[0].body @@ -1560,7 +1560,7 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest assert text_body.startswith('Dear Enrolled Student') for body in [text_body, html_body]: - assert 'You have been unenrolled from {display_name} at edx.org by a member of the course staff.'.format( + assert u'You have been unenrolled from {display_name} at edx.org by a member of the course staff.'.format( display_name=self.course.display_name, ) in body @@ -1572,7 +1572,7 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest url = reverse('students_update_enrollment', kwargs={'course_id': text_type(self.course.id)}) response = self.client.post(url, {'identifiers': self.allowed_email, 'action': 'unenroll', 'email_students': True}) - print("type(self.allowed_email): {}".format(type(self.allowed_email))) + print(u"type(self.allowed_email): {}".format(type(self.allowed_email))) self.assertEqual(response.status_code, 200) # test the response data @@ -1608,7 +1608,7 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest self.assertEqual(len(mail.outbox), 1) self.assertEqual( mail.outbox[0].subject, - 'You have been unenrolled from {display_name}'.format(display_name=self.course.display_name,) + u'You have been unenrolled from {display_name}'.format(display_name=self.course.display_name,) ) text_body = mail.outbox[0].body @@ -1616,7 +1616,7 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest assert text_body.startswith('Dear Student,') for body in [text_body, html_body]: - assert 'You have been unenrolled from the course {display_name} by a member of the course staff.'.format( + assert u'You have been unenrolled from the course {display_name} by a member of the course staff.'.format( display_name=self.course.display_name, ) in body @@ -1638,7 +1638,7 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest self.assertEqual(len(mail.outbox), 1) self.assertEqual( mail.outbox[0].subject, - 'You have been invited to register for {display_name}'.format(display_name=self.course.display_name,) + u'You have been invited to register for {display_name}'.format(display_name=self.course.display_name,) ) text_body = mail.outbox[0].body @@ -1649,14 +1649,14 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest about_path=self.about_path, ) assert text_body.startswith('Dear student,') - assert 'To access this course visit {course_url} and register for this course.'.format( + assert u'To access this course visit {course_url} and register for this course.'.format( course_url=course_url, ) in text_body assert 'To access this course visit it and register:' in html_body assert course_url in html_body for body in [text_body, html_body]: - assert 'You have been invited to join {display_name} at edx.org by a member of the course staff.'.format( + assert u'You have been invited to join {display_name} at edx.org by a member of the course staff.'.format( display_name=self.course.display_name, ) in body @@ -1681,7 +1681,7 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest assert text_body.startswith('Dear student,') for body in [text_body, html_body]: - assert 'You have been invited to join {display_name} at edx.org by a member of the course staff.'.format( + assert u'You have been invited to join {display_name} at edx.org by a member of the course staff.'.format( display_name=self.course.display_name, ) in body @@ -1697,14 +1697,14 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest 'auto_enroll': True} environ = {'wsgi.url_scheme': protocol} response = self.client.post(url, params, **environ) - print("type(self.notregistered_email): {}".format(type(self.notregistered_email))) + print(u"type(self.notregistered_email): {}".format(type(self.notregistered_email))) self.assertEqual(response.status_code, 200) # Check the outbox self.assertEqual(len(mail.outbox), 1) self.assertEqual( mail.outbox[0].subject, - 'You have been invited to register for {display_name}'.format(display_name=self.course.display_name,) + u'You have been invited to register for {display_name}'.format(display_name=self.course.display_name,) ) text_body = mail.outbox[0].body @@ -1715,11 +1715,11 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest assert text_body.startswith('Dear student,') assert course_url in html_body - assert 'To access this course visit {course_url} and login.'.format(course_url=course_url) in text_body + assert u'To access this course visit {course_url} and login.'.format(course_url=course_url) in text_body assert 'To access this course click on the button below and login:' in html_body for body in [text_body, html_body]: - assert 'You have been invited to join {display_name} at edx.org by a member of the course staff.'.format( + assert u'You have been invited to join {display_name} at edx.org by a member of the course staff.'.format( display_name=self.course.display_name, ) in body @@ -2113,17 +2113,17 @@ class TestInstructorAPIBulkBetaEnrollment(SharedModuleStoreTestCase, LoginEnroll self.assertEqual(len(mail.outbox), 1) self.assertEqual( mail.outbox[0].subject, - 'You have been invited to a beta test for {display_name}'.format(display_name=self.course.display_name,) + u'You have been invited to a beta test for {display_name}'.format(display_name=self.course.display_name,) ) text_body = mail.outbox[0].body html_body = mail.outbox[0].alternatives[0][0] student_name = self.notenrolled_student.profile.name - assert text_body.startswith('Dear {student_name}'.format(student_name=student_name)) - assert 'Visit {display_name}'.format(display_name=self.course.display_name) in html_body + assert text_body.startswith(u'Dear {student_name}'.format(student_name=student_name)) + assert u'Visit {display_name}'.format(display_name=self.course.display_name) in html_body for body in [text_body, html_body]: - assert 'You have been invited to be a beta tester for {display_name} at edx.org'.format( + assert u'You have been invited to be a beta tester for {display_name} at edx.org'.format( display_name=self.course.display_name, ) in body @@ -2136,7 +2136,7 @@ class TestInstructorAPIBulkBetaEnrollment(SharedModuleStoreTestCase, LoginEnroll about_path=self.about_path, ) in body - assert 'This email was automatically sent from edx.org to {student_email}'.format( + assert u'This email was automatically sent from edx.org to {student_email}'.format( student_email=self.notenrolled_student.email, ) in body @@ -2169,16 +2169,16 @@ class TestInstructorAPIBulkBetaEnrollment(SharedModuleStoreTestCase, LoginEnroll self.assertEqual(len(mail.outbox), 1) self.assertEqual( mail.outbox[0].subject, - 'You have been invited to a beta test for {display_name}'.format(display_name=self.course.display_name) + u'You have been invited to a beta test for {display_name}'.format(display_name=self.course.display_name) ) text_body = mail.outbox[0].body html_body = mail.outbox[0].alternatives[0][0] student_name = self.notenrolled_student.profile.name - assert text_body.startswith('Dear {student_name}'.format(student_name=student_name)) + assert text_body.startswith(u'Dear {student_name}'.format(student_name=student_name)) for body in [text_body, html_body]: - assert 'You have been invited to be a beta tester for {display_name} at edx.org'.format( + assert u'You have been invited to be a beta tester for {display_name} at edx.org'.format( display_name=self.course.display_name, ) in body @@ -2191,7 +2191,7 @@ class TestInstructorAPIBulkBetaEnrollment(SharedModuleStoreTestCase, LoginEnroll course_path=self.course_path ) - assert 'This email was automatically sent from edx.org to {student_email}'.format( + assert u'This email was automatically sent from edx.org to {student_email}'.format( student_email=self.notenrolled_student.email, ) in body @@ -2206,17 +2206,17 @@ class TestInstructorAPIBulkBetaEnrollment(SharedModuleStoreTestCase, LoginEnroll text_body = mail.outbox[0].body html_body = mail.outbox[0].alternatives[0][0] student_name = self.notenrolled_student.profile.name - assert text_body.startswith('Dear {student_name}'.format(student_name=student_name)) + assert text_body.startswith(u'Dear {student_name}'.format(student_name=student_name)) for body in [text_body, html_body]: - assert 'You have been invited to be a beta tester for {display_name} at edx.org'.format( + assert u'You have been invited to be a beta tester for {display_name} at edx.org'.format( display_name=self.course.display_name, ) in body assert 'by a member of the course staff.' in body assert 'Visit edx.org' in body assert 'enroll in this course and begin the beta test' in body - assert 'This email was automatically sent from edx.org to {student_email}'.format( + assert u'This email was automatically sent from edx.org to {student_email}'.format( student_email=self.notenrolled_student.email, ) in body @@ -2312,10 +2312,10 @@ class TestInstructorAPIBulkBetaEnrollment(SharedModuleStoreTestCase, LoginEnroll text_body = mail.outbox[0].body html_body = mail.outbox[0].alternatives[0][0] - assert text_body.startswith('Dear {name}'.format(name=self.beta_tester.profile.name)) + assert text_body.startswith(u'Dear {name}'.format(name=self.beta_tester.profile.name)) for body in [text_body, html_body]: - assert 'You have been removed as a beta tester for {display_name} at edx.org'.format( + assert u'You have been removed as a beta tester for {display_name} at edx.org'.format( display_name=self.course.display_name, ) in body @@ -2324,7 +2324,7 @@ class TestInstructorAPIBulkBetaEnrollment(SharedModuleStoreTestCase, LoginEnroll assert 'Your other courses have not been affected.' in body - assert 'This email was automatically sent from edx.org to {email_address}'.format( + assert u'This email was automatically sent from edx.org to {email_address}'.format( email_address=self.beta_tester.email, ) in body @@ -2681,7 +2681,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment # submitting invalid invoice number data['invoice_number'] = 'testing' response = self.assert_request_status_code(400, url, method="POST", data=data) - self.assertIn("invoice_number must be an integer, {value} provided".format(value=data['invoice_number']), response.content) + self.assertIn(u"invoice_number must be an integer, {value} provided".format(value=data['invoice_number']), response.content) def test_get_sale_order_records_features_csv(self): """ @@ -2981,7 +2981,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment correctly in the response to get_students_features. """ for student in self.students: - student.profile.city = "Mos Eisley {}".format(student.id) + student.profile.city = u"Mos Eisley {}".format(student.id) student.profile.save() url = reverse('get_students_features', kwargs={'course_id': text_type(self.course.id)}) response = self.client.post(url, {}) @@ -3335,7 +3335,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment kwargs = {'course_id': unicode(self.course.id)} kwargs.update(extra_instructor_api_kwargs) url = reverse(instructor_api_endpoint, kwargs=kwargs) - success_status = "The {report_type} report is being created.".format(report_type=report_type) + success_status = u"The {report_type} report is being created.".format(report_type=report_type) with patch(task_api_endpoint) as patched_task_api_endpoint: patched_task_api_endpoint.return_value.task_id = "12345667-9abc-deff-ffed-cba987654321" @@ -3364,7 +3364,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment CourseFinanceAdminRole(self.course.id).add_users(self.instructor) with patch(task_api_endpoint): response = self.client.post(url, {}) - success_status = "The {report_type} report is being created." \ + success_status = u"The {report_type} report is being created." \ " To view the status of the report, see Pending" \ " Tasks below".format(report_type=report_type) self.assertIn(success_status, response.content) @@ -3877,7 +3877,7 @@ class TestEntranceExamInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginE }) self.assertEqual(response.status_code, 200) # check response - message = _('This student (%s) will skip the entrance exam.') % self.student.email + message = _(u'This student (%s) will skip the entrance exam.') % self.student.email self.assertContains(response, message) # post again with same student @@ -3886,7 +3886,7 @@ class TestEntranceExamInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginE }) # This time response message should be different - message = _('This student (%s) is already allowed to skip the entrance exam.') % self.student.email + message = _(u'This student (%s) is already allowed to skip the entrance exam.') % self.student.email self.assertContains(response, message) @@ -4768,10 +4768,10 @@ class TestCourseIssuedCertificatesData(SharedModuleStoreTestCase): for __ in xrange(certificate_count): self.generate_certificate(course_id=self.course.id, mode='honor', status=CertificateStatuses.downloadable) - current_date = datetime.date.today().strftime("%B %d, %Y") + current_date = datetime.date.today().strftime(u"%B %d, %Y") response = self.client.get(url, {'csv': 'true'}) self.assertEqual(response['Content-Type'], 'text/csv') - self.assertEqual(response['Content-Disposition'], 'attachment; filename={0}'.format('issued_certificates.csv')) + self.assertEqual(response['Content-Disposition'], u'attachment; filename={0}'.format('issued_certificates.csv')) self.assertEqual( response.content.strip(), '"CourseID","Certificate Type","Total Certificates Issued","Date Report Run"\r\n"' diff --git a/lms/djangoapps/instructor/tests/test_certificates.py b/lms/djangoapps/instructor/tests/test_certificates.py index a508103525e..0f2322fabca 100644 --- a/lms/djangoapps/instructor/tests/test_certificates.py +++ b/lms/djangoapps/instructor/tests/test_certificates.py @@ -186,7 +186,7 @@ class CertificatesInstructorDashTest(SharedModuleStoreTestCase): response = self.client.get(self.url) if expected_status == 'started': - expected = 'Generating example {name} certificate'.format(name=cert_name) + expected = u'Generating example {name} certificate'.format(name=cert_name) self.assertContains(response, expected) elif expected_status == 'error': expected = self.ERROR_REASON @@ -195,7 +195,7 @@ class CertificatesInstructorDashTest(SharedModuleStoreTestCase): expected = self.DOWNLOAD_URL self.assertContains(response, expected) else: - self.fail("Invalid certificate status: {status}".format(status=expected_status)) + self.fail(u"Invalid certificate status: {status}".format(status=expected_status)) def _assert_enable_certs_button_is_disabled(self): """Check that the "enable student-generated certificates" button is disabled. """ @@ -685,7 +685,7 @@ class CertificateExceptionViewInstructorApiTest(SharedModuleStoreTestCase): # Assert Error Message self.assertEqual( res_json['message'], - "{user} is not enrolled in this course. Please check your spelling and retry.".format( + u"{user} is not enrolled in this course. Please check your spelling and retry.".format( user=self.certificate_exception['user_name'] ) ) diff --git a/lms/djangoapps/instructor/tests/test_ecommerce.py b/lms/djangoapps/instructor/tests/test_ecommerce.py index 25ad7e6d224..239b448a201 100644 --- a/lms/djangoapps/instructor/tests/test_ecommerce.py +++ b/lms/djangoapps/instructor/tests/test_ecommerce.py @@ -158,7 +158,7 @@ class TestECommerceDashboardViews(SiteMixin, SharedModuleStoreTestCase): # Course Mode not exist with mode slug honor response = self.client.post(set_course_price_url, data) self.assertIn( - "CourseMode with the mode slug({mode_slug}) DoesNotExist".format(mode_slug='honor'), + u"CourseMode with the mode slug({mode_slug}) DoesNotExist".format(mode_slug='honor'), response.content ) @@ -179,7 +179,7 @@ class TestECommerceDashboardViews(SiteMixin, SharedModuleStoreTestCase): } response = self.client.post(add_coupon_url, data) self.assertIn( - "coupon with the coupon code ({code}) added successfully".format(code=data['code']), + u"coupon with the coupon code ({code}) added successfully".format(code=data['code']), response.content ) @@ -198,7 +198,7 @@ class TestECommerceDashboardViews(SiteMixin, SharedModuleStoreTestCase): 'description': 'asdsasda', 'created_by': self.instructor, 'discount': 99 } response = self.client.post(add_coupon_url, data) - self.assertIn("coupon with the coupon code ({code}) already exist".format(code='A2314'), response.content) + self.assertIn(u"coupon with the coupon code ({code}) already exist".format(code='A2314'), response.content) response = self.client.post(self.url) self.assertIn('<td>ADSADASDSAD</td>', response.content) @@ -224,7 +224,7 @@ class TestECommerceDashboardViews(SiteMixin, SharedModuleStoreTestCase): data['code'] = 'Vs23Ws4j' response = self.client.post(add_coupon_url, data) - msg = "The code ({code}) that you have tried to define is already in use as a registration code" + msg = u"The code ({code}) that you have tried to define is already in use as a registration code" self.assertIn(msg.format(code=data['code']), response.content) def test_delete_coupon(self): @@ -245,7 +245,7 @@ class TestECommerceDashboardViews(SiteMixin, SharedModuleStoreTestCase): delete_coupon_url = reverse('remove_coupon', kwargs={'course_id': text_type(self.course.id)}) response = self.client.post(delete_coupon_url, {'id': coupon.id}) self.assertIn( - 'coupon with the coupon id ({coupon_id}) updated successfully'.format(coupon_id=coupon.id), + u'coupon with the coupon id ({coupon_id}) updated successfully'.format(coupon_id=coupon.id), response.content ) @@ -254,13 +254,13 @@ class TestECommerceDashboardViews(SiteMixin, SharedModuleStoreTestCase): response = self.client.post(delete_coupon_url, {'id': coupon.id}) self.assertIn( - 'coupon with the coupon id ({coupon_id}) is already inactive'.format(coupon_id=coupon.id), + u'coupon with the coupon id ({coupon_id}) is already inactive'.format(coupon_id=coupon.id), response.content ) response = self.client.post(delete_coupon_url, {'id': 24454}) self.assertIn( - 'coupon with the coupon id ({coupon_id}) DoesNotExist'.format(coupon_id=24454), + u'coupon with the coupon id ({coupon_id}) DoesNotExist'.format(coupon_id=24454), response.content ) @@ -281,14 +281,14 @@ class TestECommerceDashboardViews(SiteMixin, SharedModuleStoreTestCase): edit_url = reverse('get_coupon_info', kwargs={'course_id': text_type(self.course.id)}) response = self.client.post(edit_url, {'id': coupon.id}) self.assertIn( - 'coupon with the coupon id ({coupon_id}) updated successfully'.format(coupon_id=coupon.id), + u'coupon with the coupon id ({coupon_id}) updated successfully'.format(coupon_id=coupon.id), response.content ) self.assertIn(coupon.display_expiry_date, response.content) response = self.client.post(edit_url, {'id': 444444}) self.assertIn( - 'coupon with the coupon id ({coupon_id}) DoesNotExist'.format(coupon_id=444444), + u'coupon with the coupon id ({coupon_id}) DoesNotExist'.format(coupon_id=444444), response.content ) @@ -300,7 +300,7 @@ class TestECommerceDashboardViews(SiteMixin, SharedModuleStoreTestCase): response = self.client.post(edit_url, {'id': coupon.id}) self.assertIn( - "coupon with the coupon id ({coupon_id}) is already inactive".format(coupon_id=coupon.id), + u"coupon with the coupon id ({coupon_id}) is already inactive".format(coupon_id=coupon.id), response.content ) @@ -323,7 +323,7 @@ class TestECommerceDashboardViews(SiteMixin, SharedModuleStoreTestCase): update_coupon_url = reverse('update_coupon', kwargs={'course_id': text_type(self.course.id)}) response = self.client.post(update_coupon_url, data=data) self.assertIn( - 'coupon with the coupon id ({coupon_id}) updated Successfully'.format(coupon_id=coupon.id), + u'coupon with the coupon id ({coupon_id}) updated Successfully'.format(coupon_id=coupon.id), response.content ) @@ -332,7 +332,7 @@ class TestECommerceDashboardViews(SiteMixin, SharedModuleStoreTestCase): data['coupon_id'] = 1000 # Coupon Not Exist with this ID response = self.client.post(update_coupon_url, data=data) - self.assertIn('coupon with the coupon id ({coupon_id}) DoesNotExist'.format(coupon_id=1000), response.content) + self.assertIn(u'coupon with the coupon id ({coupon_id}) DoesNotExist'.format(coupon_id=1000), response.content) data['coupon_id'] = '' # Coupon id is not provided response = self.client.post(update_coupon_url, data=data) diff --git a/lms/djangoapps/instructor/tests/test_enrollment.py b/lms/djangoapps/instructor/tests/test_enrollment.py index d56303e6c70..286c7724bfb 100644 --- a/lms/djangoapps/instructor/tests/test_enrollment.py +++ b/lms/djangoapps/instructor/tests/test_enrollment.py @@ -667,7 +667,7 @@ class TestSendBetaRoleEmail(CacheIsolationTestCase): def test_bad_action(self): bad_action = 'beta_tester' - error_msg = "Unexpected action received '{}' - expected 'add' or 'remove'".format(bad_action) + error_msg = u"Unexpected action received '{}' - expected 'add' or 'remove'".format(bad_action) with self.assertRaisesRegexp(ValueError, error_msg): send_beta_role_email(bad_action, self.user, self.email_params) diff --git a/lms/djangoapps/instructor/tests/test_registration_codes.py b/lms/djangoapps/instructor/tests/test_registration_codes.py index 7a82c6d5486..3be46796634 100644 --- a/lms/djangoapps/instructor/tests/test_registration_codes.py +++ b/lms/djangoapps/instructor/tests/test_registration_codes.py @@ -101,7 +101,7 @@ class TestCourseRegistrationCodeStatus(SharedModuleStoreTestCase): response = self.client.get(self.lookup_code_url, data) self.assertEqual(response.status_code, 400) json_dict = json.loads(response.content) - message = _('The enrollment code ({code}) was not found for the {course_name} course.').format( + message = _(u'The enrollment code ({code}) was not found for the {course_name} course.').format( course_name=self.course.display_name, code=data['registration_code'] ) self.assertEqual(message, json_dict['message']) @@ -239,7 +239,7 @@ class TestCourseRegistrationCodeStatus(SharedModuleStoreTestCase): self.assertEqual(response.status_code, 400) json_dict = json.loads(response.content) - message = _('The enrollment code ({code}) was not found for the {course_name} course.').format( + message = _(u'The enrollment code ({code}) was not found for the {course_name} course.').format( course_name=self.course.display_name, code=data['registration_code'] ) self.assertEqual(message, json_dict['message']) @@ -299,5 +299,5 @@ class TestCourseRegistrationCodeStatus(SharedModuleStoreTestCase): self.assertEqual(response.status_code, 400) json_dict = json.loads(response.content) - message = _('The redemption does not exist against enrollment code ({code}).').format(code=reg_code.code) + message = _(u'The redemption does not exist against enrollment code ({code}).').format(code=reg_code.code) self.assertEqual(message, json_dict['message']) diff --git a/lms/djangoapps/instructor/tests/test_services.py b/lms/djangoapps/instructor/tests/test_services.py index 84856eac9f9..be0ab2fc3c1 100644 --- a/lms/djangoapps/instructor/tests/test_services.py +++ b/lms/djangoapps/instructor/tests/test_services.py @@ -149,9 +149,9 @@ class InstructorServiceTests(SharedModuleStoreTestCase): email = "edx-proctoring@edx.org" subject = u"Proctored Exam Review: {review_status}".format(review_status="Suspicious") - body = "A proctored exam attempt for {exam_name} in {course_name} by username: {student_username} was " \ - "reviewed as {review_status} by the proctored exam review provider.\n" \ - "Review link: {url}" + body = u"A proctored exam attempt for {exam_name} in {course_name} by username: {student_username} was " \ + u"reviewed as {review_status} by the proctored exam review provider.\n" \ + u"Review link: {url}" args = { 'exam_name': 'test_exam', 'student_username': 'test_student', diff --git a/lms/djangoapps/instructor/tests/test_spoc_gradebook.py b/lms/djangoapps/instructor/tests/test_spoc_gradebook.py index 0950571b1af..4c5b34517e1 100644 --- a/lms/djangoapps/instructor/tests/test_spoc_gradebook.py +++ b/lms/djangoapps/instructor/tests/test_spoc_gradebook.py @@ -137,10 +137,10 @@ class TestLetterCutoffPolicy(TestGradebook): def test_styles(self): - self.assertIn("grade_A {color:green;}", self.response.content) - self.assertIn("grade_B {color:Chocolate;}", self.response.content) - self.assertIn("grade_C {color:DarkSlateGray;}", self.response.content) - self.assertIn("grade_D {color:DarkSlateGray;}", self.response.content) + self.assertIn(u"grade_A {color:green;}", self.response.content.decode(self.response.charset)) + self.assertIn(u"grade_B {color:Chocolate;}", self.response.content.decode(self.response.charset)) + self.assertIn(u"grade_C {color:DarkSlateGray;}", self.response.content.decode(self.response.charset)) + self.assertIn(u"grade_D {color:DarkSlateGray;}", self.response.content.decode(self.response.charset)) def test_assigned_grades(self): # Users 9-10 have >= 90% on Homeworks [2] diff --git a/lms/djangoapps/instructor/tests/views/test_instructor_dashboard.py b/lms/djangoapps/instructor/tests/views/test_instructor_dashboard.py index 0a84929933b..970892bd203 100644 --- a/lms/djangoapps/instructor/tests/views/test_instructor_dashboard.py +++ b/lms/djangoapps/instructor/tests/views/test_instructor_dashboard.py @@ -88,14 +88,14 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase, XssT """ Returns expected dashboard enrollment message with link to Insights. """ - return 'Enrollment data is now available in <a href="http://example.com/courses/{}" ' \ + return u'Enrollment data is now available in <a href="http://example.com/courses/{}" ' \ 'target="_blank">Example</a>.'.format(text_type(self.course.id)) def get_dashboard_analytics_message(self): """ Returns expected dashboard demographic message with link to Insights. """ - return 'For analytics about your course, go to <a href="http://example.com/courses/{}" ' \ + return u'For analytics about your course, go to <a href="http://example.com/courses/{}" ' \ 'target="_blank">Example</a>.'.format(text_type(self.course.id)) def test_instructor_tab(self): @@ -320,7 +320,7 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase, XssT self.assertIn('<th scope="row">Professional</th>', response.content) # dashboard link hidden - self.assertNotIn(self.get_dashboard_enrollment_message(), response.content) + self.assertNotIn(self.get_dashboard_enrollment_message(), response.content.decode(response.charset)) @patch.dict(settings.FEATURES, {'DISPLAY_ANALYTICS_ENROLLMENTS': True}) @override_settings(ANALYTICS_DASHBOARD_URL='') @@ -353,7 +353,7 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase, XssT # link to dashboard shown expected_message = self.get_dashboard_enrollment_message() - self.assertIn(expected_message, response.content) + self.assertIn(expected_message, response.content.decode(response.charset)) @override_settings(ANALYTICS_DASHBOARD_URL='') @override_settings(ANALYTICS_DASHBOARD_NAME='') @@ -377,7 +377,7 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase, XssT # link to dashboard shown expected_message = self.get_dashboard_analytics_message() - self.assertIn(expected_message, response.content) + self.assertIn(expected_message, response.content.decode(response.charset)) def add_course_to_user_cart(self, cart, course_key): """ @@ -574,7 +574,7 @@ class TestInstructorDashboardPerformance(ModuleStoreTestCase, LoginEnrollmentTes problem = ItemFactory.create( category="problem", parent=vertical, - display_name="A Problem Block %d" % i, + display_name=u"A Problem Block %d" % i, weight=1, publish_item=False, metadata={'rerandomize': 'always'}, diff --git a/lms/djangoapps/instructor/views/api.py b/lms/djangoapps/instructor/views/api.py index 0f561da25f1..42654ea15a9 100644 --- a/lms/djangoapps/instructor/views/api.py +++ b/lms/djangoapps/instructor/views/api.py @@ -150,7 +150,7 @@ log = logging.getLogger(__name__) TASK_SUBMISSION_OK = 'created' -SUCCESS_MESSAGE_TEMPLATE = _("The {report_type} report is being created. " +SUCCESS_MESSAGE_TEMPLATE = _(u"The {report_type} report is being created. " "To view the status of the report, see Pending Tasks below.") @@ -232,7 +232,7 @@ def require_level(level): if they are not in the staff group. """ if level not in ['instructor', 'staff']: - raise ValueError("unrecognized level '{}'".format(level)) + raise ValueError(u"unrecognized level '{}'".format(level)) def decorator(func): # pylint: disable=missing-docstring def wrapped(*args, **kwargs): @@ -377,7 +377,7 @@ def register_and_enroll_students(request, course_id): # pylint: disable=too-man general_errors.append({ 'username': '', 'email': '', - 'response': _('Data in row #{row_num} must have exactly four columns: email, username, full name, and country').format(row_num=row_num) + 'response': _(u'Data in row #{row_num} must have exactly four columns: email, username, full name, and country').format(row_num=row_num) }) continue @@ -403,8 +403,8 @@ def register_and_enroll_students(request, course_id): # pylint: disable=too-man # if it's not an exact match then just display a warning message, but continue onwards if not User.objects.filter(email=email, username=username).exists(): warning_message = _( - 'An account with email {email} exists but the provided username {username} ' - 'is different. Enrolling anyway with {email}.' + u'An account with email {email} exists but the provided username {username} ' + u'is different. Enrolling anyway with {email}.' ).format(email=email, username=username) warnings.append({ @@ -436,7 +436,7 @@ def register_and_enroll_students(request, course_id): # pylint: disable=too-man row_errors.append({ 'username': username, 'email': email, - 'response': _('Invalid email {email_address}.').format(email_address=email), + 'response': _(u'Invalid email {email_address}.').format(email_address=email), }) log.warning(u'Email address %s is associated with a retired user, so course enrollment was ' + u'blocked.', email) @@ -573,7 +573,7 @@ def create_and_enroll_user(email, username, name, country, password, course_id, ) except IntegrityError: errors.append({ - 'username': username, 'email': email, 'response': _('Username {user} already exists.').format(user=username) + 'username': username, 'email': email, 'response': _(u'Username {user} already exists.').format(user=username) }) except Exception as ex: # pylint: disable=broad-except log.exception(type(ex).__name__) @@ -592,15 +592,15 @@ def create_and_enroll_user(email, username, name, country, password, course_id, send_mail_to_student(email, email_params) except Exception as ex: # pylint: disable=broad-except log.exception( - "Exception '{exception}' raised while sending email to new user.".format(exception=type(ex).__name__) + u"Exception '{exception}' raised while sending email to new user.".format(exception=type(ex).__name__) ) errors.append({ 'username': username, 'email': email, 'response': - _("Error '{error}' while sending email to new user (user email={email}). " - "Without the email student would not be able to login. " - "Please contact support for further information.").format(error=type(ex).__name__, email=email), + _(u"Error '{error}' while sending email to new user (user email={email}). " + u"Without the email student would not be able to login. " + u"Please contact support for further information.").format(error=type(ex).__name__, email=email), }) else: log.info(u'email sent to new created user at %s', email) @@ -737,7 +737,7 @@ def students_update_enrollment(request, course_id): else: return HttpResponseBadRequest(strip_tags( - "Unrecognized action '{}'".format(action) + u"Unrecognized action '{}'".format(action) )) except ValidationError: @@ -822,7 +822,7 @@ def bulk_beta_modify_access(request, course_id): revoke_access(course, user, rolename) else: return HttpResponseBadRequest(strip_tags( - "Unrecognized action '{}'".format(action) + u"Unrecognized action '{}'".format(action) )) except User.DoesNotExist: error = True @@ -909,7 +909,7 @@ def modify_access(request, course_id): action = request.POST.get('action') if rolename not in ROLES: - error = strip_tags("unknown rolename '{}'".format(rolename)) + error = strip_tags(u"unknown rolename '{}'".format(rolename)) log.error(error) return HttpResponseBadRequest(error) @@ -929,7 +929,7 @@ def modify_access(request, course_id): revoke_access(course, user, rolename) else: return HttpResponseBadRequest(strip_tags( - "unrecognized action '{}'".format(action) + u"unrecognized action u'{}'".format(action) )) response_payload = { @@ -1143,7 +1143,7 @@ def sale_validation(request, course_id): invoice_number = int(invoice_number) except ValueError: return HttpResponseBadRequest( - "invoice_number must be an integer, {value} provided".format( + u"invoice_number must be an integer, {value} provided".format( value=invoice_number ) ) @@ -1160,7 +1160,7 @@ def sale_validation(request, course_id): ) obj_invoice = obj_invoice.invoice except CourseRegistrationCodeInvoiceItem.DoesNotExist: # Check for old type invoices - return HttpResponseNotFound(_("Invoice number '{num}' does not exist.").format(num=invoice_number)) + return HttpResponseNotFound(_(u"Invoice number '{num}' does not exist.").format(num=invoice_number)) if event_type == "invalidate": return invalidate_invoice(obj_invoice) @@ -1176,7 +1176,7 @@ def invalidate_invoice(obj_invoice): return HttpResponseBadRequest(_("The sale associated with this invoice has already been invalidated.")) obj_invoice.is_valid = False obj_invoice.save() - message = _('Invoice number {0} has been invalidated.').format(obj_invoice.id) + message = _(u'Invoice number {0} has been invalidated.').format(obj_invoice.id) return JsonResponse({'message': message}) @@ -1189,7 +1189,7 @@ def re_validate_invoice(obj_invoice): obj_invoice.is_valid = True obj_invoice.save() - message = _('The registration codes for invoice {0} have been re-activated.').format(obj_invoice.id) + message = _(u'The registration codes for invoice {0} have been re-activated.').format(obj_invoice.id) return JsonResponse({'message': message}) @@ -1455,7 +1455,7 @@ def get_coupon_codes(request, course_id): # pylint: disable=unused-argument query_features = [ ('code', _('Coupon Code')), ('course_id', _('Course Id')), - ('percentage_discount', _('% Discount')), + ('percentage_discount', _('% Discount')), # pylint: disable=unicode-format-string ('description', _('Description')), ('expiration_date', _('Expiration Date')), ('is_active', _('Is Active')), @@ -1901,7 +1901,7 @@ def get_anon_ids(request, course_id): # pylint: disable=unused-argument def csv_response(filename, header, rows): """Returns a CSV http response for the given header and rows (excel/utf-8).""" response = HttpResponse(content_type='text/csv') - response['Content-Disposition'] = 'attachment; filename={0}'.format(text_type(filename).encode('utf-8')) + response['Content-Disposition'] = u'attachment; filename={0}'.format(text_type(filename).encode('utf-8')) writer = csv.writer(response, dialect='excel', quotechar='"', quoting=csv.QUOTE_ALL) # In practice, there should not be non-ascii data in this query, # but trying to do the right thing anyway. @@ -1952,20 +1952,20 @@ def get_student_enrollment_status(request, course_id): # records, so let the lack of a User slide. pass - enrollment_status = _('Enrollment status for {student}: unknown').format(student=unique_student_identifier) + enrollment_status = _(u'Enrollment status for {student}: unknown').format(student=unique_student_identifier) if user and mode: if is_active: - enrollment_status = _('Enrollment status for {student}: active').format(student=user) + enrollment_status = _(u'Enrollment status for {student}: active').format(student=user) else: - enrollment_status = _('Enrollment status for {student}: inactive').format(student=user) + enrollment_status = _(u'Enrollment status for {student}: inactive').format(student=user) else: email = user.email if user else unique_student_identifier allowed = CourseEnrollmentAllowed.may_enroll_and_unenrolled(course_id) if allowed and email in [cea.email for cea in allowed]: - enrollment_status = _('Enrollment status for {student}: pending').format(student=email) + enrollment_status = _(u'Enrollment status for {student}: pending').format(student=email) else: - enrollment_status = _('Enrollment status for {student}: never enrolled').format(student=email) + enrollment_status = _(u'Enrollment status for {student}: never enrolled').format(student=email) response_payload = { 'course_id': course_id.to_deprecated_string(), @@ -2267,16 +2267,16 @@ def override_problem_score(request, course_id): if student_identifier is not None: student = get_student_from_identifier(student_identifier) else: - return _create_error_response(request, "Invalid student ID {}.".format(student_identifier)) + return _create_error_response(request, u"Invalid student ID {}.".format(student_identifier)) try: usage_key = UsageKey.from_string(problem_to_reset).map_into_course(course_key) except InvalidKeyError: - return _create_error_response(request, "Unable to parse problem id {}.".format(problem_to_reset)) + return _create_error_response(request, u"Unable to parse problem id {}.".format(problem_to_reset)) # check the user's access to this specific problem if not has_access(request.user, "staff", modulestore().get_item(usage_key)): - _create_error_response(request, "User {} does not have permission to override scores for problem {}.".format( + _create_error_response(request, u"User {} does not have permission to override scores for problem {}.".format( request.user.id, problem_to_reset )) @@ -2506,7 +2506,7 @@ def list_report_downloads(request, course_id): response_payload = { 'downloads': [ - dict(name=name, url=url, link=HTML('<a href="{}">{}</a>').format(HTML(url), Text(name))) + dict(name=name, url=url, link=HTML(u'<a href="{}">{}</a>').format(HTML(url), Text(name))) for name, url in report_store.links_for(course_id) if report_name is None or name == report_name ] } @@ -2527,7 +2527,7 @@ def list_financial_report_downloads(_request, course_id): response_payload = { 'downloads': [ - dict(name=name, url=url, link=HTML('<a href="{}">{}</a>').format(HTML(url), Text(name))) + dict(name=name, url=url, link=HTML(u'<a href="{}">{}</a>').format(HTML(url), Text(name))) for name, url in report_store.links_for(course_id) ] } @@ -2631,7 +2631,7 @@ def list_forum_members(request, course_id): if rolename not in [FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_GROUP_MODERATOR, FORUM_ROLE_COMMUNITY_TA]: return HttpResponseBadRequest(strip_tags( - "Unrecognized rolename '{}'.".format(rolename) + u"Unrecognized rolename '{}'.".format(rolename) )) try: @@ -2789,7 +2789,7 @@ def update_forum_role_membership(request, course_id): if rolename not in [FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_GROUP_MODERATOR, FORUM_ROLE_COMMUNITY_TA]: return HttpResponseBadRequest(strip_tags( - "Unrecognized rolename '{}'.".format(rolename) + u"Unrecognized rolename '{}'.".format(rolename) )) user = get_student_from_identifier(unique_student_identifier) @@ -2849,9 +2849,9 @@ def change_due_date(request, course_id): set_due_date_extension(course, unit, student, due_date) return JsonResponse(_( - 'Successfully changed due date for student {0} for {1} ' - 'to {2}').format(student.profile.name, _display_unit(unit), - due_date.strftime('%Y-%m-%d %H:%M'))) + u'Successfully changed due date for student {0} for {1} ' + u'to {2}').format(student.profile.name, _display_unit(unit), + due_date.strftime(u'%Y-%m-%d %H:%M'))) @handle_dashboard_error @@ -2874,11 +2874,11 @@ def reset_due_date(request, course_id): _("Successfully removed invalid due date extension (unit has no due date).") ) - original_due_date_str = unit.due.strftime('%Y-%m-%d %H:%M') + original_due_date_str = unit.due.strftime(u'%Y-%m-%d %H:%M') return JsonResponse(_( - 'Successfully reset due date for student {0} for {1} ' - 'to {2}').format(student.profile.name, _display_unit(unit), - original_due_date_str)) + u'Successfully reset due date for student {0} for {1} ' + u'to {2}').format(student.profile.name, _display_unit(unit), + original_due_date_str)) @handle_dashboard_error @@ -3000,9 +3000,9 @@ def mark_student_can_skip_entrance_exam(request, course_id): __, created = EntranceExamConfiguration.objects.get_or_create(user=student, course_id=course_id) if created: - message = _('This student (%s) will skip the entrance exam.') % student_identifier + message = _(u'This student (%s) will skip the entrance exam.') % student_identifier else: - message = _('This student (%s) is already allowed to skip the entrance exam.') % student_identifier + message = _(u'This student (%s) is already allowed to skip the entrance exam.') % student_identifier response_payload = { 'message': message, } @@ -3123,7 +3123,7 @@ def add_certificate_exception(course_key, student, certificate_exception): """ if len(CertificateWhitelist.get_certificate_white_list(course_key, student)) > 0: raise ValueError( - _("Student (username/email={user}) already in certificate exception list.").format(user=student.username) + _(u"Student (username/email={user}) already in certificate exception list.").format(user=student.username) ) certificate_white_list, __ = CertificateWhitelist.objects.get_or_create( @@ -3147,8 +3147,8 @@ def add_certificate_exception(course_key, student, certificate_exception): 'user_email': student.email, 'user_name': student.username, 'user_id': student.id, - 'certificate_generated': generated_certificate and generated_certificate.created_date.strftime("%B %d, %Y"), - 'created': certificate_white_list.created.strftime("%A, %B %d, %Y"), + 'certificate_generated': generated_certificate and generated_certificate.created_date.strftime(u"%B %d, %Y"), + 'created': certificate_white_list.created.strftime(u"%A, %B %d, %Y"), }) return exception @@ -3168,7 +3168,7 @@ def remove_certificate_exception(course_key, student): certificate_exception = CertificateWhitelist.objects.get(user=student, course_id=course_key) except ObjectDoesNotExist: raise ValueError( - _('Certificate exception (user={user}) does not exist in certificate white list. ' + _(u'Certificate exception (user={user}) does not exist in certificate white list. ' 'Please refresh the page and try again.').format(user=student.username) ) @@ -3237,13 +3237,13 @@ def get_student(username_or_email, course_key): try: student = get_user_by_username_or_email(username_or_email) except ObjectDoesNotExist: - raise ValueError(_("{user} does not exist in the LMS. Please check your spelling and retry.").format( + raise ValueError(_(u"{user} does not exist in the LMS. Please check your spelling and retry.").format( user=username_or_email )) # Make Sure the given student is enrolled in the course if not CourseEnrollment.is_enrolled(student, course_key): - raise ValueError(_("{user} is not enrolled in this course. Please check your spelling and retry.") + raise ValueError(_(u"{user} is not enrolled in this course. Please check your spelling and retry.") .format(user=username_or_email)) return student @@ -3321,7 +3321,7 @@ def generate_bulk_certificate_exceptions(request, course_id): """ inner method to build dict of csv data as row errors. """ - row_errors[key].append(_('user "{user}" in row# {row}').format(user=_user, row=row_count)) + row_errors[key].append(_(u'user "{user}" in row# {row}').format(user=_user, row=row_count)) if 'students_list' in request.FILES: try: @@ -3371,7 +3371,7 @@ def generate_bulk_certificate_exceptions(request, course_id): whitelist=True, notes=student[notes_index] ) - success.append(_('user "{username}" in row# {row}').format(username=user.username, row=row_num)) + success.append(_(u'user "{username}" in row# {row}').format(username=user.username, row=row_num)) else: general_errors.append(_('File is not attached.')) @@ -3438,7 +3438,7 @@ def invalidate_certificate(request, generated_certificate, certificate_invalidat generated_certificate.user, )) > 0: raise ValueError( - _("Certificate of {user} has already been invalidated. Please check your spelling and retry.").format( + _(u"Certificate of {user} has already been invalidated. Please check your spelling and retry.").format( user=generated_certificate.user.username, ) ) @@ -3446,7 +3446,7 @@ def invalidate_certificate(request, generated_certificate, certificate_invalidat # Verify that certificate user wants to invalidate is a valid one. if not generated_certificate.is_valid(): raise ValueError( - _("Certificate for student {user} is already invalid, kindly verify that certificate was generated " + _(u"Certificate for student {user} is already invalid, kindly verify that certificate was generated " "for this student and then proceed.").format(user=generated_certificate.user.username) ) @@ -3466,7 +3466,7 @@ def invalidate_certificate(request, generated_certificate, certificate_invalidat 'id': certificate_invalidation.id, 'user': certificate_invalidation.generated_certificate.user.username, 'invalidated_by': certificate_invalidation.invalidated_by.username, - 'created': certificate_invalidation.created.strftime("%B %d, %Y"), + 'created': certificate_invalidation.created.strftime(u"%B %d, %Y"), 'notes': certificate_invalidation.notes, } @@ -3522,7 +3522,7 @@ def validate_request_data_and_get_certificate(certificate_invalidation, course_k certificate = GeneratedCertificate.certificate_for_student(student, course_key) if not certificate: raise ValueError(_( - "The student {student} does not have certificate for the course {course}. Kindly verify student " + u"The student {student} does not have certificate for the course {course}. Kindly verify student " "username/email and the selected course are correct and try again." ).format(student=student.username, course=course_key.course)) return certificate diff --git a/lms/djangoapps/instructor/views/coupons.py b/lms/djangoapps/instructor/views/coupons.py index cd49e33c408..606399d9fcd 100644 --- a/lms/djangoapps/instructor/views/coupons.py +++ b/lms/djangoapps/instructor/views/coupons.py @@ -35,16 +35,16 @@ def remove_coupon(request, course_id): # pylint: disable=unused-argument coupon = Coupon.objects.get(id=coupon_id) except ObjectDoesNotExist: return JsonResponse({ - 'message': _('coupon with the coupon id ({coupon_id}) DoesNotExist').format(coupon_id=coupon_id) + 'message': _(u'coupon with the coupon id ({coupon_id}) DoesNotExist').format(coupon_id=coupon_id) }, status=400) # status code 400: Bad Request if not coupon.is_active: return JsonResponse({ - 'message': _('coupon with the coupon id ({coupon_id}) is already inactive').format(coupon_id=coupon_id) + 'message': _(u'coupon with the coupon id ({coupon_id}) is already inactive').format(coupon_id=coupon_id) }, status=400) # status code 400: Bad Request coupon.is_active = False coupon.save() return JsonResponse({ - 'message': _('coupon with the coupon id ({coupon_id}) updated successfully').format(coupon_id=coupon_id) + 'message': _(u'coupon with the coupon id ({coupon_id}) updated successfully').format(coupon_id=coupon_id) }) # status code 200: OK by default @@ -65,7 +65,7 @@ def add_coupon(request, course_id): course_registration_code = CourseRegistrationCode.objects.filter(code=code) if course_registration_code: return JsonResponse( - {'message': _("The code ({code}) that you have tried to define is already in use as a registration code").format(code=code)}, + {'message': _(u"The code ({code}) that you have tried to define is already in use as a registration code").format(code=code)}, status=400) # status code 400: Bad Request description = request.POST.get('description') @@ -100,12 +100,12 @@ def add_coupon(request, course_id): ) coupon.save() return JsonResponse( - {'message': _("coupon with the coupon code ({code}) added successfully").format(code=code)} + {'message': _(u"coupon with the coupon code ({code}) added successfully").format(code=code)} ) if coupon: return JsonResponse( - {'message': _("coupon with the coupon code ({code}) already exists for this course").format(code=code)}, + {'message': _(u"coupon with the coupon code ({code}) already exists for this course").format(code=code)}, status=400) # status code 400: Bad Request @@ -123,14 +123,14 @@ def update_coupon(request, course_id): # pylint: disable=unused-argument coupon = Coupon.objects.get(pk=coupon_id) except ObjectDoesNotExist: return JsonResponse( - {'message': _("coupon with the coupon id ({coupon_id}) DoesNotExist").format(coupon_id=coupon_id)}, + {'message': _(u"coupon with the coupon id ({coupon_id}) DoesNotExist").format(coupon_id=coupon_id)}, status=400) # status code 400: Bad Request description = request.POST.get('description') coupon.description = description coupon.save() return JsonResponse( - {'message': _("coupon with the coupon id ({coupon_id}) updated Successfully").format(coupon_id=coupon_id)} + {'message': _(u"coupon with the coupon id ({coupon_id}) updated Successfully").format(coupon_id=coupon_id)} ) @@ -150,12 +150,12 @@ def get_coupon_info(request, course_id): # pylint: disable=unused-argument coupon = Coupon.objects.get(id=coupon_id) except ObjectDoesNotExist: return JsonResponse({ - 'message': _("coupon with the coupon id ({coupon_id}) DoesNotExist").format(coupon_id=coupon_id) + 'message': _(u"coupon with the coupon id ({coupon_id}) DoesNotExist").format(coupon_id=coupon_id) }, status=400) # status code 400: Bad Request if not coupon.is_active: return JsonResponse({ - 'message': _("coupon with the coupon id ({coupon_id}) is already inactive").format(coupon_id=coupon_id) + 'message': _(u"coupon with the coupon id ({coupon_id}) is already inactive").format(coupon_id=coupon_id) }, status=400) # status code 400: Bad Request expiry_date = coupon.display_expiry_date @@ -165,5 +165,5 @@ def get_coupon_info(request, course_id): # pylint: disable=unused-argument 'coupon_course_id': text_type(coupon.course_id), 'coupon_discount': coupon.percentage_discount, 'expiry_date': expiry_date, - 'message': _('coupon with the coupon id ({coupon_id}) updated successfully').format(coupon_id=coupon_id) + 'message': _(u'coupon with the coupon id ({coupon_id}) updated successfully').format(coupon_id=coupon_id) }) # status code 200: OK by default diff --git a/lms/djangoapps/instructor/views/instructor_dashboard.py b/lms/djangoapps/instructor/views/instructor_dashboard.py index 54f52fab082..c60fc0167f4 100644 --- a/lms/djangoapps/instructor/views/instructor_dashboard.py +++ b/lms/djangoapps/instructor/views/instructor_dashboard.py @@ -136,10 +136,10 @@ def instructor_dashboard_2(request, course_id): if show_analytics_dashboard_message(course_key): # Construct a URL to the external analytics dashboard analytics_dashboard_url = '{0}/courses/{1}'.format(settings.ANALYTICS_DASHBOARD_URL, unicode(course_key)) - link_start = HTML("<a href=\"{}\" target=\"_blank\">").format(analytics_dashboard_url) + link_start = HTML(u"<a href=\"{}\" target=\"_blank\">").format(analytics_dashboard_url) analytics_dashboard_message = _( - "To gain insights into student enrollment and participation {link_start}" - "visit {analytics_dashboard_name}, our new course analytics product{link_end}." + u"To gain insights into student enrollment and participation {link_start}" + u"visit {analytics_dashboard_name}, our new course analytics product{link_end}." ) analytics_dashboard_message = Text(analytics_dashboard_message).format( link_start=link_start, link_end=HTML("</a>"), analytics_dashboard_name=settings.ANALYTICS_DASHBOARD_NAME) @@ -422,7 +422,7 @@ def set_course_mode_price(request, course_id): course_honor_mode = CourseMode.objects.filter(mode_slug='honor', course_id=course_key) if not course_honor_mode: return JsonResponse( - {'message': _("CourseMode with the mode slug({mode_slug}) DoesNotExist").format(mode_slug='honor')}, + {'message': _(u"CourseMode with the mode slug({mode_slug}) DoesNotExist").format(mode_slug='honor')}, status=400) # status code 400: Bad Request CourseModesArchive.objects.create( @@ -464,7 +464,7 @@ def _section_course_info(course, access): # dashboard_link is already made safe in _get_dashboard_link dashboard_link = _get_dashboard_link(course_key) # so we can use Text() here so it's not double-escaped and rendering HTML on the front-end - message = Text(_("Enrollment data is now available in {dashboard_link}.")).format(dashboard_link=dashboard_link) + message = Text(_(u"Enrollment data is now available in {dashboard_link}.")).format(dashboard_link=dashboard_link) section_data['enrollment_message'] = message if settings.FEATURES.get('ENABLE_SYSADMIN_DASHBOARD'): @@ -472,7 +472,7 @@ def _section_course_info(course, access): try: sorted_cutoffs = sorted(course.grade_cutoffs.items(), key=lambda i: i[1], reverse=True) - advance = lambda memo, (letter, score): "{}: {}, ".format(letter, score) + memo + advance = lambda memo, (letter, score): u"{}: {}, ".format(letter, score) + memo section_data['grade_cutoffs'] = reduce(advance, sorted_cutoffs, "")[:-2] except Exception: # pylint: disable=broad-except section_data['grade_cutoffs'] = "Not Available" @@ -710,7 +710,7 @@ def _section_send_email(course, access): def _get_dashboard_link(course_key): """ Construct a URL to the external analytics dashboard """ - analytics_dashboard_url = '{0}/courses/{1}'.format(settings.ANALYTICS_DASHBOARD_URL, unicode(course_key)) + analytics_dashboard_url = u'{0}/courses/{1}'.format(settings.ANALYTICS_DASHBOARD_URL, unicode(course_key)) link = HTML(u"<a href=\"{0}\" target=\"_blank\">{1}</a>").format( analytics_dashboard_url, settings.ANALYTICS_DASHBOARD_NAME ) diff --git a/lms/djangoapps/instructor/views/instructor_task_helpers.py b/lms/djangoapps/instructor/views/instructor_task_helpers.py index df5935f3210..945d022d300 100644 --- a/lms/djangoapps/instructor/views/instructor_task_helpers.py +++ b/lms/djangoapps/instructor/views/instructor_task_helpers.py @@ -53,7 +53,7 @@ def extract_email_features(email_task): try: task_input_information = json.loads(email_task.task_input) except ValueError: - log.error("Could not parse task input as valid json; task input: %s", email_task.task_input) + log.error(u"Could not parse task input as valid json; task input: %s", email_task.task_input) return email_error_information() email = CourseEmail.objects.get(id=task_input_information['email_id']) @@ -74,13 +74,13 @@ def extract_email_features(email_task): try: task_output = json.loads(email_task.task_output) except ValueError: - log.error("Could not parse task output as valid json; task output: %s", email_task.task_output) + log.error(u"Could not parse task output as valid json; task output: %s", email_task.task_output) else: if 'succeeded' in task_output and task_output['succeeded'] > 0: num_emails = task_output['succeeded'] number_sent = ungettext( - "{num_emails} sent", - "{num_emails} sent", + u"{num_emails} sent", + u"{num_emails} sent", num_emails ).format(num_emails=num_emails) @@ -88,8 +88,8 @@ def extract_email_features(email_task): num_emails = task_output['failed'] number_sent += ", " number_sent += ungettext( - "{num_emails} failed", - "{num_emails} failed", + u"{num_emails} failed", + u"{num_emails} failed", num_emails ).format(num_emails=num_emails) @@ -121,7 +121,7 @@ def extract_task_features(task): try: task_output = json.loads(task.task_output) except ValueError: - log.error("Could not parse task output as valid json; task output: %s", task.task_output) + log.error(u"Could not parse task output as valid json; task output: %s", task.task_output) else: if 'duration_ms' in task_output: duration_sec = int(task_output['duration_ms'] / 1000.0) diff --git a/lms/djangoapps/instructor/views/registration_codes.py b/lms/djangoapps/instructor/views/registration_codes.py index 1c1123ff92e..48e37bff1cf 100644 --- a/lms/djangoapps/instructor/views/registration_codes.py +++ b/lms/djangoapps/instructor/views/registration_codes.py @@ -37,7 +37,7 @@ def look_up_registration_code(request, course_id): 'is_registration_code_exists': False, 'is_registration_code_valid': False, 'is_registration_code_redeemed': False, - 'message': _('The enrollment code ({code}) was not found for the {course_name} course.').format( + 'message': _(u'The enrollment code ({code}) was not found for the {course_name} course.').format( code=code, course_name=course.display_name ) }, status=400) # status code 200: OK by default @@ -78,7 +78,7 @@ def registration_code_details(request, course_id): registration_code = CourseRegistrationCode.objects.get(code=code) except CourseRegistrationCode.DoesNotExist: return JsonResponse({ - 'message': _('The enrollment code ({code}) was not found for the {course_name} course.').format( + 'message': _(u'The enrollment code ({code}) was not found for the {course_name} course.').format( code=code, course_name=course.display_name )}, status=400) @@ -97,7 +97,7 @@ def registration_code_details(request, course_id): code_redemption = RegistrationCodeRedemption.get_registration_code_redemption(code, course_key) if code_redemption is None: return JsonResponse({ - 'message': _('The redemption does not exist against enrollment code ({code}).').format( + 'message': _(u'The redemption does not exist against enrollment code ({code}).').format( code=code)}, status=400) delete_redemption_entry(request, code_redemption, course_key) @@ -124,5 +124,5 @@ def delete_redemption_entry(request, code_redemption, course_key): send_mail_to_student(email_address, email_params) # remove the redemption entry from the database. - log.info('deleting redemption entry (%s) from the database.', code_redemption.id) + log.info(u'deleting redemption entry (%s) from the database.', code_redemption.id) code_redemption.delete() diff --git a/lms/djangoapps/instructor/views/tools.py b/lms/djangoapps/instructor/views/tools.py index e78d42c9799..71f8e424c02 100644 --- a/lms/djangoapps/instructor/views/tools.py +++ b/lms/djangoapps/instructor/views/tools.py @@ -83,7 +83,7 @@ def require_student_from_identifier(unique_student_identifier): return get_student_from_identifier(unique_student_identifier) except User.DoesNotExist: raise DashboardError( - _("Could not find student matching identifier: {student_identifier}").format( + _(u"Could not find student matching identifier: {student_identifier}").format( student_identifier=unique_student_identifier ) ) @@ -120,7 +120,7 @@ def find_unit(course, url): unit = find(course, url) if unit is None: - raise DashboardError(_("Couldn't find module for url: {0}").format(url)) + raise DashboardError(_(u"Couldn't find module for url: {0}").format(url)) return unit @@ -169,7 +169,7 @@ def set_due_date_extension(course, unit, student, due_date): original_due_date = getattr(unit, 'due', None) if not original_due_date: - raise DashboardError(_("Unit {0} has no due date to extend.").format(unit.location)) + raise DashboardError(_(u"Unit {0} has no due date to extend.").format(unit.location)) if due_date < original_due_date: raise DashboardError(_("An extended due date must be later than the original due date.")) @@ -196,7 +196,7 @@ def dump_module_extensions(course, unit): field='due') for override in query: due = DATE_FIELD.from_json(json.loads(override.value)) - due = due.strftime("%Y-%m-%d %H:%M") + due = due.strftime(u"%Y-%m-%d %H:%M") fullname = override.student.profile.name data.append(dict(zip( header, @@ -204,7 +204,7 @@ def dump_module_extensions(course, unit): data.sort(key=lambda x: x[header[0]]) return { "header": header, - "title": _("Users with due date extensions for {0}").format( + "title": _(u"Users with due date extensions for {0}").format( title_or_url(unit)), "data": data } @@ -228,12 +228,12 @@ def dump_student_extensions(course, student): if location not in units: continue due = DATE_FIELD.from_json(json.loads(override.value)) - due = due.strftime("%Y-%m-%d %H:%M") + due = due.strftime(u"%Y-%m-%d %H:%M") title = title_or_url(units[location]) data.append(dict(zip(header, (title, due)))) return { "header": header, - "title": _("Due date extensions for {0} {1} ({2})").format( + "title": _(u"Due date extensions for {0} {1} ({2})").format( student.first_name, student.last_name, student.username), "data": data} diff --git a/lms/djangoapps/instructor_analytics/basic.py b/lms/djangoapps/instructor_analytics/basic.py index 3a5130c116c..30f22fb7e8e 100644 --- a/lms/djangoapps/instructor_analytics/basic.py +++ b/lms/djangoapps/instructor_analytics/basic.py @@ -22,6 +22,7 @@ from courseware.models import StudentModule from lms.djangoapps.grades.context import grading_context_for_course from lms.djangoapps.verify_student.services import IDVerificationService from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers +from openedx.core.djangolib.markup import HTML, Text from shoppingcart.models import ( CouponRedemption, CourseRegCodeItem, @@ -190,7 +191,7 @@ def issued_certificates(course_key, features): ] """ - report_run_date = datetime.date.today().strftime("%B %d, %Y") + report_run_date = datetime.date.today().strftime(u"%B %d, %Y") certificate_features = [x for x in CERTIFICATE_FEATURES if x in features] generated_certificates = list(GeneratedCertificate.eligible_certificates.filter( course_id=course_key, @@ -339,12 +340,12 @@ def get_proctored_exam_results(course_key, features): for status in comment_statuses: comment_list = exam_attempt.get( - '{status} Comments'.format(status=status), + u'{status} Comments'.format(status=status), [] ) proctored_exam.update({ - '{status} Count'.format(status=status): len(comment_list), - '{status} Comments'.format(status=status): '; '.join(comment_list), + u'{status} Count'.format(status=status): len(comment_list), + u'{status} Comments'.format(status=status): '; '.join(comment_list), }) return proctored_exam @@ -517,26 +518,26 @@ def dump_grading_context(course): msg += '\n' msg += "Graded sections:\n" for subgrader, category, weight in course.grader.subgraders: - msg += " subgrader=%s, type=%s, category=%s, weight=%s\n"\ + msg += u" subgrader=%s, type=%s, category=%s, weight=%s\n"\ % (subgrader.__class__, subgrader.type, category, weight) subgrader.index = 1 graders[subgrader.type] = subgrader msg += hbar - msg += "Listing grading context for course %s\n" % text_type(course.id) + msg += u"Listing grading context for course %s\n" % text_type(course.id) gcontext = grading_context_for_course(course) msg += "graded sections:\n" msg += '%s\n' % gcontext['all_graded_subsections_by_type'].keys() for (gsomething, gsvals) in gcontext['all_graded_subsections_by_type'].items(): - msg += "--> Section %s:\n" % (gsomething) + msg += u"--> Section %s:\n" % (gsomething) for sec in gsvals: sdesc = sec['subsection_block'] frmat = getattr(sdesc, 'format', None) aname = '' if frmat in graders: gform = graders[frmat] - aname = '%s %02d' % (gform.short_label, gform.index) + aname = u'%s %02d' % (gform.short_label, gform.index) gform.index += 1 elif sdesc.display_name in graders: gform = graders[sdesc.display_name] @@ -544,9 +545,9 @@ def dump_grading_context(course): notes = '' if getattr(sdesc, 'score_by_attempt', False): notes = ', score by attempt!' - msg += " %s (format=%s, Assignment=%s%s)\n"\ + msg += u" %s (format=%s, Assignment=%s%s)\n"\ % (sdesc.display_name, frmat, aname, notes) msg += "all graded blocks:\n" msg += "length=%d\n" % gcontext['count_all_graded_blocks'] - msg = '<pre>%s</pre>' % msg.replace('<', '<') + msg = HTML('<pre>{}</pre>').format(Text(msg)) return msg diff --git a/lms/djangoapps/instructor_analytics/csvs.py b/lms/djangoapps/instructor_analytics/csvs.py index 77fda1d07c8..f66e748bf68 100644 --- a/lms/djangoapps/instructor_analytics/csvs.py +++ b/lms/djangoapps/instructor_analytics/csvs.py @@ -21,7 +21,7 @@ def create_csv_response(filename, header, datarows): """ response = HttpResponse(content_type='text/csv') - response['Content-Disposition'] = 'attachment; filename={0}'.format(filename) + response['Content-Disposition'] = u'attachment; filename={0}'.format(filename) csvwriter = csv.writer( response, dialect='excel', diff --git a/lms/djangoapps/instructor_analytics/distributions.py b/lms/djangoapps/instructor_analytics/distributions.py index fe2394625a6..93d1c9bcb24 100644 --- a/lms/djangoapps/instructor_analytics/distributions.py +++ b/lms/djangoapps/instructor_analytics/distributions.py @@ -1,4 +1,4 @@ -""" +u""" Profile Distributions Aggregate sums for values of fields in students profiles. @@ -95,7 +95,7 @@ def profile_distribution(course_id, feature): if feature not in AVAILABLE_PROFILE_FEATURES: raise ValueError( - "unsupported feature requested for distribution '{}'".format( + u"unsupported feature requested for distribution u'{}'".format( feature) ) diff --git a/lms/djangoapps/instructor_analytics/tests/test_basic.py b/lms/djangoapps/instructor_analytics/tests/test_basic.py index cffbeed0e07..c59ea00d4cd 100644 --- a/lms/djangoapps/instructor_analytics/tests/test_basic.py +++ b/lms/djangoapps/instructor_analytics/tests/test_basic.py @@ -62,8 +62,8 @@ class TestAnalyticsBasic(ModuleStoreTestCase): self.instructor = InstructorFactory(course_key=self.course_key) for user in self.users: user.profile.meta = json.dumps({ - "position": "edX expert {}".format(user.id), - "company": "Open edX Inc {}".format(user.id), + "position": u"edX expert {}".format(user.id), + "company": u"Open edX Inc {}".format(user.id), }) user.profile.save() self.students_who_may_enroll = list(self.users) + [UserFactory() for _ in range(5)] @@ -125,8 +125,8 @@ class TestAnalyticsBasic(ModuleStoreTestCase): def test_enrolled_students_features_keys(self): query_features = ('username', 'name', 'email', 'city', 'country',) for user in self.users: - user.profile.city = "Mos Eisley {}".format(user.id) - user.profile.country = "Tatooine {}".format(user.id) + user.profile.city = u"Mos Eisley {}".format(user.id) + user.profile.country = u"Tatooine {}".format(user.id) user.profile.save() for feature in query_features: self.assertIn(feature, AVAILABLE_FEATURES) @@ -163,8 +163,8 @@ class TestAnalyticsBasic(ModuleStoreTestCase): self.assertEqual(len(userreports), len(self.users)) for userreport in userreports: self.assertEqual(set(userreport.keys()), set(query_features)) - self.assertIn(userreport['meta.position'], ["edX expert {}".format(user.id) for user in self.users]) - self.assertIn(userreport['meta.company'], ["Open edX Inc {}".format(user.id) for user in self.users]) + self.assertIn(userreport['meta.position'], [u"edX expert {}".format(user.id) for user in self.users]) + self.assertIn(userreport['meta.company'], [u"Open edX Inc {}".format(user.id) for user in self.users]) def test_enrolled_students_enrollment_verification(self): """ diff --git a/lms/djangoapps/instructor_analytics/tests/test_csvs.py b/lms/djangoapps/instructor_analytics/tests/test_csvs.py index 8a82bb0bab3..e7983a5fe95 100644 --- a/lms/djangoapps/instructor_analytics/tests/test_csvs.py +++ b/lms/djangoapps/instructor_analytics/tests/test_csvs.py @@ -16,7 +16,7 @@ class TestAnalyticsCSVS(TestCase): res = create_csv_response('robot.csv', header, datarows) self.assertEqual(res['Content-Type'], 'text/csv') - self.assertEqual(res['Content-Disposition'], 'attachment; filename={0}'.format('robot.csv')) + self.assertEqual(res['Content-Disposition'], u'attachment; filename={0}'.format('robot.csv')) self.assertEqual(res.content.strip(), '"Name","Email"') def test_create_csv_response(self): @@ -25,7 +25,7 @@ class TestAnalyticsCSVS(TestCase): res = create_csv_response('robot.csv', header, datarows) self.assertEqual(res['Content-Type'], 'text/csv') - self.assertEqual(res['Content-Disposition'], 'attachment; filename={0}'.format('robot.csv')) + self.assertEqual(res['Content-Disposition'], u'attachment; filename={0}'.format('robot.csv')) self.assertEqual(res.content.strip(), '"Name","Email"\r\n"Jim","jim@edy.org"\r\n"Jake","jake@edy.org"\r\n"Jeeves","jeeves@edy.org"') def test_create_csv_response_empty(self): @@ -34,7 +34,7 @@ class TestAnalyticsCSVS(TestCase): res = create_csv_response('robot.csv', header, datarows) self.assertEqual(res['Content-Type'], 'text/csv') - self.assertEqual(res['Content-Disposition'], 'attachment; filename={0}'.format('robot.csv')) + self.assertEqual(res['Content-Disposition'], u'attachment; filename={0}'.format('robot.csv')) self.assertEqual(res.content.strip(), '') @@ -79,7 +79,7 @@ class TestAnalyticsFormatDictlist(TestCase): res = create_csv_response('robot.csv', header, datarows) self.assertEqual(res['Content-Type'], 'text/csv') - self.assertEqual(res['Content-Disposition'], 'attachment; filename={0}'.format('robot.csv')) + self.assertEqual(res['Content-Disposition'], u'attachment; filename={0}'.format('robot.csv')) self.assertEqual(res.content.strip(), '"Name","Email"\r\n"Jim","jim@edy.org"\r\n"Jake","jake@edy.org"\r\n"Jeeves","jeeves@edy.org"') diff --git a/lms/djangoapps/instructor_task/api.py b/lms/djangoapps/instructor_task/api.py index 9cd38750d27..dda5be3c656 100644 --- a/lms/djangoapps/instructor_task/api.py +++ b/lms/djangoapps/instructor_task/api.py @@ -308,7 +308,7 @@ def submit_bulk_course_email(request, course_key, email_id): targets = Counter([target.target_type for target in email_obj.targets.all()]) targets = [ target if count <= 1 else - "{} {}".format(count, target) + u"{} {}".format(count, target) for target, count in targets.iteritems() ] diff --git a/lms/djangoapps/instructor_task/api_helper.py b/lms/djangoapps/instructor_task/api_helper.py index 1504ef747d3..ddd53ddc067 100644 --- a/lms/djangoapps/instructor_task/api_helper.py +++ b/lms/djangoapps/instructor_task/api_helper.py @@ -75,7 +75,7 @@ def _reserve_task(course_id, task_type, task_key, task_input, requester): """ if _task_is_running(course_id, task_type, task_key): - log.warning("Duplicate task found for task_type %s and task_key %s", task_type, task_key) + log.warning(u"Duplicate task found for task_type %s and task_key %s", task_type, task_key) error_message = generate_already_running_error_message(task_type) raise AlreadyRunningError(error_message) @@ -85,7 +85,7 @@ def _reserve_task(course_id, task_type, task_key, task_input, requester): most_recent_id = "None found" finally: log.warning( - "No duplicate tasks found: task_type %s, task_key %s, and most recent task_id = %s", + u"No duplicate tasks found: task_type %s, task_key %s, and most recent task_id = %s", task_type, task_key, most_recent_id @@ -118,7 +118,7 @@ def generate_already_running_error_message(task_type): if report_types.get(task_type): message = _( - "The {report_type} report is being created. " + u"The {report_type} report is being created. " "To view the status of the report, see Pending Tasks below. " "You will be able to download the report when it is complete." ).format(report_type=report_types.get(task_type)) @@ -213,20 +213,20 @@ def _update_instructor_task(instructor_task, task_result): elif result_state in [PROGRESS, SUCCESS]: # construct a status message directly from the task result's result: # it needs to go back with the entry passed in. - log.info("background task (%s), state %s: result: %s", task_id, result_state, returned_result) + log.info(u"background task (%s), state %s: result: %s", task_id, result_state, returned_result) task_output = InstructorTask.create_output_for_success(returned_result) elif result_state == FAILURE: # on failure, the result's result contains the exception that caused the failure exception = returned_result traceback = result_traceback if result_traceback is not None else '' - log.warning("background task (%s) failed: %s %s", task_id, returned_result, traceback) + log.warning(u"background task (%s) failed: %s %s", task_id, returned_result, traceback) task_output = InstructorTask.create_output_for_failure(exception, result_traceback) elif result_state == REVOKED: # on revocation, the result's result doesn't contain anything # but we cannot rely on the worker thread to set this status, # so we set it here. entry_needs_saving = True - log.warning("background task (%s) revoked.", task_id) + log.warning(u"background task (%s) revoked.", task_id) task_output = InstructorTask.create_output_for_revoked() # save progress and state into the entry, even if it's not being saved: @@ -256,7 +256,7 @@ def _handle_instructor_task_failure(instructor_task, error): """ Do required operations if task creation was not complete. """ - log.info("instructor task (%s) failed, result: %s", instructor_task.task_id, text_type(error)) + log.info(u"instructor task (%s) failed, result: %s", instructor_task.task_id, text_type(error)) _update_instructor_task_state(instructor_task, FAILURE, text_type(error)) raise QueueConnectionError() @@ -273,7 +273,7 @@ def get_updated_instructor_task(task_id): try: instructor_task = InstructorTask.objects.get(task_id=task_id) except InstructorTask.DoesNotExist: - log.warning("query for InstructorTask status failed: task_id=(%s) not found", task_id) + log.warning(u"query for InstructorTask status failed: task_id=(%s) not found", task_id) return None # if the task is not already known to be done, then we need to query diff --git a/lms/djangoapps/instructor_task/models.py b/lms/djangoapps/instructor_task/models.py index 2938e8d561d..612f07f075a 100644 --- a/lms/djangoapps/instructor_task/models.py +++ b/lms/djangoapps/instructor_task/models.py @@ -99,7 +99,7 @@ class InstructorTask(models.Model): # check length of task_input, and return an exception if it's too long: if len(json_task_input) > 265: - fmt = 'Task input longer than 265: "{input}" for "{task}" of "{course}"' + fmt = u'Task input longer than 265: "{input}" for "{task}" of "{course}"' msg = fmt.format(input=json_task_input, task=task_type, course=course_id) raise ValueError(msg) @@ -135,7 +135,7 @@ class InstructorTask(models.Model): # will fit in the column. In the meantime, just return an exception. json_output = json.dumps(returned_result) if len(json_output) > 1023: - raise ValueError("Length of task output is too long: {0}".format(json_output)) + raise ValueError(u"Length of task output is too long: {0}".format(json_output)) return json_output @staticmethod diff --git a/lms/djangoapps/instructor_task/subtasks.py b/lms/djangoapps/instructor_task/subtasks.py index fc209625ab3..206ea6ecd75 100644 --- a/lms/djangoapps/instructor_task/subtasks.py +++ b/lms/djangoapps/instructor_task/subtasks.py @@ -113,7 +113,7 @@ def _generate_items_for_subtask( # more items than items_per_task allows. We expect this to be a small enough # number as to be negligible. if num_items_queued != total_num_items: - TASK_LOG.info("Number of items generated by chunking %s not equal to original total %s", num_items_queued, total_num_items) + TASK_LOG.info(u"Number of items generated by chunking %s not equal to original total %s", num_items_queued, total_num_items) class SubtaskStatus(object): @@ -302,7 +302,7 @@ def queue_subtasks_for_query( # Update the InstructorTask with information about the subtasks we've defined. TASK_LOG.info( - "Task %s: updating InstructorTask %s with subtask info for %s subtasks to process %s items.", + u"Task %s: updating InstructorTask %s with subtask info for %s subtasks to process %s items.", task_id, entry.id, total_num_subtasks, @@ -325,7 +325,7 @@ def queue_subtasks_for_query( # Now create the subtasks, and start them running. TASK_LOG.info( - "Task %s: creating %s subtasks to process %s items.", + u"Task %s: creating %s subtasks to process %s items.", task_id, total_num_subtasks, total_num_items, @@ -359,7 +359,7 @@ def _acquire_subtask_lock(task_id): key = "subtask-{}".format(task_id) succeeded = cache.add(key, 'true', SUBTASK_LOCK_EXPIRE) if not succeeded: - TASK_LOG.warning("task_id '%s': already locked. Contains value '%s'", task_id, cache.get(key)) + TASK_LOG.warning(u"task_id '%s': already locked. Contains value '%s'", task_id, cache.get(key)) return succeeded @@ -401,7 +401,7 @@ def check_subtask_is_valid(entry_id, current_task_id, new_subtask_status): # Confirm that the InstructorTask actually defines subtasks. entry = InstructorTask.objects.get(pk=entry_id) if len(entry.subtasks) == 0: - format_str = "Unexpected task_id '{}': unable to find subtasks of instructor task '{}': rejecting task {}" + format_str = u"Unexpected task_id '{}': unable to find subtasks of instructor task '{}': rejecting task {}" msg = format_str.format(current_task_id, entry, new_subtask_status) TASK_LOG.warning(msg) raise DuplicateTaskException(msg) @@ -410,7 +410,7 @@ def check_subtask_is_valid(entry_id, current_task_id, new_subtask_status): subtask_dict = json.loads(entry.subtasks) subtask_status_info = subtask_dict['status'] if current_task_id not in subtask_status_info: - format_str = "Unexpected task_id '{}': unable to find status for subtask of instructor task '{}': rejecting task {}" + format_str = u"Unexpected task_id '{}': unable to find status for subtask of instructor task '{}': rejecting task {}" msg = format_str.format(current_task_id, entry, new_subtask_status) TASK_LOG.warning(msg) raise DuplicateTaskException(msg) @@ -420,7 +420,7 @@ def check_subtask_is_valid(entry_id, current_task_id, new_subtask_status): subtask_status = SubtaskStatus.from_dict(subtask_status_info[current_task_id]) subtask_state = subtask_status.state if subtask_state in READY_STATES: - format_str = "Unexpected task_id '{}': already completed - status {} for subtask of instructor task '{}': rejecting task {}" + format_str = u"Unexpected task_id '{}': already completed - status {} for subtask of instructor task '{}': rejecting task {}" msg = format_str.format(current_task_id, subtask_status, entry, new_subtask_status) TASK_LOG.warning(msg) raise DuplicateTaskException(msg) @@ -433,7 +433,7 @@ def check_subtask_is_valid(entry_id, current_task_id, new_subtask_status): new_retry_count = new_subtask_status.get_retry_count() current_retry_count = subtask_status.get_retry_count() if new_retry_count < current_retry_count: - format_str = "Unexpected task_id '{}': already retried - status {} for subtask of instructor task '{}': rejecting task {}" + format_str = u"Unexpected task_id '{}': already retried - status {} for subtask of instructor task '{}': rejecting task {}" msg = format_str.format(current_task_id, subtask_status, entry, new_subtask_status) TASK_LOG.warning(msg) raise DuplicateTaskException(msg) @@ -442,7 +442,7 @@ def check_subtask_is_valid(entry_id, current_task_id, new_subtask_status): # If it fails, then it means that another worker is already in the # middle of working on this. if not _acquire_subtask_lock(current_task_id): - format_str = "Unexpected task_id '{}': already being executed - for subtask of instructor task '{}'" + format_str = u"Unexpected task_id '{}': already being executed - for subtask of instructor task '{}'" msg = format_str.format(current_task_id, entry) TASK_LOG.warning(msg) raise DuplicateTaskException(msg) @@ -466,11 +466,11 @@ def update_subtask_status(entry_id, current_task_id, new_subtask_status, retry_c # If we fail, try again recursively. retry_count += 1 if retry_count < MAX_DATABASE_LOCK_RETRIES: - TASK_LOG.info("Retrying to update status for subtask %s of instructor task %d with status %s: retry %d", + TASK_LOG.info(u"Retrying to update status for subtask %s of instructor task %d with status %s: retry %d", current_task_id, entry_id, new_subtask_status, retry_count) update_subtask_status(entry_id, current_task_id, new_subtask_status, retry_count) else: - TASK_LOG.info("Failed to update status after %d retries for subtask %s of instructor task %d with status %s", + TASK_LOG.info(u"Failed to update status after %d retries for subtask %s of instructor task %d with status %s", retry_count, current_task_id, entry_id, new_subtask_status) raise finally: @@ -508,7 +508,7 @@ def _update_subtask_status(entry_id, current_task_id, new_subtask_status): is the value of the SubtaskStatus.to_dict(), but could be expanded in future to store information about failure messages, progress made, etc. """ - TASK_LOG.info("Preparing to update status for subtask %s for instructor task %d with status %s", + TASK_LOG.info(u"Preparing to update status for subtask %s for instructor task %d with status %s", current_task_id, entry_id, new_subtask_status) try: @@ -517,7 +517,7 @@ def _update_subtask_status(entry_id, current_task_id, new_subtask_status): subtask_status_info = subtask_dict['status'] if current_task_id not in subtask_status_info: # unexpected error -- raise an exception - format_str = "Unexpected task_id '{}': unable to update status for subtask of instructor task '{}'" + format_str = u"Unexpected task_id '{}': unable to update status for subtask of instructor task '{}'" msg = format_str.format(current_task_id, entry_id) TASK_LOG.warning(msg) raise ValueError(msg) @@ -564,7 +564,7 @@ def _update_subtask_status(entry_id, current_task_id, new_subtask_status): TASK_LOG.debug("about to save....") entry.save() - TASK_LOG.info("Task output updated to %s for subtask %s of instructor task %d", + TASK_LOG.info(u"Task output updated to %s for subtask %s of instructor task %d", entry.task_output, current_task_id, entry_id) except Exception: TASK_LOG.exception("Unexpected error while updating InstructorTask.") diff --git a/lms/djangoapps/instructor_task/tasks_base.py b/lms/djangoapps/instructor_task/tasks_base.py index 1b7419feaad..c650b809129 100644 --- a/lms/djangoapps/instructor_task/tasks_base.py +++ b/lms/djangoapps/instructor_task/tasks_base.py @@ -49,7 +49,7 @@ class BaseInstructorTask(Task): This is JSON-serialized and stored in the task_output column of the InstructorTask entry. """ - TASK_LOG.debug('Task %s: success returned with progress: %s', task_id, task_progress) + TASK_LOG.debug(u'Task %s: success returned with progress: %s', task_id, task_progress) # We should be able to find the InstructorTask object to update # based on the task_id here, without having to dig into the # original args to the task. On the other hand, the entry_id diff --git a/lms/djangoapps/instructor_task/tasks_helper/module_state.py b/lms/djangoapps/instructor_task/tasks_helper/module_state.py index 6508ff63e7e..5d20274720f 100644 --- a/lms/djangoapps/instructor_task/tasks_helper/module_state.py +++ b/lms/djangoapps/instructor_task/tasks_helper/module_state.py @@ -101,7 +101,7 @@ def perform_module_state_update(update_fcn, filter_fcn, _entry_id, course_id, ta elif update_status == UPDATE_STATUS_SKIPPED: task_progress.skipped += 1 else: - raise UpdateProblemModuleStateError("Unexpected update_status returned: {}".format(update_status)) + raise UpdateProblemModuleStateError(u"Unexpected update_status returned: {}".format(update_status)) return task_progress.update_task_state() @@ -141,7 +141,7 @@ def rescore_problem_module_state(xmodule_instance_args, module_descriptor, stude if instance is None: # Either permissions just changed, or someone is trying to be clever # and load something they shouldn't have access to. - msg = "No module {location} for student {student}--access denied?".format( + msg = u"No module {location} for student {student}--access denied?".format( location=usage_key, student=student ) @@ -151,7 +151,7 @@ def rescore_problem_module_state(xmodule_instance_args, module_descriptor, stude if not hasattr(instance, 'rescore'): # This should not happen, since it should be already checked in the # caller, but check here to be sure. - msg = "Specified module {0} of type {1} does not support rescoring.".format(usage_key, instance.__class__) + msg = u"Specified module {0} of type {1} does not support rescoring.".format(usage_key, instance.__class__) raise UpdateProblemModuleStateError(msg) # We check here to see if the problem has any submissions. If it does not, we don't want to rescore it @@ -226,7 +226,7 @@ def override_score_module_state(xmodule_instance_args, module_descriptor, studen if instance is None: # Either permissions just changed, or someone is trying to be clever # and load something they shouldn't have access to. - msg = "No module {location} for student {student}--access denied?".format( + msg = u"No module {location} for student {student}--access denied?".format( location=usage_key, student=student ) diff --git a/lms/djangoapps/instructor_task/tests/test_base.py b/lms/djangoapps/instructor_task/tests/test_base.py index 80bad8b4c5c..ad48703176f 100644 --- a/lms/djangoapps/instructor_task/tests/test_base.py +++ b/lms/djangoapps/instructor_task/tests/test_base.py @@ -219,7 +219,7 @@ class InstructorTaskModuleTestCase(InstructorTaskCourseTestCase): Returns the factory args for the option problem type. """ return { - 'question_text': 'The correct answer is {0}'.format(correct_answer), + 'question_text': u'The correct answer is {0}'.format(correct_answer), 'options': [OPTION_1, OPTION_2], 'correct_option': correct_answer, 'num_responses': num_responses, diff --git a/lms/djangoapps/instructor_task/tests/test_integration.py b/lms/djangoapps/instructor_task/tests/test_integration.py index 770e25ffc20..6cd1e550b34 100644 --- a/lms/djangoapps/instructor_task/tests/test_integration.py +++ b/lms/djangoapps/instructor_task/tests/test_integration.py @@ -354,7 +354,7 @@ class TestRescoringTask(TestIntegrationTask): to not-equals). """ factory = CustomResponseXMLFactory() - script = textwrap.dedent(""" + script = textwrap.dedent(u""" def check_func(expect, answer_given): expected = str(random.randint(0, 100)) return {'ok': answer_given %s expected, 'msg': expected} @@ -400,7 +400,7 @@ class TestRescoringTask(TestIntegrationTask): module = self.get_student_module(user.username, descriptor) state = json.loads(module.state) correct_map = state['correct_map'] - log.info("Correct Map: %s", correct_map) + log.info(u"Correct Map: %s", correct_map) # only one response, so pull it out: answer = correct_map.values()[0]['msg'] self.submit_student_answer(user.username, problem_url_name, [answer, answer]) @@ -596,7 +596,7 @@ class TestGradeReportConditionalContent(TestReportMixin, TestConditionalContent, def user_partition_group(user): """Return a dict having single key with value equals to students group in partition""" - group_config_hdr_tpl = 'Experiment Group ({})' + group_config_hdr_tpl = u'Experiment Group ({})' return { group_config_hdr_tpl.format(self.partition.name): self.partition.scheme.get_group_for_user( self.course.id, user, self.partition diff --git a/lms/djangoapps/instructor_task/tests/test_tasks.py b/lms/djangoapps/instructor_task/tests/test_tasks.py index 87a618870e7..471a1e811a3 100644 --- a/lms/djangoapps/instructor_task/tests/test_tasks.py +++ b/lms/djangoapps/instructor_task/tests/test_tasks.py @@ -433,7 +433,7 @@ class TestRescoreInstructorTask(TestInstructorTasks): entry = InstructorTask.objects.get(id=task_entry.id) output = json.loads(entry.task_output) self.assertEquals(output['exception'], "UpdateProblemModuleStateError") - self.assertEquals(output['message'], "Specified module {0} of type {1} does not support rescoring.".format( + self.assertEquals(output['message'], u"Specified module {0} of type {1} does not support rescoring.".format( self.location, mock_instance.__class__, )) diff --git a/lms/djangoapps/instructor_task/tests/test_tasks_helper.py b/lms/djangoapps/instructor_task/tests/test_tasks_helper.py index 858ed24245c..cf2b660f23b 100644 --- a/lms/djangoapps/instructor_task/tests/test_tasks_helper.py +++ b/lms/djangoapps/instructor_task/tests/test_tasks_helper.py @@ -1079,10 +1079,10 @@ class TestProblemReportSplitTestContent(TestReportMixin, TestConditionalContent, self.course = CourseFactory.create( grading_policy={ "GRADER": [{ - "type": "Homework %d" % i, + "type": u"Homework %d" % i, "min_count": 1, "drop_count": 0, - "short_label": "HW %d" % i, + "short_label": u"HW %d" % i, "weight": 1.0 } for i in xrange(1, grader_num)] } @@ -1097,10 +1097,10 @@ class TestProblemReportSplitTestContent(TestReportMixin, TestConditionalContent, problem_vertical_list = [] for i in xrange(1, grader_num): - chapter_name = 'Chapter %d' % i - problem_section_name = 'Problem section %d' % i - problem_section_format = 'Homework %d' % i - problem_vertical_name = 'Problem Unit %d' % i + chapter_name = u'Chapter %d' % i + problem_section_name = u'Problem section %d' % i + problem_section_format = u'Homework %d' % i + problem_vertical_name = u'Problem Unit %d' % i chapter = ItemFactory.create(parent_location=self.course.location, display_name=chapter_name) @@ -1124,7 +1124,7 @@ class TestProblemReportSplitTestContent(TestReportMixin, TestConditionalContent, for i in xrange(1, grader_num): problem_url = 'test_problem_%d' % i self.define_option_problem(problem_url, parent=problem_vertical_list[i - 1]) - title = 'Homework %d 1: Problem section %d - %s' % (i, i, problem_url) + title = u'Homework %d 1: Problem section %d - %s' % (i, i, problem_url) problem_names.append(title) header_row = [u'Student ID', u'Email', u'Username', u'Enrollment Status', u'Grade'] diff --git a/lms/djangoapps/instructor_task/tests/test_views.py b/lms/djangoapps/instructor_task/tests/test_views.py index c1fa1ece192..137a705f9b3 100644 --- a/lms/djangoapps/instructor_task/tests/test_views.py +++ b/lms/djangoapps/instructor_task/tests/test_views.py @@ -366,7 +366,7 @@ class InstructorTaskReportTest(InstructorTaskTestCase): def test_get_info_for_broken_output(self): # check for non-JSON task_output instructor_task = self._create_success_entry() - instructor_task.task_output = "{ bad" + instructor_task.task_output = u"{ bad" succeeded, message = get_task_completion_info(instructor_task) self.assertFalse(succeeded) self.assertEquals(message, "No parsable status information available") @@ -382,7 +382,7 @@ class InstructorTaskReportTest(InstructorTaskTestCase): def test_get_info_for_broken_input(self): # check for non-JSON task_input, but then just ignore it instructor_task = self._create_success_entry() - instructor_task.task_input = "{ bad" + instructor_task.task_input = u"{ bad" succeeded, message = get_task_completion_info(instructor_task) self.assertFalse(succeeded) self.assertEquals(message, "Status: rescored 2 of 3 (out of 5)") diff --git a/lms/djangoapps/instructor_task/views.py b/lms/djangoapps/instructor_task/views.py index f272651f65f..36e10d46180 100644 --- a/lms/djangoapps/instructor_task/views.py +++ b/lms/djangoapps/instructor_task/views.py @@ -106,13 +106,13 @@ def get_task_completion_info(instructor_task): # we're more surprised if there is no output for a completed task, but just warn: if instructor_task.task_output is None: - log.warning(_("No task_output information found for instructor_task {0}").format(instructor_task.task_id)) + log.warning(_(u"No task_output information found for instructor_task {0}").format(instructor_task.task_id)) return (succeeded, _("No status information available")) try: task_output = json.loads(instructor_task.task_output) except ValueError: - fmt = _("No parsable task_output information found for instructor_task {0}: {1}") + fmt = _(u"No parsable task_output information found for instructor_task {0}: {1}") log.warning(fmt.format(instructor_task.task_id, instructor_task.task_output)) return (succeeded, _("No parsable status information available")) @@ -120,7 +120,7 @@ def get_task_completion_info(instructor_task): return (succeeded, task_output.get('message', _('No message provided'))) if any([key not in task_output for key in ['action_name', 'attempted', 'total']]): - fmt = _("Invalid task_output information found for instructor_task {0}: {1}") + fmt = _(u"Invalid task_output information found for instructor_task {0}: {1}") log.warning(fmt.format(instructor_task.task_id, instructor_task.task_output)) return (succeeded, _("No progress status information available")) @@ -141,7 +141,7 @@ def get_task_completion_info(instructor_task): try: task_input = json.loads(instructor_task.task_input) except ValueError: - fmt = _("No parsable task_input information found for instructor_task {0}: {1}") + fmt = _(u"No parsable task_input information found for instructor_task {0}: {1}") log.warning(fmt.format(instructor_task.task_id, instructor_task.task_input)) else: student = task_input.get('student') @@ -152,72 +152,72 @@ def get_task_completion_info(instructor_task): if instructor_task.task_state == PROGRESS: # special message for providing progress updates: # Translators: {action} is a past-tense verb that is localized separately. {attempted} and {succeeded} are counts. - msg_format = _("Progress: {action} {succeeded} of {attempted} so far") + msg_format = _(u"Progress: {action} {succeeded} of {attempted} so far") elif student is not None and problem_url is not None: # this reports on actions on problems for a particular student: if num_attempted == 0: # Translators: {action} is a past-tense verb that is localized separately. {student} is a student identifier. - msg_format = _("Unable to find submission to be {action} for student '{student}'") + msg_format = _(u"Unable to find submission to be {action} for student '{student}'") elif num_succeeded == 0: # Translators: {action} is a past-tense verb that is localized separately. {student} is a student identifier. - msg_format = _("Problem failed to be {action} for student '{student}'") + msg_format = _(u"Problem failed to be {action} for student '{student}'") else: succeeded = True # Translators: {action} is a past-tense verb that is localized separately. {student} is a student identifier. - msg_format = _("Problem successfully {action} for student '{student}'") + msg_format = _(u"Problem successfully {action} for student '{student}'") elif student is not None and entrance_exam_url is not None: # this reports on actions on entrance exam for a particular student: if num_attempted == 0: # Translators: {action} is a past-tense verb that is localized separately. # {student} is a student identifier. - msg_format = _("Unable to find entrance exam submission to be {action} for student '{student}'") + msg_format = _(u"Unable to find entrance exam submission to be {action} for student '{student}'") else: succeeded = True # Translators: {action} is a past-tense verb that is localized separately. # {student} is a student identifier. - msg_format = _("Entrance exam successfully {action} for student '{student}'") + msg_format = _(u"Entrance exam successfully {action} for student '{student}'") elif student is None and problem_url is not None: # this reports on actions on problems for all students: if num_attempted == 0: # Translators: {action} is a past-tense verb that is localized separately. - msg_format = _("Unable to find any students with submissions to be {action}") + msg_format = _(u"Unable to find any students with submissions to be {action}") elif num_succeeded == 0: # Translators: {action} is a past-tense verb that is localized separately. {attempted} is a count. - msg_format = _("Problem failed to be {action} for any of {attempted} students") + msg_format = _(u"Problem failed to be {action} for any of {attempted} students") elif num_succeeded == num_attempted: succeeded = True # Translators: {action} is a past-tense verb that is localized separately. {attempted} is a count. - msg_format = _("Problem successfully {action} for {attempted} students") + msg_format = _(u"Problem successfully {action} for {attempted} students") else: # num_succeeded < num_attempted # Translators: {action} is a past-tense verb that is localized separately. {succeeded} and {attempted} are counts. - msg_format = _("Problem {action} for {succeeded} of {attempted} students") + msg_format = _(u"Problem {action} for {succeeded} of {attempted} students") elif email_id is not None: # this reports on actions on bulk emails if num_attempted == 0: # Translators: {action} is a past-tense verb that is localized separately. - msg_format = _("Unable to find any recipients to be {action}") + msg_format = _(u"Unable to find any recipients to be {action}") elif num_succeeded == 0: # Translators: {action} is a past-tense verb that is localized separately. {attempted} is a count. - msg_format = _("Message failed to be {action} for any of {attempted} recipients ") + msg_format = _(u"Message failed to be {action} for any of {attempted} recipients ") elif num_succeeded == num_attempted: succeeded = True # Translators: {action} is a past-tense verb that is localized separately. {attempted} is a count. - msg_format = _("Message successfully {action} for {attempted} recipients") + msg_format = _(u"Message successfully {action} for {attempted} recipients") else: # num_succeeded < num_attempted # Translators: {action} is a past-tense verb that is localized separately. {succeeded} and {attempted} are counts. - msg_format = _("Message {action} for {succeeded} of {attempted} recipients") + msg_format = _(u"Message {action} for {succeeded} of {attempted} recipients") else: # provide a default: # Translators: {action} is a past-tense verb that is localized separately. {succeeded} and {attempted} are counts. - msg_format = _("Status: {action} {succeeded} of {attempted}") + msg_format = _(u"Status: {action} {succeeded} of {attempted}") if num_skipped > 0: # Translators: {skipped} is a count. This message is appended to task progress status messages. - msg_format += _(" (skipping {skipped})") + msg_format += _(u" (skipping {skipped})") if student is None and num_attempted != num_total: # Translators: {total} is a count. This message is appended to task progress status messages. - msg_format += _(" (out of {total})") + msg_format += _(u" (out of {total})") # Update status in task result object itself: message = msg_format.format( diff --git a/lms/djangoapps/learner_dashboard/tests/test_programs.py b/lms/djangoapps/learner_dashboard/tests/test_programs.py index 634b5cbaeb1..78c741e8630 100644 --- a/lms/djangoapps/learner_dashboard/tests/test_programs.py +++ b/lms/djangoapps/learner_dashboard/tests/test_programs.py @@ -36,7 +36,7 @@ def load_serialized_data(response, key): """ Extract and deserialize serialized data from the response. """ - pattern = re.compile(r'{key}: (?P<data>\[.*\])'.format(key=key)) + pattern = re.compile(ur'{key}: (?P<data>\[.*\])'.format(key=key)) match = pattern.search(response.content) serialized = match.group('data') @@ -215,7 +215,7 @@ class TestProgramDetails(ProgramsApiConfigMixin, CatalogIntegrationMixin, Shared self.assertContains(response, 'programData') self.assertContains(response, 'urls') self.assertContains(response, - '"program_record_url": "{}/records/programs/'.format(CREDENTIALS_PUBLIC_SERVICE_URL)) + u'"program_record_url": "{}/records/programs/'.format(CREDENTIALS_PUBLIC_SERVICE_URL)) self.assertContains(response, 'program_listing_url') self.assertContains(response, self.program_data['title']) self.assert_programs_tab_present(response) diff --git a/lms/djangoapps/lms_xblock/mixin.py b/lms/djangoapps/lms_xblock/mixin.py index 9eb49423762..4c415eab0de 100644 --- a/lms/djangoapps/lms_xblock/mixin.py +++ b/lms/djangoapps/lms_xblock/mixin.py @@ -155,7 +155,7 @@ class LmsBlockMixin(XBlockMixin): if user_partition.id == user_partition_id: return user_partition - raise NoSuchUserPartitionError("could not find a UserPartition with ID [{}]".format(user_partition_id)) + raise NoSuchUserPartitionError(u"could not find a UserPartition with ID [{}]".format(user_partition_id)) def _has_nonsensical_access_settings(self): """ diff --git a/lms/djangoapps/lms_xblock/runtime.py b/lms/djangoapps/lms_xblock/runtime.py index d25516995b5..8cb9f240d3c 100644 --- a/lms/djangoapps/lms_xblock/runtime.py +++ b/lms/djangoapps/lms_xblock/runtime.py @@ -35,7 +35,7 @@ def handler_url(block, handler_name, suffix='', query='', thirdparty=False): # to ask for handler URLs without a student context. func = getattr(block.__class__, handler_name, None) if not func: - raise ValueError("{!r} is not a function name".format(handler_name)) + raise ValueError(u"{!r} is not a function name".format(handler_name)) # Is the following necessary? ProxyAttribute causes an UndefinedContext error # if trying this without the module system. @@ -104,7 +104,7 @@ class UserTagsService(object): key: the key for the value we want """ if scope != user_course_tag_api.COURSE_SCOPE: - raise ValueError("unexpected scope {0}".format(scope)) + raise ValueError(u"unexpected scope {0}".format(scope)) return user_course_tag_api.get_course_tag( self._get_current_user(), @@ -120,7 +120,7 @@ class UserTagsService(object): value: the value to set """ if scope != user_course_tag_api.COURSE_SCOPE: - raise ValueError("unexpected scope {0}".format(scope)) + raise ValueError(u"unexpected scope {0}".format(scope)) return user_course_tag_api.set_course_tag( self._get_current_user(), diff --git a/lms/djangoapps/lti_provider/outcomes.py b/lms/djangoapps/lti_provider/outcomes.py index a69fede350b..892dac39a6c 100644 --- a/lms/djangoapps/lti_provider/outcomes.py +++ b/lms/djangoapps/lti_provider/outcomes.py @@ -37,9 +37,9 @@ def store_outcome_parameters(request_params, user, lti_consumer): # to figure out the result service URL. As it stands, though, this # is a badly-formed LTI request log.warn( - "Outcome Service: lis_outcome_service_url parameter missing " - "from scored assignment; we will be unable to return a score. " - "Request parameters: %s", + u"Outcome Service: lis_outcome_service_url parameter missing " + u"from scored assignment; we will be unable to return a score. " + u"Request parameters: %s", request_params ) return @@ -140,8 +140,8 @@ def send_score_update(assignment, score): # necessary. if not (response and check_replace_result_response(response)): log.error( - "Outcome Service: Failed to update score on LTI consumer. " - "User: %s, course: %s, usage: %s, score: %s, status: %s, body: %s", + u"Outcome Service: Failed to update score on LTI consumer. " + u"User: %s, course: %s, usage: %s, score: %s, status: %s, body: %s", assignment.user, assignment.course_key, assignment.usage_key, @@ -190,7 +190,7 @@ def check_replace_result_response(response): # Pylint doesn't recognize members in the LXML module if response.status_code != 200: log.error( - "Outcome service response: Unexpected status code %s", + u"Outcome service response: Unexpected status code %s", response.status_code ) return False @@ -199,7 +199,7 @@ def check_replace_result_response(response): xml = response.content root = etree.fromstring(xml) except etree.ParseError as ex: - log.error("Outcome service response: Failed to parse XML: %s\n %s", ex, xml) + log.error(u"Outcome service response: Failed to parse XML: %s\n %s", ex, xml) return False major_codes = root.xpath( @@ -207,14 +207,14 @@ def check_replace_result_response(response): namespaces={'ns': 'http://www.imsglobal.org/services/ltiv1p1/xsd/imsoms_v1p0'}) if len(major_codes) != 1: log.error( - "Outcome service response: Expected exactly one imsx_codeMajor field in response. Received %s", + u"Outcome service response: Expected exactly one imsx_codeMajor field in response. Received %s", major_codes ) return False if major_codes[0].text != 'success': log.error( - "Outcome service response: Unexpected major code: %s.", + u"Outcome service response: Unexpected major code: %s.", major_codes[0].text ) return False diff --git a/lms/djangoapps/lti_provider/signals.py b/lms/djangoapps/lti_provider/signals.py index ff7eaceb19a..f6975fb5892 100644 --- a/lms/djangoapps/lti_provider/signals.py +++ b/lms/djangoapps/lti_provider/signals.py @@ -62,7 +62,7 @@ def score_changed_handler(sender, **kwargs): # pylint: disable=unused-argument ) else: log.error( - "Outcome Service: Required signal parameter is None. " + u"Outcome Service: Required signal parameter is None. " "points_possible: %s, points_earned: %s, user_id: %s, " "course_id: %s, usage_id: %s", points_possible, points_earned, user_id, course_id, usage_id diff --git a/lms/djangoapps/lti_provider/tasks.py b/lms/djangoapps/lti_provider/tasks.py index 6839ef154fb..d0a4ef61bce 100644 --- a/lms/djangoapps/lti_provider/tasks.py +++ b/lms/djangoapps/lti_provider/tasks.py @@ -45,7 +45,7 @@ def send_composite_outcome(user_id, course_id, assignment_id, version): assignment = GradedAssignment.objects.get(id=assignment_id) if version != assignment.version_number: log.info( - "Score passback for GradedAssignment %s skipped. More recent score available.", + u"Score passback for GradedAssignment %s skipped. More recent score available.", assignment.id ) return diff --git a/lms/djangoapps/lti_provider/tests/test_outcomes.py b/lms/djangoapps/lti_provider/tests/test_outcomes.py index 88dae5d598c..0d8b9980385 100644 --- a/lms/djangoapps/lti_provider/tests/test_outcomes.py +++ b/lms/djangoapps/lti_provider/tests/test_outcomes.py @@ -187,7 +187,7 @@ class XmlHandlingTest(TestCase): """ shard = 4 - response_xml = """ + response_xml = u""" <imsx_POXEnvelopeResponse xmlns = "http://www.imsglobal.org/services/ltiv1p1/xsd/imsoms_v1p0"> <imsx_POXHeader> <imsx_POXResponseHeaderInfo> diff --git a/lms/djangoapps/lti_provider/tests/test_users.py b/lms/djangoapps/lti_provider/tests/test_users.py index b326161d730..e4500917887 100644 --- a/lms/djangoapps/lti_provider/tests/test_users.py +++ b/lms/djangoapps/lti_provider/tests/test_users.py @@ -68,7 +68,7 @@ class UserManagementHelperTest(TestCase): for char in range(len(username)): self.assertIn( username[char], string.ascii_letters + string.digits, - "Username has forbidden character '{}'".format(username[char]) + u"Username has forbidden character '{}'".format(username[char]) ) diff --git a/lms/djangoapps/lti_provider/views.py b/lms/djangoapps/lti_provider/views.py index cc32e1a78c2..05c39b9bed4 100644 --- a/lms/djangoapps/lti_provider/views.py +++ b/lms/djangoapps/lti_provider/views.py @@ -76,7 +76,7 @@ def lti_launch(request, course_id, usage_id): course_key, usage_key = parse_course_and_usage_keys(course_id, usage_id) except InvalidKeyError: log.error( - 'Invalid course key %s or usage key %s from request %s', + u'Invalid course key %s or usage key %s from request %s', course_id, usage_id, request diff --git a/lms/djangoapps/mailing/management/commands/mailchimp_id.py b/lms/djangoapps/mailing/management/commands/mailchimp_id.py index dfc24f2a785..75ed9a55877 100644 --- a/lms/djangoapps/mailing/management/commands/mailchimp_id.py +++ b/lms/djangoapps/mailing/management/commands/mailchimp_id.py @@ -42,8 +42,8 @@ class Command(BaseCommand): list_with_id = by_web_id.get(web_id, None) if list_with_id: - print("id: {} for web_id: {}".format(list_with_id['id'], web_id)) - print("list name: {}".format(list_with_id['name'])) + print(u"id: {} for web_id: {}".format(list_with_id['id'], web_id)) + print(u"list name: {}".format(list_with_id['name'])) else: - print("list with web_id: {} not found.".format(web_id)) + print(u"list with web_id: {} not found.".format(web_id)) sys.exit(1) diff --git a/lms/djangoapps/mailing/management/commands/mailchimp_sync_course.py b/lms/djangoapps/mailing/management/commands/mailchimp_sync_course.py index e7ee5070ce6..3c4f117f146 100644 --- a/lms/djangoapps/mailing/management/commands/mailchimp_sync_course.py +++ b/lms/djangoapps/mailing/management/commands/mailchimp_sync_course.py @@ -54,7 +54,7 @@ class Command(BaseCommand): course_id = options['course_id'] num_segments = options['num_segments'] - log.info('Syncronizing email list for %s', course_id) + log.info(u'Syncronizing email list for %s', course_id) mailchimp = connect_mailchimp(key) @@ -106,7 +106,7 @@ def verify_list(mailchimp, list_id, course_id): list_name = lists[0]['name'] - log.debug('list name: %s', list_name) + log.debug(u'list name: %s', list_name) # check that we are connecting to the correct list parts = course_id.replace('_', ' ').replace('/', ' ').split() @@ -294,7 +294,7 @@ def subscribe_with_data(mailchimp, list_id, user_data): update_existing=True) log.debug( - "Added: %s Error on: %s", result['add_count'], result['error_count'] + u"Added: %s Error on: %s", result['add_count'], result['error_count'] ) diff --git a/lms/djangoapps/mobile_api/video_outlines/views.py b/lms/djangoapps/mobile_api/video_outlines/views.py index 3244f9d12b8..168178cd6dc 100644 --- a/lms/djangoapps/mobile_api/video_outlines/views.py +++ b/lms/djangoapps/mobile_api/video_outlines/views.py @@ -122,6 +122,6 @@ class VideoTranscripts(generics.RetrieveAPIView): raise Http404(u'Transcript not found for {}, lang: {}'.format(block_id, lang)) response = HttpResponse(content, content_type=mimetype) - response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename.encode('utf-8')) + response['Content-Disposition'] = u'attachment; filename="{}"'.format(filename) return response diff --git a/lms/djangoapps/notes/api.py b/lms/djangoapps/notes/api.py index e59b220fb9f..ed736d5501a 100644 --- a/lms/djangoapps/notes/api.py +++ b/lms/djangoapps/notes/api.py @@ -57,7 +57,7 @@ def api_request(request, course_id, **kwargs): # Verify that the api should be accessible to this course if not api_enabled(request, course_key): - log.debug('Notes are disabled for course: {0}'.format(course_id)) + log.debug(u'Notes are disabled for course: {0}'.format(course_id)) raise Http404 # Locate the requested resource @@ -67,21 +67,21 @@ def api_request(request, course_id, **kwargs): resource = resource_map.get(resource_name) if resource is None: - log.debug('Resource "{0}" does not exist'.format(resource_name)) + log.debug(u'Resource "{0}" does not exist'.format(resource_name)) raise Http404 if resource_method not in list(resource.keys()): - log.debug('Resource "{0}" does not support method "{1}"'.format(resource_name, resource_method)) + log.debug(u'Resource "{0}" does not support method "{1}"'.format(resource_name, resource_method)) raise Http404 # Execute the action associated with the resource func = resource.get(resource_method) module = globals() if func not in module: - log.debug('Function "{0}" does not exist for request {1} {2}'.format(func, resource_method, resource_name)) + log.debug(u'Function "{0}" does not exist for request {1} {2}'.format(func, resource_method, resource_name)) raise Http404 - log.debug('API request: {0} {1}'.format(resource_method, resource_name)) + log.debug(u'API request: {0} {1}'.format(resource_method, resource_name)) api_response = module[func](request, course_key, **kwargs) http_response = api_format(api_response) @@ -104,7 +104,7 @@ def api_format(api_response): http_response['Content-type'] = content_type http_response.content = content - log.debug('API response type: {0} content: {1}'.format(content_type, content)) + log.debug(u'API response type: {0} content: {1}'.format(content_type, content)) return http_response diff --git a/lms/djangoapps/rss_proxy/views.py b/lms/djangoapps/rss_proxy/views.py index 15a2a54dd94..1028cfcb834 100644 --- a/lms/djangoapps/rss_proxy/views.py +++ b/lms/djangoapps/rss_proxy/views.py @@ -24,7 +24,7 @@ def proxy(request): status_code = 200 rss = cache.get(cache_key, '') print(cache_key) - print('Cached rss: %s' % rss) + print(u'Cached rss: %s' % rss) if not rss: # Go get the RSS from the URL if it was not cached resp = requests.get(url) diff --git a/lms/djangoapps/shoppingcart/admin.py b/lms/djangoapps/shoppingcart/admin.py index 0cf9e20df09..563a5800f56 100644 --- a/lms/djangoapps/shoppingcart/admin.py +++ b/lms/djangoapps/shoppingcart/admin.py @@ -43,8 +43,8 @@ class SoftDeleteCouponAdmin(admin.ModelAdmin): if queryset.count() == 1: message_bit = "1 coupon entry was" else: - message_bit = "%s coupon entries were" % queryset.count() - self.message_user(request, "%s successfully deleted." % message_bit) + message_bit = u"%s coupon entries were" % queryset.count() + self.message_user(request, u"%s successfully deleted." % message_bit) def delete_model(self, request, obj): """override the default behavior of single instance of model delete method""" diff --git a/lms/djangoapps/shoppingcart/management/commands/retire_order.py b/lms/djangoapps/shoppingcart/management/commands/retire_order.py index 2113aad8859..2f7be94076a 100644 --- a/lms/djangoapps/shoppingcart/management/commands/retire_order.py +++ b/lms/djangoapps/shoppingcart/management/commands/retire_order.py @@ -37,11 +37,11 @@ class Command(BaseCommand): try: order.retire() except (UnexpectedOrderItemStatus, InvalidStatusToRetire) as err: - print("Did not retire order {order}: {message}".format( + print(u"Did not retire order {order}: {message}".format( order=order.id, message=text_type(err) )) else: - print("retired order {order_id} from status {old_status} to status {new_status}".format( + print(u"retired order {order_id} from status {old_status} to status {new_status}".format( order_id=order.id, old_status=old_status, new_status=order.status, diff --git a/lms/djangoapps/shoppingcart/models.py b/lms/djangoapps/shoppingcart/models.py index b6642492716..c5967fd3bea 100644 --- a/lms/djangoapps/shoppingcart/models.py +++ b/lms/djangoapps/shoppingcart/models.py @@ -193,7 +193,7 @@ class Order(models.Model): Also removes any code redemption associated with the order_item """ if item.order.status == 'cart': - log.info("order item %s removed for user %s", str(item.id), user) + log.info(u"order item %s removed for user %s", str(item.id), user) item.delete() # remove any redemption entry associated with the item CouponRedemption.remove_code_redemption_from_item(item, user) @@ -364,7 +364,7 @@ class Order(models.Model): if not is_order_type_business: subject = _("Order Payment Confirmation") else: - subject = _('Confirmation and Registration Codes for the following courses: {course_name_list}').format( + subject = _(u'Confirmation and Registration Codes for the following courses: {course_name_list}').format( course_name_list=joined_course_names ) @@ -390,7 +390,7 @@ class Order(models.Model): 'course_names': ", ".join(course_names), 'dashboard_url': dashboard_url, 'currency_symbol': settings.PAID_COURSE_REGISTRATION_CURRENCY[1], - 'order_placed_by': '{username} ({email})'.format( + 'order_placed_by': u'{username} ({email})'.format( username=self.user.username, email=self.user.email ), 'has_billing_info': settings.FEATURES['STORE_BILLING_INFO'], @@ -421,7 +421,7 @@ class Order(models.Model): email.attach(u'pdf_not_available.txt', file_buffer.getvalue(), 'text/plain') email.send() except (smtplib.SMTPException, BotoServerError): # sadly need to handle diff. mail backends individually - log.error('Failed sending confirmation e-mail for order %d', self.id) + log.error(u'Failed sending confirmation e-mail for order %d', self.id) def purchase(self, first='', last='', street1='', street2='', city='', state='', postalcode='', country='', ccnum='', cardtype='', processor_reply_dump=''): @@ -597,7 +597,7 @@ class Order(models.Model): if self.status not in ORDER_STATUS_MAP.keys(): raise InvalidStatusToRetire( - "order status {order_status} is not 'paying' or 'cart'".format( + u"order status {order_status} is not 'paying' or 'cart'".format( order_status=self.status ) ) @@ -1344,7 +1344,7 @@ class Coupon(models.Model): """ return the coupon expiration date in the readable format """ - return (self.expiration_date - timedelta(days=1)).strftime("%B %d, %Y") if self.expiration_date else None + return (self.expiration_date - timedelta(days=1)).strftime(u"%B %d, %Y") if self.expiration_date else None class CouponRedemption(models.Model): @@ -1537,7 +1537,7 @@ class PaidCourseRegistration(OrderItem): # throw errors if it doesn't. course = modulestore().get_course(course_id) if not course: - log.error("User {} tried to add non-existent course {} to cart id {}" + log.error(u"User {} tried to add non-existent course {} to cart id {}" .format(order.user.email, course_id, order.id)) raise CourseDoesNotExistException @@ -1551,7 +1551,7 @@ class PaidCourseRegistration(OrderItem): raise ItemAlreadyInCartException if CourseEnrollment.is_enrolled(user=order.user, course_key=course_id): - log.warning("User {} trying to add course {} to cart id {}, already registered" + log.warning(u"User {} trying to add course {} to cart id {}, already registered" .format(order.user.email, course_id, order.id)) raise AlreadyEnrolledInCourseException @@ -1581,7 +1581,7 @@ class PaidCourseRegistration(OrderItem): item.report_comments = item.csv_report_comments order.save() item.save() - log.info("User {} added course registration {} to cart: order {}" + log.info(u"User {} added course registration {} to cart: order {}" .format(order.user.email, course_id, order.id)) CourseEnrollment.send_signal_full(EnrollStatusChange.paid_start, @@ -1605,7 +1605,7 @@ class PaidCourseRegistration(OrderItem): self.course_enrollment = CourseEnrollment.enroll(user=self.user, course_key=self.course_id, mode=self.mode) self.save() - log.info("Enrolled {0} in paid course {1}, paid ${2}" + log.info(u"Enrolled {0} in paid course {1}, paid ${2}" .format(self.user.email, self.course_id, self.line_cost)) self.course_enrollment.send_signal(EnrollStatusChange.paid_complete, cost=self.line_cost, currency=self.currency) @@ -1617,7 +1617,7 @@ class PaidCourseRegistration(OrderItem): """ notification = Text(_( u"Please visit your {link_start}dashboard{link_end} " - u"to see your new course." + "to see your new course." )).format( link_start=HTML(u'<a href="{url}">').format(url=reverse('dashboard')), link_end=HTML(u'</a>'), @@ -1724,17 +1724,17 @@ class CourseRegCodeItem(OrderItem): # throw errors if it doesn't. course = modulestore().get_course(course_id) if not course: - log.error("User {} tried to add non-existent course {} to cart id {}" + log.error(u"User {} tried to add non-existent course {} to cart id {}" .format(order.user.email, course_id, order.id)) raise CourseDoesNotExistException if cls.contained_in_order(order, course_id): - log.warning("User {} tried to add PaidCourseRegistration for course {}, already in cart id {}" + log.warning(u"User {} tried to add PaidCourseRegistration for course {}, already in cart id {}" .format(order.user.email, course_id, order.id)) raise ItemAlreadyInCartException if CourseEnrollment.is_enrolled(user=order.user, course_key=course_id): - log.warning("User {} trying to add course {} to cart id {}, already registered" + log.warning(u"User {} trying to add course {} to cart id {}, already registered" .format(order.user.email, course_id, order.id)) raise AlreadyEnrolledInCourseException @@ -1764,7 +1764,7 @@ class CourseRegCodeItem(OrderItem): item.report_comments = item.csv_report_comments order.save() item.save() - log.info("User {} added course registration {} to cart: order {}" + log.info(u"User {} added course registration {} to cart: order {}" .format(order.user.email, course_id, order.id)) return item @@ -1787,7 +1787,7 @@ class CourseRegCodeItem(OrderItem): for i in range(total_registration_codes): # pylint: disable=unused-variable save_registration_code(self.user, self.course_id, self.mode, order=self.order) - log.info("Enrolled {0} in paid course {1}, paid ${2}" + log.info(u"Enrolled {0} in paid course {1}, paid ${2}" .format(self.user.email, self.course_id, self.line_cost)) @property @@ -1899,16 +1899,16 @@ class CertificateItem(OrderItem): order_number = target_cert.order_id # send billing an email so they can handle refunding subject = _("[Refund] User-Requested Refund") - message = "User {user} ({user_email}) has requested a refund on Order #{order_number}.".format(user=course_enrollment.user, - user_email=course_enrollment.user.email, - order_number=order_number) + message = u"User {user} ({user_email}) has requested a refund on Order #{order_number}.".format(user=course_enrollment.user, + user_email=course_enrollment.user.email, + order_number=order_number) to_email = [settings.PAYMENT_SUPPORT_EMAIL] from_email = configuration_helpers.get_value('payment_support_email', settings.PAYMENT_SUPPORT_EMAIL) try: send_mail(subject, message, from_email, to_email, fail_silently=False) except Exception as exception: # pylint: disable=broad-except err_str = ('Failed sending email to billing to request a refund for verified certificate' - ' (User {user}, Course {course}, CourseEnrollmentID {ce_id}, Order #{order})\n{exception}') + u' (User {user}, Course {course}, CourseEnrollmentID {ce_id}, Order #{order})\n{exception}') log.error(err_str.format( user=course_enrollment.user, course=course_enrollment.course_id, @@ -1969,7 +1969,7 @@ class CertificateItem(OrderItem): # Translators: In this particular case, mode_name refers to a # particular mode (i.e. Honor Code Certificate, Verified Certificate, etc) # by which a user could enroll in the given course. - item.line_desc = _("{mode_name} for course {course}").format( + item.line_desc = _(u"{mode_name} for course {course}").format( mode_name=mode_info.name, course=course_name ) @@ -2004,7 +2004,7 @@ class CertificateItem(OrderItem): verification_url = "http://{domain}{path}".format(domain=domain, path=path) verification_reminder = _( - "If you haven't verified your identity yet, please start the verification process ({verification_url})." + u"If you haven't verified your identity yet, please start the verification process ({verification_url})." ).format(verification_url=verification_url) if is_professional_mode_verified: @@ -2012,10 +2012,10 @@ class CertificateItem(OrderItem): "course start date. ") refund_reminder = _( - "{refund_reminder_msg}" - "To receive your refund, contact {billing_email}. " - "Please include your order number in your email. " - "Please do NOT include your credit card information." + u"{refund_reminder_msg}" + u"To receive your refund, contact {billing_email}. " + u"Please include your order number in your email. " + u"Please do NOT include your credit card information." ).format( refund_reminder_msg=refund_reminder_msg, billing_email=settings.PAYMENT_SUPPORT_EMAIL diff --git a/lms/djangoapps/shoppingcart/pdf.py b/lms/djangoapps/shoppingcart/pdf.py index c80fc3cbf5a..eb2f5bc626c 100644 --- a/lms/djangoapps/shoppingcart/pdf.py +++ b/lms/djangoapps/shoppingcart/pdf.py @@ -64,7 +64,7 @@ class NumberedCanvas(Canvas): self.drawRightString( 200 * mm, 12 * mm, - _("Page {page_number} of {page_count}").format(page_number=self._pageNumber, page_count=page_count) + _(u"Page {page_number} of {page_count}").format(page_number=self._pageNumber, page_count=page_count) ) @@ -181,7 +181,7 @@ class PDFInvoice(object): try: img = Image.open(img_path) except IOError, ex: - log.exception('Pdf unable to open the image file: %s', str(ex)) + log.exception(u'Pdf unable to open the image file: %s', str(ex)) img = None return img @@ -381,7 +381,7 @@ class PDFInvoice(object): if self.is_invoice: # only print TaxID if we are generating an Invoice totals_data.append( - ['', '{tax_label}: {tax_id}'.format(tax_label=self.tax_label, tax_id=self.tax_id)] + ['', u'{tax_label}: {tax_id}'.format(tax_label=self.tax_label, tax_id=self.tax_id)] ) heights = 8 * mm diff --git a/lms/djangoapps/shoppingcart/processors/CyberSource2.py b/lms/djangoapps/shoppingcart/processors/CyberSource2.py index e12d7aa1237..7157a8bce85 100644 --- a/lms/djangoapps/shoppingcart/processors/CyberSource2.py +++ b/lms/djangoapps/shoppingcart/processors/CyberSource2.py @@ -39,6 +39,7 @@ from six import text_type from edxmako.shortcuts import render_to_string from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers +from openedx.core.djangolib.markup import HTML, Text from shoppingcart.models import Order from shoppingcart.processors.exceptions import * from shoppingcart.processors.helpers import get_processor_config @@ -293,7 +294,7 @@ def get_purchase_params(cart, callback_url=None, extra_data=None): params['amount'] = amount params['currency'] = cart.currency - params['orderNumber'] = "OrderId: {0:d}".format(cart.id) + params['orderNumber'] = u"OrderId: {0:d}".format(cart.id) params['access_key'] = get_processor_config().get('ACCESS_KEY', '') params['profile_id'] = get_processor_config().get('PROFILE_ID', '') @@ -416,7 +417,7 @@ def _record_purchase(params, order): if settings.FEATURES.get("LOG_POSTPAY_CALLBACKS"): log.info( - "Order %d purchased with params: %s", order.id, json.dumps(params) + u"Order %d purchased with params: %s", order.id, json.dumps(params) ) # Mark the order as purchased and store the billing information @@ -447,7 +448,7 @@ def _record_payment_info(params, order): """ if settings.FEATURES.get("LOG_POSTPAY_CALLBACKS"): log.info( - "Order %d processed (but not completed) with params: %s", order.id, json.dumps(params) + u"Order %d processed (but not completed) with params: %s", order.id, json.dumps(params) ) order.processor_reply_dump = json.dumps(params) @@ -467,15 +468,15 @@ def _get_processor_decline_html(params): """ payment_support_email = configuration_helpers.get_value('payment_support_email', settings.PAYMENT_SUPPORT_EMAIL) return _format_error_html( - _( - "Sorry! Our payment processor did not accept your payment. " - "The decision they returned was {decision}, " - "and the reason was {reason}. " - "You were not charged. Please try a different form of payment. " - "Contact us with payment-related questions at {email}." - ).format( - decision='<span class="decision">{decision}</span>'.format(decision=params['decision']), - reason='<span class="reason">{reason_code}:{reason_msg}</span>'.format( + Text(_( + u"Sorry! Our payment processor did not accept your payment. " + u"The decision they returned was {decision}, " + u"and the reason was {reason}. " + u"You were not charged. Please try a different form of payment. " + u"Contact us with payment-related questions at {email}." + )).format( + decision=HTML(u'<span class="decision">{decision}</span>').format(decision=params['decision']), + reason=HTML(u'<span class="reason">{reason_code}:{reason_msg}</span>').format( reason_code=params['reason_code'], reason_msg=REASONCODE_MAP.get(params['reason_code']) ), @@ -498,37 +499,37 @@ def _get_processor_exception_html(exception): payment_support_email = configuration_helpers.get_value('payment_support_email', settings.PAYMENT_SUPPORT_EMAIL) if isinstance(exception, CCProcessorDataException): return _format_error_html( - _( + Text(_( u"Sorry! Our payment processor sent us back a payment confirmation that had inconsistent data! " u"We apologize that we cannot verify whether the charge went through and take further action on your order. " u"The specific error message is: {msg} " u"Your credit card may possibly have been charged. Contact us with payment-specific questions at {email}." - ).format( - msg=u'<span class="exception_msg">{msg}</span>'.format(msg=text_type(exception)), + )).format( + msg=HTML(u'<span class="exception_msg">{msg}</span>').format(msg=text_type(exception)), email=payment_support_email ) ) elif isinstance(exception, CCProcessorWrongAmountException): return _format_error_html( - _( + Text(_( u"Sorry! Due to an error your purchase was charged for a different amount than the order total! " u"The specific error message is: {msg}. " u"Your credit card has probably been charged. Contact us with payment-specific questions at {email}." - ).format( - msg=u'<span class="exception_msg">{msg}</span>'.format(msg=text_type(exception)), + )).format( + msg=HTML(u'<span class="exception_msg">{msg}</span>').format(msg=text_type(exception)), email=payment_support_email ) ) elif isinstance(exception, CCProcessorSignatureException): return _format_error_html( - _( + Text(_( u"Sorry! Our payment processor sent us back a corrupted message regarding your charge, so we are " u"unable to validate that the message actually came from the payment processor. " u"The specific error message is: {msg}. " u"We apologize that we cannot verify whether the charge went through and take further action on your order. " u"Your credit card may possibly have been charged. Contact us with payment-specific questions at {email}." - ).format( - msg=u'<span class="exception_msg">{msg}</span>'.format(msg=text_type(exception)), + )).format( + msg=HTML(u'<span class="exception_msg">{msg}</span>').format(msg=text_type(exception)), email=payment_support_email ) ) @@ -562,7 +563,7 @@ def _get_processor_exception_html(exception): def _format_error_html(msg): """ Format an HTML error message """ - return u'<p class="error_msg">{msg}</p>'.format(msg=msg) + return HTML(u'<p class="error_msg">{msg}</p>').format(msg=msg) CARDTYPE_MAP = defaultdict(lambda: "UNKNOWN") @@ -664,7 +665,7 @@ REASONCODE_MAP.update( """)), '233': _('General decline by the processor. Possible action: retry with another form of payment.'), '234': _( - "There is a problem with the information in your CyberSource account. Please let us know at {0}" + u"There is a problem with the information in your CyberSource account. Please let us know at {0}" ).format(settings.PAYMENT_SUPPORT_EMAIL), '235': _('The requested capture amount exceeds the originally authorized amount.'), '236': _('Processor Failure. Possible action: retry the payment'), diff --git a/lms/djangoapps/shoppingcart/processors/tests/test_CyberSource2.py b/lms/djangoapps/shoppingcart/processors/tests/test_CyberSource2.py index 5f07ebddfd6..c3b77380363 100644 --- a/lms/djangoapps/shoppingcart/processors/tests/test_CyberSource2.py +++ b/lms/djangoapps/shoppingcart/processors/tests/test_CyberSource2.py @@ -80,7 +80,7 @@ class CyberSource2Test(TestCase): # Parameters determined by the order model self.assertEqual(params['amount'], '10.00') self.assertEqual(params['currency'], 'usd') - self.assertEqual(params['orderNumber'], 'OrderId: {order_id}'.format(order_id=self.order.id)) + self.assertEqual(params['orderNumber'], u'OrderId: {order_id}'.format(order_id=self.order.id)) self.assertEqual(params['reference_number'], self.order.id) # Parameters determined by the Django (test) settings @@ -149,7 +149,7 @@ class CyberSource2Test(TestCase): # Expect that we processed the payment successfully self.assertTrue( result['success'], - msg="Payment was not successful: {error}".format(error=result.get('error_html')) + msg=u"Payment was not successful: {error}".format(error=result.get('error_html')) ) self.assertEqual(result['error_html'], '') @@ -232,7 +232,7 @@ class CyberSource2Test(TestCase): # Expect that we processed the payment successfully self.assertTrue( result['success'], - msg="Payment was not successful: {error}".format(error=result.get('error_html')) + msg=u"Payment was not successful: {error}".format(error=result.get('error_html')) ) self.assertEqual(result['error_html'], '') self.assert_dump_recorded(result['order']) diff --git a/lms/djangoapps/shoppingcart/tests/test_pdf.py b/lms/djangoapps/shoppingcart/tests/test_pdf.py index fb03bcf6197..4f044d12360 100644 --- a/lms/djangoapps/shoppingcart/tests/test_pdf.py +++ b/lms/djangoapps/shoppingcart/tests/test_pdf.py @@ -59,7 +59,7 @@ class TestPdfFile(unittest.TestCase): return the dictionary with the dummy data """ return { - 'item_description': 'Course %s Description' % index, + 'item_description': u'Course %s Description' % index, 'quantity': index, 'list_price': 10, 'discount': discount, diff --git a/lms/djangoapps/shoppingcart/tests/test_reports.py b/lms/djangoapps/shoppingcart/tests/test_reports.py index a53150b2843..995e39ef4fe 100644 --- a/lms/djangoapps/shoppingcart/tests/test_reports.py +++ b/lms/djangoapps/shoppingcart/tests/test_reports.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - """ Tests for the Shopping Cart Models """ @@ -242,7 +241,7 @@ class ItemizedPurchaseReportTest(ModuleStoreTestCase): """ # delete the matching annotation self.annotation.delete() - self.assertEqual(u"", self.reg.csv_report_comments) + self.assertEqual("", self.reg.csv_report_comments) def test_paidcourseregistrationannotation_unicode(self): """ diff --git a/lms/djangoapps/shoppingcart/tests/test_views.py b/lms/djangoapps/shoppingcart/tests/test_views.py index 7d478edddeb..23b480b0c1b 100644 --- a/lms/djangoapps/shoppingcart/tests/test_views.py +++ b/lms/djangoapps/shoppingcart/tests/test_views.py @@ -288,7 +288,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): self.login_user() resp = self.client.post(reverse('add_course_to_cart', args=[text_type(self.course_key)])) self.assertEqual(resp.status_code, 400) - self.assertIn('The course {0} is already in your cart.'.format(text_type(self.course_key)), resp.content) + self.assertIn(u'The course {0} is already in your cart.'.format(text_type(self.course_key)), resp.content) def test_course_discount_invalid_coupon(self): self.add_coupon(self.course_key, True, self.coupon_code) @@ -296,7 +296,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): non_existing_code = "non_existing_code" resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': non_existing_code}) self.assertEqual(resp.status_code, 404) - self.assertIn("Discount does not exist against code '{0}'.".format(non_existing_code), resp.content) + self.assertIn(u"Discount does not exist against code '{0}'.".format(non_existing_code), resp.content) def test_valid_qty_greater_then_one_and_purchase_type_should_business(self): qty = 2 @@ -418,14 +418,14 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): non_existing_code = "non_existing_code" resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': non_existing_code}) self.assertEqual(resp.status_code, 404) - self.assertIn("Discount does not exist against code '{0}'.".format(non_existing_code), resp.content) + self.assertIn(u"Discount does not exist against code '{0}'.".format(non_existing_code), resp.content) def test_course_discount_inactive_coupon(self): self.add_coupon(self.course_key, False, self.coupon_code) self.add_course_to_user_cart(self.course_key) resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code}) self.assertEqual(resp.status_code, 404) - self.assertIn("Discount does not exist against code '{0}'.".format(self.coupon_code), resp.content) + self.assertIn(u"Discount does not exist against code '{0}'.".format(self.coupon_code), resp.content) def test_course_does_not_exist_in_cart_against_valid_coupon(self): course_key = text_type(self.course_key) + 'testing' @@ -434,7 +434,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code}) self.assertEqual(resp.status_code, 404) - self.assertIn("Discount does not exist against code '{0}'.".format(self.coupon_code), resp.content) + self.assertIn(u"Discount does not exist against code '{0}'.".format(self.coupon_code), resp.content) def test_inactive_registration_code_returns_error(self): """ @@ -450,7 +450,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.reg_code}) self.assertEqual(resp.status_code, 400) self.assertIn( - "This enrollment code ({enrollment_code}) is no longer valid.".format( + u"This enrollment code ({enrollment_code}) is no longer valid.".format( enrollment_code=self.reg_code), resp.content) def test_course_does_not_exist_in_cart_against_valid_reg_code(self): @@ -460,7 +460,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.reg_code}) self.assertEqual(resp.status_code, 404) - self.assertIn("Code '{0}' is not valid for any course in the shopping cart.".format(self.reg_code), resp.content) + self.assertIn(u"Code '{0}' is not valid for any course in the shopping cart.".format(self.reg_code), resp.content) def test_cart_item_qty_greater_than_1_against_valid_reg_code(self): course_key = text_type(self.course_key) @@ -611,7 +611,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): # the item has been removed when using the registration code for the first time resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.reg_code}) self.assertEqual(resp.status_code, 400) - self.assertIn("This enrollment code ({enrollment_code}) is not valid.".format( + self.assertIn(u"This enrollment code ({enrollment_code}) is not valid.".format( enrollment_code=self.reg_code ), resp.content) @@ -649,7 +649,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): resp = self.client.post(reverse('shoppingcart.views.remove_item', args=[]), {'id': reg_item.id}) debug_log.assert_called_with( - 'Code redemption does not exist for order item id=%s.', + u'Code redemption does not exist for order item id=%s.', str(reg_item.id) ) @@ -671,7 +671,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): self.assertEqual(resp.status_code, 200) self.assertEquals(self.cart.orderitem_set.count(), 0) info_log.assert_called_with( - 'Coupon "%s" redemption entry removed for user "%s" for order item "%s"', + u'Coupon "%s" redemption entry removed for user "%s" for order item "%s"', self.coupon_code, self.user, str(reg_item.id) @@ -690,7 +690,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): self.assertEqual(resp.status_code, 200) info_log.assert_called_with( - 'Coupon redemption entry removed for user %s for order %s', + u'Coupon redemption entry removed for user %s for order %s', self.user, reg_item.id ) @@ -724,7 +724,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): self.assertEqual(resp.status_code, 200) self.assertEquals(self.cart.orderitem_set.count(), 1) info_log.assert_called_with( - 'Coupon "%s" redemption entry removed for user "%s" for order item "%s"', + 'Coupon "%s" redemption entry removed for user "%s" for order item "%s"', # pylint: disable=unicode-format-string,line-too-long self.coupon_code, self.user, str(reg_item.id) @@ -743,7 +743,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): self.assertEqual(resp.status_code, 200) self.assertEquals(self.cart.orderitem_set.count(), 1) - info_log.assert_called_with("order item %s removed for user %s", str(cert_item.id), self.user) + info_log.assert_called_with(u"order item %s removed for user %s", str(cert_item.id), self.user) @patch('shoppingcart.views.log.info') def test_remove_coupon_redemption_on_clear_cart(self, info_log): @@ -761,7 +761,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): self.assertEquals(self.cart.orderitem_set.count(), 0) info_log.assert_called_with( - 'Coupon redemption entry removed for user %s for order %s', + u'Coupon redemption entry removed for user %s for order %s', self.user, reg_item.id ) @@ -771,7 +771,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): self.login_user() resp = self.client.post(reverse('add_course_to_cart', args=[text_type(self.course_key)])) self.assertEqual(resp.status_code, 400) - self.assertIn('You are already registered in course {0}.'.format(text_type(self.course_key)), resp.content) + self.assertIn(u'You are already registered in course {0}.'.format(text_type(self.course_key)), resp.content) def test_add_nonexistent_course_to_cart(self): self.login_user() @@ -864,7 +864,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): {'id': cert_item.id}) self.assertEqual(resp2.status_code, 200) exception_log.assert_called_with( - 'Cannot remove cart OrderItem id=%s. DoesNotExist or item is already purchased', str(cert_item.id) + u'Cannot remove cart OrderItem id=%s. DoesNotExist or item is already purchased', str(cert_item.id) ) resp3 = self.client.post( @@ -873,7 +873,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): ) self.assertEqual(resp3.status_code, 200) exception_log.assert_called_with( - 'Cannot remove cart OrderItem id=%s. DoesNotExist or item is already purchased', + u'Cannot remove cart OrderItem id=%s. DoesNotExist or item is already purchased', '-1' ) @@ -936,7 +936,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): 'unit_cost': 40, 'quantity': 1, 'line_cost': 40, - 'line_desc': '{} for course Test Course'.format(self.verified_course_mode.mode_display_name), + 'line_desc': u'{} for course Test Course'.format(self.verified_course_mode.mode_display_name), 'course_key': unicode(self.verified_course_key) }) @@ -1004,7 +1004,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): 'unit_cost': 40, 'quantity': 1, 'line_cost': 40, - 'line_desc': '{} for course Test Course'.format(self.verified_course_mode.mode_display_name), + 'line_desc': u'{} for course Test Course'.format(self.verified_course_mode.mode_display_name), 'course_key': unicode(self.verified_course_key) }) @@ -1266,14 +1266,17 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): self.assertFalse(context['reg_code_info_list'][0]['is_redeemed']) self.assertFalse(context['reg_code_info_list'][1]['is_redeemed']) - self.assertIn(self.cart.purchase_time.strftime("%B %d, %Y"), resp.content) + self.assertIn(self.cart.purchase_time.strftime(u"%B %d, %Y"), resp.content) self.assertIn(self.cart.company_name, resp.content) self.assertIn(self.cart.company_contact_name, resp.content) self.assertIn(self.cart.company_contact_email, resp.content) self.assertIn(self.cart.recipient_email, resp.content) - self.assertIn("Invoice #{order_id}".format(order_id=self.cart.id), resp.content) - self.assertIn('You have successfully purchased <b>{total_registration_codes} course registration codes' - .format(total_registration_codes=context['total_registration_codes']), resp.content) + self.assertIn(u"Invoice #{order_id}".format(order_id=self.cart.id), resp.content.decode(resp.charset)) + codes_string = u'You have successfully purchased <b>{total_registration_codes} course registration codes' + self.assertIn(codes_string.format( + total_registration_codes=context['total_registration_codes']), + resp.content.decode(resp.charset) + ) # now redeem one of registration code from the previous order redeem_url = reverse('register_code_redemption', args=[context['reg_code_info_list'][0]['code']]) @@ -1638,7 +1641,9 @@ class ShoppingcartViewsClosedEnrollment(ModuleStoreTestCase): # coupon redemption entry should also be deleted when the item is expired. resp = self.client.get(reverse('shoppingcart.views.show_cart', args=[])) self.assertEqual(resp.status_code, 200) - self.assertIn("{course_name} has been removed because the enrollment period has closed.".format(course_name=self.testing_course.display_name), resp.content) + self.assertIn(u"{course_name} has been removed because the enrollment period has closed.".format( + course_name=self.testing_course.display_name), resp.content.decode(resp.charset) + ) # now the redemption entry should be deleted from the table. coupon_redemption = CouponRedemption.objects.filter(coupon__course_id=expired_course_item.course_id, @@ -1678,7 +1683,12 @@ class ShoppingcartViewsClosedEnrollment(ModuleStoreTestCase): resp = self.client.get(reverse('shoppingcart.views.show_cart', args=[])) self.assertEqual(resp.status_code, 200) - self.assertIn("{course_name} has been removed because the enrollment period has closed.".format(course_name=self.testing_course.display_name), resp.content) + self.assertIn( + u"{course_name} has been removed because the enrollment period has closed.".format( + course_name=self.testing_course.display_name + ), + resp.content.decode(resp.charset) + ) self.assertIn('40.00', resp.content) def test_is_enrollment_closed_when_order_type_is_business(self): @@ -1701,7 +1711,12 @@ class ShoppingcartViewsClosedEnrollment(ModuleStoreTestCase): # so we delete that item from the cart and display the message in the cart resp = self.client.get(reverse('shoppingcart.views.show_cart', args=[])) self.assertEqual(resp.status_code, 200) - self.assertIn("{course_name} has been removed because the enrollment period has closed.".format(course_name=self.testing_course.display_name), resp.content) + self.assertIn( + u"{course_name} has been removed because the enrollment period has closed.".format( + course_name=self.testing_course.display_name + ), + resp.content.decode(resp.charset) + ) self.assertIn('40.00', resp.content) diff --git a/lms/djangoapps/shoppingcart/views.py b/lms/djangoapps/shoppingcart/views.py index 5f22048649f..afeaff1d2cb 100644 --- a/lms/djangoapps/shoppingcart/views.py +++ b/lms/djangoapps/shoppingcart/views.py @@ -117,10 +117,10 @@ def add_course_to_cart(request, course_id): except CourseDoesNotExistException: return HttpResponseNotFound(_('The course you requested does not exist.')) except ItemAlreadyInCartException: - return HttpResponseBadRequest(_('The course {course_id} is already in your cart.').format(course_id=course_id)) + return HttpResponseBadRequest(_(u'The course {course_id} is already in your cart.').format(course_id=course_id)) except AlreadyEnrolledInCourseException: return HttpResponseBadRequest( - _('You are already registered in course {course_id}.').format(course_id=course_id)) + _(u'You are already registered in course {course_id}.').format(course_id=course_id)) else: # in case a coupon redemption code has been applied, new items should also get a discount if applicable. order = paid_course_item.order @@ -293,7 +293,7 @@ def use_code(request): try: course_reg = CourseRegistrationCode.objects.get(code=code) except CourseRegistrationCode.DoesNotExist: - return HttpResponseNotFound(_("Discount does not exist against code '{code}'.").format(code=code)) + return HttpResponseNotFound(_(u"Discount does not exist against code '{code}'.").format(code=code)) return use_registration_code(course_reg, request.user) @@ -318,7 +318,7 @@ def get_reg_code_validity(registration_code, request, limiter): reg_code_already_redeemed = RegistrationCodeRedemption.is_registration_code_redeemed(registration_code) if not reg_code_is_valid: # tick the rate limiter counter - AUDIT_LOG.info("Redemption of a invalid RegistrationCode %s", registration_code) + AUDIT_LOG.info(u"Redemption of a invalid RegistrationCode %s", registration_code) limiter.tick_bad_request_counter(request) raise Http404() @@ -465,7 +465,7 @@ def use_registration_code(course_reg, user): if not course_reg.is_valid: log.warning(u"The enrollment code (%s) is no longer valid.", course_reg.code) return HttpResponseBadRequest( - _("This enrollment code ({enrollment_code}) is no longer valid.").format( + _(u"This enrollment code ({enrollment_code}) is no longer valid.").format( enrollment_code=course_reg.code ) ) @@ -473,7 +473,7 @@ def use_registration_code(course_reg, user): if RegistrationCodeRedemption.is_registration_code_redeemed(course_reg.code): log.warning(u"This enrollment code ({%s}) has already been used.", course_reg.code) return HttpResponseBadRequest( - _("This enrollment code ({enrollment_code}) is not valid.").format( + _(u"This enrollment code ({enrollment_code}) is not valid.").format( enrollment_code=course_reg.code ) ) @@ -483,7 +483,7 @@ def use_registration_code(course_reg, user): except ItemNotFoundInCartException: log.warning(u"Course item does not exist against registration code '%s'", course_reg.code) return HttpResponseNotFound( - _("Code '{registration_code}' is not valid for any course in the shopping cart.").format( + _(u"Code '{registration_code}' is not valid for any course in the shopping cart.").format( registration_code=course_reg.code ) ) @@ -521,7 +521,7 @@ def use_coupon_code(coupons, user): if not is_redemption_applied: log.warning(u"Discount does not exist against code '%s'.", coupons[0].code) - return HttpResponseNotFound(_("Discount does not exist against code '{code}'.").format(code=coupons[0].code)) + return HttpResponseNotFound(_(u"Discount does not exist against code '{code}'.").format(code=coupons[0].code)) return HttpResponse( json.dumps({'response': 'success', 'coupon_code_applied': True}), @@ -950,7 +950,7 @@ def _show_receipt_html(request, order): 'currency': settings.PAID_COURSE_REGISTRATION_CURRENCY[0], 'total_registration_codes': total_registration_codes, 'reg_code_info_list': reg_code_info_list, - 'order_purchase_date': order.purchase_time.strftime("%B %d, %Y"), + 'order_purchase_date': order.purchase_time.strftime(u"%B %d, %Y"), } # We want to have the ability to override the default receipt page when @@ -1022,8 +1022,8 @@ def csv_report(request): items = report.rows() response = HttpResponse(content_type='text/csv') - filename = "purchases_report_{}.csv".format(datetime.datetime.now(pytz.UTC).strftime("%Y-%m-%d-%H-%M-%S")) - response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename) + filename = u"purchases_report_{}.csv".format(datetime.datetime.now(pytz.UTC).strftime(u"%Y-%m-%d-%H-%M-%S")) + response['Content-Disposition'] = u'attachment; filename="{}"'.format(filename) report.write_csv(response) return response diff --git a/lms/djangoapps/static_template_view/tests/test_views.py b/lms/djangoapps/static_template_view/tests/test_views.py index ed8f00e488a..f4c998a79d1 100644 --- a/lms/djangoapps/static_template_view/tests/test_views.py +++ b/lms/djangoapps/static_template_view/tests/test_views.py @@ -119,7 +119,7 @@ class MarketingSiteViewTests(TestCase): resp = self.client.get(url, HTTP_HOST=settings.MICROSITE_TEST_HOSTNAME) self.assertContains( resp, - 'There has been a 500 error on the <em>{platform_name}</em> servers'.format( + u'There has been a 500 error on the <em>{platform_name}</em> servers'.format( platform_name=settings.MICROSITE_CONFIGURATION['test_site']['platform_name'] ), status_code=500 diff --git a/lms/djangoapps/staticbook/views.py b/lms/djangoapps/staticbook/views.py index 0ffa9095638..2137a30678a 100644 --- a/lms/djangoapps/staticbook/views.py +++ b/lms/djangoapps/staticbook/views.py @@ -24,7 +24,7 @@ def index(request, course_id, book_index, page=None): book_index = int(book_index) if book_index < 0 or book_index >= len(course.textbooks): - raise Http404("Invalid book index value: {0}".format(book_index)) + raise Http404(u"Invalid book index value: {0}".format(book_index)) textbook = course.textbooks[book_index] table_of_contents = textbook.table_of_contents @@ -82,7 +82,7 @@ def pdf_index(request, course_id, book_index, chapter=None, page=None): book_index = int(book_index) if book_index < 0 or book_index >= len(course.pdf_textbooks): - raise Http404("Invalid book index value: {0}".format(book_index)) + raise Http404(u"Invalid book index value: {0}".format(book_index)) textbook = course.pdf_textbooks[book_index] viewer_params = '&file=' @@ -150,7 +150,7 @@ def html_index(request, course_id, book_index, chapter=None): book_index = int(book_index) if book_index < 0 or book_index >= len(course.html_textbooks): - raise Http404("Invalid book index value: {0}".format(book_index)) + raise Http404(u"Invalid book index value: {0}".format(book_index)) textbook = course.html_textbooks[book_index] if 'url' in textbook: diff --git a/lms/djangoapps/support/tests/test_refund.py b/lms/djangoapps/support/tests/test_refund.py index 5446d3b6a98..8f47cab6489 100644 --- a/lms/djangoapps/support/tests/test_refund.py +++ b/lms/djangoapps/support/tests/test_refund.py @@ -107,7 +107,7 @@ class RefundTests(ModuleStoreTestCase): def test_no_order(self): self._enroll(purchase=False) response = self.client.post('/support/refund/', self.form_pars) - self.assertContains(response, 'No order found for %s' % self.student.username) + self.assertContains(response, u'No order found for %s' % self.student.username) def test_valid_order(self): self._enroll() @@ -124,7 +124,7 @@ class RefundTests(ModuleStoreTestCase): self.assertTrue(response.status_code, 302) response = self.client.get(response.get('location')) - self.assertContains(response, "Unenrolled %s from" % self.student) + self.assertContains(response, u"Unenrolled %s from" % self.student) self.assertContains(response, "Refunded 1.00 for order id") self.assertFalse(CourseEnrollment.is_enrolled(self.student, self.course_id)) diff --git a/lms/djangoapps/support/views/refund.py b/lms/djangoapps/support/views/refund.py index 1c13e0cd310..2617c1b6bcc 100644 --- a/lms/djangoapps/support/views/refund.py +++ b/lms/djangoapps/support/views/refund.py @@ -60,7 +60,7 @@ class RefundForm(forms.Form): if user and course_id: self.cleaned_data['enrollment'] = enrollment = CourseEnrollment.get_or_create_enrollment(user, course_id) if enrollment.refundable(): - msg = _("Course {course_id} not past the refund window.").format(course_id=course_id) + msg = _(u"Course {course_id} not past the refund window.").format(course_id=course_id) raise forms.ValidationError(msg) try: self.cleaned_data['cert'] = enrollment.certificateitem_set.filter( @@ -68,7 +68,7 @@ class RefundForm(forms.Form): status='purchased' )[0] except IndexError: - msg = _("No order found for {user} in course {course_id}").format(user=user, course_id=course_id) + msg = _(u"No order found for {user} in course {course_id}").format(user=user, course_id=course_id) raise forms.ValidationError(msg) return self.cleaned_data @@ -125,14 +125,14 @@ class RefundSupportView(FormView): log.info(u"%s manually refunded %s %s", self.request.user, user, course_id) messages.success( self.request, - _("Unenrolled {user} from {course_id}").format( + _(u"Unenrolled {user} from {course_id}").format( user=user, course_id=course_id ) ) messages.success( self.request, - _("Refunded {cost} for order id {order_id}").format( + _(u"Refunded {cost} for order id {order_id}").format( cost=cert.unit_cost, order_id=cert.order.id ) diff --git a/lms/djangoapps/survey/models.py b/lms/djangoapps/survey/models.py index a8fa845bdd9..e7500c7878a 100644 --- a/lms/djangoapps/survey/models.py +++ b/lms/djangoapps/survey/models.py @@ -11,6 +11,7 @@ from lxml import etree from model_utils.models import TimeStampedModel from opaque_keys.edx.django.models import CourseKeyField +from openedx.core.djangolib.markup import HTML from student.models import User from survey.exceptions import SurveyFormNameAlreadyExists, SurveyFormNotFound @@ -52,8 +53,8 @@ class SurveyForm(TimeStampedModel): try: fields = cls.get_field_names_from_html(html) except Exception as ex: - log.exception("Cannot parse SurveyForm html: {}".format(ex)) - raise ValidationError("Cannot parse SurveyForm as HTML: {}".format(ex)) + log.exception(u"Cannot parse SurveyForm html: {}".format(ex)) + raise ValidationError(u"Cannot parse SurveyForm as HTML: {}".format(ex)) if not len(fields): raise ValidationError("SurveyForms must contain at least one form input field") @@ -146,7 +147,7 @@ class SurveyForm(TimeStampedModel): # make sure the form is wrap in some outer single element # otherwise lxml can't parse it # NOTE: This wrapping doesn't change the ability to query it - tree = etree.fromstring(u'<div>{}</div>'.format(html)) + tree = etree.fromstring(HTML(u'<div>{}</div>').format(HTML(html))) input_fields = ( tree.findall('.//input') + tree.findall('.//select') + diff --git a/lms/djangoapps/teams/management/commands/tests/test_reindex_course_team.py b/lms/djangoapps/teams/management/commands/tests/test_reindex_course_team.py index 7253bf99124..acb8bece08c 100644 --- a/lms/djangoapps/teams/management/commands/tests/test_reindex_course_team.py +++ b/lms/djangoapps/teams/management/commands/tests/test_reindex_course_team.py @@ -62,7 +62,7 @@ class ReindexCourseTeamTest(SharedModuleStoreTestCase): Test that raises CommandError for invalid team id. """ team_id = u'team4' - error_str = 'Argument {} is not a course_team team_id'.format(team_id) + error_str = u'Argument {} is not a course_team team_id'.format(team_id) with self.assertRaisesRegexp(CommandError, error_str): call_command('reindex_course_team', team_id) diff --git a/lms/djangoapps/teams/models.py b/lms/djangoapps/teams/models.py index d91225d1930..4064dd0567f 100644 --- a/lms/djangoapps/teams/models.py +++ b/lms/djangoapps/teams/models.py @@ -198,7 +198,7 @@ class CourseTeamMembership(models.Model): # Allow it *only* if the current value is None. if current_value is not None: raise ImmutableMembershipFieldException( - "Field %r shouldn't change from %r to %r" % (name, current_value, value) + u"Field %r shouldn't change from %r to %r" % (name, current_value, value) ) super(CourseTeamMembership, self).__setattr__(name, value) diff --git a/lms/djangoapps/teams/search_indexes.py b/lms/djangoapps/teams/search_indexes.py index 187f5a9d5ce..a94a4b9792a 100644 --- a/lms/djangoapps/teams/search_indexes.py +++ b/lms/djangoapps/teams/search_indexes.py @@ -120,7 +120,7 @@ class CourseTeamIndexer(object): try: return SearchEngine.get_search_engine(index=cls.INDEX_NAME) except ConnectionError as err: - logging.error('Error connecting to elasticsearch: %s', err) + logging.error(u'Error connecting to elasticsearch: %s', err) raise ElasticSearchConnectionError @classmethod diff --git a/lms/djangoapps/teams/tests/factories.py b/lms/djangoapps/teams/tests/factories.py index a4991df4c25..750a06f0f32 100644 --- a/lms/djangoapps/teams/tests/factories.py +++ b/lms/djangoapps/teams/tests/factories.py @@ -23,7 +23,7 @@ class CourseTeamFactory(DjangoModelFactory): team_id = factory.Sequence('team-{0}'.format) discussion_topic_id = factory.LazyAttribute(lambda a: uuid4().hex) - name = factory.Sequence("Awesome Team {0}".format) + name = factory.Sequence(u"Awesome Team {0}".format) description = "A simple description" last_activity_at = LAST_ACTIVITY_AT diff --git a/lms/djangoapps/teams/tests/test_views.py b/lms/djangoapps/teams/tests/test_views.py index 4cc1d794ce2..d0696f25704 100644 --- a/lms/djangoapps/teams/tests/test_views.py +++ b/lms/djangoapps/teams/tests/test_views.py @@ -46,9 +46,9 @@ class TestDashboard(SharedModuleStoreTestCase): "max_team_size": 10, "topics": [ { - "name": "Topic {}".format(topic_id), + "name": u"Topic {}".format(topic_id), "id": topic_id, - "description": "Description for topic {}".format(topic_id) + "description": u"Description for topic {}".format(topic_id) } for topic_id in range(cls.NUM_TOPICS) ] @@ -178,19 +178,17 @@ class TestDashboard(SharedModuleStoreTestCase): # Check that initially list of user teams in course one is empty course_one_teams_url = reverse('teams_dashboard', args=[self.course.id]) response = self.client.get(course_one_teams_url) - self.assertIn('"teams": {"count": 0', response.content) - + self.assertIn('"teams": {"count": 0', response.content) # pylint: disable=unicode-format-string # Add user to a course one team course_one_team.add_user(self.user) # Check that list of user teams in course one is not empty, it is one now response = self.client.get(course_one_teams_url) - self.assertIn('"teams": {"count": 1', response.content) - + self.assertIn('"teams": {"count": 1', response.content) # pylint: disable=unicode-format-string # Check that list of user teams in course two is still empty course_two_teams_url = reverse('teams_dashboard', args=[course_two.id]) response = self.client.get(course_two_teams_url) - self.assertIn('"teams": {"count": 0', response.content) + self.assertIn('"teams": {"count": 0', response.content) # pylint: disable=unicode-format-string class TeamAPITestCase(APITestCase, SharedModuleStoreTestCase): @@ -209,7 +207,7 @@ class TeamAPITestCase(APITestCase, SharedModuleStoreTestCase): { 'id': 'topic_{}'.format(i), 'name': name, - 'description': 'Description for topic {}.'.format(i) + 'description': u'Description for topic {}.'.format(i) } for i, name in enumerate([u'Sólar power', 'Wind Power', 'Nuclear Power', 'Coal Power']) ] } @@ -407,10 +405,10 @@ class TeamAPITestCase(APITestCase, SharedModuleStoreTestCase): self.assertEqual( expected_status, response.status_code, - msg="Expected status {expected} but got {actual}: {content}".format( + msg=u"Expected status {expected} but got {actual}: {content}".format( expected=expected_status, actual=response.status_code, - content=response.content, + content=response.content.decode(response.charset), ) ) diff --git a/lms/djangoapps/teams/views.py b/lms/djangoapps/teams/views.py index cd7ff037f34..5a392ec7390 100644 --- a/lms/djangoapps/teams/views.py +++ b/lms/djangoapps/teams/views.py @@ -372,7 +372,7 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView): result_filter.update({'course_id': course_key}) except InvalidKeyError: error = build_api_error( - ugettext_noop("The supplied course id {course_id} is not valid."), + ugettext_noop(u"The supplied course id {course_id} is not valid."), course_id=course_id_string, ) return Response(error, status=status.HTTP_400_BAD_REQUEST) @@ -399,7 +399,7 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView): if topic_id is not None: if topic_id not in [topic['id'] for topic in course_module.teams_configuration['topics']]: error = build_api_error( - ugettext_noop('The supplied topic id {topic_id} is not valid'), + ugettext_noop(u'The supplied topic id {topic_id} is not valid'), topic_id=topic_id ) return Response(error, status=status.HTTP_400_BAD_REQUEST) @@ -448,7 +448,7 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView): queryset = queryset.order_by('-last_activity_at', 'team_size') else: return Response({ - 'developer_message': "unsupported order_by value {ordering}".format(ordering=order_by_input), + 'developer_message': u"unsupported order_by value {ordering}".format(ordering=order_by_input), # Translators: 'ordering' is a string describing a way # of ordering a list. For example, {ordering} may be # 'name', indicating that the user wants to sort the @@ -477,7 +477,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.'), + ugettext_noop(u'The supplied course_id {course_id} is not valid.'), course_id=course_id ) return Response({ @@ -673,7 +673,7 @@ class TeamsDetailView(ExpandableFieldViewMixin, RetrievePatchAPIView): # Note: also deletes all team memberships associated with this team team.delete() - log.info('user %d deleted team %s', request.user.id, team_id) + log.info(u'user %d deleted team %s', request.user.id, team_id) emit_team_event('edx.team.deleted', team.course_id, { 'team_id': team_id, }) @@ -755,7 +755,7 @@ class TopicListView(GenericAPIView): return Response({ 'field_errors': { 'course_id': build_api_error( - ugettext_noop("The supplied course id {course_id} is not valid."), + ugettext_noop(u"The supplied course id {course_id} is not valid."), course_id=course_id_string ) } @@ -777,7 +777,7 @@ class TopicListView(GenericAPIView): ordering = request.query_params.get('order_by', 'name') if ordering not in ['name', 'team_count']: return Response({ - 'developer_message': "unsupported order_by value {ordering}".format(ordering=ordering), + 'developer_message': u"unsupported order_by value {ordering}".format(ordering=ordering), # Translators: 'ordering' is a string describing a way # of ordering a list. For example, {ordering} may be # 'name', indicating that the user wants to sort the @@ -1125,7 +1125,7 @@ class MembershipListView(ExpandableFieldViewMixin, GenericAPIView): except AlreadyOnTeamInCourse: return Response( build_api_error( - ugettext_noop("The user {username} is already a member of a team in this course."), + ugettext_noop(u"The user {username} is already a member of a team in this course."), username=username ), status=status.HTTP_400_BAD_REQUEST @@ -1133,7 +1133,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."), + ugettext_noop(u"The user {username} is not enrolled in the course associated with this team."), username=username ), status=status.HTTP_400_BAD_REQUEST diff --git a/lms/djangoapps/verify_student/management/commands/manual_verifications.py b/lms/djangoapps/verify_student/management/commands/manual_verifications.py index 37421332fd7..304042239af 100644 --- a/lms/djangoapps/verify_student/management/commands/manual_verifications.py +++ b/lms/djangoapps/verify_student/management/commands/manual_verifications.py @@ -48,9 +48,9 @@ class Command(BaseCommand): len(failed_emails), total_emails )) - log.error('Failed emails:{}'.format(pformat(failed_emails))) + log.error(u'Failed emails:{}'.format(pformat(failed_emails))) else: - log.info('Successfully generated manual verification for {} emails.'.format(total_emails)) + log.info(u'Successfully generated manual verification for {} emails.'.format(total_emails)) def _generate_manual_verification_from_file(self, email_ids_file): """ diff --git a/lms/djangoapps/verify_student/management/commands/retry_failed_photo_verifications.py b/lms/djangoapps/verify_student/management/commands/retry_failed_photo_verifications.py index a100a5cf333..598c868286e 100644 --- a/lms/djangoapps/verify_student/management/commands/retry_failed_photo_verifications.py +++ b/lms/djangoapps/verify_student/management/commands/retry_failed_photo_verifications.py @@ -30,14 +30,14 @@ class Command(BaseCommand): attempts_to_retry = SoftwareSecurePhotoVerification.objects.filter(status='must_retry') force_must_retry = False - print("Attempting to retry {0} failed PhotoVerification submissions".format(len(attempts_to_retry))) + print(u"Attempting to retry {0} failed PhotoVerification submissions".format(len(attempts_to_retry))) for index, attempt in enumerate(attempts_to_retry): - print("Retrying submission #{0} (ID: {1}, User: {2})".format(index, attempt.id, attempt.user)) + print(u"Retrying submission #{0} (ID: {1}, User: {2})".format(index, attempt.id, attempt.user)) # Set the attempts status to 'must_retry' so that we can re-submit it if force_must_retry: attempt.status = 'must_retry' attempt.submit(copy_id_photo_from=attempt.copy_id_photo_from) - print("Retry result: {0}".format(attempt.status)) + print(u"Retry result: {0}".format(attempt.status)) print("Done resubmitting failed photo verifications") diff --git a/lms/djangoapps/verify_student/models.py b/lms/djangoapps/verify_student/models.py index f333b018886..83f7d58342f 100644 --- a/lms/djangoapps/verify_student/models.py +++ b/lms/djangoapps/verify_student/models.py @@ -649,7 +649,7 @@ class SoftwareSecurePhotoVerification(PhotoVerification): self.save() except Exception: # pylint: disable=broad-except log.exception( - 'Software Secure submission failed for user %s, setting status to must_retry', + u'Software Secure submission failed for user %s, setting status to must_retry', self.user.username ) self.status = "must_retry" @@ -695,9 +695,9 @@ class SoftwareSecurePhotoVerification(PhotoVerification): if parsed_error: parsed_errors.append(parsed_error) else: - log.debug('Ignoring photo verification error message: %s', message) + log.debug(u'Ignoring photo verification error message: %s', message) except Exception: # pylint: disable=broad-except - log.exception('Failed to parse error message for SoftwareSecurePhotoVerification %d', self.pk) + log.exception(u'Failed to parse error message for SoftwareSecurePhotoVerification %d', self.pk) return parsed_errors @@ -836,7 +836,7 @@ class SoftwareSecurePhotoVerification(PhotoVerification): headers, body = self.create_request() header_txt = "\n".join( - "{}: {}".format(h, v) for h, v in sorted(headers.items()) + u"{}: {}".format(h, v) for h, v in sorted(headers.items()) ) body_txt = json.dumps(body, indent=2, sort_keys=True, ensure_ascii=False).encode('utf-8') @@ -873,20 +873,20 @@ class SoftwareSecurePhotoVerification(PhotoVerification): verify=False ) - log.info("Sent request to Software Secure for receipt ID %s.", self.receipt_id) + log.info(u"Sent request to Software Secure for receipt ID %s.", self.receipt_id) if copy_id_photo_from is not None: log.info( ( - "Software Secure attempt with receipt ID %s used the same photo ID " - "data as the receipt with ID %s" + u"Software Secure attempt with receipt ID %s used the same photo ID " + u"data as the receipt with ID %s" ), self.receipt_id, copy_id_photo_from.receipt_id ) log.debug("Headers:\n{}\n\n".format(headers)) log.debug("Body:\n{}\n\n".format(body)) - log.debug("Return code: {}".format(response.status_code)) - log.debug("Return message:\n\n{}\n\n".format(response.text)) + log.debug(u"Return code: {}".format(response.status_code)) + log.debug(u"Return message:\n\n{}\n\n".format(response.text)) return response @@ -923,7 +923,7 @@ class VerificationDeadline(TimeStampedModel): deadline = models.DateTimeField( help_text=ugettext_lazy( u"The datetime after which users are no longer allowed " - u"to submit photos for verification." + "to submit photos for verification." ) ) diff --git a/lms/djangoapps/verify_student/services.py b/lms/djangoapps/verify_student/services.py index 59c01951e7d..f815a9cf909 100644 --- a/lms/djangoapps/verify_student/services.py +++ b/lms/djangoapps/verify_student/services.py @@ -194,7 +194,7 @@ class IDVerificationService(object): if attempt.created_at < earliest_allowed_verification_date(): if user_status['should_display']: user_status['status'] = 'expired' - user_status['error'] = _("Your {platform_name} verification has expired.").format( + user_status['error'] = _(u"Your {platform_name} verification has expired.").format( platform_name=configuration_helpers.get_value('platform_name', settings.PLATFORM_NAME), ) else: diff --git a/lms/djangoapps/verify_student/ssencrypt.py b/lms/djangoapps/verify_student/ssencrypt.py index b8c29d8a3e0..e7aeeba37fe 100644 --- a/lms/djangoapps/verify_student/ssencrypt.py +++ b/lms/djangoapps/verify_student/ssencrypt.py @@ -149,12 +149,12 @@ def has_valid_signature(method, headers_dict, body_dict, access_key, secret_key) if post_access_key != access_key: log.error("Posted access key does not match ours") - log.debug("Their access: %s; Our access: %s", post_access_key, access_key) + log.debug(u"Their access: %s; Our access: %s", post_access_key, access_key) return False if post_signature != expected_signature: log.error("Posted signature does not match expected") - log.debug("Their sig: %s; Expected: %s", post_signature, expected_signature) + log.debug(u"Their sig: %s; Expected: %s", post_signature, expected_signature) return False return True @@ -169,7 +169,7 @@ def generate_signed_message(method, headers_dict, body_dict, access_key, secret_ # hmac needs a byte string for it's starting key, can't be unicode. hashed = hmac.new(secret_key.encode('utf-8'), message, sha256) signature = binascii.b2a_base64(hashed.digest()).rstrip('\n') - authorization_header = "SSI {}:{}".format(access_key, signature) + authorization_header = u"SSI {}:{}".format(access_key, signature) message += '\n' return message, signature, authorization_header diff --git a/lms/djangoapps/verify_student/tasks.py b/lms/djangoapps/verify_student/tasks.py index ceb5ac858d2..63fe41a4214 100644 --- a/lms/djangoapps/verify_student/tasks.py +++ b/lms/djangoapps/verify_student/tasks.py @@ -37,4 +37,4 @@ def send_verification_status_email(context): fail_silently=False ) except SMTPException: - log.warning("Failure in sending verification status e-mail to %s", dest_addr) + log.warning(u"Failure in sending verification status e-mail to %s", dest_addr) diff --git a/lms/djangoapps/verify_student/tests/fake_software_secure.py b/lms/djangoapps/verify_student/tests/fake_software_secure.py index cbae6181e82..f587f0bb38c 100644 --- a/lms/djangoapps/verify_student/tests/fake_software_secure.py +++ b/lms/djangoapps/verify_student/tests/fake_software_secure.py @@ -35,7 +35,7 @@ class SoftwareSecureFakeView(View): access_key = settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_ACCESS_KEY"] context = { 'receipt_id': None, - 'authorization_code': 'SIS {}:0000'.format(access_key), + 'authorization_code': u'SIS {}:0000'.format(access_key), 'results_callback': reverse('verify_student_results_callback') } diff --git a/lms/djangoapps/verify_student/tests/test_models.py b/lms/djangoapps/verify_student/tests/test_models.py index be256b584b6..ab8fee466b6 100644 --- a/lms/djangoapps/verify_student/tests/test_models.py +++ b/lms/djangoapps/verify_student/tests/test_models.py @@ -234,7 +234,7 @@ class TestPhotoVerification(TestVerification, MockS3Mixin, ModuleStoreTestCase): self.assertEqual(attempt.status, "must_retry") logger.check( ('lms.djangoapps.verify_student.models', 'ERROR', - 'Software Secure submission failed for user %s, setting status to must_retry' + u'Software Secure submission failed for user %s, setting status to must_retry' % attempt.user.username)) @mock.patch.dict(settings.FEATURES, {'AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING': True}) diff --git a/lms/djangoapps/verify_student/tests/test_views.py b/lms/djangoapps/verify_student/tests/test_views.py index a5c88bd6b0d..6c191966c71 100644 --- a/lms/djangoapps/verify_student/tests/test_views.py +++ b/lms/djangoapps/verify_student/tests/test_views.py @@ -983,9 +983,9 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin): response_dict = self._get_page_data(response) for req, displayed in response_dict['requirements'].iteritems(): if req in requirements: - self.assertTrue(displayed, msg="Expected '{req}' requirement to be displayed".format(req=req)) + self.assertTrue(displayed, msg=u"Expected '{req}' requirement to be displayed".format(req=req)) else: - self.assertFalse(displayed, msg="Expected '{req}' requirement to be hidden".format(req=req)) + self.assertFalse(displayed, msg=u"Expected '{req}' requirement to be hidden".format(req=req)) def _assert_course_details(self, response, course_key, display_name, url): """Check the course information on the page. """ @@ -1629,7 +1629,7 @@ class TestSubmitPhotosForVerification(TestCase): """ if expect_email: # Verify that photo submission confirmation email was sent - subject = _("{platform_name} ID Verification Photos Received").format( + subject = _(u"{platform_name} ID Verification Photos Received").format( platform_name=settings.PLATFORM_NAME ) self.assertEqual(len(mail.outbox), 1) diff --git a/lms/djangoapps/verify_student/views.py b/lms/djangoapps/verify_student/views.py index 27d8e7c1d86..db601878b1c 100644 --- a/lms/djangoapps/verify_student/views.py +++ b/lms/djangoapps/verify_student/views.py @@ -711,7 +711,7 @@ class PayAndVerifyView(View): """ if deadline_name not in [self.VERIFICATION_DEADLINE, self.UPGRADE_DEADLINE]: - log.error("Invalid deadline name %s. Skipping check for whether the deadline passed.", deadline_name) + log.error(u"Invalid deadline name %s. Skipping check for whether the deadline passed.", deadline_name) return None deadline_passed = ( @@ -743,7 +743,7 @@ def checkout_with_ecommerce_service(user, course_key, course_mode, processor): return result.get('payment_data') except SlumberBaseException: params = {'username': user.username, 'mode': course_mode.slug, 'course_id': course_id} - log.exception('Failed to create order for %(username)s %(mode)s mode of %(course_id)s', params) + log.exception(u'Failed to create order for %(username)s %(mode)s mode of %(course_id)s', params) raise finally: audit_log( @@ -951,7 +951,7 @@ class SubmitPhotosView(View): if "photo_id_image" not in params and not has_initial_verification: log.error( ( - "User %s does not have an initial verification attempt " + u"User %s does not have an initial verification attempt " "and no photo ID image data was provided. " "This most likely means that the JavaScript client is not " "correctly constructing the request to submit photos." @@ -993,7 +993,7 @@ class SubmitPhotosView(View): return HttpResponseBadRequest(_("No profile found for user")) except AccountValidationError: msg = _( - "Name must be at least {min_length} characters long." + u"Name must be at least {min_length} characters long." ).format(min_length=NAME_MIN_LENGTH) return HttpResponseBadRequest(msg) @@ -1071,7 +1071,7 @@ class SubmitPhotosView(View): 'platform_name': configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME) } - subject = _("{platform_name} ID Verification Photos Received").format(platform_name=context['platform_name']) + subject = _(u"{platform_name} ID Verification Photos Received").format(platform_name=context['platform_name']) message = render_to_string('emails/photo_submission_confirmation.txt', context) from_address = configuration_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL) to_address = user.email @@ -1082,7 +1082,7 @@ class SubmitPhotosView(View): # We catch all exceptions and log them. # It would be much, much worse to roll back the transaction due to an uncaught # exception than to skip sending the notification email. - log.exception("Could not send notification email for initial verification for user %s", user.id) + log.exception(u"Could not send notification email for initial verification for user %s", user.id) def _fire_event(self, user, event_name, parameters): """ @@ -1111,12 +1111,12 @@ def results_callback(request): try: body_dict = json.loads(body) except ValueError: - log.exception("Invalid JSON received from Software Secure:\n\n{}\n".format(body)) - return HttpResponseBadRequest("Invalid JSON. Received:\n\n{}".format(body)) + log.exception(u"Invalid JSON received from Software Secure:\n\n{}\n".format(body)) + return HttpResponseBadRequest(u"Invalid JSON. Received:\n\n{}".format(body)) if not isinstance(body_dict, dict): - log.error("Reply from Software Secure is not a dict:\n\n{}\n".format(body)) - return HttpResponseBadRequest("JSON should be dict. Received:\n\n{}".format(body)) + log.error(u"Reply from Software Secure is not a dict:\n\n{}\n".format(body)) + return HttpResponseBadRequest(u"JSON should be dict. Received:\n\n{}".format(body)) headers = { "Authorization": request.META.get("HTTP_AUTHORIZATION", ""), @@ -1150,23 +1150,23 @@ def results_callback(request): try: attempt = SoftwareSecurePhotoVerification.objects.get(receipt_id=receipt_id) except SoftwareSecurePhotoVerification.DoesNotExist: - log.error("Software Secure posted back for receipt_id %s, but not found", receipt_id) - return HttpResponseBadRequest("edX ID {} not found".format(receipt_id)) + log.error(u"Software Secure posted back for receipt_id %s, but not found", receipt_id) + return HttpResponseBadRequest(u"edX ID {} not found".format(receipt_id)) user = attempt.user verification_status_email_vars = { 'platform_name': settings.PLATFORM_NAME, } if result == "PASS": - log.debug("Approving verification for %s", receipt_id) + log.debug(u"Approving verification for %s", receipt_id) attempt.approve() - status = "approved" + status = u"approved" expiry_date = datetime.date.today() + datetime.timedelta( days=settings.VERIFY_STUDENT["DAYS_GOOD_FOR"] ) verification_status_email_vars['expiry_date'] = expiry_date.strftime("%m/%d/%Y") verification_status_email_vars['full_name'] = user.profile.name - subject = _("Your {platform_name} ID Verification Approved").format( + subject = _(u"Your {platform_name} ID Verification Approved").format( platform_name=settings.PLATFORM_NAME ) context = { @@ -1178,14 +1178,14 @@ def results_callback(request): send_verification_status_email.delay(context) elif result == "FAIL": - log.debug("Denying verification for %s", receipt_id) + log.debug(u"Denying verification for %s", receipt_id) attempt.deny(json.dumps(reason), error_code=error_code) status = "denied" reverify_url = '{}{}'.format(settings.LMS_ROOT_URL, reverse("verify_student_reverify")) verification_status_email_vars['reasons'] = reason verification_status_email_vars['reverify_url'] = reverify_url verification_status_email_vars['faq_url'] = settings.ID_VERIFICATION_SUPPORT_LINK - subject = _("Your {platform_name} Verification Has Been Denied").format( + subject = _(u"Your {platform_name} Verification Has Been Denied").format( platform_name=settings.PLATFORM_NAME ) context = { @@ -1197,14 +1197,14 @@ def results_callback(request): send_verification_status_email.delay(context) elif result == "SYSTEM FAIL": - log.debug("System failure for %s -- resetting to must_retry", receipt_id) + log.debug(u"System failure for %s -- resetting to must_retry", receipt_id) attempt.system_error(json.dumps(reason), error_code=error_code) status = "error" - log.error("Software Secure callback attempt for %s failed: %s", receipt_id, reason) + log.error(u"Software Secure callback attempt for %s failed: %s", receipt_id, reason) else: - log.error("Software Secure returned unknown result %s", result) + log.error(u"Software Secure returned unknown result %s", result) return HttpResponseBadRequest( - "Result {} not understood. Known results: PASS, FAIL, SYSTEM FAIL".format(result) + u"Result {} not understood. Known results: PASS, FAIL, SYSTEM FAIL".format(result) ) return HttpResponse("OK!") diff --git a/lms/envs/aws.py b/lms/envs/aws.py index 932550d6c21..5492b7d1973 100644 --- a/lms/envs/aws.py +++ b/lms/envs/aws.py @@ -375,7 +375,7 @@ if "TRACKING_IGNORE_URL_PATTERNS" in ENV_TOKENS: SSL_AUTH_EMAIL_DOMAIN = ENV_TOKENS.get("SSL_AUTH_EMAIL_DOMAIN", "MIT.EDU") SSL_AUTH_DN_FORMAT_STRING = ENV_TOKENS.get( "SSL_AUTH_DN_FORMAT_STRING", - "/C=US/ST=Massachusetts/O=Massachusetts Institute of Technology/OU=Client CA v1/CN={0}/emailAddress={1}" + u"/C=US/ST=Massachusetts/O=Massachusetts Institute of Technology/OU=Client CA v1/CN={0}/emailAddress={1}" ) # Django CAS external authentication settings diff --git a/lms/envs/common.py b/lms/envs/common.py index 7629aebd984..e29afff4821 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -2381,28 +2381,28 @@ SOCIAL_MEDIA_FOOTER_DISPLAY = { # translate this the way that Facebook advertises in your language. "title": _("Facebook"), "icon": "fa-facebook-square", - "action": _("Like {platform_name} on Facebook") + "action": _(u"Like {platform_name} on Facebook") }, "twitter": { # Translators: This is the website name of www.twitter.com. Please # translate this the way that Twitter advertises in your language. "title": _("Twitter"), "icon": "fa-twitter-square", - "action": _("Follow {platform_name} on Twitter") + "action": _(u"Follow {platform_name} on Twitter") }, "linkedin": { # Translators: This is the website name of www.linkedin.com. Please # translate this the way that LinkedIn advertises in your language. "title": _("LinkedIn"), "icon": "fa-linkedin-square", - "action": _("Follow {platform_name} on LinkedIn") + "action": _(u"Follow {platform_name} on LinkedIn") }, "google_plus": { # Translators: This is the website name of plus.google.com. Please # translate this the way that Google+ advertises in your language. "title": _("Google+"), "icon": "fa-google-plus-square", - "action": _("Follow {platform_name} on Google+") + "action": _(u"Follow {platform_name} on Google+") }, "tumblr": { # Translators: This is the website name of www.tumblr.com. Please @@ -2421,7 +2421,7 @@ SOCIAL_MEDIA_FOOTER_DISPLAY = { # translate this the way that Reddit advertises in your language. "title": _("Reddit"), "icon": "fa-reddit-square", - "action": _("Subscribe to the {platform_name} subreddit"), + "action": _(u"Subscribe to the {platform_name} subreddit"), }, "vk": { # Translators: This is the website name of https://vk.com. Please @@ -2440,7 +2440,7 @@ SOCIAL_MEDIA_FOOTER_DISPLAY = { # translate this the way that YouTube advertises in your language. "title": _("Youtube"), "icon": "fa-youtube-square", - "action": _("Subscribe to the {platform_name} YouTube channel") + "action": _(u"Subscribe to the {platform_name} YouTube channel") } } @@ -3324,11 +3324,11 @@ ENTERPRISE_CUSTOMER_LOGO_IMAGE_SIZE = 512 # Enterprise logo image size limit i ENTERPRISE_PLATFORM_WELCOME_TEMPLATE = _(u'Welcome to {platform_name}.') ENTERPRISE_SPECIFIC_BRANDED_WELCOME_TEMPLATE = _( - 'You have left the {start_bold}{enterprise_name}{end_bold} website and are now on the {platform_name} site. ' - '{enterprise_name} has partnered with {platform_name} to offer you high-quality, always available learning ' - 'programs to help you advance your knowledge and career. ' - '{line_break}Please note that {platform_name} has a different {privacy_policy_link_start}Privacy Policy' - '{privacy_policy_link_end} from {enterprise_name}.' + u'You have left the {start_bold}{enterprise_name}{end_bold} website and are now on the {platform_name} site. ' + u'{enterprise_name} has partnered with {platform_name} to offer you high-quality, always available learning ' + u'programs to help you advance your knowledge and career. ' + u'{line_break}Please note that {platform_name} has a different {privacy_policy_link_start}Privacy Policy' + u'{privacy_policy_link_end} from {enterprise_name}.' ) ENTERPRISE_TAGLINE = '' ENTERPRISE_EXCLUDED_REGISTRATION_FIELDS = { diff --git a/lms/envs/devstack.py b/lms/envs/devstack.py index 662d9a19691..26dd18f9360 100644 --- a/lms/envs/devstack.py +++ b/lms/envs/devstack.py @@ -230,6 +230,7 @@ CORS_ALLOW_HEADERS = corsheaders_default_headers + ( LOGIN_REDIRECT_WHITELIST = [CMS_BASE] ###################### JWTs ###################### +# pylint: disable=unicode-format-string JWT_AUTH.update({ 'JWT_ISSUER': OAUTH_OIDC_ISSUER, 'JWT_AUDIENCE': 'lms-key', @@ -255,7 +256,7 @@ JWT_AUTH.update({ 'y5ZLcTUomo4rZLjghVpq6KZxfS6I1Vz79ZsMVUWEdXOYePCKKsrQG20ogQEkmTf9FT_SouC6jPcHLXw"}]}' ), }) - +# pylint: enable=unicode-format-string ##################################################################### from openedx.core.djangoapps.plugins import plugin_settings, constants as plugin_constants plugin_settings.add_plugins(__name__, plugin_constants.ProjectType.LMS, plugin_constants.SettingsType.DEVSTACK) diff --git a/lms/envs/production.py b/lms/envs/production.py index 240c57a703b..2f9cbfd2216 100644 --- a/lms/envs/production.py +++ b/lms/envs/production.py @@ -379,7 +379,7 @@ if "TRACKING_IGNORE_URL_PATTERNS" in ENV_TOKENS: SSL_AUTH_EMAIL_DOMAIN = ENV_TOKENS.get("SSL_AUTH_EMAIL_DOMAIN", "MIT.EDU") SSL_AUTH_DN_FORMAT_STRING = ENV_TOKENS.get( "SSL_AUTH_DN_FORMAT_STRING", - "/C=US/ST=Massachusetts/O=Massachusetts Institute of Technology/OU=Client CA v1/CN={0}/emailAddress={1}" + u"/C=US/ST=Massachusetts/O=Massachusetts Institute of Technology/OU=Client CA v1/CN={0}/emailAddress={1}" ) # Django CAS external authentication settings diff --git a/lms/envs/test.py b/lms/envs/test.py index d5f094f6eb2..2d5caf4d291 100644 --- a/lms/envs/test.py +++ b/lms/envs/test.py @@ -584,7 +584,7 @@ VIDEO_TRANSCRIPTS_SETTINGS = dict( ) ####################### Authentication Settings ########################## - +# pylint: disable=unicode-format-string JWT_AUTH.update({ 'JWT_PUBLIC_SIGNING_JWK_SET': ( '{"keys": [{"kid": "BTZ9HA6K", "e": "AQAB", "kty": "RSA", "n": "o5cn3ljSRi6FaDEKTn0PS-oL9EFyv1pI7dRgffQLD1qf5D6' @@ -606,7 +606,7 @@ JWT_AUTH.update({ ': "RSA"}' ), }) - +# pylint: enable=unicode-format-string ####################### Plugin Settings ########################## from openedx.core.djangoapps.plugins import plugin_settings, constants as plugin_constants diff --git a/lms/lib/comment_client/models.py b/lms/lib/comment_client/models.py index cbf5cd257a6..35a781bb07b 100644 --- a/lms/lib/comment_client/models.py +++ b/lms/lib/comment_client/models.py @@ -29,7 +29,7 @@ class Model(object): return self.attributes[name] except KeyError: if self.retrieved or self.id is None: - raise AttributeError("Field {0} does not exist".format(name)) + raise AttributeError(u"Field {0} does not exist".format(name)) self.retrieve() return self.__getattr__(name) @@ -41,12 +41,12 @@ class Model(object): def __getitem__(self, key): if key not in self.accessible_fields: - raise KeyError("Field {0} does not exist".format(key)) + raise KeyError(u"Field {0} does not exist".format(key)) return self.attributes.get(key) def __setitem__(self, key, value): if key not in self.accessible_fields + self.updatable_fields: - raise KeyError("Field {0} does not exist".format(key)) + raise KeyError(u"Field {0} does not exist".format(key)) self.attributes.__setitem__(key, value) def items(self, *args, **kwargs): @@ -103,7 +103,7 @@ class Model(object): self.__setattr__(k, v) else: log.warning( - "Unexpected field {field_name} in model {model_name}".format( + u"Unexpected field {field_name} in model {model_name}".format( field_name=k, model_name=self.__class__.__name__ ) @@ -172,11 +172,11 @@ class Model(object): if cls.base_url is None: raise CommentClientRequestError("Must provide base_url when using default url function") if action not in cls.DEFAULT_ACTIONS: - raise ValueError("Invalid action {0}. The supported action must be in {1}".format(action, str(cls.DEFAULT_ACTIONS))) + raise ValueError(u"Invalid action {0}. The supported action must be in {1}".format(action, str(cls.DEFAULT_ACTIONS))) elif action in cls.DEFAULT_ACTIONS_WITH_ID: try: return cls.url_with_id(params) except KeyError: - raise CommentClientRequestError("Cannot perform action {0} without id".format(action)) + raise CommentClientRequestError(u"Cannot perform action {0} without id".format(action)) else: # action must be in DEFAULT_ACTIONS_WITHOUT_ID now return cls.url_without_id() diff --git a/lms/templates/shoppingcart/receipt.html b/lms/templates/shoppingcart/receipt.html index c0a0870ebc4..a9f0305586f 100644 --- a/lms/templates/shoppingcart/receipt.html +++ b/lms/templates/shoppingcart/receipt.html @@ -7,6 +7,7 @@ from django.utils.translation import ungettext from django.urls import reverse from markupsafe import escape from openedx.core.lib.courses import course_image_url +from openedx.core.djangolib.markup import HTML, Text %> <%block name="billing_details_highlight"> @@ -34,29 +35,31 @@ from openedx.core.lib.courses import course_image_url <% dashboard_url = reverse('dashboard') %> <a href="${dashboard_url}" class="blue pull-right">${_("View Dashboard")} <span class="icon fa fa-caret-right" aria-hidden="true"></span></a> <span class="mt-7"> - ${_(u"You have successfully been enrolled for {course_names}. " - u"The following receipt has been emailed to {receipient_emails}").format( - course_names=u"<b>{course_names}</b>".format( - course_names=escape(appended_course_names) - ), - receipient_emails=u"<strong>{receipient_emails}</strong>".format( + ${Text(_( + u"You have successfully been enrolled for {course_names}. " + u"The following receipt has been emailed to {receipient_emails}" + )).format( + course_names=HTML(u"<b>{course_names}</b>").format( + course_names=appended_course_names + ), + receipient_emails=HTML(u"<strong>{receipient_emails}</strong>").format( receipient_emails=appended_recipient_emails - ), + ), )} </span> % elif order_type == 'business': - ${ungettext( - "You have successfully purchased <b>{number} course registration code</b> for {course_names}.", - "You have successfully purchased <b>{number} course registration codes</b> for {course_names}.", + ${HTML(ungettext( + u"You have successfully purchased <b>{number} course registration code</b> for {course_names}.", + u"You have successfully purchased <b>{number} course registration codes</b> for {course_names}.", total_registration_codes - ).format( + )).format( number=total_registration_codes, - course_names=u"<b>{course_names}</b>".format( + course_names=HTML(u"<b>{course_names}</b>").format( course_names=escape(appended_course_names) ) )} - ${_("The following receipt has been emailed to {receipient_emails}").format( - receipient_emails=u"<strong>{receipient_emails}</strong>".format( + ${Text(_(u"The following receipt has been emailed to {receipient_emails}")).format( + receipient_emails=HTML(u"<strong>{receipient_emails}</strong>").format( receipient_emails=appended_recipient_emails, ) )} @@ -293,7 +296,7 @@ from openedx.core.lib.courses import course_image_url <div class="clearfix"> <div class="image"> <img class="item-image" src="${course_image_url(course)}" - alt="${course.display_number_with_default | h} ${course.display_name_with_default_escaped} Image"/> + alt="${course.display_number_with_default | h} ${course.display_name_with_default | h} Image"/> </div> <div class="data-input"> @@ -352,7 +355,7 @@ from openedx.core.lib.courses import course_image_url % if any_refunds: <span> ## Translators: Please keep the "<del>" and "</del>" tags around your translation of the word "this" in your translation. - ${_("Note: items with strikethough like <del>this</del> have been refunded.")} + ${HTML(_("Note: items with strikethough like <del>this</del> have been refunded."))} </span> % endif <span class="pull-right">${_("Total")}: <b> ${currency_symbol}${"{0:0.2f}".format(order.total_cost)} ${currency.upper()}</b></span> -- GitLab