Skip to content

Fall back to AJAX on a Moodle course-context validation error#64

Merged
erseco merged 3 commits into
mainfrom
issue-63-list-courses-context-fallback
Jul 8, 2026
Merged

Fall back to AJAX on a Moodle course-context validation error#64
erseco merged 3 commits into
mainfrom
issue-63-list-courses-context-fallback

Conversation

@erseco

@erseco erseco commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Summary

list_courses()'s webservice-to-AJAX fallback only triggered on an invalid/expired token. Broadens it to also cover a real, CI-observed Moodle course-context validation quirk, so callers transparently recover via AJAX instead of erroring out.

Linked issue

Closes #63

Specification

See #63 for the full write-up and CI evidence (two separate failed runs, three different tests affected, all on PR #62).

Implementation details

  • src/py_moodle/transport/webservice.py: renamed the single _INVALID_TOKEN_MARKER to a _TRANSPORT_UNAVAILABLE_MARKERS tuple, adding "cannot execute functions in the course context" (the stable, generic part of the Moodle message — the course id and exact sub-message vary) alongside the existing invalid-token marker. Both now raise TransportUnavailableError (fall back to AJAX) instead of TransportError (raise immediately).
  • tests/unit/test_transport.py: two new regression tests reproducing the exact error message seen in CI, at both the webservice_transport.call() level and the public list_courses() level.

Test plan

  • Added the failing tests first.
  • Confirmed they failed against the pre-fix code (via git stash on just the source file) — reproduced the exact CI traceback shape.
  • Implemented the fix (broadened marker list).
  • Confirmed the two new tests pass, plus all 10 tests in test_transport.py.
  • Confirmed the full pytest tests/unit suite (199 tests) and make lint are still green.

Commands run:

pytest tests/unit/test_transport.py -k context_error -q   # red, via git stash on webservice.py
git stash pop
pytest tests/unit/test_transport.py -q                     # green, all 10 pass
pytest tests/unit -q                                        # 199 passed
black --check src tests && isort --check-only src tests && flake8

Backward compatibility

Fully backward compatible. Only broadens which errors trigger the existing AJAX fallback path (already exercised by test_list_courses_falls_back_to_ajax_on_invalid_token); does not change list_courses()'s signature, return shape, or any other function's behavior. Genuine, non-context, non-token TransportErrors (e.g. permissions denials) still raise immediately, unchanged, per the existing test_webservice_call_raises_transport_error_on_other_moodle_exception test.

Risk assessment

The marker-string approach matches this file's existing, already-reviewed convention (_INVALID_TOKEN_MARKER) rather than introducing a new classification mechanism. As with any English-substring match on a Moodle error message, it's not immune to locale/wording drift in a future Moodle release — same caveat that already applied to the invalid-token marker before this PR.

Manual verification

Can't reproduce this specific race against a live Moodle instance from this environment on demand (it's timing-dependent), but the CI evidence in #63 is the real-world reproduction. The regression test in test_transport.py reproduces the exact error message deterministically without needing live Moodle or a race.

Notes for reviewers

This was discovered while verifying PR #62 (test de-flaking), not something #62 introduced — #62 is unrelated test-fixture code; this is a production src/py_moodle/transport/webservice.py fix. Kept as its own focused PR rather than folded into #62.

erseco added 2 commits July 7, 2026 22:25
list_courses() only fell back from the webservice transport to AJAX on
an invalid/expired token (TransportUnavailableError); any other
TransportError was re-raised immediately, per #40's stricter,
deliberately-reviewed replacement of the previous bare except Exception.

Confirmed in CI (PR #62, two separate runs) that a generic,
non-course-scoped call like core_course_get_courses can still fail with
'You cannot execute functions in the course context (course id:N) ...
Context does not exist' -- a course-context validation quirk unrelated
to the token -- causing list_courses() (and anything built on it) to
error out instead of transparently recovering via AJAX, which re-derives
context from the current session rather than a cached webservice-side
lookup.

Broadens the webservice transport's fallback-worthy marker list to also
cover this message. Added a failing-first regression test reproducing
the exact CI error message, confirmed red against the pre-fix code via
git stash, green after.
@erseco erseco merged commit da3349e into main Jul 8, 2026
48 of 53 checks passed
@erseco erseco deleted the issue-63-list-courses-context-fallback branch July 8, 2026 00:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

list_courses() doesn't fall back to AJAX for a 'context does not exist' webservice error

1 participant