• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

uw-it-aca / canvas-sis-provisioner / 4306449590

pending completion
4306449590

Pull #804

github

GitHub
Merge 6f704f5f3 into 97ed31c00
Pull Request #804: use correct xlist_id for url

1 of 1 new or added line in 1 file covered. (100.0%)

4478 of 7936 relevant lines covered (56.43%)

0.56 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

25.76
/sis_provisioner/views/canvas.py
1
# Copyright 2023 UW-IT, University of Washington
2
# SPDX-License-Identifier: Apache-2.0
3

4

5
from django.conf import settings
1✔
6
from sis_provisioner.models.course import Course
1✔
7
from sis_provisioner.views.admin import RESTDispatch
1✔
8
from sis_provisioner.dao.canvas import (
1✔
9
    valid_canvas_id, get_account_by_id, get_course_by_id, get_course_by_sis_id)
10
from restclients_core.exceptions import DataFailureException
1✔
11
from logging import getLogger
1✔
12
from bs4 import BeautifulSoup
1✔
13
from urllib.request import urlopen
1✔
14
import re
1✔
15

16

17
logger = getLogger(__name__)
1✔
18

19

20
class CanvasCourseView(RESTDispatch):
1✔
21
    """ Performs query for Canvas course by sis_id.
22
        GET returns 200 with Canvas Course model
23
    """
24
    def get(self, request, *args, **kwargs):
1✔
25
        course_id = kwargs.get('sis_id')
×
26
        params = {'state': ['all']}
×
27
        try:
×
28
            if valid_canvas_id(course_id):
×
29
                course = get_course_by_id(course_id, params)
×
30
            else:
31
                course = get_course_by_sis_id(course_id, params)
×
32

33
            course_rep = {
×
34
                'course_id': course.course_id,
35
                'sis_course_id': course.sis_course_id,
36
                'sws_course_id': course.sws_course_id(),
37
                'account_id': course.account_id,
38
                'term': {
39
                    'term_id': course.term.term_id,
40
                    'sis_term_id': course.term.sis_term_id,
41
                    'name': course.term.name
42
                },
43
                'course_name': course.name,
44
                'course_url': self.course_url(course.course_id),
45
                'workflow_state': course.workflow_state,
46
                'public_syllabus': course.public_syllabus,
47
                'syllabus_body': course.syllabus_body
48
            }
49

50
            if course.sis_course_id is not None:
×
51
                try:
×
52
                    model = Course.objects.get(course_id=course.sis_course_id)
×
53
                    course_rep.update(model.json_data(
×
54
                        include_sws_url=self.can_view_source_data(request)))
55
                    if model.xlist_id:
×
56
                        course_rep['xlist_url'] = self.course_url(
×
57
                            'sis_course_id:{}'.format(model.xlist_id))
58
                except Course.DoesNotExist:
×
59
                    pass
×
60

61
            return self.json_response(course_rep)
×
62
        except DataFailureException as ex:
×
63
            if ex.status == 404:
×
64
                return self.error_response(
×
65
                    404, "Course not found in Canvas: {}".format(ex.msg))
66
            return self.error_response(
×
67
                400, "Unable to retrieve course data: {}".format(ex.msg))
68

69
    def course_url(self, course_id):
1✔
70
        return '{host}/courses/{course_id}'.format(
×
71
            host=getattr(settings, 'RESTCLIENTS_CANVAS_HOST', ''),
72
            course_id=course_id)
73

74

75
class CanvasAccountView(RESTDispatch):
1✔
76
    """ Performs query for Canvas account by account_id
77
        GET returns 200 with Canvas Course model
78
    """
79
    def get(self, request, *args, **kwargs):
1✔
80
        try:
×
81
            account = get_account_by_id(kwargs.get('account_id'))
×
82
            return self.json_response({
×
83
                'account_id': account.account_id,
84
                'sis_account_id': account.sis_account_id,
85
                'name': account.name,
86
                'parent_account_id': account.parent_account_id,
87
                'root_account_id': account.root_account_id,
88
                'account_url': "{host}/accounts/{account_id}".format(
89
                    host=getattr(settings, 'RESTCLIENTS_CANVAS_HOST', ''),
90
                    account_id=account.account_id)
91
            })
92

93
        except Exception as e:
×
94
            return self.error_response(
×
95
                400, "Unable to retrieve account: {}".format(e))
96

97

98
class CanvasStatus(RESTDispatch):
1✔
99
    def get(self, request, *args, **kwargs):
1✔
100
        status_url = 'http://status.instructure.com'
×
101
        try:
×
102
            page = urlopen(status_url)
×
103
            soup = BeautifulSoup(page, 'html.parser')
×
104
            components = []
×
105
            for x in soup.body.find_all(
×
106
                    'div', class_='component-inner-container'):
107
                name = x.find('span', class_='name').get_text(strip=True)
×
108
                status = x.find('span', class_='component-status').get_text(
×
109
                    strip=True)
110
                state = 'status-unknown'
×
111

112
                for c in x['class']:
×
113
                    if 'status-' in c:
×
114
                        state = c
×
115
                        break
×
116

117
                try:
×
118
                    name = re.sub(r'Support:', '', name)
×
119
                    name = re.sub(r'[^\/\w\s]', '', name)
×
120
                    name = name.strip()
×
121
                except (TypeError, AttributeError):
×
122
                    pass
×
123

124
                components.append({
×
125
                    'url': status_url,
126
                    'component': name,
127
                    'status': status,
128
                    'state': state
129
                })
130

131
        except Exception as err:
×
132
            components = [{
×
133
                'component': 'Canvas',
134
                'status': 'Unknown',
135
                'state': 'status-unknown',
136
                'url': status_url
137
            }, {
138
                'component': 'Status currently unavailable',
139
                'status': 'Unknown',
140
                'state': 'status-unknown',
141
                'url': status_url
142
            }]
143

144
        return self.json_response(components)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc