示例#1
0
 def test_definition_key_replace(self, key_class, attr_value):
     attr, value = attr_value
     key = key_class(
         DefinitionLocator('block_type', 'abcd1234abcd1234abcd1234'),
         'aside')
     new_key = key.replace(**{attr: value})
     self.assertEqual(getattr(new_key, attr), value)
示例#2
0
 def test_description_locator_url(self):
     random_value = random.randrange(16**24)
     object_id = f'{random_value:024x}'
     definition_locator = DefinitionLocator('html', object_id)
     self.assertEqual(
         f'def-v1:{object_id}+{DefinitionLocator.BLOCK_TYPE_PREFIX}@html',
         str(definition_locator))
     self.assertEqual(definition_locator,
                      DefinitionKey.from_string(str(definition_locator)))
 def __init__(self, modulestore, block_type, definition_id,
              field_converter):
     """
     Simple placeholder for yet-to-be-fetched data
     :param modulestore: the pymongo db connection with the definitions
     :param definition_locator: the id of the record in the above to fetch
     """
     self.modulestore = modulestore
     self.definition_locator = DefinitionLocator(block_type, definition_id)
     self.field_converter = field_converter
示例#4
0
 def test_description_locator_url(self):
     object_id = '{:024x}'.format(random.randrange(16**24))
     definition_locator = DefinitionLocator('html', object_id)
     self.assertEqual(
         'def-v1:{}+{}@html'.format(object_id,
                                    DefinitionLocator.BLOCK_TYPE_PREFIX),
         text_type(definition_locator))
     self.assertEqual(
         definition_locator,
         DefinitionKey.from_string(text_type(definition_locator)))
示例#5
0
    def get_definition_id(self, usage_id):
        if isinstance(usage_id.block_id, LocalId):
            # a LocalId indicates that this block hasn't been persisted yet, and is instead stored
            # in-memory in the local_modules dictionary.
            return self._cds.local_modules[usage_id].scope_ids.def_id
        else:
            block_key = BlockKey.from_usage_key(usage_id)
            module_data = self._cds.get_module_data(block_key,
                                                    usage_id.course_key)

            if module_data.definition is not None:
                return DefinitionLocator(usage_id.block_type,
                                         module_data.definition)
            else:
                raise ValueError(
                    "All non-local blocks should have a definition specified")
示例#6
0
 def test_description_locator_version(self):
     object_id = '{:024x}'.format(random.randrange(16**24))
     definition_locator = DefinitionLocator('html', object_id)
     self.assertEqual(object_id, str(definition_locator.version()))
示例#7
0
class TestAsideKeys(TestCase):
    """Test of Aside keys."""
    @ddt.data(*itertools.product([
        AsideUsageKeyV1,
        AsideUsageKeyV2,
    ], [
        Location.from_string('i4x://org/course/cat/name'),
        BlockUsageLocator(CourseLocator('org', 'course', 'run'), 'block_type',
                          'block_id'),
    ], ['aside', 'aside_b']))
    @ddt.unpack
    def test_usage_round_trip_deserialized(self, key_class, usage_key,
                                           aside_type):
        key = key_class(usage_key, aside_type)
        serialized = text_type(key)
        deserialized = AsideUsageKey.from_string(serialized)
        self.assertEqual(key, deserialized)
        self.assertEqual(usage_key, key.usage_key, usage_key)
        self.assertEqual(usage_key, deserialized.usage_key)
        self.assertEqual(aside_type, key.aside_type)
        self.assertEqual(aside_type, deserialized.aside_type)

    @ddt.data(
        'aside-usage-v1:i4x://org/course/cat/name::aside',
        'aside-usage-v1:block-v1:org+course+cat+type@block_type+block@name::aside',
        'aside-usage-v2:lib-block-v1$:$:+-+branch@-+version@000000000000000000000000+type@-+block@-::0',
        'aside-usage-v2:i4x$://-/-/-/$:$:-::0',
        'aside-usage-v2:i4x$://-/-/-/$:$:$:-::0',
        'aside-usage-v2:i4x$://-/-/$:$:$:$:$:/-::0',
    )
    def test_usage_round_trip_serialized(self, aside_key):
        deserialized = AsideUsageKey.from_string(aside_key)
        serialized = text_type(deserialized)
        self.assertEqual(aside_key, serialized)

    @ddt.data(*itertools.product([
        AsideDefinitionKeyV1,
        AsideDefinitionKeyV2,
    ], [
        DefinitionLocator('block_type', 'abcd1234abcd1234abcd1234'),
    ], ['aside', 'aside_b']))
    @ddt.unpack
    def test_definition_round_trip_deserialized(self, key_class,
                                                definition_key, aside_type):
        key = key_class(definition_key, aside_type)
        serialized = text_type(key)
        deserialized = AsideDefinitionKey.from_string(serialized)
        self.assertEqual(key, deserialized)
        self.assertEqual(definition_key, key.definition_key, definition_key)
        self.assertEqual(definition_key, deserialized.definition_key)
        self.assertEqual(aside_type, key.aside_type)
        self.assertEqual(aside_type, deserialized.aside_type)

    @ddt.data(
        'aside-def-v1:def-v1:abcd1234abcd1234abcd1234+type@block_type::aside',
        'aside-def-v2:def-v1$:abcd1234abcd1234abcd1234+type@block_type::aside')
    def test_definition_round_trip_serialized(self, aside_key):
        deserialized = AsideDefinitionKey.from_string(aside_key)
        serialized = text_type(deserialized)
        self.assertEqual(aside_key, serialized)

    @ddt.data(*itertools.product(
        [
            AsideUsageKeyV1,
            AsideUsageKeyV2,
        ],
        [
            ('aside_type', 'bside'),
            ('usage_key',
             BlockUsageLocator(CourseLocator('borg', 'horse', 'gun'),
                               'lock_type', 'lock_id')),
            ('block_id', 'lock_id'),
            ('block_type', 'lock_type'),
            # BlockUsageLocator can't `replace` a definition_key, so skip for now
            # ('definition_key', DefinitionLocator('block_type', 'abcd1234abcd1234abcd1234')),
            ('course_key', CourseLocator('borg', 'horse', 'gun')),
        ]))
    @ddt.unpack
    def test_usage_key_replace(self, key_class, attr_value):
        attr, value = attr_value
        key = key_class(
            BlockUsageLocator(CourseLocator('org', 'course', 'run'),
                              'block_type', 'block_id'), 'aside')
        new_key = key.replace(**{attr: value})
        self.assertEqual(getattr(new_key, attr), value)

    @ddt.data(*itertools.product([
        AsideDefinitionKeyV1,
        AsideDefinitionKeyV2,
    ], [
        ('aside_type', 'bside'),
        ('definition_key',
         DefinitionLocator('block_type', 'abcd1234abcd1234abcd1234')),
        ('block_type', 'lock_type'),
    ]))
    @ddt.unpack
    def test_definition_key_replace(self, key_class, attr_value):
        attr, value = attr_value
        key = key_class(
            DefinitionLocator('block_type', 'abcd1234abcd1234abcd1234'),
            'aside')
        new_key = key.replace(**{attr: value})
        self.assertEqual(getattr(new_key, attr), value)
    def xblock_from_json(self,
                         class_,
                         course_key,
                         block_key,
                         block_data,
                         course_entry_override=None,
                         **kwargs):
        """
        Load and return block info.
        """
        if course_entry_override is None:
            course_entry_override = self.course_entry
        else:
            # most recent retrieval is most likely the right one for next caller (see comment above fn)
            self.course_entry = CourseEnvelope(
                course_entry_override.course_key, self.course_entry.structure)

        definition_id = block_data.definition

        # If no usage id is provided, generate an in-memory id
        if block_key is None:
            block_key = BlockKey(block_data.block_type, LocalId())

        convert_fields = lambda field: self.modulestore.convert_references_to_keys(
            course_key,
            class_,
            field,
            self.course_entry.structure['blocks'],
        )

        if definition_id is not None and not block_data.definition_loaded:
            definition_loader = DefinitionLazyLoader(
                self.modulestore,
                course_key,
                block_key.type,
                definition_id,
                convert_fields,
            )
        else:
            definition_loader = None

        # If no definition id is provide, generate an in-memory id
        if definition_id is None:
            definition_id = LocalId()

        # Construct the Block Usage Locator:
        block_locator = course_key.make_usage_key(
            block_type=block_key.type,
            block_id=block_key.id,
        )

        converted_fields = convert_fields(block_data.fields)
        converted_defaults = convert_fields(block_data.defaults)
        if block_key in self._parent_map:
            parent_key = self._parent_map[block_key]
            parent = course_key.make_usage_key(parent_key.type, parent_key.id)
        else:
            parent = None
        try:
            kvs = SplitMongoKVS(definition_loader,
                                converted_fields,
                                converted_defaults,
                                parent=parent,
                                field_decorator=kwargs.get('field_decorator'))

            if InheritanceMixin in self.modulestore.xblock_mixins:
                field_data = inheriting_field_data(kvs)
            else:
                field_data = KvsFieldData(kvs)

            module = self.construct_xblock_from_class(
                class_,
                ScopeIds(None, block_key.type, definition_id, block_locator),
                field_data,
                for_parent=kwargs.get('for_parent'))
        except Exception:  # pylint: disable=broad-except
            log.warning("Failed to load descriptor", exc_info=True)
            return ErrorDescriptor.from_json(
                block_data,
                self,
                course_entry_override.course_key.make_usage_key(
                    block_type='error', block_id=block_key.id),
                error_msg=exc_info_to_str(sys.exc_info()))

        edit_info = block_data.edit_info
        module._edited_by = edit_info.edited_by  # pylint: disable=protected-access
        module._edited_on = edit_info.edited_on  # pylint: disable=protected-access
        module.previous_version = edit_info.previous_version
        module.update_version = edit_info.update_version
        module.source_version = edit_info.source_version
        module.definition_locator = DefinitionLocator(block_key.type,
                                                      definition_id)
        # decache any pending field settings
        module.save()

        # If this is an in-memory block, store it in this system
        if isinstance(block_locator.block_id, LocalId):
            self.local_modules[block_locator] = module

        return module
示例#9
0
    def xblock_from_json(self,
                         class_,
                         course_key,
                         block_id,
                         json_data,
                         inherited_settings,
                         course_entry_override=None,
                         **kwargs):
        if course_entry_override is None:
            course_entry_override = self.course_entry
        else:
            # most recent retrieval is most likely the right one for next caller (see comment above fn)
            self.course_entry['branch'] = course_entry_override['branch']
            self.course_entry['org'] = course_entry_override['org']
            self.course_entry['course'] = course_entry_override['course']
            self.course_entry['run'] = course_entry_override['run']

        definition_id = json_data.get('definition')
        block_type = json_data['category']
        if block_id is not None:
            if inherited_settings is None:
                # see if there's a value in course_entry
                if (block_type,
                        block_id) in self.course_entry['inherited_settings']:
                    inherited_settings = self.course_entry[
                        'inherited_settings'][(block_type, block_id)]
            elif (block_type,
                  block_id) not in self.course_entry['inherited_settings']:
                self.course_entry['inherited_settings'][(
                    block_type, block_id)] = inherited_settings

        if definition_id is not None and not json_data.get(
                'definition_loaded', False):
            definition_loader = DefinitionLazyLoader(
                self.modulestore, block_type, definition_id,
                lambda fields: self.modulestore.convert_references_to_keys(
                    course_key,
                    self.load_block_type(block_type),
                    fields,
                    self.course_entry['structure']['blocks'],
                ))
        else:
            definition_loader = None

        # If no definition id is provide, generate an in-memory id
        if definition_id is None:
            definition_id = LocalId()

        # If no usage id is provided, generate an in-memory id
        if block_id is None:
            block_id = LocalId()

        block_locator = BlockUsageLocator(
            course_key,
            block_type=block_type,
            block_id=block_id,
        )

        converted_fields = self.modulestore.convert_references_to_keys(
            block_locator.course_key,
            class_,
            json_data.get('fields', {}),
            self.course_entry['structure']['blocks'],
        )
        kvs = SplitMongoKVS(definition_loader, converted_fields,
                            inherited_settings, **kwargs)
        field_data = KvsFieldData(kvs)

        try:
            module = self.construct_xblock_from_class(
                class_,
                ScopeIds(None, block_type, definition_id, block_locator),
                field_data,
            )
        except Exception:
            log.warning("Failed to load descriptor", exc_info=True)
            return ErrorDescriptor.from_json(
                json_data,
                self,
                BlockUsageLocator(CourseLocator(
                    version_guid=course_entry_override['structure']['_id']),
                                  block_type='error',
                                  block_id=block_id),
                error_msg=exc_info_to_str(sys.exc_info()))

        edit_info = json_data.get('edit_info', {})
        module._edited_by = edit_info.get('edited_by')
        module._edited_on = edit_info.get('edited_on')
        module.previous_version = edit_info.get('previous_version')
        module.update_version = edit_info.get('update_version')
        module.source_version = edit_info.get('source_version', None)
        module.definition_locator = DefinitionLocator(block_type,
                                                      definition_id)
        # decache any pending field settings
        module.save()

        # If this is an in-memory block, store it in this system
        if isinstance(block_locator.block_id, LocalId):
            self.local_modules[block_locator] = module

        return module
    def xblock_from_json(self,
                         class_,
                         course_key,
                         block_key,
                         json_data,
                         course_entry_override=None,
                         **kwargs):
        if course_entry_override is None:
            course_entry_override = self.course_entry
        else:
            # most recent retrieval is most likely the right one for next caller (see comment above fn)
            self.course_entry = CourseEnvelope(
                course_entry_override.course_key, self.course_entry.structure)

        definition_id = json_data.get('definition')

        # If no usage id is provided, generate an in-memory id
        if block_key is None:
            block_key = BlockKey(json_data['block_type'], LocalId())

        if definition_id is not None and not json_data.get(
                'definition_loaded', False):
            definition_loader = DefinitionLazyLoader(
                self.modulestore, course_key, block_key.type, definition_id,
                lambda fields: self.modulestore.convert_references_to_keys(
                    course_key,
                    self.load_block_type(block_key.type),
                    fields,
                    self.course_entry.structure['blocks'],
                ))
        else:
            definition_loader = None

        # If no definition id is provide, generate an in-memory id
        if definition_id is None:
            definition_id = LocalId()

        block_locator = BlockUsageLocator(
            course_key,
            block_type=block_key.type,
            block_id=block_key.id,
        )

        converted_fields = self.modulestore.convert_references_to_keys(
            block_locator.course_key,
            class_,
            json_data.get('fields', {}),
            self.course_entry.structure['blocks'],
        )
        if block_key in self._parent_map:
            parent_key = self._parent_map[block_key]
            parent = course_key.make_usage_key(parent_key.type, parent_key.id)
        else:
            parent = None
        kvs = SplitMongoKVS(definition_loader,
                            converted_fields,
                            parent=parent,
                            field_decorator=kwargs.get('field_decorator'))

        if InheritanceMixin in self.modulestore.xblock_mixins:
            field_data = inheriting_field_data(kvs)
        else:
            field_data = KvsFieldData(kvs)

        try:
            module = self.construct_xblock_from_class(
                class_,
                ScopeIds(None, block_key.type, definition_id, block_locator),
                field_data,
            )
        except Exception:
            log.warning("Failed to load descriptor", exc_info=True)
            return ErrorDescriptor.from_json(
                json_data,
                self,
                course_entry_override.course_key.make_usage_key(
                    block_type='error', block_id=block_key.id),
                error_msg=exc_info_to_str(sys.exc_info()))

        edit_info = json_data.get('edit_info', {})
        module._edited_by = edit_info.get('edited_by')
        module._edited_on = edit_info.get('edited_on')
        module.previous_version = edit_info.get('previous_version')
        module.update_version = edit_info.get('update_version')
        module.source_version = edit_info.get('source_version', None)
        module.definition_locator = DefinitionLocator(block_key.type,
                                                      definition_id)
        # decache any pending field settings
        module.save()

        # If this is an in-memory block, store it in this system
        if isinstance(block_locator.block_id, LocalId):
            self.local_modules[block_locator] = module

        return module
class TestAsideKeys(TestCase):
    """Test of Aside keys."""
    @ddt.data(
        (Location.from_string('i4x://org/course/cat/name'), 'aside'),
        (BlockUsageLocator(CourseLocator('org', 'course', 'run'), 'block_type',
                           'block_id'), 'aside'),
    )
    @ddt.unpack
    def test_usage_round_trip_deserialized(self, usage_key, aside_type):
        key = AsideUsageKeyV1(usage_key, aside_type)
        serialized = unicode(key)
        deserialized = AsideUsageKey.from_string(serialized)
        self.assertEquals(key, deserialized)
        self.assertEquals(usage_key, key.usage_key, usage_key)
        self.assertEquals(usage_key, deserialized.usage_key)
        self.assertEquals(aside_type, key.aside_type)
        self.assertEquals(aside_type, deserialized.aside_type)

    @ddt.data(
        'aside-usage-v1:i4x://org/course/cat/name::aside',
        'aside-usage-v1:block-v1:org+course+cat+type@block_type+block@name::aside',
    )
    def test_usage_round_trip_serialized(self, aside_key):
        deserialized = AsideUsageKey.from_string(aside_key)
        serialized = unicode(deserialized)
        self.assertEquals(aside_key, serialized)

    @ddt.data(
        (DefinitionLocator('block_type', 'abcd1234abcd1234abcd1234'), 'aside'),
    )
    @ddt.unpack
    def test_definition_round_trip_deserialized(self, definition_key,
                                                aside_type):
        key = AsideDefinitionKeyV1(definition_key, aside_type)
        serialized = unicode(key)
        deserialized = AsideDefinitionKey.from_string(serialized)
        self.assertEquals(key, deserialized)
        self.assertEquals(definition_key, key.definition_key, definition_key)
        self.assertEquals(definition_key, deserialized.definition_key)
        self.assertEquals(aside_type, key.aside_type)
        self.assertEquals(aside_type, deserialized.aside_type)

    @ddt.data(
        'aside-def-v1:def-v1:abcd1234abcd1234abcd1234+type@block_type::aside')
    def test_definition_round_trip_serialized(self, aside_key):
        deserialized = AsideDefinitionKey.from_string(aside_key)
        serialized = unicode(deserialized)
        self.assertEquals(aside_key, serialized)

    @ddt.data(
        ('aside_type', 'bside'),
        ('usage_key',
         BlockUsageLocator(CourseLocator('borg', 'horse', 'gun'), 'lock_type',
                           'lock_id')),
        ('block_id', 'lock_id'),
        ('block_type', 'lock_type'),
        # BlockUsageLocator can't `replace` a definition_key, so skip for now
        # ('definition_key', DefinitionLocator('block_type', 'abcd1234abcd1234abcd1234')),
        ('course_key', CourseLocator('borg', 'horse', 'gun')),
    )
    @ddt.unpack
    def test_usage_key_replace(self, attr, value):
        key = AsideUsageKeyV1(
            BlockUsageLocator(CourseLocator('org', 'course', 'run'),
                              'block_type', 'block_id'), 'aside')
        new_key = key.replace(**{attr: value})
        self.assertEquals(getattr(new_key, attr), value)

    @ddt.data(
        ('aside_type', 'bside'),
        ('definition_key',
         DefinitionLocator('block_type', 'abcd1234abcd1234abcd1234')),
        ('block_type', 'lock_type'),
    )
    @ddt.unpack
    def test_definition_key_replace(self, attr, value):
        key = AsideDefinitionKeyV1(
            DefinitionLocator('block_type', 'abcd1234abcd1234abcd1234'),
            'aside')
        new_key = key.replace(**{attr: value})
        self.assertEquals(getattr(new_key, attr), value)
 def test_definition_key_replace(self, attr, value):
     key = AsideDefinitionKeyV1(
         DefinitionLocator('block_type', 'abcd1234abcd1234abcd1234'),
         'aside')
     new_key = key.replace(**{attr: value})
     self.assertEquals(getattr(new_key, attr), value)
示例#13
0
 def test_description_locator_version(self):
     object_id = '{:024x}'.format(random.randrange(16 ** 24))
     definition_locator = DefinitionLocator('html', object_id)
     self.assertEqual(object_id, str(definition_locator.version()))
示例#14
0
 def test_description_locator_version(self):
     random_value = random.randrange(16**24)
     object_id = f'{random_value:024x}'
     definition_locator = DefinitionLocator('html', object_id)
     self.assertEqual(object_id, str(definition_locator.version))