Transformer: BlockDepthTransformer
This commit is contained in:
committed by
J. Cliff Dyer
parent
75a2355b74
commit
9abebe0599
63
lms/djangoapps/course_api/blocks/transformers/block_depth.py
Normal file
63
lms/djangoapps/course_api/blocks/transformers/block_depth.py
Normal file
@@ -0,0 +1,63 @@
|
||||
"""
|
||||
Block Depth Transformer
|
||||
"""
|
||||
from openedx.core.lib.block_cache.transformer import BlockStructureTransformer
|
||||
|
||||
|
||||
class BlockDepthTransformer(BlockStructureTransformer):
|
||||
"""
|
||||
Keep track of the depth of each block within the block structure. In case
|
||||
of multiple paths to a given node (in a DAG), use the shallowest depth.
|
||||
"""
|
||||
VERSION = 1
|
||||
BLOCK_DEPTH = 'block_depth'
|
||||
|
||||
def __init__(self, requested_depth=None):
|
||||
self.requested_depth = requested_depth
|
||||
|
||||
@classmethod
|
||||
def name(cls):
|
||||
return "blocks_api:block_depth"
|
||||
|
||||
@classmethod
|
||||
def get_block_depth(cls, block_structure, block_key):
|
||||
"""
|
||||
Return the precalculated depth of a block within the block_structure:
|
||||
|
||||
Arguments:
|
||||
block_structure: a BlockStructure instance
|
||||
block_key: the key of the block whose depth we want to know
|
||||
|
||||
Returns:
|
||||
int
|
||||
"""
|
||||
return block_structure.get_transformer_block_field(
|
||||
block_key,
|
||||
cls,
|
||||
cls.BLOCK_DEPTH,
|
||||
)
|
||||
|
||||
def transform(self, usage_info, block_structure): # pylint: disable=unused-argument
|
||||
"""
|
||||
Mutates block_structure based on the given usage_info.
|
||||
"""
|
||||
for block_key in block_structure.topological_traversal():
|
||||
parents = block_structure.get_parents(block_key)
|
||||
if parents:
|
||||
block_depth = min(
|
||||
self.get_block_depth(block_structure, parent_key)
|
||||
for parent_key in parents
|
||||
) + 1
|
||||
else:
|
||||
block_depth = 0
|
||||
block_structure.set_transformer_block_field(
|
||||
block_key,
|
||||
self,
|
||||
self.BLOCK_DEPTH,
|
||||
block_depth
|
||||
)
|
||||
|
||||
if self.requested_depth is not None:
|
||||
block_structure.remove_block_if(
|
||||
lambda block_key: self.get_block_depth(block_structure, block_key) > self.requested_depth
|
||||
)
|
||||
@@ -0,0 +1,40 @@
|
||||
"""
|
||||
Tests for BlockDepthTransformer.
|
||||
"""
|
||||
|
||||
# pylint: disable=protected-access
|
||||
|
||||
import ddt
|
||||
from unittest import TestCase
|
||||
|
||||
from openedx.core.lib.block_cache.tests.test_utils import ChildrenMapTestMixin
|
||||
from openedx.core.lib.block_cache.block_structure import BlockStructureModulestoreData
|
||||
from ..block_depth import BlockDepthTransformer
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class BlockDepthTransformerTestCase(TestCase, ChildrenMapTestMixin):
|
||||
"""
|
||||
Test behavior of BlockDepthTransformer
|
||||
"""
|
||||
@ddt.data(
|
||||
(0, [], [], []),
|
||||
(0, ChildrenMapTestMixin.SIMPLE_CHILDREN_MAP, [[], [], [], [], []], [1, 2, 3, 4]),
|
||||
(1, ChildrenMapTestMixin.SIMPLE_CHILDREN_MAP, [[1, 2], [], [], [], []], [3, 4]),
|
||||
(2, ChildrenMapTestMixin.SIMPLE_CHILDREN_MAP, ChildrenMapTestMixin.SIMPLE_CHILDREN_MAP, []),
|
||||
(3, ChildrenMapTestMixin.SIMPLE_CHILDREN_MAP, ChildrenMapTestMixin.SIMPLE_CHILDREN_MAP, []),
|
||||
(None, ChildrenMapTestMixin.SIMPLE_CHILDREN_MAP, ChildrenMapTestMixin.SIMPLE_CHILDREN_MAP, []),
|
||||
|
||||
(0, ChildrenMapTestMixin.DAG_CHILDREN_MAP, [[], [], [], [], [], [], []], [1, 2, 3, 4, 5, 6]),
|
||||
(1, ChildrenMapTestMixin.DAG_CHILDREN_MAP, [[1, 2], [], [], [], [], [], []], [3, 4, 5, 6]),
|
||||
(2, ChildrenMapTestMixin.DAG_CHILDREN_MAP, [[1, 2], [3], [3, 4], [], [], [], []], [5, 6]),
|
||||
(3, ChildrenMapTestMixin.DAG_CHILDREN_MAP, ChildrenMapTestMixin.DAG_CHILDREN_MAP, []),
|
||||
(4, ChildrenMapTestMixin.DAG_CHILDREN_MAP, ChildrenMapTestMixin.DAG_CHILDREN_MAP, []),
|
||||
(None, ChildrenMapTestMixin.DAG_CHILDREN_MAP, ChildrenMapTestMixin.DAG_CHILDREN_MAP, []),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_block_depth(self, block_depth, children_map, transformed_children_map, missing_blocks):
|
||||
block_structure = self.create_block_structure(BlockStructureModulestoreData, children_map)
|
||||
BlockDepthTransformer(block_depth).transform(usage_info=None, block_structure=block_structure)
|
||||
block_structure._prune_unreachable()
|
||||
self.assert_block_structure(block_structure, transformed_children_map, missing_blocks)
|
||||
Reference in New Issue
Block a user