Skip to content
Snippets Groups Projects
Commit b4110ffa authored by Christopher Bohn's avatar Christopher Bohn :thinking:
Browse files

Can now create student rosters from Canvas only (without Gitlab)

parent 4653d4f9
Branches
No related tags found
No related merge requests found
......@@ -3,8 +3,10 @@ from typing import ClassVar, Dict, Iterable, List, Optional, Union
from canvasapi import Canvas
from canvasapi.assignment import Assignment, AssignmentGroup
from canvasapi.course import Course
from canvasapi.exceptions import ResourceDoesNotExist
from canvasapi.group import Group, GroupCategory
from canvasapi.quiz import QuizSubmission, QuizSubmissionQuestion
from canvasapi.section import Section
from canvasapi.submission import Submission
from canvasapi.user import User
......@@ -631,6 +633,90 @@ class CanvasAssignmentGroup:
"""
class CanvasCourseSection:
canvas_section: Section
def __init__(self, section: Section, course: "CanvasCourse"):
super().__init__()
self.canvas_section = section
self.course = course
def get_students(self) -> List[CanvasUser]:
# course_students: List[CanvasUser] = None
course_students: List[CanvasUser] = self.course.get_students()
enrollments = self.canvas_section.get_enrollments()
students: List[CanvasUser] = []
for enrollment in enrollments:
if enrollment.role == 'StudentEnrollment':
user_json = enrollment.user
"""
try:
user = self.course.canvas_course.get_user(int(user_json['sis_user_id']),
'sis_user_id') # TODO re-encapsulate
students.append(CanvasUser(user))
except ResourceDoesNotExist:
if course_students is None:
course_students = self.course.get_students()
candidates = list(filter(lambda c: c.get_username() == user_json['login_id'], course_students))
if len(candidates) == 1:
students.append(candidates[0])
print(f'WARNING: Canvas user {user_json["name"]} located indirectly '
f'(could not directly locate Canvas REST resource). Adding to list.')
elif len(candidates) > 1:
print(f'ERROR: Indirectly found {len(candidates)} canvas users for {user_json["name"]} '
f'using the "unique" login {user_json["login_id"]}. Adding none of them. '
f'(Could not directly locate Canvas REST resource)')
else:
print(f'ERROR: Could not locate canvas user: {user_json["name"]}')
"""
candidates = list(filter(lambda c: c.get_username() == user_json['login_id'], course_students))
if len(candidates) == 1:
students.append(candidates[0])
elif len(candidates) > 1:
print(f'ERROR: Indirectly found {len(candidates)} canvas users for {user_json["name"]} '
f'using the "unique" login {user_json["login_id"]}. Adding none of them.')
else:
print(f'ERROR: Could not locate canvas user: {user_json["name"]}')
return students
def __repr__(self) -> str:
return self.canvas_section.name
"""
{
// The unique identifier for the section.
"id": 1,
// The name of the section.
"name": "Section A",
// The sis id of the section. This field is only included if the user has
// permission to view SIS information.
"sis_section_id": "s34643",
// Optional: The integration ID of the section. This field is only included if
// the user has permission to view SIS information.
"integration_id": "3452342345",
// The unique identifier for the SIS import if created through SIS. This field
// is only included if the user has permission to manage SIS information.
"sis_import_id": 47,
// The unique Canvas identifier for the course in which the section belongs
"course_id": 7,
// The unique SIS identifier for the course in which the section belongs. This
// field is only included if the user has permission to view SIS information.
"sis_course_id": "7",
// the start date for the section, if applicable
"start_at": "2012-06-01T00:00:00-06:00",
// the end date for the section, if applicable
"end_at": null,
// Restrict user enrollments to the start and end dates of the section
"restrict_enrollments_to_section_dates": null,
// The unique identifier of the original course of a cross-listed section
"nonxlist_course_id": null,
// optional: the total number of active and invited students in the section
"total_students": 13
}
"""
# THE COURSE ITSELF
......@@ -694,6 +780,13 @@ class CanvasCourse:
assignments.append(CanvasAssignment(assignment))
return assignments
def get_sections(self):
canvas_sections: Iterable[Section] = self.canvas_course.get_sections()
sections: List[CanvasCourseSection] = []
for section in canvas_sections:
sections.append(CanvasCourseSection(section, self))
return sections
def __repr__(self) -> str:
return f'{self.canvas_course.course_code}: {self.canvas_course.name}'
......
import csv
from api.canvas_classes import *
if __name__ == '__main__':
canvas_course_id: int = int(input("What is the Canvas course ID? "))
filename: str = input("What file do you want to save the roster to? ")
course: CanvasCourse = CanvasCourse(canvas_course_id)
# students: List[CanvasUser] = course.get_students()
fields = ['SortableName', 'ReadableName', 'Section', 'NUID', 'Username', 'Email']
with open(filename, mode='w') as csv_file:
# writer = csv.DictWriter(csv_file, fieldnames=fields)
# writer.writeheader()
writer = csv.writer(csv_file)
writer.writerow(fields)
for section in list(sorted(course.get_sections(), key=lambda s: s.__repr__())):
for student in list(sorted(section.get_students(), key=lambda s: s.get_sortable_name())):
writer.writerow([student.get_sortable_name(), student.get_name(), section,
student.get_nuid(), student.get_username(), student.get_email()])
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment