Course Blocks API: Support accessing a substructure MA-1604

This commit is contained in:
Nimisha Asthagiri
2016-02-18 01:32:26 -05:00
parent 080b7d7bbd
commit d969f48646
8 changed files with 91 additions and 30 deletions

View File

@@ -102,6 +102,21 @@ class BlockStructure(object):
"""
return self._block_relations[usage_key].children if self.has_block(usage_key) else []
def set_root_block(self, usage_key):
"""
Sets the given usage key as the new root of the block structure.
Note: This method does *not* prune the rest of the structure. For
performance reasons, it is left to the caller to decide when exactly
to prune.
Arguments:
usage_key - The usage key of the block that is to be set as the
new root of the block structure.
"""
self.root_block_usage_key = usage_key
self._block_relations[usage_key].parents = []
def has_block(self, usage_key):
"""
Returns whether a block with the given usage_key is in this

View File

@@ -1,5 +1,5 @@
"""
Application-specific exceptions raised by the block cache framework.
Application-specific exceptions raised by the block structure framework.
"""
@@ -8,3 +8,10 @@ class TransformerException(Exception):
Exception class for Transformer related errors.
"""
pass
class UsageKeyNotInBlockStructure(Exception):
"""
Exception for when a usage key is not found within a block structure.
"""
pass

View File

@@ -2,8 +2,9 @@
Top-level module for the Block Structure framework with a class for managing
BlockStructures.
"""
from .factory import BlockStructureFactory
from .cache import BlockStructureCache
from .factory import BlockStructureFactory
from .exceptions import UsageKeyNotInBlockStructure
from .transformers import BlockStructureTransformers
@@ -30,23 +31,39 @@ class BlockStructureManager(object):
self.modulestore = modulestore
self.block_structure_cache = BlockStructureCache(cache)
def get_transformed(self, transformers):
def get_transformed(self, transformers, starting_block_usage_key=None):
"""
Returns the transformed Block Structure for the root_block_usage_key,
getting block data from the cache and modulestore, as needed.
starting at starting_block_usage_key, getting block data from the cache
and modulestore, as needed.
Details: Same as the get_collected method, except the transformers'
Details: Similar to the get_collected method, except the transformers'
transform methods are also called.
Arguments:
transformers (BlockStructureTransformers) - Collection of
transformers to apply.
starting_block_usage_key (UsageKey) - Specifies the starting block
in the block structure that is to be transformed.
If None, root_block_usage_key is used.
Returns:
BlockStructureBlockData - A transformed block structure,
starting at self.root_block_usage_key.
starting at starting_block_usage_key.
"""
block_structure = self.get_collected()
if starting_block_usage_key:
# Override the root_block_usage_key so traversals start at the
# requested location. The rest of the structure will be pruned
# as part of the transformation.
if not block_structure.has_block(starting_block_usage_key):
raise UsageKeyNotInBlockStructure(
"The requested usage_key '{0}' is not found in the block_structure with root '{1}'",
unicode(starting_block_usage_key),
unicode(self.root_block_usage_key),
)
block_structure.set_root_block(starting_block_usage_key)
transformers.transform(block_structure)
return block_structure

View File

@@ -3,6 +3,7 @@ Tests for manager.py
"""
from unittest import TestCase
from ..exceptions import UsageKeyNotInBlockStructure
from ..manager import BlockStructureManager
from ..transformers import BlockStructureTransformers
from .helpers import (
@@ -127,6 +128,19 @@ class TestBlockStructureManager(TestCase, ChildrenMapTestMixin):
TestTransformer1.assert_collected(block_structure)
TestTransformer1.assert_transformed(block_structure)
def test_get_transformed_with_starting_block(self):
with mock_registered_transformers(self.registered_transformers):
block_structure = self.bs_manager.get_transformed(self.transformers, starting_block_usage_key=1)
substructure_of_children_map = [[], [3, 4], [], [], []]
self.assert_block_structure(block_structure, substructure_of_children_map, missing_blocks=[0, 2])
TestTransformer1.assert_collected(block_structure)
TestTransformer1.assert_transformed(block_structure)
def test_get_transformed_with_nonexistent_starting_block(self):
with mock_registered_transformers(self.registered_transformers):
with self.assertRaises(UsageKeyNotInBlockStructure):
self.bs_manager.get_transformed(self.transformers, starting_block_usage_key=100)
def test_get_collected_cached(self):
self.collect_and_verify(expect_modulestore_called=True, expect_cache_updated=True)
self.collect_and_verify(expect_modulestore_called=False, expect_cache_updated=False)