Repository navigation
feat: add filters for learner block binds and course API responses - #410
asadali145 wants to merge 5 commits into
Conversation
|
Thanks for the pull request, @asadali145! This repository is currently maintained by Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review. 🔘 Get product approvalIf you haven't already, check this list to see if your contribution needs to go through the product review process.
🔘 Provide contextTo help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:
🔘 Get a green buildIf one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green. DetailsWhere can I find more information?If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources: When can I expect my changes to be merged?Our goal is to get community contributions seen and reviewed as efficiently as possible. However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:
💡 As a result it may take up to several weeks or months to complete a review and merge your PR. |
7d0212e to
002b205
Compare
002b205 to
3418f51
Compare
There was a problem hiding this comment.
🟢 Approval recommended
The additive filters follow existing pipeline contracts, with no identified blocking issues.
No open issues 🎉
What changed in this PR
Adds five public filters so plugins can customize learner-specific content beyond render-time hooks.
Changes:
- Adds filters for bound XBlocks and transformed course block structures.
- Adds filters for serialized course outline, course home metadata, and courseware metadata responses.
- Documents filter contracts and adds pass-through tests.
| File | Description |
|---|---|
| src/openedx_filters/learning/tests/test_filters.py | Tests return values for all five new filters. |
| src/openedx_filters/learning/filters.py | Defines the filters, pipeline arguments, and trigger documentation. |
Review effort: Balanced
Drop this commit before review; openedx/openedx-filters#410 must be released first. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
3418f51 to
6529410
Compare
Add LearnerXBlockBound, CourseBlocksTransformCompleted, CourseOutlineAPIRenderStarted, CourseHomeMetadataAPIRenderStarted and CoursewareMetadataAPIRenderStarted, so plugins can adjust how course content is presented to a learner on each request: blocks right after they are bound (including handler requests, where render filters do not run), the learner's transformed course block structure, and serialized course outline and metadata API responses. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…vigation responses Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
9247d0a to
5b603e6
Compare

Description
Adds nine filters so a plugin can adjust how course content is presented to a learner on each request: blocks right after they are bound to the learner, the learner's transformed course block structure, and the serialized course outline, metadata, progress, dates, course home outline and navigation API responses.
Today the content filters are render-time only (
VerticalBlockChildRenderStarted,RenderXBlockStarted,VerticalBlockRenderCompleted). They do not run on XBlock handler requests (problem Submit / Reset / Show Answer, ORA steps), on sequence metadata (unit titles), on course pages (custom pages, handouts, updates, about), or on the cached block structure and outline behind the course outline, navigation sidebar, breadcrumbs, dates and progress page. A change a plugin makes at render time is therefore lost as soon as the learner interacts with the block or opens the outline.New filters:
LearnerXBlockBoundorg.openedx.learning.xblock.bound.v1block, user, course_keyCourseBlocksTransformCompletedorg.openedx.learning.course_blocks.transform.completed.v1block_structure, user, starting_block_usage_keyoverride_xblock_fieldwithout touching the shared block structure cache.CourseOutlineAPIRenderStartedorg.openedx.learning.course_outline.api.render.started.v1course_key, user, dataCourseHomeMetadataAPIRenderStartedorg.openedx.learning.course_home_metadata.api.render.started.v1course_key, user, dataCoursewareMetadataAPIRenderStartedorg.openedx.learning.courseware_metadata.api.render.started.v1course_key, user, dataCourseHomeProgressAPIRenderStartedorg.openedx.learning.course_home_progress.api.render.started.v1course_key, user, datauseris the learner whose progress is shown.CourseHomeDatesAPIRenderStartedorg.openedx.learning.course_home_dates.api.render.started.v1course_key, user, dataCourseHomeOutlineAPIRenderStartedorg.openedx.learning.course_home_outline.api.render.started.v1course_key, user, dataCourseNavigationAPIRenderStartedorg.openedx.learning.course_navigation.api.render.started.v1course_key, user, dataFor the response filters,
useris the user the response is built for: the learner whose data is shown, also when staff view it or masquerade as them.Example uses: per-learner or per-cohort content variants, accessibility adjustments to block text, or presenting alternative course content without duplicating the course.
Each filter follows the existing pattern in
src/openedx_filters/learning/filters.py(standalone class, Purpose / Filter Type / Trigger docstring sections,run_pipelinewith named arguments) and has a test insrc/openedx_filters/learning/tests/test_filters.py.Supporting information
Testing instructions
make requirements(oruv sync), thenpytest src/openedx_filters/learning/tests/test_filters.py.make quality(ruff, pycodestyle, pylint including the filter-docstring checks, mypy).OPEN_EDX_FILTERS_CONFIG(for example one that changesblock.display_namein memory forLearnerXBlockBound), and confirm it runs when loading a unit, submitting a problem, and opening the course outline.Deadline
None.
Other information
LearnerXBlockBoundruns for every block bind. With no pipeline configured,run_pipelinereturns immediately; steps should return early when they have nothing to do.LearnerXBlockBoundinto narrower per-view filters if reviewers prefer.Checklists
Merge Checklist:
Post Merge: