canvaslms 5.2__py3-none-any.whl → 5.3__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/modules.nw +49 -7
- canvaslms/cli/modules.py +24 -6
- canvaslms/cli/pages.nw +5 -0
- {canvaslms-5.2.dist-info → canvaslms-5.3.dist-info}/METADATA +1 -1
- {canvaslms-5.2.dist-info → canvaslms-5.3.dist-info}/RECORD +8 -8
- {canvaslms-5.2.dist-info → canvaslms-5.3.dist-info}/WHEEL +0 -0
- {canvaslms-5.2.dist-info → canvaslms-5.3.dist-info}/entry_points.txt +0 -0
- {canvaslms-5.2.dist-info → canvaslms-5.3.dist-info}/licenses/LICENSE +0 -0
canvaslms/cli/modules.nw
CHANGED
|
@@ -501,16 +501,27 @@ def get_item_modules(course, item_type, item_id):
|
|
|
501
501
|
|
|
502
502
|
The matching logic differs by item type.
|
|
503
503
|
For assignments, Canvas stores the assignment ID in [[content_id]].
|
|
504
|
-
For pages, Canvas stores the URL slug in [[page_url]].
|
|
504
|
+
For pages, Canvas stores the URL slug in [[page_url]]. However, Canvas may
|
|
505
|
+
redirect old URLs to new ones, so we need to resolve the URL before comparing
|
|
506
|
+
(see [[<<check if page item matches by resolving url>>]]).
|
|
505
507
|
<<check if item matches and add module to list>>=
|
|
506
508
|
if item_type == 'Assignment':
|
|
507
509
|
if hasattr(item, 'content_id') and item.content_id == item_id:
|
|
508
510
|
modules.append(module.name)
|
|
509
511
|
break
|
|
510
512
|
elif item_type == 'Page':
|
|
511
|
-
if hasattr(item, 'page_url')
|
|
512
|
-
|
|
513
|
-
|
|
513
|
+
if hasattr(item, 'page_url'):
|
|
514
|
+
if item.page_url == item_id:
|
|
515
|
+
modules.append(module.name)
|
|
516
|
+
break
|
|
517
|
+
# Check if URLs resolve to same page (handles redirects)
|
|
518
|
+
try:
|
|
519
|
+
resolved_page = course.get_page(item.page_url)
|
|
520
|
+
if resolved_page.url == item_id:
|
|
521
|
+
modules.append(module.name)
|
|
522
|
+
break
|
|
523
|
+
except Exception:
|
|
524
|
+
pass
|
|
514
525
|
@
|
|
515
526
|
|
|
516
527
|
\subsection{Updating module membership based on patterns}
|
|
@@ -575,6 +586,21 @@ for module in all_modules:
|
|
|
575
586
|
@
|
|
576
587
|
|
|
577
588
|
We search the module's items to find if our item is currently present.
|
|
589
|
+
|
|
590
|
+
For pages, we need to handle URL redirects. Canvas may store an old URL in the
|
|
591
|
+
module item that redirects to the canonical URL we're checking against. For
|
|
592
|
+
example, a page might have been added to a module with URL
|
|
593
|
+
\enquote{page-on-campus+zoom}, but Canvas later changed the canonical URL to
|
|
594
|
+
\enquote{page-on-zoom+campus}. The module item still stores the old URL, but
|
|
595
|
+
when we fetch the page using [[course.get_page()]], Canvas returns the page
|
|
596
|
+
with its new canonical URL.
|
|
597
|
+
|
|
598
|
+
Without handling this, the direct comparison [[item.page_url == item_id]] would
|
|
599
|
+
fail, causing the page to be added to the module again (creating duplicates).
|
|
600
|
+
|
|
601
|
+
To detect this, we fetch the page using the module item's [[page_url]] and
|
|
602
|
+
compare its canonical [[url]] attribute with [[item_id]]. This adds an API call
|
|
603
|
+
per page item, but only when the direct comparison fails.
|
|
578
604
|
<<find current module item if present>>=
|
|
579
605
|
current_item = None
|
|
580
606
|
try:
|
|
@@ -586,13 +612,29 @@ try:
|
|
|
586
612
|
current_item = item
|
|
587
613
|
break
|
|
588
614
|
elif item_type == 'Page':
|
|
589
|
-
if hasattr(item, 'page_url')
|
|
590
|
-
|
|
591
|
-
break
|
|
615
|
+
if hasattr(item, 'page_url'):
|
|
616
|
+
<<check if page item matches by resolving url>>
|
|
592
617
|
except Exception:
|
|
593
618
|
pass
|
|
594
619
|
@
|
|
595
620
|
|
|
621
|
+
When comparing page URLs, we first try a direct match. If that fails, we fetch
|
|
622
|
+
the page to get its canonical URL and compare that. This handles the case where
|
|
623
|
+
Canvas has created a redirect from an old URL to a new one.
|
|
624
|
+
<<check if page item matches by resolving url>>=
|
|
625
|
+
if item.page_url == item_id:
|
|
626
|
+
current_item = item
|
|
627
|
+
break
|
|
628
|
+
# URLs don't match directly; check if they resolve to same page
|
|
629
|
+
try:
|
|
630
|
+
resolved_page = course.get_page(item.page_url)
|
|
631
|
+
if resolved_page.url == item_id:
|
|
632
|
+
current_item = item
|
|
633
|
+
break
|
|
634
|
+
except Exception:
|
|
635
|
+
pass # Page doesn't exist or can't be fetched
|
|
636
|
+
@
|
|
637
|
+
|
|
596
638
|
Finally, we add or remove based on comparing current vs desired state.
|
|
597
639
|
When adding, we use [[create_module_item]] with the appropriate type and ID.
|
|
598
640
|
When removing, we call [[delete()]] on the module item object.
|
canvaslms/cli/modules.py
CHANGED
|
@@ -209,9 +209,18 @@ def get_item_modules(course, item_type, item_id):
|
|
|
209
209
|
modules.append(module.name)
|
|
210
210
|
break
|
|
211
211
|
elif item_type == "Page":
|
|
212
|
-
if hasattr(item, "page_url")
|
|
213
|
-
|
|
214
|
-
|
|
212
|
+
if hasattr(item, "page_url"):
|
|
213
|
+
if item.page_url == item_id:
|
|
214
|
+
modules.append(module.name)
|
|
215
|
+
break
|
|
216
|
+
# Check if URLs resolve to same page (handles redirects)
|
|
217
|
+
try:
|
|
218
|
+
resolved_page = course.get_page(item.page_url)
|
|
219
|
+
if resolved_page.url == item_id:
|
|
220
|
+
modules.append(module.name)
|
|
221
|
+
break
|
|
222
|
+
except Exception:
|
|
223
|
+
pass
|
|
215
224
|
except Exception:
|
|
216
225
|
# Skip modules we can't access
|
|
217
226
|
pass
|
|
@@ -254,9 +263,18 @@ def update_item_modules(course, item_type, item_id, module_regexes):
|
|
|
254
263
|
current_item = item
|
|
255
264
|
break
|
|
256
265
|
elif item_type == "Page":
|
|
257
|
-
if hasattr(item, "page_url")
|
|
258
|
-
|
|
259
|
-
|
|
266
|
+
if hasattr(item, "page_url"):
|
|
267
|
+
if item.page_url == item_id:
|
|
268
|
+
current_item = item
|
|
269
|
+
break
|
|
270
|
+
# URLs don't match directly; check if they resolve to same page
|
|
271
|
+
try:
|
|
272
|
+
resolved_page = course.get_page(item.page_url)
|
|
273
|
+
if resolved_page.url == item_id:
|
|
274
|
+
current_item = item
|
|
275
|
+
break
|
|
276
|
+
except Exception:
|
|
277
|
+
pass # Page doesn't exist or can't be fetched
|
|
260
278
|
except Exception:
|
|
261
279
|
pass
|
|
262
280
|
should_be_in = module.id in matching_module_ids
|
canvaslms/cli/pages.nw
CHANGED
|
@@ -523,6 +523,11 @@ title to find the page. This is the most common case when creating or updating
|
|
|
523
523
|
pages from Markdown files: the user specifies a title in the front matter and
|
|
524
524
|
expects the command to find or create a page with that title.
|
|
525
525
|
|
|
526
|
+
This behavior is critical for safety. Without it, the command would fall back to
|
|
527
|
+
filter-based matching with the default [[-p '.*']] pattern, which matches
|
|
528
|
+
\emph{all} pages in the course. The result would be catastrophic: every page
|
|
529
|
+
would be overwritten with the content from the file.
|
|
530
|
+
|
|
526
531
|
We use exact title matching (not regex) to avoid accidentally updating multiple
|
|
527
532
|
pages. If exactly one page matches, we update it. If no pages match and
|
|
528
533
|
[[--create]] is specified, we create a new page. If multiple pages match, we
|
|
@@ -20,9 +20,9 @@ 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
22
|
canvaslms/cli/login.py,sha256=GSO_wIT4TvCOwxaNW0VfUqjrkzsHvnImuSH4SdCu92M,2751
|
|
23
|
-
canvaslms/cli/modules.nw,sha256=
|
|
24
|
-
canvaslms/cli/modules.py,sha256=
|
|
25
|
-
canvaslms/cli/pages.nw,sha256=
|
|
23
|
+
canvaslms/cli/modules.nw,sha256=VZkb9u9VGmXoCyJpPyByFrOanqbKSLnIRPxODSfldxo,23689
|
|
24
|
+
canvaslms/cli/modules.py,sha256=7pnKU6ex6zH4OC2SxLMn4uzc0cDl3pAVFcR9WJi317c,12426
|
|
25
|
+
canvaslms/cli/pages.nw,sha256=njm6oQT22ryI8Z7O62d-qivQjbMX_je5OwhgHEvtVUg,28934
|
|
26
26
|
canvaslms/cli/pages.py,sha256=lW8DpMeyQQoVcu7ztSj_PdW-oUJC0HSh5mDeo8BuaRc,27713
|
|
27
27
|
canvaslms/cli/quizzes.nw,sha256=nO0lAJLpE03fwPTV8wCC0Zr65p7J5x2H7J0OU8KW5CA,203138
|
|
28
28
|
canvaslms/cli/quizzes.py,sha256=gx-SPm0rI2XNVUl5Qm7s4UHvsvitwFyrNh35J3Lay9Y,152014
|
|
@@ -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.3.dist-info/METADATA,sha256=rvvX57QhCQT6AtrYaPIaBZ5JJ1KDay6O-zOSd61f2SA,5978
|
|
61
|
+
canvaslms-5.3.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
62
|
+
canvaslms-5.3.dist-info/entry_points.txt,sha256=lyblfkLbodN5yb7q1c6-rwIoJPV-ygXrB9PYb5boHXM,48
|
|
63
|
+
canvaslms-5.3.dist-info/licenses/LICENSE,sha256=N_TKsbzzD5Ax5fWJqEQk9bkwtf394MJkNeFld4HV6-E,1074
|
|
64
|
+
canvaslms-5.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|