Commit fcbc8446 by E. Kolpakov

Problem type filtering on `update_children` event

parent 66874aca
......@@ -2,10 +2,12 @@
import json
import logging
import sys
from lxml import etree
from pkg_resources import resource_string
from .capa_base import CapaMixin, CapaFields, ComplexEncoder
from capa import inputtypes
from .progress import Progress
from xmodule.x_module import XModule, module_attr
from xmodule.raw_module import RawDescriptor
......@@ -172,6 +174,13 @@ class CapaDescriptor(CapaFields, RawDescriptor):
])
return non_editable_fields
@property
def problem_types(self):
""" Low-level problem type introspection for content libraries filtering by problem type """
tree = etree.XML(self.data)
registered_tas = inputtypes.registry.registered_tags()
return set([node.tag for node in tree.iter() if node.tag in registered_tas])
# Proxy to CapaModule for access to any of its attributes
answer_available = module_attr('answer_available')
check_button_name = module_attr('check_button_name')
......
......@@ -222,23 +222,6 @@ class LibraryContentModule(LibraryContentFields, XModule, StudioEditableModule):
as children of this block, but only a subset of those children are shown to
any particular student.
"""
def _filter_children(self, child_locator):
"""
Filters children by CAPA problem type, if configured
"""
if self.capa_type == ANY_CAPA_TYPE_VALUE:
return True
if child_locator.block_type != CAPA_BLOCK_TYPE:
return False
block = self.runtime.get_block(child_locator)
if not hasattr(block, 'lcp'):
return True
return any(self.capa_type in capa_input.tags for capa_input in block.lcp.inputs.values())
def selected_children(self):
"""
Returns a set() of block_ids indicating which of the possible children
......@@ -255,7 +238,7 @@ class LibraryContentModule(LibraryContentFields, XModule, StudioEditableModule):
return self._selected_set # pylint: disable=access-member-before-definition
# Determine which of our children we will show:
selected = set(tuple(k) for k in self.selected) # set of (block_type, block_id) tuples
valid_block_keys = set([(c.block_type, c.block_id) for c in self.children if self._filter_children(c)]) # pylint: disable=no-member
valid_block_keys = set([(c.block_type, c.block_id) for c in self.children]) # pylint: disable=no-member
# Remove any selected blocks that are no longer valid:
selected -= (selected - valid_block_keys)
# If max_count has been decreased, we may have to drop some previously selected blocks:
......
......@@ -5,8 +5,9 @@ import hashlib
from django.core.exceptions import PermissionDenied
from opaque_keys.edx.locator import LibraryLocator
from xblock.fields import Scope
from xmodule.library_content_module import LibraryVersionReference
from xmodule.library_content_module import LibraryVersionReference, ANY_CAPA_TYPE_VALUE
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.capa_module import CapaDescriptor
class LibraryToolsService(object):
......@@ -45,6 +46,18 @@ class LibraryToolsService(object):
return library.location.library_key.version_guid
return None
def _filter_child(self, dest_block, child_descriptor):
"""
Filters children by CAPA problem type, if configured
"""
if dest_block.capa_type == ANY_CAPA_TYPE_VALUE:
return True
if not isinstance(child_descriptor, CapaDescriptor):
return False
return dest_block.capa_type in child_descriptor.problem_types
def update_children(self, dest_block, user_id, user_perms=None, update_db=True):
"""
This method is to be used when any of the libraries that a LibraryContentModule
......@@ -91,13 +104,16 @@ class LibraryToolsService(object):
new_libraries = []
for library_key, library in libraries:
def copy_children_recursively(from_block):
def copy_children_recursively(from_block, filter_problem_type=True):
"""
Internal method to copy blocks from the library recursively
"""
new_children = []
for child_key in from_block.children:
child = self.store.get_item(child_key, depth=9)
if filter_problem_type and not self._filter_child(dest_block, child):
continue
# We compute a block_id for each matching child block found in the library.
# block_ids are unique within any branch, but are not unique per-course or globally.
# We need our block_ids to be consistent when content in the library is updated, so
......@@ -125,7 +141,7 @@ class LibraryToolsService(object):
)
new_children.append(new_child_info.location)
return new_children
root_children.extend(copy_children_recursively(from_block=library))
root_children.extend(copy_children_recursively(from_block=library, filter_problem_type=True))
new_libraries.append(LibraryVersionReference(library_key, library.location.library_key.version_guid))
dest_block.source_libraries = new_libraries
dest_block.children = root_children
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment