lms.backend.canvas.backend

  1# pylint: disable=abstract-method
  2
  3import typing
  4
  5import quizcomp.model.quiz
  6
  7import lms.backend.canvas.courses.assignments.list
  8import lms.backend.canvas.courses.assignments.scores.list
  9import lms.backend.canvas.courses.assignments.scores.upload
 10import lms.backend.canvas.courses.gradebook.fetch
 11import lms.backend.canvas.courses.groupsets.create
 12import lms.backend.canvas.courses.groupsets.delete
 13import lms.backend.canvas.courses.groupsets.list
 14import lms.backend.canvas.courses.groupsets.memberships.list
 15import lms.backend.canvas.courses.groups.create
 16import lms.backend.canvas.courses.groups.delete
 17import lms.backend.canvas.courses.groups.list
 18import lms.backend.canvas.courses.groups.memberships.add
 19import lms.backend.canvas.courses.groups.memberships.list
 20import lms.backend.canvas.courses.groups.memberships.subtract
 21import lms.backend.canvas.courses.list
 22import lms.backend.canvas.courses.quizzes.download
 23import lms.backend.canvas.courses.quizzes.list
 24import lms.backend.canvas.courses.quizzes.remove
 25import lms.backend.canvas.courses.quizzes.upload
 26import lms.backend.canvas.courses.syllabus.fetch
 27import lms.backend.canvas.courses.users.list
 28import lms.backend.canvas.courses.users.scores.list
 29import lms.model.assignments
 30import lms.model.backend
 31import lms.model.constants
 32import lms.model.courses
 33import lms.model.groups
 34import lms.model.groupsets
 35import lms.model.scores
 36import lms.model.users
 37import lms.util.parse
 38
 39class CanvasBackend(lms.model.backend.APIBackend):
 40    """ An API backend for Instructure's Canvas LMS. """
 41
 42    def __init__(self,
 43            **kwargs: typing.Any) -> None:
 44        super().__init__(**kwargs)
 45
 46        assert(self.config.backend_type == lms.model.constants.BackendType.CANVAS)
 47
 48        if (self.config.auth_token is None):
 49            raise ValueError("Canvas backends require a token.")
 50
 51        self.auth_token: str = self.config.auth_token.cleartext
 52        """
 53        The (cleartext) token to authenticate with.
 54        This is set in config and compied for type checking.
 55        """
 56
 57    def get_standard_headers(self, write: bool = False) -> typing.Dict[str, str]:
 58        headers = super().get_standard_headers(write)
 59
 60        headers['Authorization'] = f"Bearer {self.auth_token}"
 61
 62        return headers
 63
 64    def courses_list(self,
 65            **kwargs: typing.Any) -> typing.List[lms.model.courses.Course]:
 66        return lms.backend.canvas.courses.list.request(self)
 67
 68    def courses_assignments_list(self,
 69            course_id: str,
 70            **kwargs: typing.Any) -> typing.List[lms.model.assignments.Assignment]:
 71        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
 72        return lms.backend.canvas.courses.assignments.list.request(self, parsed_course_id)
 73
 74    def courses_assignments_scores_list(self,
 75            course_id: str,
 76            assignment_id: str,
 77            **kwargs: typing.Any) -> typing.List[lms.model.scores.AssignmentScore]:
 78        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
 79        parsed_assignment_id = lms.util.parse.required_int(assignment_id, 'assignment_id')
 80        return lms.backend.canvas.courses.assignments.scores.list.request(self, parsed_course_id, parsed_assignment_id)
 81
 82    def courses_assignments_scores_upload(self,
 83            course_id: str,
 84            assignment_id: str,
 85            scores: typing.Dict[str, lms.model.scores.ScoreFragment],
 86            **kwargs: typing.Any) -> int:
 87        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
 88        parsed_assignment_id = lms.util.parse.required_int(assignment_id, 'assignment_id')
 89        parsed_scores = {lms.util.parse.required_int(user_id, 'user_id'): score for (user_id, score) in scores.items()}
 90        return lms.backend.canvas.courses.assignments.scores.upload.request(self, parsed_course_id, parsed_assignment_id, parsed_scores)
 91
 92    def courses_gradebook_fetch(self,
 93            course_id: str,
 94            assignment_ids: typing.Collection[str],
 95            user_ids: typing.Collection[str],
 96            **kwargs: typing.Any) -> lms.model.scores.Gradebook:
 97        if ((len(assignment_ids) == 0) or (len(user_ids) == 0)):
 98            assignment_queries = [lms.model.assignments.AssignmentQuery(id = id) for id in assignment_ids]
 99            user_queries = [lms.model.users.UserQuery(id = id) for id in user_ids]
100            return lms.model.scores.Gradebook(assignment_queries, user_queries)
101
102        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
103        parsed_assignment_ids = [lms.util.parse.required_int(assignment_id, 'assignment_id') for assignment_id in assignment_ids]
104        parsed_user_ids = [lms.util.parse.required_int(user_id, 'user_id') for user_id in user_ids]
105
106        return lms.backend.canvas.courses.gradebook.fetch.request(self, parsed_course_id, parsed_assignment_ids, parsed_user_ids)
107
108    def courses_groupsets_create(self,
109            course_id: str,
110            name: str,
111            **kwargs: typing.Any) -> lms.model.groupsets.GroupSet:
112        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
113        return lms.backend.canvas.courses.groupsets.create.request(self, parsed_course_id, name)
114
115    def courses_groupsets_delete(self,
116            course_id: str,
117            groupset_id: str,
118            **kwargs: typing.Any) -> bool:
119        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
120        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
121        return lms.backend.canvas.courses.groupsets.delete.request(self, parsed_course_id, parsed_groupset_id)
122
123    def courses_groupsets_list(self,
124            course_id: str,
125            **kwargs: typing.Any) -> typing.List[lms.model.groupsets.GroupSet]:
126        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
127        return lms.backend.canvas.courses.groupsets.list.request(self, parsed_course_id)
128
129    def courses_groupsets_memberships_list(self,
130            course_id: str,
131            groupset_id: str,
132            **kwargs: typing.Any) -> typing.List[lms.model.groupsets.GroupSetMembership]:
133        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
134        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
135        return lms.backend.canvas.courses.groupsets.memberships.list.request(self, parsed_course_id, parsed_groupset_id)
136
137    def courses_groups_create(self,
138            course_id: str,
139            groupset_id: str,
140            name: str,
141            **kwargs: typing.Any) -> lms.model.groups.Group:
142        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
143        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
144        return lms.backend.canvas.courses.groups.create.request(self, parsed_course_id, parsed_groupset_id, name)
145
146    def courses_groups_delete(self,
147            course_id: str,
148            groupset_id: str,
149            group_id: str,
150            **kwargs: typing.Any) -> bool:
151        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
152        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
153        parsed_group_id = lms.util.parse.required_int(group_id, 'group_id')
154        return lms.backend.canvas.courses.groups.delete.request(self, parsed_course_id, parsed_groupset_id, parsed_group_id)
155
156    def courses_groups_list(self,
157            course_id: str,
158            groupset_id: str,
159            **kwargs: typing.Any) -> typing.List[lms.model.groups.Group]:
160        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
161        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
162        return lms.backend.canvas.courses.groups.list.request(self, parsed_course_id, parsed_groupset_id)
163
164    def courses_groups_memberships_add(self,
165            course_id: str,
166            groupset_id: str,
167            group_id: str,
168            user_ids: typing.Collection[str],
169            **kwargs: typing.Any) -> int:
170        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
171        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
172        parsed_group_id = lms.util.parse.required_int(group_id, 'group_id')
173        parsed_user_ids = [lms.util.parse.required_int(user_id, 'user_id') for user_id in user_ids]
174        return lms.backend.canvas.courses.groups.memberships.add.request(self, parsed_course_id, parsed_groupset_id, parsed_group_id, parsed_user_ids)
175
176    def courses_groups_memberships_list(self,
177            course_id: str,
178            groupset_id: str,
179            group_id: str,
180            **kwargs: typing.Any) -> typing.List[lms.model.groupsets.GroupSetMembership]:
181        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
182        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
183        parsed_group_id = lms.util.parse.required_int(group_id, 'group_id')
184        return lms.backend.canvas.courses.groups.memberships.list.request(self, parsed_course_id, parsed_groupset_id, parsed_group_id)
185
186    def courses_groups_memberships_subtract(self,
187            course_id: str,
188            groupset_id: str,
189            group_id: str,
190            user_ids: typing.Collection[str],
191            **kwargs: typing.Any) -> int:
192        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
193        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
194        parsed_group_id = lms.util.parse.required_int(group_id, 'group_id')
195        parsed_user_ids = [lms.util.parse.required_int(user_id, 'user_id') for user_id in user_ids]
196        return lms.backend.canvas.courses.groups.memberships.subtract.request(self,
197                parsed_course_id, parsed_groupset_id, parsed_group_id, parsed_user_ids)
198
199    def courses_quizzes_download(self,
200            course_id: str,
201            quiz_id: str,
202            **kwargs: typing.Any) -> quizcomp.model.quiz.Quiz:
203        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
204        parsed_quiz_id = lms.util.parse.required_int(quiz_id, 'quiz_id')
205        return lms.backend.canvas.courses.quizzes.download.request(self, parsed_course_id, parsed_quiz_id)
206
207    def courses_quizzes_list(self,
208            course_id: str,
209            **kwargs: typing.Any) -> typing.List[lms.model.assignments.Assignment]:
210        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
211        return lms.backend.canvas.courses.quizzes.list.request(self, parsed_course_id)
212
213    def courses_quizzes_remove(self,
214            course_id: str,
215            quiz_id: str,
216            **kwargs: typing.Any) -> None:
217        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
218        parsed_quiz_id = lms.util.parse.required_int(quiz_id, 'quiz_id')
219        lms.backend.canvas.courses.quizzes.remove.request(self, parsed_course_id, parsed_quiz_id)
220
221    def courses_quizzes_upload(self,
222            course_id: str,
223            quiz: quizcomp.model.quiz.Quiz,
224            **kwargs: typing.Any) -> lms.model.assignments.Assignment:
225        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
226        return lms.backend.canvas.courses.quizzes.upload.request(self, parsed_course_id, quiz)
227
228    def courses_syllabus_fetch(self,
229            course_id: str,
230            **kwargs: typing.Any) -> typing.Union[str, None]:
231        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
232        return lms.backend.canvas.courses.syllabus.fetch.request(self, parsed_course_id)
233
234    def courses_users_list(self,
235            course_id: str,
236            **kwargs: typing.Any) -> typing.List[lms.model.users.CourseUser]:
237        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
238        return lms.backend.canvas.courses.users.list.request(self, parsed_course_id)
239
240    def courses_users_scores_list(self,
241            course_id: str,
242            user_id: str,
243            **kwargs: typing.Any) -> typing.List[lms.model.scores.AssignmentScore]:
244        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
245        parsed_user_id = lms.util.parse.required_int(user_id, 'user_id')
246        return lms.backend.canvas.courses.users.scores.list.request(self, parsed_course_id, parsed_user_id)
class CanvasBackend(lms.model.backend.APIBackend):
 40class CanvasBackend(lms.model.backend.APIBackend):
 41    """ An API backend for Instructure's Canvas LMS. """
 42
 43    def __init__(self,
 44            **kwargs: typing.Any) -> None:
 45        super().__init__(**kwargs)
 46
 47        assert(self.config.backend_type == lms.model.constants.BackendType.CANVAS)
 48
 49        if (self.config.auth_token is None):
 50            raise ValueError("Canvas backends require a token.")
 51
 52        self.auth_token: str = self.config.auth_token.cleartext
 53        """
 54        The (cleartext) token to authenticate with.
 55        This is set in config and compied for type checking.
 56        """
 57
 58    def get_standard_headers(self, write: bool = False) -> typing.Dict[str, str]:
 59        headers = super().get_standard_headers(write)
 60
 61        headers['Authorization'] = f"Bearer {self.auth_token}"
 62
 63        return headers
 64
 65    def courses_list(self,
 66            **kwargs: typing.Any) -> typing.List[lms.model.courses.Course]:
 67        return lms.backend.canvas.courses.list.request(self)
 68
 69    def courses_assignments_list(self,
 70            course_id: str,
 71            **kwargs: typing.Any) -> typing.List[lms.model.assignments.Assignment]:
 72        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
 73        return lms.backend.canvas.courses.assignments.list.request(self, parsed_course_id)
 74
 75    def courses_assignments_scores_list(self,
 76            course_id: str,
 77            assignment_id: str,
 78            **kwargs: typing.Any) -> typing.List[lms.model.scores.AssignmentScore]:
 79        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
 80        parsed_assignment_id = lms.util.parse.required_int(assignment_id, 'assignment_id')
 81        return lms.backend.canvas.courses.assignments.scores.list.request(self, parsed_course_id, parsed_assignment_id)
 82
 83    def courses_assignments_scores_upload(self,
 84            course_id: str,
 85            assignment_id: str,
 86            scores: typing.Dict[str, lms.model.scores.ScoreFragment],
 87            **kwargs: typing.Any) -> int:
 88        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
 89        parsed_assignment_id = lms.util.parse.required_int(assignment_id, 'assignment_id')
 90        parsed_scores = {lms.util.parse.required_int(user_id, 'user_id'): score for (user_id, score) in scores.items()}
 91        return lms.backend.canvas.courses.assignments.scores.upload.request(self, parsed_course_id, parsed_assignment_id, parsed_scores)
 92
 93    def courses_gradebook_fetch(self,
 94            course_id: str,
 95            assignment_ids: typing.Collection[str],
 96            user_ids: typing.Collection[str],
 97            **kwargs: typing.Any) -> lms.model.scores.Gradebook:
 98        if ((len(assignment_ids) == 0) or (len(user_ids) == 0)):
 99            assignment_queries = [lms.model.assignments.AssignmentQuery(id = id) for id in assignment_ids]
100            user_queries = [lms.model.users.UserQuery(id = id) for id in user_ids]
101            return lms.model.scores.Gradebook(assignment_queries, user_queries)
102
103        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
104        parsed_assignment_ids = [lms.util.parse.required_int(assignment_id, 'assignment_id') for assignment_id in assignment_ids]
105        parsed_user_ids = [lms.util.parse.required_int(user_id, 'user_id') for user_id in user_ids]
106
107        return lms.backend.canvas.courses.gradebook.fetch.request(self, parsed_course_id, parsed_assignment_ids, parsed_user_ids)
108
109    def courses_groupsets_create(self,
110            course_id: str,
111            name: str,
112            **kwargs: typing.Any) -> lms.model.groupsets.GroupSet:
113        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
114        return lms.backend.canvas.courses.groupsets.create.request(self, parsed_course_id, name)
115
116    def courses_groupsets_delete(self,
117            course_id: str,
118            groupset_id: str,
119            **kwargs: typing.Any) -> bool:
120        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
121        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
122        return lms.backend.canvas.courses.groupsets.delete.request(self, parsed_course_id, parsed_groupset_id)
123
124    def courses_groupsets_list(self,
125            course_id: str,
126            **kwargs: typing.Any) -> typing.List[lms.model.groupsets.GroupSet]:
127        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
128        return lms.backend.canvas.courses.groupsets.list.request(self, parsed_course_id)
129
130    def courses_groupsets_memberships_list(self,
131            course_id: str,
132            groupset_id: str,
133            **kwargs: typing.Any) -> typing.List[lms.model.groupsets.GroupSetMembership]:
134        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
135        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
136        return lms.backend.canvas.courses.groupsets.memberships.list.request(self, parsed_course_id, parsed_groupset_id)
137
138    def courses_groups_create(self,
139            course_id: str,
140            groupset_id: str,
141            name: str,
142            **kwargs: typing.Any) -> lms.model.groups.Group:
143        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
144        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
145        return lms.backend.canvas.courses.groups.create.request(self, parsed_course_id, parsed_groupset_id, name)
146
147    def courses_groups_delete(self,
148            course_id: str,
149            groupset_id: str,
150            group_id: str,
151            **kwargs: typing.Any) -> bool:
152        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
153        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
154        parsed_group_id = lms.util.parse.required_int(group_id, 'group_id')
155        return lms.backend.canvas.courses.groups.delete.request(self, parsed_course_id, parsed_groupset_id, parsed_group_id)
156
157    def courses_groups_list(self,
158            course_id: str,
159            groupset_id: str,
160            **kwargs: typing.Any) -> typing.List[lms.model.groups.Group]:
161        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
162        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
163        return lms.backend.canvas.courses.groups.list.request(self, parsed_course_id, parsed_groupset_id)
164
165    def courses_groups_memberships_add(self,
166            course_id: str,
167            groupset_id: str,
168            group_id: str,
169            user_ids: typing.Collection[str],
170            **kwargs: typing.Any) -> int:
171        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
172        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
173        parsed_group_id = lms.util.parse.required_int(group_id, 'group_id')
174        parsed_user_ids = [lms.util.parse.required_int(user_id, 'user_id') for user_id in user_ids]
175        return lms.backend.canvas.courses.groups.memberships.add.request(self, parsed_course_id, parsed_groupset_id, parsed_group_id, parsed_user_ids)
176
177    def courses_groups_memberships_list(self,
178            course_id: str,
179            groupset_id: str,
180            group_id: str,
181            **kwargs: typing.Any) -> typing.List[lms.model.groupsets.GroupSetMembership]:
182        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
183        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
184        parsed_group_id = lms.util.parse.required_int(group_id, 'group_id')
185        return lms.backend.canvas.courses.groups.memberships.list.request(self, parsed_course_id, parsed_groupset_id, parsed_group_id)
186
187    def courses_groups_memberships_subtract(self,
188            course_id: str,
189            groupset_id: str,
190            group_id: str,
191            user_ids: typing.Collection[str],
192            **kwargs: typing.Any) -> int:
193        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
194        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
195        parsed_group_id = lms.util.parse.required_int(group_id, 'group_id')
196        parsed_user_ids = [lms.util.parse.required_int(user_id, 'user_id') for user_id in user_ids]
197        return lms.backend.canvas.courses.groups.memberships.subtract.request(self,
198                parsed_course_id, parsed_groupset_id, parsed_group_id, parsed_user_ids)
199
200    def courses_quizzes_download(self,
201            course_id: str,
202            quiz_id: str,
203            **kwargs: typing.Any) -> quizcomp.model.quiz.Quiz:
204        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
205        parsed_quiz_id = lms.util.parse.required_int(quiz_id, 'quiz_id')
206        return lms.backend.canvas.courses.quizzes.download.request(self, parsed_course_id, parsed_quiz_id)
207
208    def courses_quizzes_list(self,
209            course_id: str,
210            **kwargs: typing.Any) -> typing.List[lms.model.assignments.Assignment]:
211        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
212        return lms.backend.canvas.courses.quizzes.list.request(self, parsed_course_id)
213
214    def courses_quizzes_remove(self,
215            course_id: str,
216            quiz_id: str,
217            **kwargs: typing.Any) -> None:
218        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
219        parsed_quiz_id = lms.util.parse.required_int(quiz_id, 'quiz_id')
220        lms.backend.canvas.courses.quizzes.remove.request(self, parsed_course_id, parsed_quiz_id)
221
222    def courses_quizzes_upload(self,
223            course_id: str,
224            quiz: quizcomp.model.quiz.Quiz,
225            **kwargs: typing.Any) -> lms.model.assignments.Assignment:
226        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
227        return lms.backend.canvas.courses.quizzes.upload.request(self, parsed_course_id, quiz)
228
229    def courses_syllabus_fetch(self,
230            course_id: str,
231            **kwargs: typing.Any) -> typing.Union[str, None]:
232        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
233        return lms.backend.canvas.courses.syllabus.fetch.request(self, parsed_course_id)
234
235    def courses_users_list(self,
236            course_id: str,
237            **kwargs: typing.Any) -> typing.List[lms.model.users.CourseUser]:
238        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
239        return lms.backend.canvas.courses.users.list.request(self, parsed_course_id)
240
241    def courses_users_scores_list(self,
242            course_id: str,
243            user_id: str,
244            **kwargs: typing.Any) -> typing.List[lms.model.scores.AssignmentScore]:
245        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
246        parsed_user_id = lms.util.parse.required_int(user_id, 'user_id')
247        return lms.backend.canvas.courses.users.scores.list.request(self, parsed_course_id, parsed_user_id)

An API backend for Instructure's Canvas LMS.

CanvasBackend(**kwargs: Any)
43    def __init__(self,
44            **kwargs: typing.Any) -> None:
45        super().__init__(**kwargs)
46
47        assert(self.config.backend_type == lms.model.constants.BackendType.CANVAS)
48
49        if (self.config.auth_token is None):
50            raise ValueError("Canvas backends require a token.")
51
52        self.auth_token: str = self.config.auth_token.cleartext
53        """
54        The (cleartext) token to authenticate with.
55        This is set in config and compied for type checking.
56        """
auth_token: str

The (cleartext) token to authenticate with. This is set in config and compied for type checking.

def get_standard_headers(self, write: bool = False) -> Dict[str, str]:
58    def get_standard_headers(self, write: bool = False) -> typing.Dict[str, str]:
59        headers = super().get_standard_headers(write)
60
61        headers['Authorization'] = f"Bearer {self.auth_token}"
62
63        return headers

Get standard headers for this backend. Children should take care to set the write header when performing a write operation.

def courses_list(self, **kwargs: Any) -> List[lms.model.courses.Course]:
65    def courses_list(self,
66            **kwargs: typing.Any) -> typing.List[lms.model.courses.Course]:
67        return lms.backend.canvas.courses.list.request(self)

List the courses associated with the context user.

def courses_assignments_list( self, course_id: str, **kwargs: Any) -> List[lms.model.assignments.Assignment]:
69    def courses_assignments_list(self,
70            course_id: str,
71            **kwargs: typing.Any) -> typing.List[lms.model.assignments.Assignment]:
72        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
73        return lms.backend.canvas.courses.assignments.list.request(self, parsed_course_id)

List the assignments associated with the given course.

def courses_assignments_scores_list( self, course_id: str, assignment_id: str, **kwargs: Any) -> List[lms.model.scores.AssignmentScore]:
75    def courses_assignments_scores_list(self,
76            course_id: str,
77            assignment_id: str,
78            **kwargs: typing.Any) -> typing.List[lms.model.scores.AssignmentScore]:
79        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
80        parsed_assignment_id = lms.util.parse.required_int(assignment_id, 'assignment_id')
81        return lms.backend.canvas.courses.assignments.scores.list.request(self, parsed_course_id, parsed_assignment_id)

List the scores associated with the given assignment.

def courses_assignments_scores_upload( self, course_id: str, assignment_id: str, scores: Dict[str, lms.model.scores.ScoreFragment], **kwargs: Any) -> int:
83    def courses_assignments_scores_upload(self,
84            course_id: str,
85            assignment_id: str,
86            scores: typing.Dict[str, lms.model.scores.ScoreFragment],
87            **kwargs: typing.Any) -> int:
88        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
89        parsed_assignment_id = lms.util.parse.required_int(assignment_id, 'assignment_id')
90        parsed_scores = {lms.util.parse.required_int(user_id, 'user_id'): score for (user_id, score) in scores.items()}
91        return lms.backend.canvas.courses.assignments.scores.upload.request(self, parsed_course_id, parsed_assignment_id, parsed_scores)

Upload assignment scores (indexed by user id). A None score (ScoreFragment.score) indicates that the score should be cleared. Return the number of scores sent to the LMS.

def courses_gradebook_fetch( self, course_id: str, assignment_ids: Collection[str], user_ids: Collection[str], **kwargs: Any) -> lms.model.scores.Gradebook:
 93    def courses_gradebook_fetch(self,
 94            course_id: str,
 95            assignment_ids: typing.Collection[str],
 96            user_ids: typing.Collection[str],
 97            **kwargs: typing.Any) -> lms.model.scores.Gradebook:
 98        if ((len(assignment_ids) == 0) or (len(user_ids) == 0)):
 99            assignment_queries = [lms.model.assignments.AssignmentQuery(id = id) for id in assignment_ids]
100            user_queries = [lms.model.users.UserQuery(id = id) for id in user_ids]
101            return lms.model.scores.Gradebook(assignment_queries, user_queries)
102
103        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
104        parsed_assignment_ids = [lms.util.parse.required_int(assignment_id, 'assignment_id') for assignment_id in assignment_ids]
105        parsed_user_ids = [lms.util.parse.required_int(user_id, 'user_id') for user_id in user_ids]
106
107        return lms.backend.canvas.courses.gradebook.fetch.request(self, parsed_course_id, parsed_assignment_ids, parsed_user_ids)

Get a gradebook with the specified users and assignments. If either the assignments or users is empty, an empty gradebook will be returned.

def courses_groupsets_create( self, course_id: str, name: str, **kwargs: Any) -> lms.model.groupsets.GroupSet:
109    def courses_groupsets_create(self,
110            course_id: str,
111            name: str,
112            **kwargs: typing.Any) -> lms.model.groupsets.GroupSet:
113        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
114        return lms.backend.canvas.courses.groupsets.create.request(self, parsed_course_id, name)

Create a group set.

def courses_groupsets_delete(self, course_id: str, groupset_id: str, **kwargs: Any) -> bool:
116    def courses_groupsets_delete(self,
117            course_id: str,
118            groupset_id: str,
119            **kwargs: typing.Any) -> bool:
120        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
121        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
122        return lms.backend.canvas.courses.groupsets.delete.request(self, parsed_course_id, parsed_groupset_id)

Delete a group set.

def courses_groupsets_list( self, course_id: str, **kwargs: Any) -> List[lms.model.groupsets.GroupSet]:
124    def courses_groupsets_list(self,
125            course_id: str,
126            **kwargs: typing.Any) -> typing.List[lms.model.groupsets.GroupSet]:
127        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
128        return lms.backend.canvas.courses.groupsets.list.request(self, parsed_course_id)

List the group sets associated with the given course.

def courses_groupsets_memberships_list( self, course_id: str, groupset_id: str, **kwargs: Any) -> List[lms.model.groupsets.GroupSetMembership]:
130    def courses_groupsets_memberships_list(self,
131            course_id: str,
132            groupset_id: str,
133            **kwargs: typing.Any) -> typing.List[lms.model.groupsets.GroupSetMembership]:
134        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
135        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
136        return lms.backend.canvas.courses.groupsets.memberships.list.request(self, parsed_course_id, parsed_groupset_id)

List the membership of the group sets associated with the given course.

def courses_groups_create( self, course_id: str, groupset_id: str, name: str, **kwargs: Any) -> lms.model.groups.Group:
138    def courses_groups_create(self,
139            course_id: str,
140            groupset_id: str,
141            name: str,
142            **kwargs: typing.Any) -> lms.model.groups.Group:
143        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
144        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
145        return lms.backend.canvas.courses.groups.create.request(self, parsed_course_id, parsed_groupset_id, name)

Create a group.

def courses_groups_delete( self, course_id: str, groupset_id: str, group_id: str, **kwargs: Any) -> bool:
147    def courses_groups_delete(self,
148            course_id: str,
149            groupset_id: str,
150            group_id: str,
151            **kwargs: typing.Any) -> bool:
152        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
153        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
154        parsed_group_id = lms.util.parse.required_int(group_id, 'group_id')
155        return lms.backend.canvas.courses.groups.delete.request(self, parsed_course_id, parsed_groupset_id, parsed_group_id)

Delete a group.

def courses_groups_list( self, course_id: str, groupset_id: str, **kwargs: Any) -> List[lms.model.groups.Group]:
157    def courses_groups_list(self,
158            course_id: str,
159            groupset_id: str,
160            **kwargs: typing.Any) -> typing.List[lms.model.groups.Group]:
161        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
162        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
163        return lms.backend.canvas.courses.groups.list.request(self, parsed_course_id, parsed_groupset_id)

List the groups associated with the given course.

def courses_groups_memberships_add( self, course_id: str, groupset_id: str, group_id: str, user_ids: Collection[str], **kwargs: Any) -> int:
165    def courses_groups_memberships_add(self,
166            course_id: str,
167            groupset_id: str,
168            group_id: str,
169            user_ids: typing.Collection[str],
170            **kwargs: typing.Any) -> int:
171        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
172        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
173        parsed_group_id = lms.util.parse.required_int(group_id, 'group_id')
174        parsed_user_ids = [lms.util.parse.required_int(user_id, 'user_id') for user_id in user_ids]
175        return lms.backend.canvas.courses.groups.memberships.add.request(self, parsed_course_id, parsed_groupset_id, parsed_group_id, parsed_user_ids)

Add the specified users to the group.

def courses_groups_memberships_list( self, course_id: str, groupset_id: str, group_id: str, **kwargs: Any) -> List[lms.model.groupsets.GroupSetMembership]:
177    def courses_groups_memberships_list(self,
178            course_id: str,
179            groupset_id: str,
180            group_id: str,
181            **kwargs: typing.Any) -> typing.List[lms.model.groupsets.GroupSetMembership]:
182        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
183        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
184        parsed_group_id = lms.util.parse.required_int(group_id, 'group_id')
185        return lms.backend.canvas.courses.groups.memberships.list.request(self, parsed_course_id, parsed_groupset_id, parsed_group_id)

List the membership of the group associated with the given group set.

def courses_groups_memberships_subtract( self, course_id: str, groupset_id: str, group_id: str, user_ids: Collection[str], **kwargs: Any) -> int:
187    def courses_groups_memberships_subtract(self,
188            course_id: str,
189            groupset_id: str,
190            group_id: str,
191            user_ids: typing.Collection[str],
192            **kwargs: typing.Any) -> int:
193        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
194        parsed_groupset_id = lms.util.parse.required_int(groupset_id, 'groupset_id')
195        parsed_group_id = lms.util.parse.required_int(group_id, 'group_id')
196        parsed_user_ids = [lms.util.parse.required_int(user_id, 'user_id') for user_id in user_ids]
197        return lms.backend.canvas.courses.groups.memberships.subtract.request(self,
198                parsed_course_id, parsed_groupset_id, parsed_group_id, parsed_user_ids)

Subtract the specified users from the group.

def courses_quizzes_download( self, course_id: str, quiz_id: str, **kwargs: Any) -> quizcomp.model.quiz.Quiz:
200    def courses_quizzes_download(self,
201            course_id: str,
202            quiz_id: str,
203            **kwargs: typing.Any) -> quizcomp.model.quiz.Quiz:
204        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
205        parsed_quiz_id = lms.util.parse.required_int(quiz_id, 'quiz_id')
206        return lms.backend.canvas.courses.quizzes.download.request(self, parsed_course_id, parsed_quiz_id)

Download a quiz from the LMS into a Quiz Composer quiz. This will only fetch the full quiz, not write it to disk.

def courses_quizzes_list( self, course_id: str, **kwargs: Any) -> List[lms.model.assignments.Assignment]:
208    def courses_quizzes_list(self,
209            course_id: str,
210            **kwargs: typing.Any) -> typing.List[lms.model.assignments.Assignment]:
211        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
212        return lms.backend.canvas.courses.quizzes.list.request(self, parsed_course_id)

List the quizzes associated with the given course. If specified, additional resources associated with the quiz (e.g., images) may also be fetched.

def courses_quizzes_remove(self, course_id: str, quiz_id: str, **kwargs: Any) -> None:
214    def courses_quizzes_remove(self,
215            course_id: str,
216            quiz_id: str,
217            **kwargs: typing.Any) -> None:
218        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
219        parsed_quiz_id = lms.util.parse.required_int(quiz_id, 'quiz_id')
220        lms.backend.canvas.courses.quizzes.remove.request(self, parsed_course_id, parsed_quiz_id)

Remove quiz from the LMS.

def courses_quizzes_upload( self, course_id: str, quiz: quizcomp.model.quiz.Quiz, **kwargs: Any) -> lms.model.assignments.Assignment:
222    def courses_quizzes_upload(self,
223            course_id: str,
224            quiz: quizcomp.model.quiz.Quiz,
225            **kwargs: typing.Any) -> lms.model.assignments.Assignment:
226        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
227        return lms.backend.canvas.courses.quizzes.upload.request(self, parsed_course_id, quiz)

Upload a single quiz to the LMS.

This method assumes that there is no quiz with a matching name. To handle that case, use courses_quizzes_resolve_and_upload() with force = True.

def courses_syllabus_fetch(self, course_id: str, **kwargs: Any) -> Optional[str]:
229    def courses_syllabus_fetch(self,
230            course_id: str,
231            **kwargs: typing.Any) -> typing.Union[str, None]:
232        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
233        return lms.backend.canvas.courses.syllabus.fetch.request(self, parsed_course_id)

Get the syllabus for a course, or None if no syllabus exists.

def courses_users_list(self, course_id: str, **kwargs: Any) -> List[lms.model.users.CourseUser]:
235    def courses_users_list(self,
236            course_id: str,
237            **kwargs: typing.Any) -> typing.List[lms.model.users.CourseUser]:
238        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
239        return lms.backend.canvas.courses.users.list.request(self, parsed_course_id)

List the users associated with the given course.

def courses_users_scores_list( self, course_id: str, user_id: str, **kwargs: Any) -> List[lms.model.scores.AssignmentScore]:
241    def courses_users_scores_list(self,
242            course_id: str,
243            user_id: str,
244            **kwargs: typing.Any) -> typing.List[lms.model.scores.AssignmentScore]:
245        parsed_course_id = lms.util.parse.required_int(course_id, 'course_id')
246        parsed_user_id = lms.util.parse.required_int(user_id, 'user_id')
247        return lms.backend.canvas.courses.users.scores.list.request(self, parsed_course_id, parsed_user_id)

List the scores associated with the given user.

Inherited Members
lms.model.backend.APIBackend
config
backend_type
server
testing
is_testing
reset_connection
not_found
courses_get
courses_fetch
courses_assignments_get
courses_assignments_fetch
courses_assignments_resolve_and_list
courses_assignments_scores_get
courses_assignments_scores_fetch
courses_assignments_scores_resolve_and_list
courses_assignments_scores_resolve_and_upload
courses_gradebook_get
courses_gradebook_list
courses_gradebook_resolve_and_list
courses_gradebook_resolve_and_upload
courses_gradebook_upload
courses_groupsets_resolve_and_create
courses_groupsets_resolve_and_delete
courses_groupsets_get
courses_groupsets_fetch
courses_groupsets_resolve_and_list
courses_groupsets_memberships_resolve_and_add
courses_groupsets_memberships_resolve_and_set
courses_groupsets_memberships_resolve_and_subtract
courses_groupsets_memberships_resolve_and_list
courses_groups_resolve_and_create
courses_groups_resolve_and_delete
courses_groups_get
courses_groups_fetch
courses_groups_resolve_and_list
courses_groups_memberships_resolve_and_add
courses_groups_memberships_resolve_and_list
courses_groups_memberships_resolve_and_set
courses_groups_memberships_resolve_and_subtract
courses_quizzes_resolve_and_download
courses_quizzes_get
courses_quizzes_fetch
courses_quizzes_resolve_and_list
courses_quizzes_resolve_and_remove
courses_quizzes_resolve_and_upload
courses_syllabus_get
courses_users_get
courses_users_fetch
courses_users_resolve_and_list
courses_users_scores_get
courses_users_scores_fetch
courses_users_scores_resolve_and_list
parse_assignment_query
parse_assignment_queries
parse_course_query
parse_course_queries
parse_groupset_query
parse_groupset_queries
parse_group_query
parse_group_queries
parse_user_query
parse_user_queries
resolve_assignment_query
resolve_assignment_queries
resolve_course_query
resolve_course_queries
resolve_group_queries
resolve_group_query
resolve_groupset_queries
resolve_groupset_query
resolve_quiz_query
resolve_quiz_queries
resolve_user_queries