""" Grades Transformer """ from django.test.client import RequestFactory from openedx.core.lib.block_structure.transformer import BlockStructureTransformer from openedx.core.djangoapps.util.user_utils import SystemUser from .. import module_render from courseware.model_data import FieldDataCache class GradesTransformer(BlockStructureTransformer): """ The GradesTransformer collects grading information and stores it on the block structure. No runtime transformations are performed. The following values are stored as xblock_fields on their respective blocks in the block structure: due: (datetime) when the problem is due. format: (string) what type of problem it is graded: (boolean) has_score: (boolean) weight: (numeric) Additionally, the following value is calculated and stored as a transformer_block_field for each block: max_score: (numeric) """ VERSION = 1 FIELDS_TO_COLLECT = [u'due', u'format', u'graded', u'has_score', u'weight'] @classmethod def name(cls): """ Unique identifier for the transformer's class; same identifier used in setup.py. """ return u'grades' @classmethod def collect(cls, block_structure): """ Collects any information that's necessary to execute this transformer's transform method. """ block_structure.request_xblock_fields(*cls.FIELDS_TO_COLLECT) cls._collect_max_scores(block_structure) def transform(self, block_structure, usage_context): """ Perform no transformations. """ pass @classmethod def _collect_max_scores(cls, block_structure): """ Collect the `max_score` for every block in the provided `block_structure`. """ for module in cls._iter_scorable_xmodules(block_structure): cls._collect_max_score(block_structure, module) @classmethod def _collect_max_score(cls, block_structure, module): """ Collect the `max_score` from the given module, storing it as a `transformer_block_field` associated with the `GradesTransformer`. """ score = module.max_score() block_structure.set_transformer_block_field(module.location, cls, 'max_score', score) @staticmethod def _iter_scorable_xmodules(block_structure): """ Loop through all the blocks locators in the block structure, and retrieve the module (XModule or XBlock) associated with that locator. For implementation reasons, we need to pull the max_score from the XModule, even though the data is not user specific. Here we bind the data to a SystemUser. """ request = RequestFactory().get('/dummy-collect-max-grades') user = SystemUser() request.user = user request.session = {} root_block = block_structure.get_xblock(block_structure.root_block_usage_key) course_key = block_structure.root_block_usage_key.course_key cache = FieldDataCache.cache_for_descriptor_descendents( course_id=course_key, user=request.user, descriptor=root_block, descriptor_filter=lambda descriptor: descriptor.has_score, ) for block_locator in block_structure.post_order_traversal(): block = block_structure.get_xblock(block_locator) if getattr(block, 'has_score', False): module = module_render.get_module_for_descriptor(user, request, block, cache, course_key) yield module