Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,11 @@ jobs:

- name: Check formatting with black and isort
run: |
black --check syncmymoodle
isort --check-only syncmymoodle
black --check syncmymoodle tests
isort --check-only syncmymoodle tests

- name: Run tests
run: python -m pytest

# Disabled for now, until we refactor the main project
# - name: Lint with flake8
Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,16 @@ test = [
"flake8",
"flake8-bugbear",
"mypy",
"pytest",
"types-requests"
]

[tool.isort]
profile = "black"

[tool.black]
target-version = ["py311"]

[tool.mypy]
warn_unused_configs = true
warn_redundant_casts = true
Expand Down
16 changes: 9 additions & 7 deletions syncmymoodle/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def add_child(
):
if url:
url = url.replace("?forcedownload=1", "").replace(
"mod_page/content/3", "mod_page/content"
"mod_page/content/3/", "mod_page/content/"
)
url = url.replace("webservice/pluginfile.php", "pluginfile.php")

Expand Down Expand Up @@ -1825,7 +1825,7 @@ def sync(self):
info_res = bs(
self.session.get(info_url).text, features="lxml"
)
attempts = info_res.findAll(
attempts = info_res.find_all(
"a",
{
"title": "Überprüfung der eigenen Antworten dieses Versuchs"
Expand Down Expand Up @@ -2055,18 +2055,20 @@ def download_file(self, node):

local_conflict = False
old_etag = getattr(old_node, "etag", None) if old_node is not None else None
etag_check_failed = False
if old_etag:
# Prefer using the old ETag (hash) to detect whether the local file
# still matches the previously downloaded version.
try:
if not self._local_file_matches_etag(downloadpath, old_etag):
local_conflict = True
except Exception:
# If we cannot safely compare using the ETag, fall back to the
# timestamp-based heuristic below.
local_conflict = False
# A faulty/unusable ETag cache is treated as if we had no
# cached ETag at all: fall back to the timestamp/HEAD
# heuristic below to decide whether this is a conflict.
etag_check_failed = True

if not old_etag:
if not old_etag or etag_check_failed:
if cached_timemodified is not None:
# Fallback: compare local mtime with the previous Moodle timestamp.
try:
Expand Down Expand Up @@ -2267,7 +2269,7 @@ def _extract_opencast_episode_id(self, url):
def _extract_lti_form_data(self, soup):
return {
input_tag["name"]: input_tag.get("value", "")
for input_tag in soup.findAll("input")
for input_tag in soup.find_all("input")
if input_tag.get("name")
}

Expand Down
1 change: 1 addition & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

6 changes: 6 additions & 0 deletions tests/fixtures/html/external_overview.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<!doctype html>
<html>
<body>
<a href="https://www.youtube.com/watch?v=directvid01">overview video</a>
</body>
</html>
6 changes: 6 additions & 0 deletions tests/fixtures/html/h5p_iframe.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<!doctype html>
<html>
<body>
<a href="https://www.youtube.com/watch?v=h5pvideo001">h5p video</a>
</body>
</html>
6 changes: 6 additions & 0 deletions tests/fixtures/html/h5p_view.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<!doctype html>
<html>
<body>
<iframe src="/h5p/embed/317"></iframe>
</body>
</html>
12 changes: 12 additions & 0 deletions tests/fixtures/html/page_module.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html>
<body>
<div class="video-js">
<video>
<source src="/pluginfile.php/104/mod_page/content/315/page-video.mp4" type="video/mp4">
</video>
</div>
<a href="https://www.youtube.com/watch?v=pagevideo01">page video</a>
<iframe src="https://engage.streaming.rwth-aachen.de/play/33333333-4444-4555-8666-777777777777"></iframe>
</body>
</html>
10 changes: 10 additions & 0 deletions tests/fixtures/moodle/assignment_opencast_assignments.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"assignments": [
{
"id": 402,
"cmid": 302,
"intro": "<p>Watch the embedded recording.</p><iframe src=\"https://engage.streaming.rwth-aachen.de/play/11111111-2222-4333-8444-555555555555\"></iframe>",
"introattachments": []
}
]
}
13 changes: 13 additions & 0 deletions tests/fixtures/moodle/assignment_opencast_course.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[
{
"id": 202,
"name": "Assignments",
"modules": [
{
"id": 302,
"name": "Video reflection",
"modname": "assign"
}
]
}
]
17 changes: 17 additions & 0 deletions tests/fixtures/moodle/courses.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[
{
"id": 101,
"shortname": "(VO) Data Science",
"idnumber": "26ss-data-science"
},
{
"id": 102,
"shortname": "(UE) Software Quality",
"idnumber": "26ss-software-quality"
},
{
"id": 103,
"shortname": "Robust Moodle Fixtures",
"idnumber": "26ss-fixtures"
}
]
17 changes: 17 additions & 0 deletions tests/fixtures/moodle/mixed_assignments.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"assignments": [
{
"id": 412,
"cmid": 312,
"intro": "<p>Use the template and upload your answer.</p>",
"introattachments": [
{
"filename": "essay-template.docx",
"filepath": "/",
"fileurl": "https://moodle.rwth-aachen.de/pluginfile.php/104/mod_assign/introattachment/essay-template.docx",
"timemodified": 1710000105
}
]
}
]
}
100 changes: 100 additions & 0 deletions tests/fixtures/moodle/mixed_course.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
[
{
"id": 210,
"name": "Materials",
"modules": [
{
"id": 310,
"name": "Lecture slides",
"modname": "resource",
"contents": [
{
"type": "file",
"filename": "lecture-slides.pdf",
"filepath": "/",
"fileurl": "https://moodle.rwth-aachen.de/pluginfile.php/104/mod_resource/content/1/lecture-slides.pdf",
"mimetype": "application/pdf",
"timemodified": 1710000100
}
]
},
{
"id": 311,
"name": "Data folder",
"modname": "folder",
"contents": [
{
"type": "file",
"filename": "measurements.csv",
"filepath": "/Data/Raw/",
"fileurl": "https://moodle.rwth-aachen.de/pluginfile.php/104/mod_folder/content/0/Data/Raw/measurements.csv",
"mimetype": "text/csv",
"timemodified": 1710000101
}
]
},
{
"id": 312,
"name": "Essay upload",
"modname": "assign"
},
{
"id": 313,
"name": "Direct external PDF",
"modname": "url",
"contents": [
{
"type": "file",
"filename": "direct.pdf",
"filepath": "/",
"fileurl": "https://files.example.test/direct.pdf",
"mimetype": "application/pdf",
"timemodified": 1710000102
}
]
},
{
"id": 314,
"name": "External HTML page",
"modname": "url",
"contents": [
{
"type": "file",
"filename": "overview.html",
"filepath": "/",
"fileurl": "https://files.example.test/overview.html",
"mimetype": "text/html",
"timemodified": 1710000103
}
]
},
{
"id": 315,
"name": "Page module",
"modname": "page",
"url": "https://moodle.rwth-aachen.de/mod/page/view.php?id=315",
"contents": [
{
"type": "file",
"filename": "index.html",
"filepath": "/",
"fileurl": "https://moodle.rwth-aachen.de/pluginfile.php/104/mod_page/content/315/index.html",
"mimetype": "text/html",
"timemodified": 1710000104
}
]
},
{
"id": 316,
"name": "Label module",
"modname": "label",
"description": "<p>Label video https://youtu.be/labelvid001</p>"
},
{
"id": 317,
"name": "H5P module",
"modname": "h5pactivity"
}
]
}
]
7 changes: 7 additions & 0 deletions tests/fixtures/moodle/mixed_courses.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"id": 104,
"shortname": "Comprehensive Sync",
"idnumber": "26ss-comprehensive"
}
]
6 changes: 6 additions & 0 deletions tests/fixtures/moodle/mixed_folders.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
{
"coursemodule": 311,
"intro": "<p>Folder intro video https://youtu.be/foldervid01</p>"
}
]
8 changes: 8 additions & 0 deletions tests/fixtures/moodle/mixed_submission_files.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
{
"filename": "feedback.txt",
"filepath": "/Feedback/",
"fileurl": "https://moodle.rwth-aachen.de/pluginfile.php/104/mod_assign/feedback/feedback.txt",
"timemodified": 1710000106
}
]
31 changes: 31 additions & 0 deletions tests/fixtures/moodle/nested_folder_course.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[
{
"id": 201,
"name": "General",
"modules": [
{
"id": 301,
"name": "Dataset folder",
"modname": "folder",
"contents": [
{
"type": "file",
"filename": "anscombe.csv",
"filepath": "/Data/CSV/",
"fileurl": "https://moodle.rwth-aachen.de/pluginfile.php/101/mod_folder/content/0/Data/CSV/anscombe.csv?forcedownload=1",
"mimetype": "text/csv",
"timemodified": 1710000000
},
{
"type": "file",
"filename": "iris.csv",
"filepath": "/Data/CSV/",
"fileurl": "https://moodle.rwth-aachen.de/pluginfile.php/101/mod_folder/content/0/Data/CSV/iris.csv?forcedownload=1",
"mimetype": "text/csv",
"timemodified": 1710000001
}
]
}
]
}
]
18 changes: 18 additions & 0 deletions tests/fixtures/moodle/opencast_lti_course.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[
{
"id": 220,
"name": "Opencast",
"modules": [
{
"id": 501,
"name": "Single LTI",
"modname": "lti"
},
{
"id": 502,
"name": "Series LTI",
"modname": "lti"
}
]
}
]
Loading