diff --git a/lms/djangoapps/courseware/courses.py b/lms/djangoapps/courseware/courses.py index 98e2882919504a876a32628217ff7159ef2f1f69..506a4b6f4c8d397e075a3334d1674518c06e1e8b 100644 --- a/lms/djangoapps/courseware/courses.py +++ b/lms/djangoapps/courseware/courses.py @@ -618,7 +618,15 @@ def get_current_child(xmodule, min_depth=None, requested_child=None): return _get_child(content_children) if content_children else None child = None - if hasattr(xmodule, 'position'): + + try: + # In python 3, hasattr() catches AttributeErrors only then returns False. + # All other exceptions bubble up the call stack. + has_position = hasattr(xmodule, 'position') # This conditions returns AssertionError from xblock.fields lib. + except AssertionError: + return child + + if has_position: children = xmodule.get_display_items() if len(children) > 0: if xmodule.position is not None and not requested_child: diff --git a/lms/djangoapps/courseware/tests/test_masquerade.py b/lms/djangoapps/courseware/tests/test_masquerade.py index 4c6a0d1a11aee597309751a97a0f980f43f16c9f..a6ce93ff17fcdbd3b7f1e22e8d74c18856d0ac3d 100644 --- a/lms/djangoapps/courseware/tests/test_masquerade.py +++ b/lms/djangoapps/courseware/tests/test_masquerade.py @@ -127,7 +127,7 @@ class MasqueradeTestCase(SharedModuleStoreTestCase, LoginEnrollmentTestCase): """ Verifies that the staff debug control visibility is as expected (for staff only). """ - content = self.get_courseware_page().content + content = self.get_courseware_page().content.decode('utf-8') self.assertIn(self.sequential_display_name, content, "Subsection should be visible") self.assertEqual(staff_debug_expected, 'Staff Debug Info' in content) @@ -150,7 +150,7 @@ class MasqueradeTestCase(SharedModuleStoreTestCase, LoginEnrollmentTestCase): """ Verifies that "Show Answer" is only present when expected (for staff only). """ - problem_html = json.loads(self.get_problem().content)['html'] + problem_html = json.loads(self.get_problem().content.decode('utf-8'))['html'] self.assertIn(self.problem_display_name, problem_html) self.assertEqual(show_answer_expected, "Show Answer" in problem_html) @@ -295,7 +295,7 @@ class TestStaffMasqueradeAsSpecificStudent(StaffMasqueradeTestCase, ProblemSubmi The return value is a string like u'1/2'. """ - json_data = json.loads(self.look_at_question(self.problem_display_name).content) + json_data = json.loads(self.look_at_question(self.problem_display_name).content.decode('utf-8')) progress = '%s/%s' % (str(json_data['current_score']), str(json_data['total_possible'])) return progress @@ -329,7 +329,7 @@ class TestStaffMasqueradeAsSpecificStudent(StaffMasqueradeTestCase, ProblemSubmi self.login_staff() response = self.get_course_info_page() self.assertEqual(response.status_code, 200) - content = response.content + content = response.content.decode('utf-8') self.assertIn("OOGIE BLOOGIE", content) # Masquerade as the student,enable the self paced configuration, and check we can see the info page. @@ -337,7 +337,7 @@ class TestStaffMasqueradeAsSpecificStudent(StaffMasqueradeTestCase, ProblemSubmi self.update_masquerade(role='student', user_name=self.student_user.username) response = self.get_course_info_page() self.assertEqual(response.status_code, 200) - content = response.content + content = response.content.decode('utf-8') self.assertIn("OOGIE BLOOGIE", content) @ddt.data( @@ -421,12 +421,12 @@ class TestStaffMasqueradeAsSpecificStudent(StaffMasqueradeTestCase, ProblemSubmi """ # Log in as staff, and check we can see the info page. self.login_staff() - content = self.get_course_info_page().content + content = self.get_course_info_page().content.decode('utf-8') self.assertIn("OOGIE BLOOGIE", content) # Masquerade as the student, and check we can see the info page. self.update_masquerade(role='student', user_name=self.student_user.username) - content = self.get_course_info_page().content + content = self.get_course_info_page().content.decode('utf-8') self.assertIn("OOGIE BLOOGIE", content) def test_masquerade_as_specific_student_progress(self): @@ -436,20 +436,20 @@ class TestStaffMasqueradeAsSpecificStudent(StaffMasqueradeTestCase, ProblemSubmi # Give the student some correct answers, check their progress page self.login_student() self.submit_answer('Correct', 'Correct') - student_progress = self.get_progress_page().content + student_progress = self.get_progress_page().content.decode('utf-8') self.assertNotIn("1 of 2 possible points", student_progress) self.assertIn("2 of 2 possible points", student_progress) # Staff answers are slightly different self.login_staff() self.submit_answer('Incorrect', 'Correct') - staff_progress = self.get_progress_page().content + staff_progress = self.get_progress_page().content.decode('utf-8') self.assertNotIn("2 of 2 possible points", staff_progress) self.assertIn("1 of 2 possible points", staff_progress) # Should now see the student's scores self.update_masquerade(role='student', user_name=self.student_user.username) - masquerade_progress = self.get_progress_page().content + masquerade_progress = self.get_progress_page().content.decode('utf-8') self.assertNotIn("1 of 2 possible points", masquerade_progress) self.assertIn("2 of 2 possible points", masquerade_progress) diff --git a/lms/templates/courseware/progress_graph.js b/lms/templates/courseware/progress_graph.js index 8c1bb8c9d987be627f5d88765dcbf3284ae04bed..e71c66e9a9fc7cecc77679f4ecd124e60b9301b1 100644 --- a/lms/templates/courseware/progress_graph.js +++ b/lms/templates/courseware/progress_graph.js @@ -3,6 +3,7 @@ import bleach import json import math + import six from openedx.core.djangolib.js_utils import ( dump_js_escaped_json, js_escaped_string @@ -100,7 +101,7 @@ $(function () { extraColorIndex = len(categories) #Keeping track of the next color to use for categories not in categories[] if show_grade_breakdown: - for section in grade_summary['grade_breakdown'].itervalues(): + for section in six.itervalues(grade_summary['grade_breakdown']): if section['percent'] > 0: if section['category'] in categories: color = categories[ section['category'] ]['color'] diff --git a/openedx/core/djangolib/js_utils.py b/openedx/core/djangolib/js_utils.py index c8fed03af0ac524c1776434f511906c9a3d2a9d3..d223a12c5471a1cbfa1420c6b125e8d401a4f653 100644 --- a/openedx/core/djangolib/js_utils.py +++ b/openedx/core/djangolib/js_utils.py @@ -69,7 +69,12 @@ def dump_js_escaped_json(obj, cls=EdxJSONEncoder): (string) Escaped encoded JSON. """ - json_string = json.dumps(obj, ensure_ascii=True, cls=cls) + try: + json_string = json.dumps(obj, ensure_ascii=True, cls=cls) + except: # pylint: disable=bare-except + # in some cases dict_values appear here. + json_string = json.dumps(list(obj), ensure_ascii=True, cls=cls) + json_string = _escape_json_for_js(json_string) return json_string