def handle(self, *args, **options): self._canvas = Canvas() self._tools = ExternalTools() self._accounts = Accounts() self._courses = Courses() self._options = options csv.register_dialect("unix_newline", lineterminator="\n") self._writer = csv.writer(sys.stdout, dialect="unix_newline") self._headers = [ 'tool_name', 'tool_id', 'tool_type', 'account_name', 'account_id' ] if self._options['courses']: self._headers.append('course_name') self._headers.append('course_id') self._headers.append('term') if options['sessionless']: self._headers.append('sessionless url') if re.match(r'^\d+$', options['account_id']): account = self._accounts.get_account(options['account_id']) else: account = self._accounts.get_account_by_sis_id( options['account_id']) try: self.report_external_tools(account) except DataFailureException as err: if err.status == 404: print('Unknown Sub-Account \"%s\"' % (options['account_id']), file=sys.stderr)
def get_enrollments_for_regid(self, regid, params={}, include_courses=False): """ Return a list of enrollments for the passed user regid. https://canvas.instructure.com/doc/api/enrollments.html#method.enrollments_api.index """ sis_user_id = self._sis_id(regid, sis_field="user") url = USERS_API.format(sis_user_id) + "/enrollments" courses = Courses() if include_courses else None enrollments = [] for datum in self._get_paged_resource(url, params=params): enrollment = CanvasEnrollment(data=datum) if include_courses: course_id = datum["course_id"] course = courses.get_course(course_id) if course.sis_course_id is not None: enrollment.course = course # the following 3 lines are not removed # to be backward compatible. enrollment.course_name = course.name enrollments.append(enrollment) return enrollments
def handle(self, *args, **options): file_path = options.get('file_path') outfile = open('submissions.csv', 'wb') csv.register_dialect('unix_newline', lineterminator='\n') writer = csv.writer(outfile, dialect='unix_newline') course_client = Courses() sub_client = Submissions() file_total = 0 with open(file_path, 'rb') as csvfile: writer.writerow([ 'course_id', 'assignment_id', 'term_id', 'filename', 'content_type', 'size', 'url' ]) reader = csv.reader(csvfile) for row in reader: if not len(row): continue course_id = row[0] assignment_id = row[1] assignment_total = 0 if course_id == 'course_id': continue try: course = course_client.get_course(course_id) if course.term.sis_term_id is None: # Default term print('Skipping: %s' % course.name) continue subs = sub_client.get_submissions_by_course_and_assignment( course_id, assignment_id) except DataFailureException as ex: if ex.status == 404: continue else: raise for submission in subs: for attachment in submission.attachments: writer.writerow([ course_id, assignment_id, course.term.sis_term_id, attachment.display_name.encode('utf-8'), attachment.content_type, attachment.size, attachment.url ]) assignment_total += 1 file_total += assignment_total print('%s: %s, total: %s' % (course.sis_course_id, assignment_total, file_total)) outfile.close()
def test_create_course(self, mock_create): mock_create.return_value = None canvas = Courses() canvas.create_course(88888, "Created Course") mock_create.assert_called_with('/api/v1/accounts/88888/courses', {'course': { 'name': 'Created Course' }})
def handle(self, *args, **options): sis_term_id = options.get('term_sis_id') report_client = Reports() term = report_client.get_term_by_sis_id(sis_term_id) user_report = report_client.create_course_sis_export_report( settings.RESTCLIENTS_CANVAS_ACCOUNT_ID, term_id=term.term_id) sis_data = report_client.get_report_data(user_report) report_client.delete_report(user_report) ind_study_regexp = re.compile("-[A-F0-9]{32}$") course_client = Courses() print(["course_id", "name", "published", "public_syllabus"]) row_count = sum(1 for row in csv.reader(sis_data)) curr_row = 0 for row in csv.reader(sis_data): curr_row += 1 if not len(row): continue sis_course_id = row[0] course_name = row[1] try: valid_academic_course_sis_id(sis_course_id) except CoursePolicyException: continue if ind_study_regexp.match(sis_course_id): continue try: course = course_client.get_course_by_sis_id( sis_course_id, params={"include": "syllabus_body"}) except DataFailureException as ex: print(ex) continue if course.syllabus_body is None: continue csv_line = [ sis_course_id, course_name, str(course.workflow_state), course.public_syllabus, ] print(csv_line) print("Remaining: {}".format(row_count - curr_row)) print(csv_line) sleep(1)
def test_update_sis_id(self, mock_update): mock_update.return_value = None canvas = Courses() canvas.update_sis_id(149650, "NEW_SIS_ID") mock_update.assert_called_with( '/api/v1/courses/149650', {'course': { 'sis_course_id': 'NEW_SIS_ID' }})
def get_courses(): settings_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'settings.cfg') use_configparser_backend(settings_path, 'Canvas') account_id = getattr(settings, 'RESTCLIENTS_CANVAS_ACCOUNT_ID') params = {'per_page': 100} canvas = Courses() for course in canvas.get_courses_in_account(account_id, params): print(course.name)
def handle(self, *args, **options): term_sis_id = options.get('term_sis_id') report_client = Reports() term = report_client.get_term_by_sis_id(term_sis_id) user_report = report_client.create_course_provisioning_report( settings.RESTCLIENTS_CANVAS_ACCOUNT_ID, term_id=term.term_id) sis_data = report_client.get_report_data(user_report) report_client.delete_report(user_report) ind_study_regexp = re.compile("-[A-F0-9]{32}$") course_client = Courses() for row in csv.reader(sis_data): if not len(row): continue sis_course_id = row[1] status = row[8] try: valid_academic_course_sis_id(sis_course_id) except CoursePolicyException: continue if ind_study_regexp.match(sis_course_id): continue if status is not None and status == "active": print(sis_course_id)
def test_course_with_params(self): canvas = Courses() course1 = canvas.get_course(149650, params={"include": ["term"]}) self.assertEquals(course1.term.term_id, 810, "Course contains term data") self.assertEquals(course1.syllabus_body, None, "Course doesn't contain syllabus_body") course2 = canvas.get_course(149650, params={"include": ["syllabus_body"]}) self.assertEquals(course2.syllabus_body, "Syllabus", "Course contains syllabus_body") self.assertEquals(course1.term.term_id, 810, "Course contains term data")
def test_courses_by_regid(self): canvas = Courses() courses = canvas.get_courses_for_regid( "9136CCB8F66711D5BE060004AC494FFE") self.assertEquals(len(courses), 1, "Has 1 canvas enrollment") course = courses[0] self.assertEquals(course.course_url, "https://canvas.uw.edu/courses/149650", "Has proper course url") self.assertEquals(course.sis_course_id, "2013-spring-PHYS-121-A", "Course doesnt contain SIS ID") self.assertEquals(course.sws_course_id(), "2013,spring,PHYS,121/A", "Course doesnt contain SIS ID") self.assertEquals(course.account_id, 84378, "Has proper account id")
def test_published_courses(self): canvas = Courses() courses = canvas.get_published_courses_in_account_by_sis_id( 'uwcourse:seattle:arts-&-sciences:amath:amath') self.assertEquals(len(courses), 7, "Too few courses") course = courses[2] self.assertEquals(course.course_id, 141414, "Has proper course id") self.assertEquals(course.sis_course_id, "2013-spring-AMATH-403-A") self.assertEquals(course.sws_course_id(), "2013,spring,AMATH,403/A") self.assertEquals( course.name, "AMATH 403 A: Methods For Partial Differential Equations") self.assertEquals(course.account_id, 333333, "Has proper account id") self.assertEquals(course.course_url, "https://canvas.uw.edu/courses/141414", "Has proper course url")
def test_course(self): canvas = Courses() course = canvas.get_course(149650) self.assertEquals(course.course_id, 149650, "Has proper course id") self.assertEquals(course.course_url, "https://canvas.uw.edu/courses/149650", "Has proper course url") self.assertEquals(course.sis_course_id, "2013-spring-PHYS-121-A") self.assertEquals(course.sws_course_id(), "2013,spring,PHYS,121/A") self.assertEquals(course.sws_instructor_regid(), None) self.assertEquals(course.is_academic_sis_id(), True) self.assertEquals(course.account_id, 84378, "Has proper account id") self.assertEquals(course.term.sis_term_id, "2013-spring", "SIS term id") self.assertEquals(course.term.term_id, 810, "Term id") self.assertEquals(course.public_syllabus, False, "public_syllabus") self.assertEquals(course.workflow_state, "unpublished", "workflow_state") self.assertEquals(course.grading_standard_id, 25, "grading_standard_id") self.assertTrue(course.is_unpublished)
def update_course_sis_id(course_id, course_sis_id): return Courses().update_sis_id(course_id, course_sis_id)
def get_course_by_sis_id(course_sis_id): return Courses().get_course_by_sis_id(course_sis_id)
def get_course_by_id(course_id): return Courses().get_course(course_id)
def get_courses_for_regid(self, regid): deprecation("Use uw_canvas.courses.get_courses_for_regid") from uw_canvas.courses import Courses return Courses().get_courses_for_regid(regid)
class Command(BaseCommand): help = "Report externals tools in account" def add_arguments(self, parser): parser.add_argument( '-a', '--account', action='store', dest='account_id', default=default_account, help=('show external tools in account by id or ' 'sis_id (default: {})').format(default_account)) parser.add_argument('-r', '--recurse', action='store_true', dest='recurse', default=False, help='recurse through subaccounts') parser.add_argument('-c', '--courses', action='store_true', dest='courses', default=False, help='include account courses in report') parser.add_argument('-t', '--term', action='store', dest='term', default='', help='include only courses in given term') parser.add_argument( '-s', '--sessionless-url', action='store_true', dest='sessionless', default=False, help='show sessionless url with each external tool') def handle(self, *args, **options): self._canvas = Canvas() self._tools = ExternalTools() self._accounts = Accounts() self._courses = Courses() self._options = options csv.register_dialect("unix_newline", lineterminator="\n") self._writer = csv.writer(sys.stdout, dialect="unix_newline") self._headers = [ 'tool_name', 'tool_id', 'tool_type', 'account_name', 'account_id' ] if self._options['courses']: self._headers.append('course_name') self._headers.append('course_id') self._headers.append('term') if options['sessionless']: self._headers.append('sessionless url') if re.match(r'^\d+$', options['account_id']): account = self._accounts.get_account(options['account_id']) else: account = self._accounts.get_account_by_sis_id( options['account_id']) try: self.report_external_tools(account) except DataFailureException as err: if err.status == 404: print('Unknown Sub-Account \"%s\"' % (options['account_id']), file=sys.stderr) def report_external_tools(self, account): tools = self._tools.get_external_tools_in_account(account.account_id) self._print_tools(tools, account) if self._options['courses']: params = { "by_subaccounts": [account.account_id], "include": ["term"] } if self._options['term']: params['enrollment_term_id'] = self._canvas.get_term_by_sis_id( self._options['term']).term_id courses = self._courses.get_published_courses_in_account( account.account_id, params=params) for course in courses: tools = self._tools.get_external_tools_in_course( course.course_id) self._print_tools(tools, account, course) if self._options['recurse']: subaccounts = self._accounts.get_sub_accounts(account.account_id) for account in subaccounts: self.report_external_tools(account) def _print_tools(self, tools, account, course=None): if len(tools): if self._headers: self._writer.writerow(self._headers) self._headers = None for tool in tools: tool_types = [] for tt in ['account', 'course', 'user']: if tool.get("{}_navigation".format(tt)): tool_types.append(tt) tool_type = ' & '.join(tool_types) line = [ tool['name'], tool['id'], tool_type, account.name, account.account_id ] if self._options['courses']: if course: line.extend([ course.name, course.course_id, course.term.name if course.term else '' ]) else: line.extend(['', '', '']) if self._options['sessionless']: try: tools = self._tools url = tools.get_sessionless_launch_url_from_account( tool['id'], account.account_id) line.append(url['url']) except DataFailureException as ex: line.append('') self._writer.writerow(line)