Beispiel #1
0
 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
Beispiel #2
0
    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)
        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 = VideoDescriptor._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,
            field_data,

            # 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)
        )
        return video
Beispiel #4
0
    def definition_to_xml(self, resource_fs):
        '''If the contents are valid xml, write them to filename.xml.  Otherwise,
        write just <html filename="" [meta-attrs="..."]> to filename.xml, and the html
        string to filename.html.
        '''
        try:
            return etree.fromstring(self.data)
        except etree.XMLSyntaxError:
            pass

        # Not proper format.  Write html to file, return an empty tag
        pathname = name_to_pathname(self.url_name)
        filepath = u'{category}/{pathname}.html'.format(category=self.category,
                                                    pathname=pathname)

        resource_fs.makedir(os.path.dirname(filepath), recursive=True, allow_recreate=True)
        with resource_fs.open(filepath, 'w') as file:
            html_data = self.data.encode('utf-8')
            file.write(html_data)

        # write out the relative name
        relname = path(pathname).basename()

        elt = etree.Element('html')
        elt.set("filename", relname)
        return elt
Beispiel #5
0
    def definition_to_xml(self, resource_fs):
        '''If the contents are valid xml, write them to filename.xml.  Otherwise,
        write just <html filename="" [meta-attrs="..."]> to filename.xml, and the html
        string to filename.html.
        '''
        try:
            return etree.fromstring(self.data)
        except etree.XMLSyntaxError:
            pass

        # Not proper format.  Write html to file, return an empty tag
        pathname = name_to_pathname(self.url_name)
        filepath = u'{category}/{pathname}.html'.format(category=self.category,
                                                        pathname=pathname)

        resource_fs.makedir(os.path.dirname(filepath),
                            recursive=True,
                            allow_recreate=True)
        with resource_fs.open(filepath, 'w') as file:
            html_data = self.data.encode('utf-8')
            file.write(html_data)

        # write out the relative name
        relname = path(pathname).basename()

        elt = etree.Element('html')
        elt.set("filename", relname)
        return elt
    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))

        upload_asset_path = VideoDescriptor._get_upload_asset_path(
            system.course_dir)
        model_data = {}
        xml = etree.fromstring(xml_data)

        display_name = xml.get('display_name')
        if display_name:
            model_data['display_name'] = display_name

        sources = xml.findall('source')
        if sources:
            model_data['source'] = [ele.get('src') for ele in sources][0]

        tracks = xml.findall('track')
        if tracks:
            for ele in tracks:
                if ele.get('srclang') == 'zh':
                    model_data['track_zh'] = upload_asset_path + ele.get(
                        'src').rsplit('/', 1)[1]
                elif ele.get('srclang') == 'en':
                    model_data['track_en'] = upload_asset_path + ele.get(
                        'src').rsplit('/', 1)[1]

        model_data['location'] = location
        video = cls(system, model_data)
        return video
Beispiel #7
0
    def definition_to_xml(self, resource_fs):
        """ Write <html filename="" [meta-attrs="..."]> to filename.xml, and the html
        string to filename.html.
        """

        # Write html to file, return an empty tag
        pathname = name_to_pathname(self.url_name)
        filepath = u"{category}/{pathname}.html".format(category=self.category, pathname=pathname)

        resource_fs.makedir(os.path.dirname(filepath), recursive=True, allow_recreate=True)
        with resource_fs.open(filepath, "w") as filestream:
            html_data = self.data.encode("utf-8")
            filestream.write(html_data)

        # write out the relative name
        relname = path(pathname).basename()

        elt = etree.Element("html")
        elt.set("filename", relname)
        return elt
    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))
        
        upload_asset_path = VideoDescriptor._get_upload_asset_path(system.course_dir)
        model_data = {}
        xml = etree.fromstring(xml_data)

        display_name = xml.get('display_name')
        if display_name:
            model_data['display_name'] = display_name

        sources = xml.findall('source')
        if sources:
            model_data['source'] = [ele.get('src') for ele in sources][0]

        tracks = xml.findall('track')
        if tracks:
            for ele in tracks:
                if ele.get('srclang') == 'zh':
                    model_data['track_zh'] = upload_asset_path + ele.get('src').rsplit('/', 1)[1]
                elif ele.get('srclang') == 'en':
                    model_data['track_en'] = upload_asset_path + ele.get('src').rsplit('/', 1)[1]

        model_data['location'] = location
        video = cls(system, model_data)
        return video
Beispiel #9
0
    def definition_to_xml(self, resource_fs):
        ''' Write <html filename="" [meta-attrs="..."]> to filename.xml, and the html
        string to filename.html.
        '''

        # Write html to file, return an empty tag
        pathname = name_to_pathname(self.url_name)
        filepath = u'{category}/{pathname}.html'.format(category=self.category,
                                                        pathname=pathname)

        resource_fs.makedirs(os.path.dirname(filepath), recreate=True)
        with resource_fs.open(filepath, 'wb') as filestream:
            html_data = self.data.encode('utf-8')
            filestream.write(html_data)

        # write out the relative name
        relname = path(pathname).basename()

        elt = etree.Element('html')
        elt.set("filename", relname)
        return elt
Beispiel #10
0
    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))
        model_data = VideoDescriptor._parse_video_xml(xml_data)
        model_data['location'] = location
        video = cls(system, model_data)
        return video
Beispiel #11
0
    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))
        model_data = VideoDescriptor._parse_video_xml(xml_data)
        model_data['location'] = location
        video = cls(system, model_data)
        return video
Beispiel #12
0
    def definition_to_xml(self, resource_fs):
        ''' Write <html filename="" [meta-attrs="..."]> to filename.xml, and the html
        string to filename.html.
        '''

        # Write html to file, return an empty tag
        pathname = name_to_pathname(self.url_name)
        filepath = u'{category}/{pathname}.html'.format(
            category=self.category,
            pathname=pathname
        )

        resource_fs.makedirs(os.path.dirname(filepath), recreate=True)
        with resource_fs.open(filepath, 'wb') as filestream:
            html_data = self.data.encode('utf-8')
            filestream.write(html_data)

        # write out the relative name
        relname = path(pathname).basename()

        elt = etree.Element('html')
        elt.set("filename", relname)
        return elt
Beispiel #13
0
    def load_definition(cls, xml_object, system, location):
        '''Load a descriptor from the specified xml_object:

        If there is a filename attribute, load it as a string, and
        log a warning if it is not parseable by etree.HTMLParser.

        If there is not a filename attribute, the definition is the body
        of the xml_object, without the root tag (do not want <html> in the
        middle of a page)
        '''
        filename = xml_object.get('filename')
        if filename is None:
            definition_xml = copy.deepcopy(xml_object)
            cls.clean_metadata_from_xml(definition_xml)
            return {'data': stringify_children(definition_xml)}, []
        else:
            # html is special.  cls.filename_extension is 'xml', but
            # if 'filename' is in the definition, that means to load
            # from .html
            # 'filename' in html pointers is a relative path
            # (not same as 'html/blah.html' when the pointer is in a directory itself)
            pointer_path = "{category}/{url_path}".format(
                category='html', url_path=name_to_pathname(location.name))
            base = path(pointer_path).dirname()
            # log.debug("base = {0}, base.dirname={1}, filename={2}".format(base, base.dirname(), filename))
            filepath = "{base}/{name}.html".format(base=base, name=filename)
            # log.debug("looking for html file for {0} at {1}".format(location, filepath))

            # VS[compat]
            # TODO (cpennington): If the file doesn't exist at the right path,
            # give the class a chance to fix it up. The file will be written out
            # again in the correct format.  This should go away once the CMS is
            # online and has imported all current (fall 2012) courses from xml
            if not system.resources_fs.exists(filepath):
                candidates = cls.backcompat_paths(filepath)
                # log.debug("candidates = {0}".format(candidates))
                for candidate in candidates:
                    if system.resources_fs.exists(candidate):
                        filepath = candidate
                        break

            try:
                with system.resources_fs.open(filepath) as file:
                    html = file.read().decode('utf-8')
                    # Log a warning if we can't parse the file, but don't error
                    if not check_html(html) and len(html) > 0:
                        msg = "Couldn't parse html in {0}, content = {1}".format(
                            filepath, html)
                        log.warning(msg)
                        system.error_tracker("Warning: " + msg)

                    definition = {'data': html}

                    # TODO (ichuang): remove this after migration
                    # for Fall 2012 LMS migration: keep filename (and unmangled filename)
                    definition['filename'] = [filepath, filename]

                    return definition, []

            except (ResourceNotFoundError) as err:
                msg = 'Unable to load file contents at path {0}: {1} '.format(
                    filepath, err)
                # add more info and re-raise
                raise Exception(msg), None, sys.exc_info()[2]
Beispiel #14
0
    def load_definition(cls, xml_object, system, location, id_generator):
        '''Load a descriptor from the specified xml_object:

        If there is a filename attribute, load it as a string, and
        log a warning if it is not parseable by etree.HTMLParser.

        If there is not a filename attribute, the definition is the body
        of the xml_object, without the root tag (do not want <html> in the
        middle of a page)

        Args:
            xml_object: an lxml.etree._Element containing the definition to load
            system: the modulestore system or runtime which caches data
            location: the usage id for the block--used to compute the filename if none in the xml_object
            id_generator: used by other impls of this method to generate the usage_id
        '''
        filename = xml_object.get('filename')
        if filename is None:
            definition_xml = copy.deepcopy(xml_object)
            cls.clean_metadata_from_xml(definition_xml)
            return {'data': stringify_children(definition_xml)}, []
        else:
            # html is special.  cls.filename_extension is 'xml', but
            # if 'filename' is in the definition, that means to load
            # from .html
            # 'filename' in html pointers is a relative path
            # (not same as 'html/blah.html' when the pointer is in a directory itself)
            pointer_path = "{category}/{url_path}".format(
                category='html',
                url_path=name_to_pathname(location.name)
            )
            base = path(pointer_path).dirname()
            # log.debug("base = {0}, base.dirname={1}, filename={2}".format(base, base.dirname(), filename))
            filepath = "{base}/{name}.html".format(base=base, name=filename)
            # log.debug("looking for html file for {0} at {1}".format(location, filepath))

            # VS[compat]
            # TODO (cpennington): If the file doesn't exist at the right path,
            # give the class a chance to fix it up. The file will be written out
            # again in the correct format.  This should go away once the CMS is
            # online and has imported all current (fall 2012) courses from xml
            if not system.resources_fs.exists(filepath):
                candidates = cls.backcompat_paths(filepath)
                # log.debug("candidates = {0}".format(candidates))
                for candidate in candidates:
                    if system.resources_fs.exists(candidate):
                        filepath = candidate
                        break

            try:
                with system.resources_fs.open(filepath) as file:
                    html = file.read().decode('utf-8')
                    # Log a warning if we can't parse the file, but don't error
                    if not check_html(html) and len(html) > 0:
                        msg = "Couldn't parse html in {0}, content = {1}".format(filepath, html)
                        log.warning(msg)
                        system.error_tracker("Warning: " + msg)

                    definition = {'data': html}

                    # TODO (ichuang): remove this after migration
                    # for Fall 2012 LMS migration: keep filename (and unmangled filename)
                    definition['filename'] = [filepath, filename]

                    return definition, []

            except (ResourceNotFoundError) as err:
                msg = 'Unable to load file contents at path {0}: {1} '.format(
                    filepath, err)
                # add more info and re-raise
                raise Exception(msg), None, sys.exc_info()[2]