Skip to content

Commit 0330c66

Browse files
committed
feat!: annotate types
WIP: annotate xblock/runtime.py WIP: remove XBlock mixin from hierarchy, just use asserts, for backcompat? WIP: DEPR non-string usage and definition keys? BREAKING CHANGE: [Developers only] Type-checked Python code using the XBlock API will likely need to be updated in order to continue passing type-checking, since XBlock's new annotations will trigger mypy (et al) to behave much more strictly. NO BREAKING CHANGES for site operators, authors, learners, etc.
1 parent 22c18de commit 0330c66

27 files changed

+970
-630
lines changed

CHANGELOG.rst

+5-1
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@ Change history for XBlock
55
Unreleased
66
----------
77

8+
6.0.0 - 2024-08-20
9+
------------------
10+
11+
* added type hints to all public classes, methods, and functions
12+
813
5.1.0 - 2024-08-07
914
------------------
1015

1116
* added ability to override an XBlock with the 'xblock.v1.overrides' entry point
1217
* added ability to override an XBlock Aside with the 'xblock_asides.v1.overrides' entry point
1318

14-
1519
5.0.0 - 2024-05-30
1620
------------------
1721

docs/conf.py

+39-8
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,6 @@
1717

1818
import django
1919

20-
MOCK_MODULES = [
21-
'webob',
22-
'lxml'
23-
]
24-
25-
for mod_name in MOCK_MODULES:
26-
sys.modules[mod_name] = mock.Mock(class_that_is_extended=object)
27-
2820

2921
# If extensions (or modules to document with autodoc) are in another directory,
3022
# add these directories to sys.path here. If the directory is relative to the
@@ -111,6 +103,11 @@
111103
# A list of ignored prefixes for module index sorting.
112104
#modindex_common_prefix = []
113105

106+
# Display the type hints in the docs as part of the function signature.
107+
# This is the default, but it could be changed to "description" or "both".
108+
# https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#confval-autodoc_typehints
109+
autodoc_typehints = "signature"
110+
114111
# When auto-doc'ing a class, write the class' docstring and the __init__ docstring
115112
# into the class docs.
116113
autoclass_content = "both"
@@ -129,6 +126,40 @@
129126
('py:class', 'aside_fn'),
130127
('py:class', 'webob.Request'),
131128
('py:class', 'webob.Response'),
129+
('py:class', 'webob.request.Request'),
130+
('py:class', 'webob.response.Response'),
131+
('py:class', 'lxml.etree._Element'),
132+
# As of Sphinx==8.0.2 and Python 3.11, its seems that Sphinx has bug(s) that make it
133+
# unable to consistently recognize classes in otherwise-valid type annotations. So, since
134+
# adding type hints to XBlock, we've had to add this big list of warning suppressions.
135+
# If you're reading this in the future with newer versions of Sphinx and/or Python, feel
136+
# free to try to whittle down this list:
137+
('py:class', 'Blocklike'),
138+
('py:class', 'BlocklikeSubclass'),
139+
('py:class', 'DefinitionKey'),
140+
('py:class', 'FieldValue'),
141+
('py:class', 'InnerFieldValue'),
142+
('py:class', 'Request'),
143+
('py:class', 'Response'),
144+
('py:class', 'UniqueIdPlaceholder'),
145+
('py:class', 'Unset'),
146+
('py:class', 'UsageKey'),
147+
('py:class', 'etree._Element'),
148+
('py:class', 'importlib.metadata.EntryPoint'),
149+
('py:class', 'importlib.metadata.EntryPoint'),
150+
('py:class', 'opaque_keys.edx.keys.DefinitionKey'),
151+
('py:class', 'opaque_keys.edx.keys.LearningContextKey'),
152+
('py:class', 'opaque_keys.edx.keys.UsageKey'),
153+
('py:class', 't.Any'),
154+
('py:class', 't.Callable'),
155+
('py:class', 't.Iterable'),
156+
('py:class', 'web_fragments.fragment.Fragment'),
157+
('py:class', 'xblock.core.Blocklike'),
158+
('py:class', 'xblock.fields.FieldValue'),
159+
('py:class', 'xblock.fields.InnerFieldValue'),
160+
('py:class', 'xblock.fields.UniqueIdPlaceholder'),
161+
('py:class', 'xblock.fields.Unset'),
162+
('py:class', 'xblock.validation.Validation'),
132163
]
133164

134165
suppress_warnings = [

mypy.ini

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ ignore_missing_imports = False
44
allow_untyped_globals = False
55
files =
66
xblock
7+
exclude =
8+
xblock.test
79

810
# Ignore web_fragments typing until it has hints.
911
[mypy-web_fragments.*]

xblock/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
XBlock Courseware Components
33
"""
44

5-
__version__ = '5.1.0'
5+
__version__ = '6.0.0'

xblock/completable.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""
22
This module defines CompletableXBlockMixin and completion mode enumeration.
33
"""
4+
from xblock.core import Blocklike, XBlockMixin
45

56

67
class XBlockCompletionMode:
@@ -12,7 +13,7 @@ class XBlockCompletionMode:
1213
EXCLUDED = "excluded"
1314

1415
@classmethod
15-
def get_mode(cls, block_class):
16+
def get_mode(cls, block_class: Blocklike | type[Blocklike]) -> str:
1617
"""
1718
Return the effective completion mode for a given block.
1819
@@ -21,17 +22,17 @@ def get_mode(cls, block_class):
2122
return getattr(block_class, 'completion_mode', cls.COMPLETABLE)
2223

2324

24-
class CompletableXBlockMixin:
25+
class CompletableXBlockMixin(XBlockMixin):
2526
"""
2627
This mixin sets attributes and provides helper method to integrate XBlock with Completion API.
2728
"""
2829

29-
has_custom_completion = True
30-
completion_mode = XBlockCompletionMode.COMPLETABLE
30+
has_custom_completion: bool = True
31+
completion_mode: str = XBlockCompletionMode.COMPLETABLE
3132

3233
# To read more on the debate about using the terms percent vs ratio, see:
3334
# https://openedx.atlassian.net/wiki/spaces/OpenDev/pages/245465398/Naming+with+Percent+or+Ratio
34-
def emit_completion(self, completion_percent):
35+
def emit_completion(self, completion_percent: float) -> None:
3536
"""
3637
Emits completion event through Completion API.
3738

0 commit comments

Comments
 (0)