From 98ec44b56cab691ce5592dcfc9b1bd5ab9413e56 Mon Sep 17 00:00:00 2001
From: Awais Qureshi <awais.qureshi@arbisoft.com>
Date: Tue, 10 Sep 2019 15:23:29 +0500
Subject: [PATCH] BOM-404 Fixing python3

---
 lms/djangoapps/courseware/courses.py          | 10 +++++++++-
 .../courseware/tests/test_masquerade.py       | 20 +++++++++----------
 lms/templates/courseware/progress_graph.js    |  3 ++-
 openedx/core/djangolib/js_utils.py            |  7 ++++++-
 4 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/lms/djangoapps/courseware/courses.py b/lms/djangoapps/courseware/courses.py
index 98e28829195..506a4b6f4c8 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 4c6a0d1a11a..a6ce93ff17f 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 8c1bb8c9d98..e71c66e9a9f 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 c8fed03af0a..d223a12c547 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
 
-- 
GitLab