fix: move BlockKey and derived_key to avoid cyclical import

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.
This commit is contained in:
Kyle D. McCormick
2024-01-12 16:38:56 -05:00
committed by Kyle McCormick
parent d772ed1519
commit e8b60aef60
8 changed files with 123 additions and 106 deletions

View File

@@ -2,17 +2,12 @@
Tests for store_utilities.py
"""
import unittest
from unittest import TestCase
from unittest.mock import Mock
import ddt
from opaque_keys.edx.keys import CourseKey
from xmodule.modulestore.split_mongo import BlockKey
from xmodule.modulestore.store_utilities import draft_node_constructor, get_draft_subtree_roots, derived_key
from xmodule.modulestore.store_utilities import draft_node_constructor, get_draft_subtree_roots
@ddt.ddt
@@ -86,43 +81,3 @@ class TestUtils(unittest.TestCase):
subtree_roots_urls = [root.url for root in get_draft_subtree_roots(block_nodes)]
# check that we return the expected urls
assert set(subtree_roots_urls) == set(expected_roots_urls)
mock_block = Mock()
mock_block.id = CourseKey.from_string('course-v1:Beeper+B33P+BOOP')
derived_key_scenarios = [
{
'courselike_source_key': CourseKey.from_string('course-v1:edX+DemoX+Demo_Course'),
'block_key': BlockKey('chapter', 'interactive_demonstrations'),
'parent': mock_block,
'expected': BlockKey(
'chapter', '5793ec64e25ed870a7dd',
),
},
{
'courselike_source_key': CourseKey.from_string('course-v1:edX+DemoX+Demo_Course'),
'block_key': BlockKey('chapter', 'interactive_demonstrations'),
'parent': BlockKey(
'chapter', 'thingy',
),
'expected': BlockKey(
'chapter', '599792a5622d85aa41e6',
),
}
]
@ddt.ddt
class TestDerivedKey(TestCase):
"""
Test reproducible block ID generation.
"""
@ddt.data(*derived_key_scenarios)
@ddt.unpack
def test_derived_key(self, courselike_source_key, block_key, parent, expected):
"""
Test that derived_key returns the expected value.
"""
self.assertEqual(derived_key(courselike_source_key, block_key, parent), expected)