'Handles caching of items once inheritance and any other one time
per course per fetch operations are done.
Arguments:
system: a CachingDescriptorSystem
base_block_ids: list of BlockIds to fetch
course_key: the destination course providing the context
depth: how deep below these to prefetch
lazy: whether to load definitions now or later'

def cache_items(self, system, base_block_ids, course_key, depth=0, lazy=True):

    with self.bulk_operations(course_key, emit_signals=False):
        new_module_data = {}
        for block_id in base_block_ids:
            new_module_data = self.descendants(system.course_entry.structure['blocks'], block_id, depth, new_module_data)
        if (not lazy):
            descendent_definitions = self.get_definitions(course_key, [block.definition for block in new_module_data.itervalues()])
            definitions = {definition['_id']: definition for definition in descendent_definitions}
            for block in new_module_data.itervalues():
                if (block.definition in definitions):
                    definition = definitions[block.definition]
                    block.fields.update(definition.get('fields'))
                    block.definition_loaded = True
        system.module_data.update(new_module_data)
        return system.module_data
