-
Notifications
You must be signed in to change notification settings - Fork 0
/
api.py
191 lines (166 loc) · 6.38 KB
/
api.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
import configparser
import os, sys
import re
from canvasapi import Canvas
from canvasapi import page
def split_url(url, expected = None):
"""
Retrieve API url, course id from full URL
Determine url type and optionally compare to expected
Current url types: folder name, file name, page name, url only
Assumes only files have a dot in their name, not folders
Example URL:
https://canvas.instance.com/courses/course_id/pages/page_name
https://canvas.instance.com/courses/course_id/files/folder/folder_name
* API url: https://canvas.instance.com
* course ID: course_id
* page name: page_name
* folder name: folder_name
* file name: file.ext
"""
# split the url
# rest: the part following 'course_id'
none, API_URL, course_id, rest, none = re.split(r'(.*)/courses/(\d*)(.*)', url)
# determine type
if rest.startswith('/pages/'):
url_type = 'page'
item_name = re.sub(r'^/pages/', '', rest)
elif rest.startswith('/files/folder/'):
# file or folder
# files have a . in their name
remainder = re.split(r'/files/folder/(.*\..*)', rest)
# if the url ends in 'folder/.' then remainder will be ['', '.', '']
# parse this as a folder (the 'root' folder)
if len(remainder) == 3 and remainder != ['', '.', '']:
url_type = 'file'
else:
url_type = 'folder'
item_name = re.sub(r'^/files/folder/', '', rest) # this becomes '.' for root
elif rest == '':
url_type = 'url only'
item_name = ''
else:
sys.exit("Unexpected url: not of type 'file', 'folder' or 'page' " + url)
# return value depends on whether a certain type was expected
if expected:
# check validity of expected result
if not expected in ['page', 'folder', 'file', 'url only']:
sys.exit("Expected url type not implemented yet: " + expected)
elif url_type != expected:
# compare result with expected
sys.exit("Unexpected type url: expected url of type '%s', got type '%s': " \
%(expected, url_type) + url)
else:
# all is good, return data
return API_URL, course_id, item_name
else:
# no particular url type was expected, so add it to what is returned
return API_URL, course_id, item_name, url_type
def get_API(config_file_name, API_URL):
"""
Parse config file
Extract correct API key
"""
config = configparser.ConfigParser()
result = config.read_file(open(os.path.expanduser(config_file_name)))
if result == []:
sys.exit("Error: could not open config file or config file was empty or malformed: " + config_file)
# Canvas API key
try:
API_KEY = config[API_URL]['api_key']
except KeyError:
sys.exit("Error: could not find the entry for 'api-key' in the Canvas instance '%s' section of the config file '%s'." % (API_URL, config_file_name))
return API_KEY
def get_course(API_URL, course_id, config_file):
"""
Connects to canvas and retrieves the course.
"""
# load configuration settings
API_KEY = get_API(config_file, API_URL)
# initialize a new Canvas object
canvas = Canvas(API_URL, API_KEY)
# get the course
try:
course = canvas.get_course(course_id)
except:
sys.exit("Could not connect to Canvas, check internet connection and/or API key in the config file %s" % config_file)
return course
def folder_exists(course, folder_name):
"""
Tests whether a folder exists for a course
The folder name is everything following the 'files/folder/' in the folder's URL:
'folder_name' in the case of this URL
https://canvas.instance.com/courses/course_id/files/folder/folder_name
OR
'folder1/folder2/folder_name' in the case of this URL
https://canvas.instance.com/courses/course_id/files/folder/folder1/folder2/folder_name
"""
for folder in course.get_folders():
if folder.full_name == 'course files/' + folder_name:
return True
return False
def find_folder(course, folder_name):
"""
Uses folder name to find the corresponding folder
"""
for folder in course.get_folders():
if folder.full_name == 'course files/' + folder_name:
return folder
def find_module(course, module_name):
"""
Uses module name to find the corresponding module
"""
for module in course.get_modules():
if module.name == module_name:
return module
def page_exists(course, page_name):
"""
Tests whether a page exists for a course
The page url is everything following the 'pages/' in the pages's URL:
'page_name' in the case of this URL
https://canvas.instance.com/courses/course_id/pages/page_name
"""
for page in course.get_pages():
if page.url == page_name:
return True
return False
def get_file(course, file_name):
"""
Finds and returns file for a course.
Returns False if file not found.
The file name is everything following the 'files/folder/' in the pages's URL:
'file.ext' in the case of this URL
https://canvas.instance.com/courses/12345/files/folder/file.ext
'subfolder/file.ext' in the case of this URL
https://canvas.instance.com/courses/12345/files/folder/subfolder/file.ext
"""
for folder in course.get_folders():
# remove leading '"course files/' from path
folder_name = strip_folder_name(folder.full_name)
# place files in a folder called 'files'
path = '' # emoty for filses in the root folder
if folder_name != '':
# subfolder, add name + a trailing '/' to path
path += folder_name + "/"
# download all files in this folder
for file in folder.get_files():
if path + file.display_name == file_name:
return file
# file not found
return False
def module_exists(course, module_name):
"""
Tests whether a module exists for a course
Looks for an existing module of the same name.
Returns the 'items_url' of the existing module
or an empty string if it does not yet exists.
"""
for module in course.get_modules():
if module.name == module_name:
return module.items_url
return ''
def strip_folder_name(long_folder_name):
"""
Removes leading '"course files/' from folder 'path'
"""
return long_folder_name[13:]