I wanted to post here some of my findings on running mypy on edx-platform. I recently added type checks to Tutor, which has allowed me to detect quite a few non-trivial bugs. Now that the Tutor code base is fully typed, I feel more confident when refactoring code or adding features. I think the Tutor code is more readable, too.
I recently noticed that some people ( @kmccormick) have started adding type annotations to edx-platform, and I think that’s great. However, mypy is not currently run as part of the edx-platform test suite. I think it would be great to do just that so I played with the mypy CLI a little. I thought it might be interesting to post here the result of running mypy on edx-platform/openedx/core
:
$ mypy --follow-imports=silent --ignore-missing-imports --allow-untyped-globals --exclude=tests openedx/core/
openedx/core/lib/blockstore_api/models.py:22: error: Unsupported converter, only named functions and types are currently supported
openedx/core/lib/blockstore_api/models.py:31: error: Unsupported converter, only named functions and types are currently supported
openedx/core/lib/blockstore_api/models.py:45: error: Unsupported converter, only named functions and types are currently supported
openedx/core/lib/blockstore_api/models.py:46: error: Unsupported converter, only named functions and types are currently supported
openedx/core/lib/blockstore_api/models.py:77: error: Unsupported converter, only named functions and types are currently supported
openedx/core/djangoapps/content/learning_sequences/data.py:177: error: Need type annotation for 'course_visibility'
openedx/core/djangoapps/content/learning_sequences/data.py:305: error: Variable "openedx.core.djangoapps.content.learning_sequences.data.User" is not valid as a type
openedx/core/djangoapps/content/learning_sequences/data.py:305: note: See https://mypy.readthedocs.io/en/latest/common_issues.html#variables-vs-type-aliases
openedx/core/djangoapps/content/learning_sequences/api/processors/base.py:36: error: Variable "openedx.core.djangoapps.content.learning_sequences.api.processors.base.User" is not valid as a type
openedx/core/djangoapps/content/learning_sequences/api/processors/base.py:36: note: See https://mypy.readthedocs.io/en/latest/common_issues.html#variables-vs-type-aliases
openedx/core/djangoapps/content/learning_sequences/api/processors/special_exams.py:61: error: User? has no attribute "id"
openedx/core/djangoapps/user_api/admin.py:117: error: "Callable[[UserRetirementStatusAdmin, Any], Any]" has no attribute "short_description"
openedx/core/djangoapps/user_api/admin.py:198: error: "Callable[[UserRetirementPartnerReportingStatusAdmin, Any, Any], Any]" has no attribute "short_description"
openedx/core/djangoapps/schedules/admin.py:53: error: "partial[Any]" has no attribute "short_description"
openedx/core/djangoapps/schedules/admin.py:54: error: "partial[Any]" has no attribute "__name__"
openedx/core/djangoapps/schedules/admin.py:139: error: "Callable[[ScheduleAdmin, Any], Any]" has no attribute "short_descriptions"
openedx/core/djangoapps/schedules/admin.py:148: error: "Callable[[ScheduleAdmin, Any], Any]" has no attribute "short_description"
openedx/core/djangoapps/schedules/admin.py:159: error: "Callable[[ScheduleAdmin, Any], Any]" has no attribute "short_description"
openedx/core/djangoapps/enrollments/serializers.py:103: error: Incompatible types in assignment (expression has type "Tuple[str, str, str, str, str, str]", base class "Meta" defined the type as "Tuple[str, str, str, str, str]")
openedx/core/djangoapps/discussions/models.py:85: error: Incompatible types in assignment (expression has type "Tuple[str, str, str]", base class "StackedConfigurationModel" defined the type as "Tuple[str]")
openedx/core/djangoapps/discussions/models.py:194: error: Name 'cls' is not defined
openedx/core/djangoapps/content/learning_sequences/api/processors/schedule.py:36: error: Variable "openedx.core.djangoapps.content.learning_sequences.api.processors.schedule.User" is not valid as a type
openedx/core/djangoapps/content/learning_sequences/api/processors/schedule.py:36: note: See https://mypy.readthedocs.io/en/latest/common_issues.html#variables-vs-type-aliases
openedx/core/djangoapps/content/learning_sequences/api/processors/schedule.py:39: error: Need type annotation for 'keys_to_schedule_fields'
openedx/core/djangoapps/content/learning_sequences/api/processors/content_gating.py:24: error: Variable "openedx.core.djangoapps.content.learning_sequences.api.processors.content_gating.User" is not valid as a type
openedx/core/djangoapps/content/learning_sequences/api/processors/content_gating.py:24: note: See https://mypy.readthedocs.io/en/latest/common_issues.html#variables-vs-type-aliases
openedx/core/djangoapps/xblock/runtime/runtime.py:376: error: Name 'Callable' is not defined
openedx/core/djangoapps/xblock/runtime/runtime.py:376: note: Did you forget to import it from "typing"? (Suggestion: "from typing import Callable")
openedx/core/djangoapps/xblock/runtime/runtime.py:376: error: Name 'UsageKey' is not defined
openedx/core/djangoapps/xblock/runtime/runtime.py:376: error: Name 'Union' is not defined
openedx/core/djangoapps/xblock/runtime/runtime.py:376: note: Did you forget to import it from "typing"? (Suggestion: "from typing import Union")
openedx/core/djangoapps/xblock/runtime/runtime.py:376: error: Name 'ANONYMOUS_USER' is not defined
openedx/core/djangoapps/xblock/runtime/runtime.py:377: error: Name 'Union' is not defined
openedx/core/djangoapps/xblock/runtime/runtime.py:377: note: Did you forget to import it from "typing"? (Suggestion: "from typing import Union")
openedx/core/djangoapps/xblock/runtime/runtime.py:402: error: Need type annotation for '_error_trackers' (hint: "_error_trackers: Dict[<type>, <type>] = ...")
openedx/core/djangoapps/discussions/admin.py:79: error: Incompatible types in assignment (expression has type "Tuple[str, str]", base class "StackedConfigModelAdmin" defined the type as "Tuple[str, str, str, str]")
openedx/core/djangoapps/content/learning_sequences/api/outlines.py:233: error: Variable "openedx.core.djangoapps.content.learning_sequences.api.outlines.User" is not valid as a type
openedx/core/djangoapps/content/learning_sequences/api/outlines.py:233: note: See https://mypy.readthedocs.io/en/latest/common_issues.html#variables-vs-type-aliases
openedx/core/djangoapps/content/learning_sequences/api/outlines.py:250: error: Variable "openedx.core.djangoapps.content.learning_sequences.api.outlines.User" is not valid as a type
openedx/core/djangoapps/content/learning_sequences/api/outlines.py:250: note: See https://mypy.readthedocs.io/en/latest/common_issues.html#variables-vs-type-aliases
openedx/core/djangoapps/content/learning_sequences/api/outlines.py:272: error: Variable "openedx.core.djangoapps.content.learning_sequences.api.outlines.User" is not valid as a type
openedx/core/djangoapps/content/learning_sequences/api/outlines.py:272: note: See https://mypy.readthedocs.io/en/latest/common_issues.html#variables-vs-type-aliases
openedx/core/djangoapps/content/learning_sequences/api/outlines.py:285: error: User? has no attribute "id"
openedx/core/djangoapps/schedules/tasks.py:195: error: Cannot assign to a type
openedx/core/djangoapps/schedules/tasks.py:209: error: Cannot assign to a type
openedx/core/djangoapps/schedules/tasks.py:223: error: Cannot assign to a type
openedx/core/djangoapps/schedules/tasks.py:270: error: Cannot assign to a type
openedx/core/djangoapps/content/learning_sequences/admin.py:87: error: "Callable[[CourseSectionSequenceInline, Any], Any]" has no attribute "short_description"
openedx/core/djangoapps/content/learning_sequences/admin.py:91: error: "Callable[[CourseSectionSequenceInline, Any], Any]" has no attribute "boolean"
openedx/core/djangoapps/content/learning_sequences/admin.py:95: error: "Callable[[CourseSectionSequenceInline, Any], Any]" has no attribute "boolean"
openedx/core/djangoapps/content/learning_sequences/admin.py:96: error: "Callable[[CourseSectionSequenceInline, Any], Any]" has no attribute "short_description"
openedx/core/djangoapps/content/learning_sequences/admin.py:100: error: "Callable[[CourseSectionSequenceInline, Any], Any]" has no attribute "boolean"
openedx/core/djangoapps/content/learning_sequences/admin.py:101: error: "Callable[[CourseSectionSequenceInline, Any], Any]" has no attribute "short_description"
openedx/core/djangoapps/content/learning_sequences/admin.py:105: error: "Callable[[CourseSectionSequenceInline, Any], Any]" has no attribute "boolean"
openedx/core/djangoapps/content/learning_sequences/admin.py:106: error: "Callable[[CourseSectionSequenceInline, Any], Any]" has no attribute "short_description"
openedx/core/djangoapps/content/learning_sequences/admin.py:110: error: "Callable[[CourseSectionSequenceInline, Any], Any]" has no attribute "boolean"
openedx/core/djangoapps/content/learning_sequences/admin.py:111: error: "Callable[[CourseSectionSequenceInline, Any], Any]" has no attribute "short_description"
openedx/core/djangoapps/content/learning_sequences/admin.py:204: error: "Callable[[CourseContextAdmin, Any], Any]" has no attribute "short_description"
openedx/core/djangoapps/content/learning_sequences/admin.py:208: error: "Callable[[CourseContextAdmin, Any], Any]" has no attribute "short_description"
openedx/core/djangoapps/content/learning_sequences/admin.py:219: error: "Callable[[CourseContextAdmin, Any], Any]" has no attribute "short_description"
openedx/core/djangoapps/content/learning_sequences/admin.py:232: error: "Callable[[CourseContextAdmin, Any], Any]" has no attribute "short_description"
openedx/core/djangoapps/content/learning_sequences/admin.py:236: error: "Callable[[CourseContextAdmin, Any], Any]" has no attribute "short_description"
openedx/core/djangoapps/content/learning_sequences/admin.py:240: error: "Callable[[CourseContextAdmin, Any], Any]" has no attribute "short_description"
openedx/core/djangoapps/schedules/management/commands/send_upgrade_reminder.py:19: error: Incompatible types in assignment (expression has type "Tuple[int]", base class "SendEmailBaseCommand" defined the type as "range")
openedx/core/djangoapps/schedules/management/commands/send_recurring_nudge.py:19: error: Incompatible types in assignment (expression has type "Tuple[int, int]", base class "SendEmailBaseCommand" defined the type as "range")
openedx/core/djangoapps/content_libraries/api.py:224: error: Name 'AccessLevel' already defined on line 152
Found 56 errors in 18 files (checked 915 source files)
Thoughts?