Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: [FC-0074] add static type checking for documentation purposes #250

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ upgrade: ## update the requirements/*.txt files with the latest packages satisf

quality: ## check coding style with pycodestyle and pylint
pylint openedx_filters test_utils *.py
mypy
pycodestyle openedx_filters *.py
pydocstyle openedx_filters *.py
isort --check-only --diff --recursive test_utils openedx_filters *.py test_settings.py
Expand Down
9 changes: 9 additions & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[mypy]
allow_untyped_globals = False
plugins =
mypy_django_plugin.main,
files =
openedx_filters

[mypy.plugins.django-stubs]
django_settings_module = "test_utils.test_settings"
2 changes: 1 addition & 1 deletion openedx_filters/course_authoring/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class LMSPageURLRequested(OpenEdxPublicFilter):
filter_type = "org.openedx.course_authoring.lms.page.url.requested.v1"

@classmethod
def run_filter(cls, url: str, org: str) -> tuple[str, str]:
def run_filter(cls, url: str, org: str) -> tuple[str | None, str | None]:
"""
Process the inputs using the configured pipeline steps to modify the URL of the page requested by the user.

Expand Down
13 changes: 11 additions & 2 deletions openedx_filters/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
"""


from typing import Optional


class OpenEdxFilterException(Exception):
"""
Base exception for filters.
Expand All @@ -18,7 +21,13 @@ class OpenEdxFilterException(Exception):
exception.
"""

def __init__(self, message="", redirect_to=None, status_code=None, **kwargs):
def __init__(
self,
message: str = "",
redirect_to: str = "",
status_code: Optional[int] = None,
**kwargs
) -> None:
"""
Init method for OpenEdxFilterException.

Expand All @@ -31,7 +40,7 @@ def __init__(self, message="", redirect_to=None, status_code=None, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)

def __str__(self):
def __str__(self) -> str:
"""
Show string representation of OpenEdxFilterException using its message.
"""
Expand Down
54 changes: 34 additions & 20 deletions openedx_filters/learning/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def __init__(self, message: str, response: Optional[HttpResponse] = None) -> Non
super().__init__(message, response=response)

@classmethod
def run_filter(cls, context: dict, template_name: str) -> tuple[dict, str]:
def run_filter(cls, context: dict[str, Any], template_name: str) -> tuple[dict[str, Any] | None, str | None]:
"""
Process the input context and template_name using the configured pipeline steps to modify the account settings.

Expand Down Expand Up @@ -159,7 +159,7 @@ def run_filter(cls, form_data: QueryDict) -> QueryDict:
"""
sensitive_data = cls.extract_sensitive_data(form_data)
data = super().run_pipeline(form_data=form_data)
form_data = data.get("form_data")
form_data = data.get("form_data", QueryDict())
form_data.update(sensitive_data)
return form_data

Expand Down Expand Up @@ -249,7 +249,7 @@ class PreventEnrollment(OpenEdxFilterException):
"""

@classmethod
def run_filter(cls, user: Any, course_key: CourseKey, mode: str) -> tuple[Any, CourseKey, str]:
def run_filter(cls, user: Any, course_key: CourseKey, mode: str) -> tuple[Any, CourseKey | None, str | None]:
"""
Process the user, course_key, and mode using the configured pipeline steps to modify the enrollment process.

Expand Down Expand Up @@ -345,14 +345,14 @@ class PreventCertificateCreation(OpenEdxFilterException):

@classmethod
def run_filter( # pylint: disable=too-many-positional-arguments
cls: type,
cls,
user: Any,
course_key: CourseKey,
mode: str,
status: str,
grade: float,
generation_mode: str,
) -> tuple[Any, CourseKey, str, str, float, str]:
) -> tuple[Any, CourseKey | None, str | None, str | None, float | None, str | None]:
"""
Process the inputs using the configured pipeline steps to modify the certificate creation process.

Expand Down Expand Up @@ -460,7 +460,7 @@ def __init__(self, message: str, response: HttpResponse) -> None:
)

@classmethod
def run_filter(cls, context: dict, custom_template: Any) -> tuple[dict, Any]:
def run_filter(cls, context: dict, custom_template: Any) -> tuple[dict[str, Any] | None, Any]:
"""
Process the context and custom_template using the configured pipeline steps to modify the certificate rendering.

Expand Down Expand Up @@ -646,7 +646,7 @@ def __init__(self, message: str, response: HttpResponse) -> None:
)

@classmethod
def run_filter(cls, context: dict, template_name: str) -> tuple[dict, str]:
def run_filter(cls, context: dict[str, Any], template_name: str) -> tuple[dict[str, Any] | None, str | None]:
"""
Process the context and template_name using the configured pipeline steps to modify the course about rendering.

Expand Down Expand Up @@ -745,7 +745,7 @@ def __init__(self, message: str, response: Optional[HttpResponse] = None) -> Non
)

@classmethod
def run_filter(cls, context: dict, template_name: str) -> tuple[dict, str]:
def run_filter(cls, context: dict[str, Any], template_name: str) -> tuple[dict[str, Any] | None, str | None]:
"""
Process the context and template_name using the configured pipeline steps to modify the dashboard rendering.

Expand Down Expand Up @@ -790,7 +790,7 @@ class PreventChildBlockRender(OpenEdxFilterException):
"""

@classmethod
def run_filter(cls, block: Any, context: dict) -> tuple[Any, dict]:
def run_filter(cls, block: Any, context: dict[str, Any]) -> tuple[Any, dict[str, Any] | None]:
"""
Process the block and context using the configured pipeline steps to modify the rendering of a child block.

Expand Down Expand Up @@ -833,7 +833,7 @@ class PreventEnrollmentQuerysetRequest(OpenEdxFilterException):
"""

@classmethod
def run_filter(cls, enrollments: QuerySet) -> QuerySet:
def run_filter(cls, enrollments: QuerySet) -> QuerySet | None:
"""
Process the enrollments QuerySet using the configured pipeline steps to modify the course enrollment data.

Expand Down Expand Up @@ -891,7 +891,11 @@ def __init__(self, message: str, response: Optional[HttpResponse] = None):
super().__init__(message, response=response)

@classmethod
def run_filter(cls, context: dict, student_view_context: dict):
def run_filter(
cls,
context: dict[str, Any],
student_view_context: dict
) -> tuple[dict[str, Any] | None, dict[str, Any] | None]:
"""
Process the inputs using the configured pipeline steps to modify the rendering of an XBlock.

Expand Down Expand Up @@ -936,7 +940,13 @@ class PreventVerticalBlockRender(OpenEdxFilterException):
"""

@classmethod
def run_filter(cls, block: Any, fragment: Any, context: dict, view: str) -> tuple[Any, Any, dict, str]:
def run_filter(
cls,
block: Any,
fragment: Any,
context: dict[str, Any],
view: str
) -> tuple[Any, Any, dict[str, Any] | None, str | None]:
"""
Process the inputs using the configured pipeline steps to modify the rendering of a vertical block.

Expand Down Expand Up @@ -976,7 +986,7 @@ class CourseHomeUrlCreationStarted(OpenEdxPublicFilter):
filter_type = "org.openedx.learning.course.homepage.url.creation.started.v1"

@classmethod
def run_filter(cls, course_key: CourseKey, course_home_url: str) -> tuple[CourseKey, str]:
def run_filter(cls, course_key: CourseKey, course_home_url: str) -> tuple[CourseKey | None, str | None]:
"""
Process the course_key and course_home_url using the configured pipeline steps to modify the course home url.

Expand Down Expand Up @@ -1013,7 +1023,11 @@ class CourseEnrollmentAPIRenderStarted(OpenEdxPublicFilter):
filter_type = "org.openedx.learning.home.enrollment.api.rendered.v1"

@classmethod
def run_filter(cls, course_key: CourseKey, serialized_enrollment: dict) -> tuple[CourseKey, dict]:
def run_filter(
cls,
course_key: CourseKey,
serialized_enrollment: dict[str, Any]
) -> tuple[CourseKey | None, dict[str, Any] | None]:
"""
Process the inputs using the configured pipeline steps to modify the course enrollment data.

Expand Down Expand Up @@ -1050,7 +1064,7 @@ class CourseRunAPIRenderStarted(OpenEdxPublicFilter):
filter_type = "org.openedx.learning.home.courserun.api.rendered.started.v1"

@classmethod
def run_filter(cls, serialized_courserun: dict) -> dict:
def run_filter(cls, serialized_courserun: dict[str, Any]) -> dict[str, Any] | None:
"""
Process the serialized_courserun using the configured pipeline steps to modify the course run data.

Expand Down Expand Up @@ -1145,7 +1159,7 @@ def __init__(self, message: str, response: Optional[HttpResponse] = None):
)

@classmethod
def run_filter(cls, context: dict, template_name: str) -> tuple[dict, str]:
def run_filter(cls, context: dict[str, Any], template_name: str) -> tuple[dict[str, Any] | None, str | None]:
"""
Process the context and template_name using the configured pipeline steps to modify the instructor dashboard.

Expand Down Expand Up @@ -1203,7 +1217,7 @@ def __init__(
super().__init__(message, context=context, template_name=template_name)

@classmethod
def run_filter(cls, context: dict, template_name: str) -> tuple[dict, str]:
def run_filter(cls, context: dict[str, Any], template_name: str) -> tuple[dict[str, Any] | None, str | None]:
"""
Process the context and template_name using the configured pipeline steps to modify the submission view.

Expand Down Expand Up @@ -1240,7 +1254,7 @@ class IDVPageURLRequested(OpenEdxPublicFilter):
filter_type = "org.openedx.learning.idv.page.url.requested.v1"

@classmethod
def run_filter(cls, url: str) -> str:
def run_filter(cls, url: str) -> str | None:
"""
Process the URL using the configured pipeline steps to modify the ID verification page URL.

Expand Down Expand Up @@ -1274,7 +1288,7 @@ class CourseAboutPageURLRequested(OpenEdxPublicFilter):
filter_type = "org.openedx.learning.course_about.page.url.requested.v1"

@classmethod
def run_filter(cls, url: str, org: str) -> tuple[str, str]:
def run_filter(cls, url: str, org: str) -> tuple[str | None, str | None]:
"""
Process the URL and org using the configured pipeline steps to modify the course about page URL.

Expand Down Expand Up @@ -1312,7 +1326,7 @@ class ScheduleQuerySetRequested(OpenEdxPublicFilter):
filter_type = "org.openedx.learning.schedule.queryset.requested.v1"

@classmethod
def run_filter(cls, schedules: QuerySet) -> QuerySet:
def run_filter(cls, schedules: QuerySet) -> QuerySet | None:
"""
Process the schedules QuerySet using the configured pipeline steps to modify the schedules data.

Expand Down
3 changes: 2 additions & 1 deletion openedx_filters/learning/tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"""
from unittest.mock import Mock, patch

from ddt import data, ddt, unpack
# Ignore the type error for ddt import since it is not recognized by mypy.
from ddt import data, ddt, unpack # type: ignore
from django.test import TestCase

from openedx_filters.learning.filters import (
Expand Down
3 changes: 2 additions & 1 deletion openedx_filters/tests/test_tooling.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"""
from unittest.mock import Mock, patch

import ddt
# Ignore the type error for ddt import since it is not recognized by mypy.
import ddt # type: ignore
from django.test import TestCase, override_settings

from openedx_filters import PipelineStep
Expand Down
15 changes: 9 additions & 6 deletions openedx_filters/tooling.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Tooling necessary to use Open edX Filters.
"""
from logging import getLogger
from typing import Any

from django.conf import settings
from django.utils.module_loading import import_string
Expand All @@ -18,14 +19,14 @@ class OpenEdxPublicFilter:

filter_type = ""

def __repr__(self):
def __repr__(self) -> str:
"""
Represent OpenEdxPublicFilter as a string.
"""
return "<OpenEdxPublicFilter: {filter_type}>".format(filter_type=self.filter_type)

@classmethod
def get_steps_for_pipeline(cls, pipeline, fail_silently):
def get_steps_for_pipeline(cls, pipeline: list, fail_silently: bool = True) -> list[type]:
"""
Get pipeline objects from paths.

Expand Down Expand Up @@ -68,7 +69,7 @@ def get_steps_for_pipeline(cls, pipeline, fail_silently):
return step_list

@classmethod
def get_pipeline_configuration(cls):
def get_pipeline_configuration(cls) -> tuple[list[str], bool, dict[str, Any]]:
"""
Get pipeline configuration from filter settings.

Expand Down Expand Up @@ -97,7 +98,9 @@ def get_pipeline_configuration(cls):
"""
filter_config = cls.get_filter_config()

pipeline, fail_silently, extra_config = [], True, {}
pipeline: list = []
fail_silently: bool = True
extra_config: dict = {}

if not filter_config:
return pipeline, fail_silently, extra_config
Expand All @@ -119,7 +122,7 @@ def get_pipeline_configuration(cls):
return pipeline, fail_silently, extra_config

@classmethod
def get_filter_config(cls):
def get_filter_config(cls) -> dict[str, Any]:
"""
Get filters configuration from settings.

Expand Down Expand Up @@ -161,7 +164,7 @@ def get_filter_config(cls):
return filters_config.get(cls.filter_type, {})

@classmethod
def run_pipeline(cls, **kwargs):
def run_pipeline(cls, **kwargs: Any) -> dict[str, Any] | Any:
"""
Execute filters in order.

Expand Down
9 changes: 6 additions & 3 deletions openedx_filters/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@
"""


from django.http import QueryDict


class SensitiveDataManagementMixin:
"""
Custom class used manage sensitive data within filter arguments.
"""

sensitive_form_data = []
sensitive_form_data: list[str] = []

@classmethod
def extract_sensitive_data(cls, form_data):
def extract_sensitive_data(cls, form_data: QueryDict) -> dict[str, str]:
"""
Extract sensitive data from its child class input arguments.

Expand All @@ -30,6 +33,6 @@ def extract_sensitive_data(cls, form_data):
for key, value in base_form_data.items():
if key in cls.sensitive_form_data:
form_data.pop(key)
sensitive_data[key] = value
sensitive_data[key] = str(value)

return sensitive_data
Loading