After we merged this PR: https://github.com/openedx/edx-platform/pull/33920 this error began popping up in logs: Unable to load XBlock 'staffgradedxblock' .... ImportError: cannot import name 'get_course_blocks' from partially initialized module 'lms.djangoapps.course_blocks.api' (most likely due to a circular import) ... The root cause was the new imports of `derived_key` and `BlockKey` into xmodule/library_content_block.py. Those new imports come from xmodule/modulestore/store_utilities.py, which runs `XBlock.load_classes()` at the module level, which fails because we are still in the process of loading xmodule/library_content_block. As a solution, we move both `derived_key` and `BlockKey` to xmodule/util/keys.py. We could potentially move that file to opaque-keys eventually, depending on how well we think that those concepts generalize. Also: * We rename the function from derived_key to derive_key, as functions should be verbs. * We combine the first to parameters of derive_key (a source ContextKey and a source BlockKey) into a single parameter (a source UsageKey). In my opinion, this makes the function call easier to understand.
46 lines
1.2 KiB
Python
46 lines
1.2 KiB
Python
"""
|
|
Tests for xmodule/util/keys.py
|
|
"""
|
|
import ddt
|
|
from unittest import TestCase
|
|
from unittest.mock import Mock
|
|
|
|
from opaque_keys.edx.locator import BlockUsageLocator
|
|
from opaque_keys.edx.keys import CourseKey
|
|
from xmodule.util.keys import BlockKey, derive_key
|
|
|
|
|
|
mock_block = Mock()
|
|
mock_block.id = CourseKey.from_string('course-v1:Beeper+B33P+BOOP')
|
|
|
|
derived_key_scenarios = [
|
|
{
|
|
'source': BlockUsageLocator.from_string(
|
|
'block-v1:edX+DemoX+Demo_Course+type@chapter+block@interactive_demonstrations'
|
|
),
|
|
'parent': mock_block,
|
|
'expected': BlockKey('chapter', '5793ec64e25ed870a7dd'),
|
|
},
|
|
{
|
|
'source': BlockUsageLocator.from_string(
|
|
'block-v1:edX+DemoX+Demo_Course+type@chapter+block@interactive_demonstrations'
|
|
),
|
|
'parent': BlockKey('chapter', 'thingy'),
|
|
'expected': BlockKey('chapter', '599792a5622d85aa41e6'),
|
|
}
|
|
]
|
|
|
|
|
|
@ddt.ddt
|
|
class TestDeriveKey(TestCase):
|
|
"""
|
|
Test reproducible block ID generation.
|
|
"""
|
|
@ddt.data(*derived_key_scenarios)
|
|
@ddt.unpack
|
|
def test_derive_key(self, source, parent, expected):
|
|
"""
|
|
Test that derive_key returns the expected value.
|
|
"""
|
|
assert derive_key(source, parent) == expected
|