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'
         }})
예제 #7
0
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)
예제 #8
0
    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)
예제 #13
0
def update_course_sis_id(course_id, course_sis_id):
    return Courses().update_sis_id(course_id, course_sis_id)
예제 #14
0
def get_course_by_sis_id(course_sis_id):
    return Courses().get_course_by_sis_id(course_sis_id)
예제 #15
0
def get_course_by_id(course_id):
    return Courses().get_course(course_id)
예제 #16
0
 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)