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 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
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)))
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")
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()))
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
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)
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()))
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))