Repository: ucfopen/canvasapi

Issue:
Quiz Assignment Overrides
**What resource needs additional coverage?**
Quiz Assignment Overrides

**What endpoints need to be covered?**
https://canvas.instructure.com/doc/api/quiz_assignment_overrides.html#method.quizzes/quiz_assignment_overrides.index

Discussion:

Patch:
diff --git a/canvasapi/course.py b/canvasapi/course.py
index 08d723b..a3850fd 100644
--- a/canvasapi/course.py
+++ b/canvasapi/course.py
@@ -1698,6 +1698,29 @@ class Course(CanvasObject):
 
         return Quiz(self._requester, quiz_json)
 
+    def get_quiz_overrides(self, **kwargs):
+        """
+        Retrieve the actual due-at, unlock-at,
+        and available-at dates for quizzes based on
+        the assignment overrides active for the current API user.
+
+        :calls: `GET /api/v1/courses/:course_id/quizzes/assignment_overrides \
+        <https://canvas.instructure.com/doc/api/quiz_assignment_overrides.html#method.quizzes/quiz_assignment_overrides.index>`_
+
+        :rtype: :class:`canvasapi.paginated_list.PaginatedList` of
+            :class:`canvasapi.quiz.QuizAssignmentOverrideSet`
+        """
+        from canvasapi.quiz import QuizAssignmentOverrideSet
+
+        return PaginatedList(
+            QuizAssignmentOverrideSet,
+            self._requester,
+            "GET",
+            "courses/{}/quizzes/assignment_overrides".format(self.id),
+            _root="quiz_assignment_overrides",
+            _kwargs=combine_kwargs(**kwargs),
+        )
+
     def get_quizzes(self, **kwargs):
         """
         Return a list of quizzes belonging to this course.
diff --git a/canvasapi/quiz.py b/canvasapi/quiz.py
index 2880211..0cce770 100644
--- a/canvasapi/quiz.py
+++ b/canvasapi/quiz.py
@@ -868,3 +868,9 @@ class QuizSubmissionQuestion(CanvasObject):
         super(QuizSubmissionQuestion, self).set_attributes(question)
 
         return True
+
+
+@python_2_unicode_compatible
+class QuizAssignmentOverrideSet(CanvasObject):
+    def __str__(self):
+        return "Overrides for quiz_id {}".format(self.quiz_id)
diff --git a/docs/quiz-ref.rst b/docs/quiz-ref.rst
index 74a24a4..32b779d 100644
--- a/docs/quiz-ref.rst
+++ b/docs/quiz-ref.rst
@@ -5,6 +5,13 @@ Quiz
 .. autoclass:: canvasapi.quiz.Quiz
     :members:
 
+=========================
+QuizAssignmentOverrideSet
+=========================
+
+.. autoclass:: canvasapi.quiz.QuizAssignmentOverrideSet
+    :members:
+
 =============
 QuizExtension
 =============
@@ -32,3 +39,17 @@ QuizSubmission
 
 .. autoclass:: canvasapi.quiz.QuizSubmission
     :members:
+
+===================
+QuizSubmissionEvent
+===================
+
+.. autoclass:: canvasapi.quiz.QuizSubmissionEvent
+    :members:
+
+======================
+QuizSubmissionQuestion
+======================
+
+.. autoclass:: canvasapi.quiz.QuizSubmissionQuestion
+    :members:


Test patch:
diff --git a/tests/fixtures/course.json b/tests/fixtures/course.json
index 0fab725..faf198b 100644
--- a/tests/fixtures/course.json
+++ b/tests/fixtures/course.json
@@ -409,6 +409,50 @@
 		},
 		"status_code": 200
 	},
+	"get_quiz_overrides": {
+		"method": "GET",
+		"endpoint": "courses/1/quizzes/assignment_overrides",
+		"data": {
+			"quiz_assignment_overrides": [{
+				"quiz_id": "1",
+				"due_dates": [{
+					"id": 1,
+					"due_at": "2014-02-21T06:59:59Z",
+					"unlock_at": null,
+					"lock_at": "2014-02-21T06:59:59Z",
+					"title": "Project X",
+					"base": true
+				}],
+				"all_dates": [{
+					"id": 1,
+					"due_at": "2014-02-21T06:59:59Z",
+					"unlock_at": null,
+					"lock_at": "2014-02-21T06:59:59Z",
+					"title": "Project X",
+					"base": true
+				}]
+			},{
+				"quiz_id": "2",
+				"due_dates": [{
+					"id": 1,
+					"due_at": "2014-02-21T06:59:59Z",
+					"unlock_at": null,
+					"lock_at": "2014-02-21T06:59:59Z",
+					"title": "Project X",
+					"base": true
+				}],
+				"all_dates": [{
+					"id": 1,
+					"due_at": "2014-02-21T06:59:59Z",
+					"unlock_at": null,
+					"lock_at": "2014-02-21T06:59:59Z",
+					"title": "Project X",
+					"base": true
+				}]
+			}]
+		},
+		"status_code": 200
+	},
 	"get_recent_students": {
 		"method": "GET",
 		"endpoint": "courses/1/recent_students",
diff --git a/tests/test_course.py b/tests/test_course.py
index b07c9ba..287b35e 100644
--- a/tests/test_course.py
+++ b/tests/test_course.py
@@ -37,7 +37,7 @@ from canvasapi.outcome import OutcomeGroup, OutcomeLink
 from canvasapi.outcome_import import OutcomeImport
 from canvasapi.paginated_list import PaginatedList
 from canvasapi.progress import Progress
-from canvasapi.quiz import Quiz, QuizExtension
+from canvasapi.quiz import Quiz, QuizExtension, QuizAssignmentOverrideSet
 from canvasapi.rubric import Rubric, RubricAssociation
 from canvasapi.section import Section
 from canvasapi.submission import GroupedSubmission, Submission
@@ -308,6 +308,29 @@ class TestCourse(unittest.TestCase):
         with self.assertRaises(ResourceDoesNotExist):
             self.course.get_quiz(settings.INVALID_ID)
 
+    # get_quiz_overrides()
+    def test_get_quiz_overrides(self, m):
+        register_uris({"course": ["get_quiz_overrides"]}, m)
+
+        overrides = self.course.get_quiz_overrides()
+        override_list = list(overrides)
+
+        self.assertEqual(len(override_list), 2)
+        self.assertIsInstance(override_list[0], QuizAssignmentOverrideSet)
+        self.assertTrue(hasattr(override_list[0], "quiz_id"))
+        self.assertTrue(hasattr(override_list[0], "due_dates"))
+        self.assertTrue(hasattr(override_list[0], "all_dates"))
+
+        attributes = ("id", "due_at", "unlock_at", "lock_at", "title", "base")
+
+        self.assertTrue(
+            all(attribute in override_list[0].due_dates[0] for attribute in attributes)
+        )
+
+        self.assertTrue(
+            all(attribute in override_list[0].all_dates[0] for attribute in attributes)
+        )
+
     # get_quizzes()
     def test_get_quizzes(self, m):
         register_uris({"course": ["list_quizzes", "list_quizzes2"]}, m)
diff --git a/tests/test_quiz.py b/tests/test_quiz.py
index bf13a87..4e87972 100644
--- a/tests/test_quiz.py
+++ b/tests/test_quiz.py
@@ -16,6 +16,7 @@ from canvasapi.quiz import (
     QuizExtension,
     QuizSubmissionEvent,
     QuizReport,
+    QuizAssignmentOverrideSet,
 )
 from canvasapi.quiz_group import QuizGroup
 from canvasapi.paginated_list import PaginatedList
@@ -730,3 +731,19 @@ class TestQuizSubmissionQuestion(unittest.TestCase):
         self.assertIsInstance(result, bool)
         self.assertTrue(result)
         self.assertFalse(self.submission_question.flagged)
+
+
+@requests_mock.Mocker()
+class TestQuizAssignmentOverrideSet(unittest.TestCase):
+    def setUp(self):
+        self.canvas = Canvas(settings.BASE_URL, settings.API_KEY)
+
+        self.override_set = QuizAssignmentOverrideSet(
+            self.canvas._Canvas__requester,
+            {"quiz_id": "1", "due_dates": None, "all_dates": None},
+        )
+
+    # __str__()
+    def test__str__(self, m):
+        string = str(self.override_set)
+        self.assertIsInstance(string, str)