def get_enrollments_for_regid(self, regid, params={}, include_courses=True): """ Return a list of enrollments for the passed user regid. https://canvas.instructure.com/doc/api/enrollments.html#method.enrollments_api.index """ url = "/api/v1/users/%s/enrollments" % ( self._sis_id(regid, sis_field="user")) courses = Courses() if include_courses else None enrollments = [] for datum in self._get_paged_resource(url, params=params): if include_courses: course_id = datum["course_id"] course = courses.get_course(course_id) if course.sis_course_id is not None: enrollment = self._enrollment_from_json(datum) enrollment.course = course # the following 3 lines are not removed # to be backward compatible. enrollment.course_url = course.course_url enrollment.course_name = course.name enrollment.sis_course_id = course.sis_course_id enrollments.append(enrollment) else: enrollment = self._enrollment_from_json(datum) enrollment.course_url = re.sub( r'/users/\d+$', '', enrollment.html_url) enrollments.append(enrollment) return enrollments
def get_enrollments_for_regid(self, regid, params={}): """ Return a list of enrollments for the passed user regid. https://canvas.instructure.com/doc/api/enrollments.html#method.enrollments_api.index """ url = "/api/v1/users/%s/enrollments" % ( self._sis_id(regid, sis_field="user")) courses = Courses() enrollments = [] for datum in self._get_paged_resource(url, params=params): course_id = datum["course_id"] course = courses.get_course(course_id) if course.sis_course_id is not None: enrollment = self._enrollment_from_json(datum) enrollment.course = course # the following 3 lines are not removed # to be backward compatible. enrollment.course_url = course.course_url enrollment.course_name = course.name enrollment.sis_course_id = course.sis_course_id enrollments.append(enrollment) return enrollments
def get_enrollments_for_regid(self, regid, params={}): """ Return a list of enrollments for the passed user regid. https://canvas.instructure.com/doc/api/enrollments.html#method.enrollments_api.index """ url = "/api/v1/users/%s/enrollments%s" % ( self._sis_id(regid, sis_field="user"), self._params(params)) courses = Courses() enrollments = [] for datum in self._get_resource(url): course_id = datum["course_id"] course = courses.get_course(course_id) if course.sis_course_id is not None: enrollment = self._enrollment_from_json(datum) enrollment.course_url = course.course_url enrollment.course_name = course.name enrollment.sis_course_id = course.sis_course_id enrollments.append(enrollment) return enrollments
def handle(self, *args, **options): if len(args): sis_term_id = args[0] else: raise CommandError("term_sis_id is required") 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: %s" % (row_count - curr_row) print csv_line sleep(1)
def test_update_sis_id(self): with self.settings( RESTCLIENTS_CANVAS_DAO_CLASS='restclients.dao_implementation.canvas.File'): canvas = Courses() course = canvas.update_sis_id(149650, "NEW_SIS_ID") 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, "NEW_SIS_ID")
def test_create_course(self): with self.settings( RESTCLIENTS_CANVAS_DAO_CLASS='restclients.dao_implementation.canvas.File'): canvas = Courses() account_id = 88888 name = "Created Course" course = canvas.create_course(account_id, name) self.assertEquals(course.course_id, 18881, "Correct course ID") self.assertEquals(course.name, name, "Correct course name") self.assertEquals(course.account_id, account_id, "Correct account ID")
def test_course_with_params(self): with self.settings( RESTCLIENTS_CANVAS_DAO_CLASS='restclients.dao_implementation.canvas.File'): 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(course2.term, None, "Course doesn't contain term")
def test_courses_by_regid(self): with self.settings( RESTCLIENTS_CANVAS_DAO_CLASS='restclients.dao_implementation.canvas.File'): canvas = Courses() # Javerage's regid 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_course(self): with self.settings( RESTCLIENTS_CANVAS_DAO_CLASS='restclients.dao_implementation.canvas.File'): 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.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")
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') accounter = self._accounts.get_account if re.match(r'^\d+$', options['account_id']) \ else self._accounts.get_account_by_sis_id try: self.report_external_tools(accounter(options['account_id'])) except DataFailureException as err: if err.status == 404: print >> sys.stderr, 'Unknown Sub-Account \"%s\"' % (options['account_id'])
def get_indexed_by_decrosslisted(by_primary, sws_sections): for section in sws_sections: base_id = section.section_label() alternate_id = None try: sis_id = section.canvas_section_sis_id() canvas_section = Sections().get_section_by_sis_id(sis_id) primary_course = Courses().get_course(canvas_section.course_id) alternate_id = primary_course.sws_course_id() except Exception as ex: # primary section doesn't have canvas_section_sis_id alternate_id = base_id if base_id not in by_primary: if alternate_id in by_primary: by_primary[base_id] = by_primary[alternate_id] return by_primary
def test_published_courses(self): with self.settings( RESTCLIENTS_CANVAS_DAO_CLASS='restclients.dao_implementation.canvas.File'): 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 handle(self, *args, **options): if options['print'] or options['dry_run']: print "section_id,canvas_enrollments,sws_enrollments,delta" canvas_courses = CanvasCourses(per_page=50) canvas_sections = CanvasSections(per_page=50) canvas_accounts = CanvasAccounts(per_page=50) for account in canvas_accounts.get_all_sub_accounts_by_sis_id(options['root_account']): if options['print']: print '# Account: "%s" (%s, %s)' % (account.name, account.sis_account_id, account.account_id) if (account.sis_account_id is not None and re.match(r'^(([^:]+:){4}|curriculum-).*$', str(account.sis_account_id))): n_courses = 0 n_sections = 0 n_bad_sections = 0 if options['all_courses']: courses = canvas_courses.get_courses_in_account_by_sis_id(account.sis_account_id) else: courses = canvas_courses.get_published_courses_in_account_by_sis_id(account.sis_account_id) for course in courses: if (course.sis_course_id is not None and re.match('^%s-' % options['term'], course.sis_course_id) and not self._is_independent_study(course.sis_course_id)): n_courses += 1 sections = canvas_sections.get_sections_with_students_in_course_by_sis_id(course.sis_course_id) for section in sections: if section.sis_section_id is not None: section_id = section.sis_section_id n_sections += 1 try: s = self.get_section_by_id(section_id) except DataFailureException, err: print '# BAD SECTION: %s' % err continue enrollments = (s.current_enrollment + s.auditors) delta = len(section.students) - enrollments if delta >= options['threshold']: n_bad_sections += 1 if options['print'] or options['dry_run']: print "%s,%s,%s,%s" % (section_id, len(section.students), enrollments, delta) if not options['dry_run']: try: section_model_id = re.sub(r'--$', '', section_id) section_model = Course.objects.get(course_id=section_model_id) except Course.DoesNotExist: section_model = Course(course_id=section_model_id) if not section_model.queue_id and section_model.priority < PRIORITY_HIGH: section_model.priority = PRIORITY_HIGH section_model.save() if options['print']: if n_courses and n_sections and n_bad_sections: print('# %s of %s (%.3s%%) sections in %s courses for %s' % (n_bad_sections, n_sections, ((n_bad_sections/float(n_sections)) * 100), n_courses, options['term']))
class Command(BaseCommand): help = "Report externals tools in account" option_list = BaseCommand.option_list + ( make_option('-a', '--account', action='store', dest='account_id', type="string", default=default_account, help='show external tools in account by id or sis_id (default: %s)' % default_account), make_option('-r', '--recurse', action='store_true', dest='recurse', default=False, help='recurse through subaccounts'), make_option('-c', '--courses', action='store_true', dest='courses', default=False, help='include account courses in report'), make_option('-t', '--term', action='store', dest='term', type="string", default='', help='include only courses in given term'), make_option('-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') accounter = self._accounts.get_account if re.match(r'^\d+$', options['account_id']) \ else self._accounts.get_account_by_sis_id try: self.report_external_tools(accounter(options['account_id'])) except DataFailureException as err: if err.status == 404: print >> sys.stderr, 'Unknown Sub-Account \"%s\"' % (options['account_id']) 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("%s_navigation" % 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: sessionless = self._tools.get_sessionless_launch_url_from_account(tool['id'], account.account_id) line.append(sessionless['url']) except DataFailureException as ex: line.append('') self._writer.writerow(line)
def get_courses_for_regid(self, regid): deprecation("Use restclients.canvas.courses.get_courses_for_regid") from restclients.canvas.courses import Courses return Courses().get_courses_for_regid(regid)