Skip to content

feat: add GradeEventContextRequested filter for grade analytics enrichment#333

Merged
felipemontoya merged 6 commits intoopenedx:mainfrom
pwnage101:pwnage101/ENT-11563
Apr 17, 2026
Merged

feat: add GradeEventContextRequested filter for grade analytics enrichment#333
felipemontoya merged 6 commits intoopenedx:mainfrom
pwnage101:pwnage101/ENT-11563

Conversation

@pwnage101
Copy link
Copy Markdown
Contributor

@pwnage101 pwnage101 commented Mar 4, 2026

Introduces a new GradeEventContextRequested filter (org.openedx.learning.grade.context.requested.v1) that allows pipeline steps to enrich the context dict emitted with grade analytics events. Adds unit tests confirming correct filter type and pipeline behavior.

ENT-11563

Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com


Blocks:

…hment

Introduces a new GradeEventContextRequested filter
(org.openedx.learning.grade.context.requested.v1) that allows pipeline
steps to enrich the context dict emitted with grade analytics events.
Adds unit tests confirming correct filter type and pipeline behavior.

ENT-11563

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comment thread openedx_filters/learning/filters.py Outdated
dict: the context dict, possibly enriched by pipeline steps.
"""
data = super().run_pipeline(context=context, user_id=user_id, course_id=course_id)
return data.get("context")
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unconventional for the return signature to differ from the arguments signature. Better would be:

Suggested change
return data.get("context")
return data.get("context"), data.get("user_id"), data.get("course_id")

@kiram15 kiram15 force-pushed the pwnage101/ENT-11563 branch 2 times, most recently from 29045b3 to bb9efce Compare April 13, 2026 19:53
@pwnage101 pwnage101 marked this pull request as ready for review April 13, 2026 20:39
Comment thread openedx_filters/learning/filters.py Outdated
filter_type = "org.openedx.learning.grade.context.requested.v1"

@classmethod
def run_filter(cls, context: dict, user_id: int, course_id: str) -> tuple[dict | None, int | None, str | None]:
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the return type should be more strict by not letting non-None input values be converted to None.

Suggested change
def run_filter(cls, context: dict, user_id: int, course_id: str) -> tuple[dict | None, int | None, str | None]:
def run_filter(cls, context: dict, user_id: int, course_id: str) -> tuple[dict, int, str]:

Comment thread openedx_filters/learning/filters.py Outdated
course_id (str): The identifier of the course.

Returns:
tuple[dict | None, int | None, str | None]:
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
tuple[dict | None, int | None, str | None]:
tuple[dict, int, str]:

Comment thread openedx_filters/learning/filters.py Outdated
Comment on lines 1470 to 1471
Copy link
Copy Markdown
Contributor Author

@pwnage101 pwnage101 Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While we're in here, I always thought this was a bug but was too late to comment on it. Unless there's an exceptional reason, I think Input types should match output types.

    def run_filter(cls, readonly_fields: set, user: Any) -> tuple[set, Any]:

@kiram15 kiram15 force-pushed the pwnage101/ENT-11563 branch from bb9efce to d08c9f7 Compare April 13, 2026 22:13
Comment thread openedx_filters/learning/filters.py Outdated
str: The course identifier.
"""
data = super().run_pipeline(context=context, user_id=user_id, course_id=course_id)
return data.get("context"), data.get("user_id"), data.get("course_id")
Copy link
Copy Markdown
Contributor Author

@pwnage101 pwnage101 Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, lets just make this strict:

Suggested change
return data.get("context"), data.get("user_id"), data.get("course_id")
return data["context"], data["user_id"], data["course_id"]

That way, if the pipeline calling code can't tolerate None values from a buggy filter, then at least we catch the error sooner. Now the error (KeyError) happens closer to the root issue inside the pipeline itself, rather than after the entire pipeline has finished and returned to openedx-platform, potentially throwing a TypeError/AttributeError resulting from working with None values unexpectedly.

@kiram15 kiram15 force-pushed the pwnage101/ENT-11563 branch from d08c9f7 to 1849e0e Compare April 14, 2026 15:50
@kiram15 kiram15 requested a review from felipemontoya April 14, 2026 16:07
@kiram15 kiram15 force-pushed the pwnage101/ENT-11563 branch from 18fbb54 to f3686fb Compare April 14, 2026 16:11
@pwnage101
Copy link
Copy Markdown
Contributor Author

✅ LGTM

@kiram15 kiram15 force-pushed the pwnage101/ENT-11563 branch from 1ddc9ba to 870eca9 Compare April 15, 2026 04:54
Comment thread setup.py
],
include_package_data=True,
install_requires=load_requirements("requirements/base.in"),
python_requires=">=3.12",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We aren't using any python 3.12 specific functionality, and this allows edx-platform to be able to pick up the new openedx-filters versions that are right now incompatible with edx-platform's python version of 3.11.

@kiram15 kiram15 force-pushed the pwnage101/ENT-11563 branch from 3f30ebe to 0cfde64 Compare April 17, 2026 18:30
Copy link
Copy Markdown
Member

@felipemontoya felipemontoya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks very clean and the accompanying platform PR is also clear and with good structure.
I think removing one more stitch in enterprise dependency while at the same time allowing others to enrich the grade analytics is completely welcomed.


@classmethod
def run_filter(cls, readonly_fields: set, user: Any) -> tuple[Any, Any]:
def run_filter(cls, readonly_fields: set, user: Any) -> tuple[set, Any]:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[info] this is coming from the last PR that added this filter where we agreed to this after the PR was merged.

@felipemontoya felipemontoya merged commit d517006 into openedx:main Apr 17, 2026
9 checks passed
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.

3 participants