canvaslms 5.5__py3-none-any.whl → 5.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- canvaslms/cli/login.py +2 -4
- canvaslms/cli/modules.nw +22 -7
- canvaslms/cli/modules.py +19 -4
- canvaslms/cli/quizzes.nw +68 -0
- canvaslms/cli/quizzes.py +28 -0
- {canvaslms-5.5.dist-info → canvaslms-5.7.dist-info}/METADATA +2 -1
- {canvaslms-5.5.dist-info → canvaslms-5.7.dist-info}/RECORD +10 -10
- {canvaslms-5.5.dist-info → canvaslms-5.7.dist-info}/WHEEL +1 -1
- {canvaslms-5.5.dist-info → canvaslms-5.7.dist-info}/entry_points.txt +0 -0
- {canvaslms-5.5.dist-info → canvaslms-5.7.dist-info}/licenses/LICENSE +0 -0
canvaslms/cli/login.py
CHANGED
|
@@ -16,8 +16,7 @@ def login_command(config, canvas, args):
|
|
|
16
16
|
)
|
|
17
17
|
hostname = input("Canvas hostname: ")
|
|
18
18
|
|
|
19
|
-
print(
|
|
20
|
-
f"""
|
|
19
|
+
print(f"""
|
|
21
20
|
Open
|
|
22
21
|
|
|
23
22
|
https://{hostname}/profile/settings
|
|
@@ -25,8 +24,7 @@ Open
|
|
|
25
24
|
in your browser. Scroll down to approved integrations and click the
|
|
26
25
|
'+ New access token' button. Fill in the required data and click the
|
|
27
26
|
'Generate token' button. Enter the token here.
|
|
28
|
-
"""
|
|
29
|
-
)
|
|
27
|
+
""")
|
|
30
28
|
|
|
31
29
|
token = input("Canvas token: ")
|
|
32
30
|
|
canvaslms/cli/modules.nw
CHANGED
|
@@ -486,6 +486,14 @@ def get_item_modules(course, item_type, item_id):
|
|
|
486
486
|
Returns:
|
|
487
487
|
List of module names containing this item
|
|
488
488
|
"""
|
|
489
|
+
target_url = None
|
|
490
|
+
if item_type == 'Page':
|
|
491
|
+
try:
|
|
492
|
+
target_url = course.get_page(item_id).url
|
|
493
|
+
except Exception:
|
|
494
|
+
# If we can't resolve the target page, fall back to raw comparisons.
|
|
495
|
+
target_url = item_id
|
|
496
|
+
|
|
489
497
|
modules = []
|
|
490
498
|
for module in course.get_modules():
|
|
491
499
|
try:
|
|
@@ -514,10 +522,10 @@ elif item_type == 'Page':
|
|
|
514
522
|
if item.page_url == item_id:
|
|
515
523
|
modules.append(module.name)
|
|
516
524
|
break
|
|
517
|
-
#
|
|
525
|
+
# Compare canonical URLs to avoid duplicates when Canvas redirects old slugs.
|
|
518
526
|
try:
|
|
519
527
|
resolved_page = course.get_page(item.page_url)
|
|
520
|
-
if resolved_page.url ==
|
|
528
|
+
if resolved_page.url == target_url:
|
|
521
529
|
modules.append(module.name)
|
|
522
530
|
break
|
|
523
531
|
except Exception:
|
|
@@ -598,11 +606,18 @@ with its new canonical URL.
|
|
|
598
606
|
Without handling this, the direct comparison [[item.page_url == item_id]] would
|
|
599
607
|
fail, causing the page to be added to the module again (creating duplicates).
|
|
600
608
|
|
|
601
|
-
To detect this, we fetch
|
|
602
|
-
|
|
603
|
-
|
|
609
|
+
To detect this, we fetch both the target page ([[item_id]]) and the module
|
|
610
|
+
item's page ([[item.page_url]]) and compare canonical [[url]] values. This adds
|
|
611
|
+
API calls, but only when the direct comparison fails.
|
|
604
612
|
<<find current module item if present>>=
|
|
605
613
|
current_item = None
|
|
614
|
+
canonical_page_url = None
|
|
615
|
+
if item_type == 'Page':
|
|
616
|
+
try:
|
|
617
|
+
canonical_page_url = course.get_page(item_id).url
|
|
618
|
+
except Exception:
|
|
619
|
+
canonical_page_url = item_id
|
|
620
|
+
|
|
606
621
|
try:
|
|
607
622
|
for item in module.get_module_items():
|
|
608
623
|
if not hasattr(item, 'type') or item.type != item_type:
|
|
@@ -625,10 +640,10 @@ Canvas has created a redirect from an old URL to a new one.
|
|
|
625
640
|
if item.page_url == item_id:
|
|
626
641
|
current_item = item
|
|
627
642
|
break
|
|
628
|
-
# URLs don't match directly;
|
|
643
|
+
# URLs don't match directly; compare canonical URLs to avoid duplicates.
|
|
629
644
|
try:
|
|
630
645
|
resolved_page = course.get_page(item.page_url)
|
|
631
|
-
if resolved_page.url ==
|
|
646
|
+
if resolved_page.url == canonical_page_url:
|
|
632
647
|
current_item = item
|
|
633
648
|
break
|
|
634
649
|
except Exception:
|
canvaslms/cli/modules.py
CHANGED
|
@@ -198,6 +198,14 @@ def get_item_modules(course, item_type, item_id):
|
|
|
198
198
|
Returns:
|
|
199
199
|
List of module names containing this item
|
|
200
200
|
"""
|
|
201
|
+
target_url = None
|
|
202
|
+
if item_type == "Page":
|
|
203
|
+
try:
|
|
204
|
+
target_url = course.get_page(item_id).url
|
|
205
|
+
except Exception:
|
|
206
|
+
# If we can't resolve the target page, fall back to raw comparisons.
|
|
207
|
+
target_url = item_id
|
|
208
|
+
|
|
201
209
|
modules = []
|
|
202
210
|
for module in course.get_modules():
|
|
203
211
|
try:
|
|
@@ -213,10 +221,10 @@ def get_item_modules(course, item_type, item_id):
|
|
|
213
221
|
if item.page_url == item_id:
|
|
214
222
|
modules.append(module.name)
|
|
215
223
|
break
|
|
216
|
-
#
|
|
224
|
+
# Compare canonical URLs to avoid duplicates when Canvas redirects old slugs.
|
|
217
225
|
try:
|
|
218
226
|
resolved_page = course.get_page(item.page_url)
|
|
219
|
-
if resolved_page.url ==
|
|
227
|
+
if resolved_page.url == target_url:
|
|
220
228
|
modules.append(module.name)
|
|
221
229
|
break
|
|
222
230
|
except Exception:
|
|
@@ -254,6 +262,13 @@ def update_item_modules(course, item_type, item_id, module_regexes):
|
|
|
254
262
|
|
|
255
263
|
for module in all_modules:
|
|
256
264
|
current_item = None
|
|
265
|
+
canonical_page_url = None
|
|
266
|
+
if item_type == "Page":
|
|
267
|
+
try:
|
|
268
|
+
canonical_page_url = course.get_page(item_id).url
|
|
269
|
+
except Exception:
|
|
270
|
+
canonical_page_url = item_id
|
|
271
|
+
|
|
257
272
|
try:
|
|
258
273
|
for item in module.get_module_items():
|
|
259
274
|
if not hasattr(item, "type") or item.type != item_type:
|
|
@@ -267,10 +282,10 @@ def update_item_modules(course, item_type, item_id, module_regexes):
|
|
|
267
282
|
if item.page_url == item_id:
|
|
268
283
|
current_item = item
|
|
269
284
|
break
|
|
270
|
-
# URLs don't match directly;
|
|
285
|
+
# URLs don't match directly; compare canonical URLs to avoid duplicates.
|
|
271
286
|
try:
|
|
272
287
|
resolved_page = course.get_page(item.page_url)
|
|
273
|
-
if resolved_page.url ==
|
|
288
|
+
if resolved_page.url == canonical_page_url:
|
|
274
289
|
current_item = item
|
|
275
290
|
break
|
|
276
291
|
except Exception:
|
canvaslms/cli/quizzes.nw
CHANGED
|
@@ -343,6 +343,7 @@ import canvaslms.cli
|
|
|
343
343
|
import canvaslms.cli.courses as courses
|
|
344
344
|
import canvaslms.cli.assignments as assignments
|
|
345
345
|
import canvaslms.cli.content as content
|
|
346
|
+
import canvaslms.cli.modules as modules
|
|
346
347
|
import canvaslms.cli.utils
|
|
347
348
|
from rich.console import Console
|
|
348
349
|
from rich.markdown import Markdown
|
|
@@ -2982,6 +2983,24 @@ NEW_QUIZ_RESULT_VIEW_SCHEMA = {
|
|
|
2982
2983
|
\subsection{File formats for quiz editing}
|
|
2983
2984
|
\label{sec:quiz-file-formats}
|
|
2984
2985
|
|
|
2986
|
+
\subsection{Updating module membership}
|
|
2987
|
+
|
|
2988
|
+
When a quiz is edited from a file, the front matter may include a [[modules]]
|
|
2989
|
+
field. We interpret this the same way as [[assignments edit]]:
|
|
2990
|
+
\begin{description}
|
|
2991
|
+
\item[Absent] Leave module membership unchanged.
|
|
2992
|
+
\item[Empty list] Remove the quiz from all modules.
|
|
2993
|
+
\item[List of regexes] Ensure the quiz appears in every matching module and is
|
|
2994
|
+
removed from non-matching modules.
|
|
2995
|
+
\end{description}
|
|
2996
|
+
|
|
2997
|
+
New Quizzes are implemented as assignments, and the module item type Canvas uses
|
|
2998
|
+
is [[Assignment]]. We therefore update membership using the quiz's assignment ID.
|
|
2999
|
+
Classic quizzes also appear as module items and can be targeted the same way.
|
|
3000
|
+
|
|
3001
|
+
We centralize this logic in a helper function so both file-based and interactive
|
|
3002
|
+
edit paths behave identically.
|
|
3003
|
+
|
|
2985
3004
|
The [[quizzes edit]] command supports three file formats, auto-detected from
|
|
2986
3005
|
the file extension and verified against the content:
|
|
2987
3006
|
\begin{description}
|
|
@@ -3003,6 +3022,18 @@ characters of the file:
|
|
|
3003
3022
|
\item Front matter format starts with [[---]]
|
|
3004
3023
|
\end{itemize}
|
|
3005
3024
|
|
|
3025
|
+
<<functions>>=
|
|
3026
|
+
def update_quiz_module_membership(quiz, module_regexes):
|
|
3027
|
+
"""Update module membership for a quiz based on module regex list"""
|
|
3028
|
+
item_id = int(quiz.id) if is_new_quiz(quiz) else quiz.id
|
|
3029
|
+
added, removed = modules.update_item_modules(
|
|
3030
|
+
quiz.course, 'Assignment', item_id, module_regexes)
|
|
3031
|
+
if added:
|
|
3032
|
+
print(f" Added to modules: {', '.join(added)}", file=sys.stderr)
|
|
3033
|
+
if removed:
|
|
3034
|
+
print(f" Removed from modules: {', '.join(removed)}", file=sys.stderr)
|
|
3035
|
+
|
|
3036
|
+
|
|
3006
3037
|
<<functions>>=
|
|
3007
3038
|
def detect_quiz_file_format(filepath):
|
|
3008
3039
|
"""Detect quiz file format from extension and content
|
|
@@ -3270,6 +3301,15 @@ If [[--replace-items]] is specified and the file contains items, we replace
|
|
|
3270
3301
|
the quiz questions. But first we check for student submissions and ask for
|
|
3271
3302
|
confirmation if any exist.
|
|
3272
3303
|
|
|
3304
|
+
If the file contains a [[modules]] key (front matter, YAML, or JSON), we also
|
|
3305
|
+
update the quiz's module membership after a successful edit. We interpret this
|
|
3306
|
+
field the same way as in [[assignments edit]]:
|
|
3307
|
+
\begin{description}
|
|
3308
|
+
\item[Absent] Module membership is not modified
|
|
3309
|
+
\item[Empty list] Quiz is removed from all modules
|
|
3310
|
+
\item[List of regexes] Quiz is placed in all modules matching the patterns
|
|
3311
|
+
\end{description}
|
|
3312
|
+
|
|
3273
3313
|
<<handle item replacement if requested>>=
|
|
3274
3314
|
items = quiz_data.get('items')
|
|
3275
3315
|
if args.replace_items and items:
|
|
@@ -3294,6 +3334,7 @@ for quiz in quiz_list:
|
|
|
3294
3334
|
success = apply_quiz_edit(quiz, settings, body, requester, args.html)
|
|
3295
3335
|
if success:
|
|
3296
3336
|
print(f"Updated quiz: {quiz.title}")
|
|
3337
|
+
<<update quiz module membership from file>>
|
|
3297
3338
|
else:
|
|
3298
3339
|
canvaslms.cli.warn(f"Failed to update quiz: {quiz.title}")
|
|
3299
3340
|
@
|
|
@@ -3396,6 +3437,8 @@ def edit_quiz_interactive(quiz, requester, html_mode=False):
|
|
|
3396
3437
|
|
|
3397
3438
|
# Apply the changes
|
|
3398
3439
|
success = apply_quiz_edit(quiz, final_attrs, final_body, requester, html_mode)
|
|
3440
|
+
if success:
|
|
3441
|
+
<<update quiz module membership interactively>>
|
|
3399
3442
|
return 'updated' if success else 'error'
|
|
3400
3443
|
@
|
|
3401
3444
|
|
|
@@ -3415,6 +3458,11 @@ The workflow is:
|
|
|
3415
3458
|
\item Apply the changes (settings only, unless [[--replace-items]])
|
|
3416
3459
|
\end{enumerate}
|
|
3417
3460
|
|
|
3461
|
+
<<update quiz module membership interactively>>=
|
|
3462
|
+
if 'modules' in final_attrs:
|
|
3463
|
+
update_quiz_module_membership(quiz, final_attrs['modules'])
|
|
3464
|
+
@
|
|
3465
|
+
|
|
3418
3466
|
<<functions>>=
|
|
3419
3467
|
def edit_quiz_interactive_json(quiz, requester, html_mode=False,
|
|
3420
3468
|
replace_items=False):
|
|
@@ -3680,6 +3728,11 @@ The [[replace_quiz_items]] function handles the complete process of replacing
|
|
|
3680
3728
|
quiz items. It first checks for submissions, then deletes existing items,
|
|
3681
3729
|
and finally creates the new items.
|
|
3682
3730
|
|
|
3731
|
+
<<update quiz module membership from file>>=
|
|
3732
|
+
if 'modules' in settings:
|
|
3733
|
+
update_quiz_module_membership(quiz, settings['modules'])
|
|
3734
|
+
@
|
|
3735
|
+
|
|
3683
3736
|
<<functions>>=
|
|
3684
3737
|
def replace_quiz_items(quiz, items, requester):
|
|
3685
3738
|
"""Replace all items in a quiz with new ones
|
|
@@ -4256,6 +4309,11 @@ The export command finds the quiz, extracts its settings, and exports all
|
|
|
4256
4309
|
questions. We reuse the existing [[export_new_quiz_items]] and
|
|
4257
4310
|
[[export_classic_questions]] functions for question export.
|
|
4258
4311
|
|
|
4312
|
+
If the quiz appears in modules, we also export a [[modules]] list. The
|
|
4313
|
+
[[quizzes edit]] command interprets this list as regex patterns, so we export
|
|
4314
|
+
module names as anchored, regex-escaped patterns (e.g., [[^FBF$]]) to mean
|
|
4315
|
+
\enquote{match this module name exactly}.
|
|
4316
|
+
|
|
4259
4317
|
<<functions>>=
|
|
4260
4318
|
def export_command(config, canvas, args):
|
|
4261
4319
|
"""Exports a complete quiz (settings + questions) to JSON"""
|
|
@@ -4305,6 +4363,11 @@ def export_full_new_quiz(quiz, requester, include_banks=True, importable=False):
|
|
|
4305
4363
|
"""
|
|
4306
4364
|
# Extract basic settings
|
|
4307
4365
|
settings = {
|
|
4366
|
+
'modules': [
|
|
4367
|
+
"^" + re.escape(name) + "$"
|
|
4368
|
+
for name in modules.get_item_modules(
|
|
4369
|
+
quiz.course, 'Assignment', int(quiz.id))
|
|
4370
|
+
],
|
|
4308
4371
|
'title': getattr(quiz, 'title', ''),
|
|
4309
4372
|
'instructions': getattr(quiz, 'instructions', '') or '',
|
|
4310
4373
|
'time_limit': getattr(quiz, 'time_limit', None),
|
|
@@ -4354,6 +4417,11 @@ def export_full_classic_quiz(quiz, importable=False):
|
|
|
4354
4417
|
"""
|
|
4355
4418
|
# Extract settings
|
|
4356
4419
|
settings = {
|
|
4420
|
+
'modules': [
|
|
4421
|
+
"^" + re.escape(name) + "$"
|
|
4422
|
+
for name in modules.get_item_modules(
|
|
4423
|
+
quiz.course, 'Assignment', quiz.id)
|
|
4424
|
+
],
|
|
4357
4425
|
'title': getattr(quiz, 'title', ''),
|
|
4358
4426
|
'description': getattr(quiz, 'description', '') or '',
|
|
4359
4427
|
'quiz_type': getattr(quiz, 'quiz_type', 'assignment'),
|
canvaslms/cli/quizzes.py
CHANGED
|
@@ -17,6 +17,7 @@ import canvaslms.cli
|
|
|
17
17
|
import canvaslms.cli.courses as courses
|
|
18
18
|
import canvaslms.cli.assignments as assignments
|
|
19
19
|
import canvaslms.cli.content as content
|
|
20
|
+
import canvaslms.cli.modules as modules
|
|
20
21
|
import canvaslms.cli.utils
|
|
21
22
|
from rich.console import Console
|
|
22
23
|
from rich.markdown import Markdown
|
|
@@ -2227,6 +2228,18 @@ def create_classic_quiz(course, quiz_params):
|
|
|
2227
2228
|
return None
|
|
2228
2229
|
|
|
2229
2230
|
|
|
2231
|
+
def update_quiz_module_membership(quiz, module_regexes):
|
|
2232
|
+
"""Update module membership for a quiz based on module regex list"""
|
|
2233
|
+
item_id = int(quiz.id) if is_new_quiz(quiz) else quiz.id
|
|
2234
|
+
added, removed = modules.update_item_modules(
|
|
2235
|
+
quiz.course, "Assignment", item_id, module_regexes
|
|
2236
|
+
)
|
|
2237
|
+
if added:
|
|
2238
|
+
print(f" Added to modules: {', '.join(added)}", file=sys.stderr)
|
|
2239
|
+
if removed:
|
|
2240
|
+
print(f" Removed from modules: {', '.join(removed)}", file=sys.stderr)
|
|
2241
|
+
|
|
2242
|
+
|
|
2230
2243
|
def detect_quiz_file_format(filepath):
|
|
2231
2244
|
"""Detect quiz file format from extension and content
|
|
2232
2245
|
|
|
@@ -2414,6 +2427,8 @@ def edit_command(config, canvas, args):
|
|
|
2414
2427
|
success = apply_quiz_edit(quiz, settings, body, requester, args.html)
|
|
2415
2428
|
if success:
|
|
2416
2429
|
print(f"Updated quiz: {quiz.title}")
|
|
2430
|
+
if "modules" in settings:
|
|
2431
|
+
update_quiz_module_membership(quiz, settings["modules"])
|
|
2417
2432
|
else:
|
|
2418
2433
|
canvaslms.cli.warn(f"Failed to update quiz: {quiz.title}")
|
|
2419
2434
|
else:
|
|
@@ -2494,6 +2509,9 @@ def edit_quiz_interactive(quiz, requester, html_mode=False):
|
|
|
2494
2509
|
|
|
2495
2510
|
# Apply the changes
|
|
2496
2511
|
success = apply_quiz_edit(quiz, final_attrs, final_body, requester, html_mode)
|
|
2512
|
+
if success:
|
|
2513
|
+
if "modules" in final_attrs:
|
|
2514
|
+
update_quiz_module_membership(quiz, final_attrs["modules"])
|
|
2497
2515
|
return "updated" if success else "error"
|
|
2498
2516
|
|
|
2499
2517
|
|
|
@@ -3176,6 +3194,12 @@ def export_full_new_quiz(quiz, requester, include_banks=True, importable=False):
|
|
|
3176
3194
|
"""
|
|
3177
3195
|
# Extract basic settings
|
|
3178
3196
|
settings = {
|
|
3197
|
+
"modules": [
|
|
3198
|
+
"^" + re.escape(name) + "$"
|
|
3199
|
+
for name in modules.get_item_modules(
|
|
3200
|
+
quiz.course, "Assignment", int(quiz.id)
|
|
3201
|
+
)
|
|
3202
|
+
],
|
|
3179
3203
|
"title": getattr(quiz, "title", ""),
|
|
3180
3204
|
"instructions": getattr(quiz, "instructions", "") or "",
|
|
3181
3205
|
"time_limit": getattr(quiz, "time_limit", None),
|
|
@@ -3214,6 +3238,10 @@ def export_full_classic_quiz(quiz, importable=False):
|
|
|
3214
3238
|
"""
|
|
3215
3239
|
# Extract settings
|
|
3216
3240
|
settings = {
|
|
3241
|
+
"modules": [
|
|
3242
|
+
"^" + re.escape(name) + "$"
|
|
3243
|
+
for name in modules.get_item_modules(quiz.course, "Assignment", quiz.id)
|
|
3244
|
+
],
|
|
3217
3245
|
"title": getattr(quiz, "title", ""),
|
|
3218
3246
|
"description": getattr(quiz, "description", "") or "",
|
|
3219
3247
|
"quiz_type": getattr(quiz, "quiz_type", "assignment"),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: canvaslms
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.7
|
|
4
4
|
Summary: Command-line interface to Canvas LMS
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -28,6 +28,7 @@ Requires-Dist: llm (>=0.16) ; (python_version >= "3.9") and (extra == "llm")
|
|
|
28
28
|
Requires-Dist: llm-anthropic (>=0.19,<0.20) ; (python_version >= "3.9") and (extra == "llm")
|
|
29
29
|
Requires-Dist: llm-azure (>=1.1,<2.0) ; (python_version >= "3.9") and (extra == "llm")
|
|
30
30
|
Requires-Dist: llm-gemini (>=0.26.1,<0.27.0) ; (python_version >= "3.9") and (extra == "llm")
|
|
31
|
+
Requires-Dist: llm-github-copilot (>=0.3.1,<1.0.0) ; (python_version >= "3.9") and (extra == "llm")
|
|
31
32
|
Requires-Dist: llm-openai-plugin (>=0.7,<0.8) ; (python_version >= "3.9") and (extra == "llm")
|
|
32
33
|
Requires-Dist: llm-python (>=0.1,<0.2) ; (python_version >= "3.9") and (extra == "llm")
|
|
33
34
|
Requires-Dist: patiencediff (>=0.2.18,<0.3.0) ; (python_version >= "3.9") and (extra == "diff")
|
|
@@ -19,13 +19,13 @@ canvaslms/cli/discussions.py,sha256=R6GbFbHYXCa0vyDf4eegGp74Pj6WGC38MEb6kY0PkWY,
|
|
|
19
19
|
canvaslms/cli/grade.nw,sha256=ms7sBiGRPbK0CJLKxxYx_CDY9LMWgKxUuf2M3FYepMs,2197
|
|
20
20
|
canvaslms/cli/grade.py,sha256=b7YkFIz64oXzcV2FcptpYJphevuCU3cdx9CilZHcG_A,662
|
|
21
21
|
canvaslms/cli/login.nw,sha256=93LyHO_LXL1WdEvMg3OLhWulgkdoO8pfjYZVLwUbX4I,4419
|
|
22
|
-
canvaslms/cli/login.py,sha256=
|
|
23
|
-
canvaslms/cli/modules.nw,sha256=
|
|
24
|
-
canvaslms/cli/modules.py,sha256=
|
|
22
|
+
canvaslms/cli/login.py,sha256=wbA5Q9fTsW1J-vraRcdq2kG4h_LFtvH_MTEay6h8GcE,2737
|
|
23
|
+
canvaslms/cli/modules.nw,sha256=rvrZe4AU_ok955GZ_ZwwFNFIHIKzft1LR9zTVLW_gic,24122
|
|
24
|
+
canvaslms/cli/modules.py,sha256=8fZpW_x7eUMUgcn8JrvbGuwtrmHsbVdNvqfcRgfF4x8,12953
|
|
25
25
|
canvaslms/cli/pages.nw,sha256=njm6oQT22ryI8Z7O62d-qivQjbMX_je5OwhgHEvtVUg,28934
|
|
26
26
|
canvaslms/cli/pages.py,sha256=lW8DpMeyQQoVcu7ztSj_PdW-oUJC0HSh5mDeo8BuaRc,27713
|
|
27
|
-
canvaslms/cli/quizzes.nw,sha256=
|
|
28
|
-
canvaslms/cli/quizzes.py,sha256=
|
|
27
|
+
canvaslms/cli/quizzes.nw,sha256=xgivQGColOzayvMn3OcxJf0V7E2K2lzindzPeBqymBw,262940
|
|
28
|
+
canvaslms/cli/quizzes.py,sha256=1gX16Mo49rO4j98xy_j7xSuIs0E9DcOJigB90imBNR4,198225
|
|
29
29
|
canvaslms/cli/results.nw,sha256=T-ry1k_cHCH_nJfvPl4d9UBbIl_SxvXjBMxyYfXgyaw,22503
|
|
30
30
|
canvaslms/cli/results.py,sha256=8ODAhC4r1ndyTHnWSSwFEeV4ab_snxTi1nkrsqqwRLg,15033
|
|
31
31
|
canvaslms/cli/results.py.broken,sha256=njHu8mKfPHqH4daxy-4LMpO6FdUBLPHiVKFFmyH8aJQ,13047
|
|
@@ -57,8 +57,8 @@ canvaslms/hacks/attachment_cache.py,sha256=LcOZqaa6jPrEJWUD-JYN5GTc3bxCbv2fr_vqu
|
|
|
57
57
|
canvaslms/hacks/canvasapi.nw,sha256=ixmIHn4tgy-ZKtQ1rqWSw97hfY2m0qtGX0de2x89lwA,136470
|
|
58
58
|
canvaslms/hacks/canvasapi.py,sha256=A-r48x7gO6143_QkuZ8n6EW66i-a2AXXr7X7oeehOAU,31868
|
|
59
59
|
canvaslms/hacks/test_hacks.py,sha256=JSJNvZqHu1E_s51HsPD7yr1gC-R-xVe-tuMMAKU9Gj8,66709
|
|
60
|
-
canvaslms-5.
|
|
61
|
-
canvaslms-5.
|
|
62
|
-
canvaslms-5.
|
|
63
|
-
canvaslms-5.
|
|
64
|
-
canvaslms-5.
|
|
60
|
+
canvaslms-5.7.dist-info/METADATA,sha256=39VhZz1uFN7Bm1W7GU2Yyxt6RI_wh3u5dd1t3kweD_w,6078
|
|
61
|
+
canvaslms-5.7.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
|
|
62
|
+
canvaslms-5.7.dist-info/entry_points.txt,sha256=lyblfkLbodN5yb7q1c6-rwIoJPV-ygXrB9PYb5boHXM,48
|
|
63
|
+
canvaslms-5.7.dist-info/licenses/LICENSE,sha256=N_TKsbzzD5Ax5fWJqEQk9bkwtf394MJkNeFld4HV6-E,1074
|
|
64
|
+
canvaslms-5.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|