def test_inherited_field(self): kvs = InheritanceKeyValueStore( initial_values={}, inherited_settings={'showanswer': 'inherited'}) model_data = KvsFieldData(kvs) descriptor = self.get_descriptor(model_data) editable_fields = descriptor.editable_metadata_fields self.assert_field_values(editable_fields, 'showanswer', InheritanceMixin.showanswer, explicitly_set=False, value='inherited', default_value='inherited') # Mimic the case where display_name WOULD have been inherited, except we explicitly set it. kvs = InheritanceKeyValueStore( initial_values={'showanswer': 'explicit'}, inherited_settings={'showanswer': 'inheritable value'}) model_data = KvsFieldData(kvs) descriptor = self.get_descriptor(model_data) editable_fields = descriptor.editable_metadata_fields self.assert_field_values(editable_fields, 'showanswer', InheritanceMixin.showanswer, explicitly_set=True, value='explicit', default_value='inheritable value')
def from_xml(cls, xml_data, system, id_generator): """ Creates an instance of this descriptor from the supplied xml_data. This may be overridden by subclasses xml_data: A string of xml that will be translated into data and children for this module system: A DescriptorSystem for interacting with external resources id_generator is used to generate course-specific urls and identifiers """ xml_object = etree.fromstring(xml_data) url_name = xml_object.get('url_name', xml_object.get('slug')) block_type = 'video' definition_id = id_generator.create_definition(block_type, url_name) usage_id = id_generator.create_usage(definition_id) if is_pointer_tag(xml_object): filepath = cls._format_filepath(xml_object.tag, name_to_pathname(url_name)) xml_object = cls.load_file(filepath, system.resources_fs, usage_id) system.parse_asides(xml_object, definition_id, usage_id, id_generator) field_data = cls._parse_video_xml(xml_object, id_generator) kvs = InheritanceKeyValueStore(initial_values=field_data) field_data = KvsFieldData(kvs) video = system.construct_xblock_from_class( cls, # We're loading a descriptor, so student_id is meaningless # We also don't have separate notions of definition and usage ids yet, # so we use the location for both ScopeIds(None, block_type, definition_id, usage_id), field_data, ) return video
def from_xml(cls, xml_data, system, org=None, course=None): """ Creates an instance of this descriptor from the supplied xml_data. This may be overridden by subclasses xml_data: A string of xml that will be translated into data and children for this module system: A DescriptorSystem for interacting with external resources org and course are optional strings that will be used in the generated modules url identifiers """ xml_object = etree.fromstring(xml_data) url_name = xml_object.get('url_name', xml_object.get('slug')) location = Location('i4x', org, course, 'video', url_name) if is_pointer_tag(xml_object): filepath = cls._format_filepath(xml_object.tag, name_to_pathname(url_name)) xml_data = etree.tostring( cls.load_file(filepath, system.resources_fs, location)) field_data = cls._parse_video_xml(xml_data) field_data['location'] = location kvs = InheritanceKeyValueStore(initial_values=field_data) field_data = DbModel(kvs) video = system.construct_xblock_from_class( cls, # We're loading a descriptor, so student_id is meaningless # We also don't have separate notions of definition and usage ids yet, # so we use the location for both ScopeIds(None, location.category, location, location), field_data, ) return video
def from_xml(cls, xml_data, system, org=None, course=None): """ Creates an instance of this descriptor from the supplied xml_data. This may be overridden by subclasses xml_data: A string of xml that will be translated into data and children for this module system: A DescriptorSystem for interacting with external resources org and course are optional strings that will be used in the generated modules url identifiers """ xml_object = etree.fromstring(xml_data) # VS[compat] -- just have the url_name lookup, once translation is done url_name = xml_object.get('url_name', xml_object.get('slug')) location = Location('i4x', org, course, xml_object.tag, url_name) # VS[compat] -- detect new-style each-in-a-file mode if is_pointer_tag(xml_object): # new style: # read the actual definition file--named using url_name.replace(':','/') filepath = cls._format_filepath(xml_object.tag, name_to_pathname(url_name)) definition_xml = cls.load_file(filepath, system.resources_fs, location) else: definition_xml = xml_object filepath = None definition, children = cls.load_definition( definition_xml, system, location) # note this removes metadata # VS[compat] -- make Ike's github preview links work in both old and # new file layouts if is_pointer_tag(xml_object): # new style -- contents actually at filepath definition['filename'] = [filepath, filepath] metadata = cls.load_metadata(definition_xml) # move definition metadata into dict dmdata = definition.get('definition_metadata', '') if dmdata: metadata['definition_metadata_raw'] = dmdata try: metadata.update(json.loads(dmdata)) except Exception as err: log.debug('Error %s in loading metadata %s' % (err, dmdata)) metadata['definition_metadata_err'] = str(err) # Set/override any metadata specified by policy k = policy_key(location) if k in system.policy: cls.apply_policy(metadata, system.policy[k]) field_data = {} field_data.update(metadata) field_data.update(definition) field_data['children'] = children field_data['xml_attributes']['filename'] = definition.get( 'filename', ['', None]) # for git link field_data['location'] = location field_data['category'] = xml_object.tag kvs = InheritanceKeyValueStore(initial_values=field_data) field_data = DbModel(kvs) return system.construct_xblock_from_class( cls, # We're loading a descriptor, so student_id is meaningless # We also don't have separate notions of definition and usage ids yet, # so we use the location for both ScopeIds(None, location.category, location, location), field_data, )
def parse_xml(cls, node, runtime, keys, id_generator): # pylint: disable=unused-argument """ Use `node` to construct a new block. Arguments: node (etree.Element): The xml node to parse into an xblock. runtime (:class:`.Runtime`): The runtime to use while parsing. keys (:class:`.ScopeIds`): The keys identifying where this block will store its data. id_generator (:class:`.IdGenerator`): An object that will allow the runtime to generate correct definition and usage ids for children of this block. Returns (XBlock): The newly parsed XBlock """ # VS[compat] -- just have the url_name lookup, once translation is done url_name = cls._get_url_name(node) def_id = id_generator.create_definition(node.tag, url_name) usage_id = id_generator.create_usage(def_id) aside_children = [] # VS[compat] -- detect new-style each-in-a-file mode if is_pointer_tag(node): # new style: # read the actual definition file--named using url_name.replace(':','/') definition_xml, filepath = cls.load_definition_xml( node, runtime, def_id) aside_children = runtime.parse_asides(definition_xml, def_id, usage_id, id_generator) else: filepath = None definition_xml = node # Note: removes metadata. definition, children = cls.load_definition(definition_xml, runtime, def_id, id_generator) # VS[compat] -- make Ike's github preview links work in both old and # new file layouts if is_pointer_tag(node): # new style -- contents actually at filepath definition['filename'] = [filepath, filepath] metadata = cls.load_metadata(definition_xml) # move definition metadata into dict dmdata = definition.get('definition_metadata', '') if dmdata: metadata['definition_metadata_raw'] = dmdata try: metadata.update(json.loads(dmdata)) except Exception as err: # lint-amnesty, pylint: disable=broad-except log.debug('Error in loading metadata %r', dmdata, exc_info=True) metadata['definition_metadata_err'] = str(err) definition_aside_children = definition.pop('aside_children', None) if definition_aside_children: aside_children.extend(definition_aside_children) # Set/override any metadata specified by policy cls.apply_policy(metadata, runtime.get_policy(usage_id)) field_data = {} field_data.update(metadata) field_data.update(definition) field_data['children'] = children field_data['xml_attributes']['filename'] = definition.get( 'filename', ['', None]) # for git link kvs = InheritanceKeyValueStore(initial_values=field_data) field_data = KvsFieldData(kvs) xblock = runtime.construct_xblock_from_class( cls, # We're loading a descriptor, so student_id is meaningless ScopeIds(None, node.tag, def_id, usage_id), field_data, ) if aside_children: asides_tags = [x.tag for x in aside_children] asides = runtime.get_asides(xblock) for asd in asides: if asd.scope_ids.block_type in asides_tags: xblock.add_aside(asd) return xblock
def parse_xml(cls, node, runtime, keys, id_generator): # pylint: disable=unused-argument """ Use `node` to construct a new block. Arguments: node (etree.Element): The xml node to parse into an xblock. runtime (:class:`.Runtime`): The runtime to use while parsing. keys (:class:`.ScopeIds`): The keys identifying where this block will store its data. id_generator (:class:`.IdGenerator`): An object that will allow the runtime to generate correct definition and usage ids for children of this block. Returns (XBlock): The newly parsed XBlock """ # VS[compat] -- just have the url_name lookup, once translation is done url_name = node.get('url_name', node.get('slug')) def_id = id_generator.create_definition(node.tag, url_name) usage_id = id_generator.create_usage(def_id) # VS[compat] -- detect new-style each-in-a-file mode if is_pointer_tag(node): # new style: # read the actual definition file--named using url_name.replace(':','/') filepath = cls._format_filepath(node.tag, name_to_pathname(url_name)) definition_xml = cls.load_file(filepath, runtime.resources_fs, def_id) runtime.parse_asides(definition_xml, def_id, usage_id, id_generator) else: filepath = None definition_xml = node dog_stats_api.increment( DEPRECATION_VSCOMPAT_EVENT, tags=["location:xmlparser_util_mixin_parse_xml"]) # Note: removes metadata. definition, children = cls.load_definition(definition_xml, runtime, def_id, id_generator) # VS[compat] -- make Ike's github preview links work in both old and # new file layouts if is_pointer_tag(node): # new style -- contents actually at filepath definition['filename'] = [filepath, filepath] metadata = cls.load_metadata(definition_xml) # move definition metadata into dict dmdata = definition.get('definition_metadata', '') if dmdata: metadata['definition_metadata_raw'] = dmdata try: metadata.update(json.loads(dmdata)) except Exception as err: log.debug('Error in loading metadata %r', dmdata, exc_info=True) metadata['definition_metadata_err'] = str(err) # Set/override any metadata specified by policy cls.apply_policy(metadata, runtime.get_policy(usage_id)) field_data = {} field_data.update(metadata) field_data.update(definition) field_data['children'] = children field_data['xml_attributes']['filename'] = definition.get( 'filename', ['', None]) # for git link kvs = InheritanceKeyValueStore(initial_values=field_data) field_data = KvsFieldData(kvs) return runtime.construct_xblock_from_class( cls, # We're loading a descriptor, so student_id is meaningless ScopeIds(None, node.tag, def_id, usage_id), field_data, )
def from_xml(cls, xml_data, system, id_generator): """ Creates an instance of this descriptor from the supplied xml_data. This may be overridden by subclasses xml_data: A string of xml that will be translated into data and children for this module system: A DescriptorSystem for interacting with external resources """ xml_object = etree.fromstring(xml_data) # VS[compat] -- just have the url_name lookup, once translation is done url_name = xml_object.get('url_name', xml_object.get('slug')) def_id = id_generator.create_definition(xml_object.tag, url_name) usage_id = id_generator.create_usage(def_id) # VS[compat] -- detect new-style each-in-a-file mode if is_pointer_tag(xml_object): # new style: # read the actual definition file--named using url_name.replace(':','/') filepath = cls._format_filepath(xml_object.tag, name_to_pathname(url_name)) definition_xml = cls.load_file(filepath, system.resources_fs, def_id) else: definition_xml = xml_object filepath = None definition, children = cls.load_definition( definition_xml, system, def_id) # note this removes metadata # VS[compat] -- make Ike's github preview links work in both old and # new file layouts if is_pointer_tag(xml_object): # new style -- contents actually at filepath definition['filename'] = [filepath, filepath] metadata = cls.load_metadata(definition_xml) # move definition metadata into dict dmdata = definition.get('definition_metadata', '') if dmdata: metadata['definition_metadata_raw'] = dmdata try: metadata.update(json.loads(dmdata)) except Exception as err: log.debug('Error in loading metadata %r', dmdata, exc_info=True) metadata['definition_metadata_err'] = str(err) # Set/override any metadata specified by policy cls.apply_policy(metadata, system.get_policy(usage_id)) field_data = {} field_data.update(metadata) field_data.update(definition) field_data['children'] = children field_data['xml_attributes']['filename'] = definition.get( 'filename', ['', None]) # for git link kvs = InheritanceKeyValueStore(initial_values=field_data) field_data = KvsFieldData(kvs) return system.construct_xblock_from_class( cls, # We're loading a descriptor, so student_id is meaningless ScopeIds(None, xml_object.tag, def_id, usage_id), field_data, )