Skip to content

Commit e7ed235

Browse files
committed
feat!: Assume that scope IDs are opaque key objects (WIP)
TODO: Bumps XBlock version to 6.0.0 Part of: #708
1 parent 306889d commit e7ed235

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

xblock/core.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,7 @@ def __init__(
799799
"""
800800
if scope_ids is UNSET:
801801
raise TypeError('scope_ids are required')
802+
scope_ids.validate_types()
802803

803804
# A cache of the parent block, retrieved from .parent
804805
self._parent_block = None

xblock/fields.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
**scopes** to associate each field with particular sets of blocks and users.
44
The hosting runtime application decides what actual storage mechanism to use
55
for each scope.
6-
76
"""
7+
from __future__ import annotations
8+
89
from collections import namedtuple
910
import copy
1011
import datetime
@@ -15,6 +16,8 @@
1516
import traceback
1617
import warnings
1718

19+
from opaque_keys.edx.keys import UsageKey, DefinitionKey
20+
1821
import dateutil.parser
1922
from lxml import etree
2023
import pytz
@@ -242,6 +245,27 @@ class ScopeIds(namedtuple('ScopeIds', 'user_id block_type def_id usage_id')):
242245
"""
243246
__slots__ = ()
244247

248+
def validate_types(self):
249+
"""
250+
Raise an AssertionError if any of the ids are an unexpected type.
251+
252+
Originally, these fields were all freely-typed; but in practice,
253+
edx-platform's XBlock runtime would fail if the ids did not match the
254+
types below. In order to make the XBlock library reflect the
255+
edx-platform reality and improve type-safety, we've decided to actually
256+
enforce the types here, per:
257+
https://github.com/openedx/XBlock/issues/708
258+
"""
259+
if self.user_id is not None:
260+
if not isinstance(self.user_id, (int, str)):
261+
raise TypeError(f"got {self.user_id=}; should be an int, str, or None")
262+
if not isinstance(self.block_type, str):
263+
raise TypeError(f"got {self.block_type=}; should be a str")
264+
if not isinstance(self.def_id, DefinitionKey):
265+
raise TypeError(f"got {self.def_id=}; should be a DefinitionKey")
266+
if not isinstance(self.usage_id, UsageKey):
267+
raise TypeError(f"got {self.usage_id=}; should be a UsageKey")
268+
245269

246270
# Define special reference that can be used as a field's default in field
247271
# definition to signal that the field should default to a unique string value

0 commit comments

Comments
 (0)