예제 #1
0
    def export(self):
        """
        Perform the export given the parameters handed to this class at init.
        """
        with self.modulestore.bulk_operations(self.courselike_key):

            fsm = OSFS(self.root_dir)
            root = lxml.etree.Element("unknown")

            # export only the published content
            with self.modulestore.branch_setting(ModuleStoreEnum.Branch.published_only, self.courselike_key):
                courselike = self.get_courselike()
                export_fs = courselike.runtime.export_fs = fsm.makeopendir(self.target_dir)

                # change all of the references inside the course to use the xml expected key type w/o version & branch
                xml_centric_courselike_key = self.get_key()
                adapt_references(courselike, xml_centric_courselike_key, export_fs)
                courselike.add_xml_to_node(root)

            # Make any needed adjustments to the root node.
            self.process_root(root, export_fs)

            # Process extra items-- drafts, assets, etc
            root_courselike_dir = self.root_dir + "/" + self.target_dir
            self.process_extra(root, courselike, root_courselike_dir, xml_centric_courselike_key, export_fs)

            # Any last pass adjustments
            self.post_process(root, export_fs)
예제 #2
0
    def export(self):
        """
        Perform the export given the parameters handed to this class at init.
        """
        with self.modulestore.bulk_operations(self.courselike_key):
            # depth = None: Traverses down the entire course structure.
            # lazy = False: Loads and caches all block definitions during traversal for fast access later
            #               -and- to eliminate many round-trips to read individual definitions.
            # Why these parameters? Because a course export needs to access all the course block information
            # eventually. Accessing it all now at the beginning increases performance of the export.
            fsm = OSFS(self.root_dir)
            courselike = self.get_courselike()
            export_fs = courselike.runtime.export_fs = fsm.makeopendir(self.target_dir)
            root_courselike_dir = self.root_dir + '/' + self.target_dir

            root = lxml.etree.Element('unknown')  # pylint: disable=no-member

            # export only the published content
            with self.modulestore.branch_setting(ModuleStoreEnum.Branch.published_only, self.courselike_key):
                # change all of the references inside the course to use the xml expected key type w/o version & branch
                xml_centric_courselike_key = self.get_key()
                adapt_references(courselike, xml_centric_courselike_key, export_fs)
                courselike.add_xml_to_node(root)

            # Make any needed adjustments to the root node.
            self.process_root(root, export_fs)

            # Process extra items-- drafts, assets, etc
            self.process_extra(root, courselike, root_courselike_dir, xml_centric_courselike_key, export_fs)

            # Any last pass adjustments
            self.post_process(root, export_fs)
예제 #3
0
    def export(self):
        """
        Perform the export given the parameters handed to this class at init.
        """
        with self.modulestore.bulk_operations(self.courselike_key):

            fsm = OSFS(self.root_dir)
            root = lxml.etree.Element('unknown')

            # export only the published content
            with self.modulestore.branch_setting(
                    ModuleStoreEnum.Branch.published_only,
                    self.courselike_key):
                courselike = self.get_courselike()
                export_fs = courselike.runtime.export_fs = fsm.makeopendir(
                    self.target_dir)

                # change all of the references inside the course to use the xml expected key type w/o version & branch
                xml_centric_courselike_key = self.get_key()
                adapt_references(courselike, xml_centric_courselike_key,
                                 export_fs)
                courselike.add_xml_to_node(root)

            # Make any needed adjustments to the root node.
            self.process_root(root, export_fs)

            # Process extra items-- drafts, assets, etc
            root_courselike_dir = self.root_dir + '/' + self.target_dir
            self.process_extra(root, courselike, root_courselike_dir,
                               xml_centric_courselike_key, export_fs)

            # Any last pass adjustments
            self.post_process(root, export_fs)
예제 #4
0
    def check_export_roundtrip(self, data_dir, course_dir, mock_get):

        # Patch network calls to retrieve the textbook TOC
        mock_get.return_value.text = dedent("""
            <?xml version="1.0"?><table_of_contents>
            <entry page="5" page_label="ii" name="Table of Contents"/>
            </table_of_contents>
        """).strip()

        root_dir = path(self.temp_dir)
        print("Copying test course to temp dir {0}".format(root_dir))

        data_dir = path(data_dir)
        shutil.copytree(data_dir / course_dir, root_dir / course_dir)

        print("Starting import")
        initial_import = XMLModuleStore(root_dir, course_dirs=[course_dir])

        courses = initial_import.get_courses()
        self.assertEquals(len(courses), 1)
        initial_course = courses[0]

        # export to the same directory--that way things like the custom_tags/ folder
        # will still be there.
        print("Starting export")
        fs = OSFS(root_dir)
        export_fs = fs.makeopendir(course_dir)

        xml = initial_course.export_to_xml(export_fs)
        with export_fs.open('course.xml', 'w') as course_xml:
            course_xml.write(xml)

        print("Starting second import")
        second_import = XMLModuleStore(root_dir, course_dirs=[course_dir])

        courses2 = second_import.get_courses()
        self.assertEquals(len(courses2), 1)
        exported_course = courses2[0]

        print("Checking course equality")

        # HACK: filenames change when changing file formats
        # during imports from old-style courses.  Ignore them.
        strip_filenames(initial_course)
        strip_filenames(exported_course)

        self.assertEquals(initial_course, exported_course)
        self.assertEquals(initial_course.id, exported_course.id)
        course_id = initial_course.id

        print("Checking key equality")
        self.assertEquals(sorted(initial_import.modules[course_id].keys()),
                          sorted(second_import.modules[course_id].keys()))

        print("Checking module equality")
        for location in initial_import.modules[course_id].keys():
            print("Checking", location)
            self.assertEquals(initial_import.modules[course_id][location],
                              second_import.modules[course_id][location])
예제 #5
0
def export_to_xml(modulestore, contentstore, course_location, root_dir, course_dir, draft_modulestore=None):

    course = modulestore.get_item(course_location)

    fs = OSFS(root_dir)
    export_fs = fs.makeopendir(course_dir)

    xml = course.export_to_xml(export_fs)
    with export_fs.open("course.xml", "w") as course_xml:
        course_xml.write(xml)

    # export the static assets
    contentstore.export_all_for_course(course_location, root_dir + "/" + course_dir + "/static/")

    # export the static tabs
    export_extra_content(export_fs, modulestore, course_location, "static_tab", "tabs", ".html")

    # export the custom tags
    export_extra_content(export_fs, modulestore, course_location, "custom_tag_template", "custom_tags")

    # export the course updates
    export_extra_content(export_fs, modulestore, course_location, "course_info", "info", ".html")

    # export the 'about' data (e.g. overview, etc.)
    export_extra_content(export_fs, modulestore, course_location, "about", "about", ".html")

    # export the grading policy
    policies_dir = export_fs.makeopendir("policies")
    course_run_policy_dir = policies_dir.makeopendir(course.location.name)
    with course_run_policy_dir.open("grading_policy.json", "w") as grading_policy:
        grading_policy.write(dumps(course.grading_policy))

    # export all of the course metadata in policy.json
    with course_run_policy_dir.open("policy.json", "w") as course_policy:
        policy = {"course/" + course.location.name: own_metadata(course)}
        course_policy.write(dumps(policy))

    # export draft content
    # NOTE: this code assumes that verticals are the top most draftable container
    # should we change the application, then this assumption will no longer
    # be valid
    if draft_modulestore is not None:
        draft_verticals = draft_modulestore.get_items(
            [None, course_location.org, course_location.course, "vertical", None, "draft"]
        )
        if len(draft_verticals) > 0:
            draft_course_dir = export_fs.makeopendir("drafts")
            for draft_vertical in draft_verticals:
                parent_locs = draft_modulestore.get_parent_locations(draft_vertical.location, course.location.course_id)
                # Don't try to export orphaned items.
                if len(parent_locs) > 0:
                    logging.debug("parent_locs = {0}".format(parent_locs))
                    draft_vertical.xml_attributes["parent_sequential_url"] = Location(parent_locs[0]).url()
                    sequential = modulestore.get_item(Location(parent_locs[0]))
                    index = sequential.children.index(draft_vertical.location.url())
                    draft_vertical.xml_attributes["index_in_children_list"] = str(index)
                    draft_vertical.export_to_xml(draft_course_dir)
예제 #6
0
    def check_export_roundtrip(self, data_dir, course_dir):
        root_dir = path(self.temp_dir)
        print("Copying test course to temp dir {0}".format(root_dir))

        data_dir = path(data_dir)
        shutil.copytree(data_dir / course_dir, root_dir / course_dir)

        print("Starting import")
        initial_import = XMLModuleStore(root_dir, course_dirs=[course_dir])

        courses = initial_import.get_courses()
        self.assertEquals(len(courses), 1)
        initial_course = courses[0]

        # export to the same directory--that way things like the custom_tags/ folder
        # will still be there.
        print("Starting export")
        fs = OSFS(root_dir)
        export_fs = fs.makeopendir(course_dir)

        xml = initial_course.export_to_xml(export_fs)
        with export_fs.open('course.xml', 'w') as course_xml:
            course_xml.write(xml)

        print("Starting second import")
        second_import = XMLModuleStore(root_dir, course_dirs=[course_dir])

        courses2 = second_import.get_courses()
        self.assertEquals(len(courses2), 1)
        exported_course = courses2[0]

        print("Checking course equality")

        # HACK: filenames change when changing file formats
        # during imports from old-style courses.  Ignore them.
        strip_filenames(initial_course)
        strip_filenames(exported_course)

        self.assertEquals(initial_course, exported_course)
        self.assertEquals(initial_course.id, exported_course.id)
        course_id = initial_course.id

        print("Checking key equality")
        self.assertEquals(sorted(initial_import.modules[course_id].keys()),
                          sorted(second_import.modules[course_id].keys()))

        print("Checking module equality")
        for location in initial_import.modules[course_id].keys():
            print("Checking", location)
            if location.category == 'html':
                print(
                    "Skipping html modules--they can't import in"
                    " final form without writing files..."
                )
                continue
            self.assertEquals(initial_import.modules[course_id][location],
                              second_import.modules[course_id][location])
    def check_export_roundtrip(self, data_dir, course_dir):
        root_dir = path(self.temp_dir)
        print("Copying test course to temp dir {0}".format(root_dir))

        data_dir = path(data_dir)
        shutil.copytree(data_dir / course_dir, root_dir / course_dir)

        print("Starting import")
        initial_import = XMLModuleStore(root_dir, course_dirs=[course_dir])

        courses = initial_import.get_courses()
        self.assertEquals(len(courses), 1)
        initial_course = courses[0]

        # export to the same directory--that way things like the custom_tags/ folder
        # will still be there.
        print("Starting export")
        fs = OSFS(root_dir)
        export_fs = fs.makeopendir(course_dir)

        xml = initial_course.export_to_xml(export_fs)
        with export_fs.open('course.xml', 'w') as course_xml:
            course_xml.write(xml)

        print("Starting second import")
        second_import = XMLModuleStore(root_dir, course_dirs=[course_dir])

        courses2 = second_import.get_courses()
        self.assertEquals(len(courses2), 1)
        exported_course = courses2[0]

        print("Checking course equality")

        # HACK: filenames change when changing file formats
        # during imports from old-style courses.  Ignore them.
        strip_filenames(initial_course)
        strip_filenames(exported_course)

        self.assertEquals(initial_course, exported_course)
        self.assertEquals(initial_course.id, exported_course.id)
        course_id = initial_course.id

        print("Checking key equality")
        self.assertEquals(sorted(initial_import.modules[course_id].keys()),
                          sorted(second_import.modules[course_id].keys()))

        print("Checking module equality")
        for location in initial_import.modules[course_id].keys():
            print("Checking", location)
            if location.category == 'html':
                print(
                    "Skipping html modules--they can't import in"
                    " final form without writing files..."
                )
                continue
            self.assertEquals(initial_import.modules[course_id][location],
                              second_import.modules[course_id][location])
def export_to_xml(modulestore, contentstore, course_location, root_dir, course_dir, draft_modulestore=None):

    course = modulestore.get_item(course_location)

    fs = OSFS(root_dir)
    export_fs = fs.makeopendir(course_dir)

    xml = course.export_to_xml(export_fs)
    with export_fs.open('course.xml', 'w') as course_xml:
        course_xml.write(xml)

    # export the static assets
    contentstore.export_all_for_course(course_location, root_dir + '/' + course_dir + '/static/')

    # export the static tabs
    export_extra_content(export_fs, modulestore, course_location, 'static_tab', 'tabs', '.html')

    # export the custom tags
    export_extra_content(export_fs, modulestore, course_location, 'custom_tag_template', 'custom_tags')

    # export the course updates
    export_extra_content(export_fs, modulestore, course_location, 'course_info', 'info', '.html')

    # export the 'about' data (e.g. overview, etc.)
    export_extra_content(export_fs, modulestore, course_location, 'about', 'about', '.html')

    # export the grading policy
    policies_dir = export_fs.makeopendir('policies')
    course_run_policy_dir = policies_dir.makeopendir(course.location.name)
    with course_run_policy_dir.open('grading_policy.json', 'w') as grading_policy:
        grading_policy.write(dumps(course.grading_policy, cls=EdxJSONEncoder))

    # export all of the course metadata in policy.json
    with course_run_policy_dir.open('policy.json', 'w') as course_policy:
        policy = {'course/' + course.location.name: own_metadata(course)}
        course_policy.write(dumps(policy, cls=EdxJSONEncoder))

    # export draft content
    # NOTE: this code assumes that verticals are the top most draftable container
    # should we change the application, then this assumption will no longer
    # be valid
    if draft_modulestore is not None:
        draft_verticals = draft_modulestore.get_items([None, course_location.org, course_location.course,
                                                       'vertical', None, 'draft'])
        if len(draft_verticals) > 0:
            draft_course_dir = export_fs.makeopendir('drafts')
            for draft_vertical in draft_verticals:
                parent_locs = draft_modulestore.get_parent_locations(draft_vertical.location, course.location.course_id)
                # Don't try to export orphaned items.
                if len(parent_locs) > 0:
                    logging.debug('parent_locs = {0}'.format(parent_locs))
                    draft_vertical.xml_attributes['parent_sequential_url'] = Location(parent_locs[0]).url()
                    sequential = modulestore.get_item(Location(parent_locs[0]))
                    index = sequential.children.index(draft_vertical.location.url())
                    draft_vertical.xml_attributes['index_in_children_list'] = str(index)
                    draft_vertical.export_to_xml(draft_course_dir)
예제 #9
0
    def export(self):
        """
        Perform the export given the parameters handed to this class at init.
        """
        with self.modulestore.bulk_operations(self.courselike_key):
            # depth = None: Traverses down the entire course structure.
            # lazy = False: Loads and caches all block definitions during traversal for fast access later
            #               -and- to eliminate many round-trips to read individual definitions.
            # Why these parameters? Because a course export needs to access all the course block information
            # eventually. Accessing it all now at the beginning increases performance of the export.
            fsm = OSFS(self.root_dir)
            courselike = self.get_courselike()
            export_fs = courselike.runtime.export_fs = fsm.makeopendir(
                self.target_dir)
            root_courselike_dir = self.root_dir + '/' + self.target_dir

            root = lxml.etree.Element('unknown')  # pylint: disable=no-member

            # export only the published content
            with self.modulestore.branch_setting(
                    ModuleStoreEnum.Branch.published_only,
                    self.courselike_key):
                # change all of the references inside the course to use the xml expected key type w/o version & branch
                xml_centric_courselike_key = self.get_key()
                adapt_references(courselike, xml_centric_courselike_key,
                                 export_fs)
                courselike.add_xml_to_node(root)

            # Make any needed adjustments to the root node.
            self.process_root(root, export_fs)

            # Process extra items-- drafts, assets, etc
            self.process_extra(root, courselike, root_courselike_dir,
                               xml_centric_courselike_key, export_fs)

            # Any last pass adjustments
            self.post_process(root, export_fs)
예제 #10
0
    def cmd_get(self, *params, **options):

        try:
            url = params[0]
        except IndexError:
            print "get <url>"
            return

        media_fs = OSFS(settings.MEDIA_ROOT)
        media_fs.makedir('favicons', allow_recreate=True)

        favicon_path = url_to_path(url)
        favicon_fs = media_fs.makeopendir(favicon_path, recursive=True)

        orig_favicon_fs = favicon_fs.makeopendir('originals')

        output_path = orig_favicon_fs.getsyspath('orig')
        convert_path = orig_favicon_fs.getsyspath('icon.png')

        try:
            icon_info = download_favicon(url, output_path, convert_path)
        except URLError, e:
            print "ERROR: %s (%s)" % (e, url)
            return
예제 #11
0
def export_to_xml(modulestore,
                  contentstore,
                  course_location,
                  root_dir,
                  course_dir,
                  draft_modulestore=None):

    course = modulestore.get_item(course_location)

    fs = OSFS(root_dir)
    export_fs = fs.makeopendir(course_dir)

    xml = course.export_to_xml(export_fs)
    with export_fs.open('course.xml', 'w') as course_xml:
        course_xml.write(xml)

    # export the static assets
    contentstore.export_all_for_course(
        course_location, root_dir + '/' + course_dir + '/static/')

    # export the static tabs
    export_extra_content(export_fs, modulestore, course_location, 'static_tab',
                         'tabs', '.html')

    # export the custom tags
    export_extra_content(export_fs, modulestore, course_location,
                         'custom_tag_template', 'custom_tags')

    # export the course updates
    export_extra_content(export_fs, modulestore, course_location,
                         'course_info', 'info', '.html')

    # export the grading policy
    policies_dir = export_fs.makeopendir('policies')
    course_run_policy_dir = policies_dir.makeopendir(course.location.name)
    with course_run_policy_dir.open('grading_policy.json',
                                    'w') as grading_policy:
        grading_policy.write(dumps(course.grading_policy))

    # export all of the course metadata in policy.json
    with course_run_policy_dir.open('policy.json', 'w') as course_policy:
        policy = {'course/' + course.location.name: own_metadata(course)}
        course_policy.write(dumps(policy))

    # export draft content
    # NOTE: this code assumes that verticals are the top most draftable container
    # should we change the application, then this assumption will no longer
    # be valid
    if draft_modulestore is not None:
        draft_verticals = draft_modulestore.get_items([
            None, course_location.org, course_location.course, 'vertical',
            None, 'draft'
        ])
        if len(draft_verticals) > 0:
            draft_course_dir = export_fs.makeopendir('drafts')
            for draft_vertical in draft_verticals:
                parent_locs = draft_modulestore.get_parent_locations(
                    draft_vertical.location, course.location.course_id)
                # Don't try to export orphaned items.
                if len(parent_locs) > 0:
                    logging.debug('parent_locs = {0}'.format(parent_locs))
                    draft_vertical.xml_attributes[
                        'parent_sequential_url'] = Location(
                            parent_locs[0]).url()
                    sequential = modulestore.get_item(Location(parent_locs[0]))
                    index = sequential.children.index(
                        draft_vertical.location.url())
                    draft_vertical.xml_attributes[
                        'index_in_children_list'] = str(index)
                    draft_vertical.export_to_xml(draft_course_dir)
예제 #12
0
    def test_export_roundtrip(self, course_dir, mock_get):

        # Patch network calls to retrieve the textbook TOC
        mock_get.return_value.text = dedent("""
            <?xml version="1.0"?><table_of_contents>
            <entry page="5" page_label="ii" name="Table of Contents"/>
            </table_of_contents>
        """).strip()

        root_dir = path(self.temp_dir)
        print("Copying test course to temp dir {0}".format(root_dir))

        data_dir = path(DATA_DIR)
        shutil.copytree(data_dir / course_dir, root_dir / course_dir)

        print("Starting import")
        initial_import = XMLModuleStore(root_dir,
                                        course_dirs=[course_dir],
                                        xblock_mixins=(XModuleMixin, ))

        courses = initial_import.get_courses()
        self.assertEquals(len(courses), 1)
        initial_course = courses[0]

        # export to the same directory--that way things like the custom_tags/ folder
        # will still be there.
        print("Starting export")
        file_system = OSFS(root_dir)
        initial_course.runtime.export_fs = file_system.makeopendir(course_dir)
        root = lxml.etree.Element('root')

        initial_course.add_xml_to_node(root)
        with initial_course.runtime.export_fs.open('course.xml',
                                                   'w') as course_xml:
            lxml.etree.ElementTree(root).write(course_xml)

        print("Starting second import")
        second_import = XMLModuleStore(root_dir,
                                       course_dirs=[course_dir],
                                       xblock_mixins=(XModuleMixin, ))

        courses2 = second_import.get_courses()
        self.assertEquals(len(courses2), 1)
        exported_course = courses2[0]

        print("Checking course equality")

        # HACK: filenames change when changing file formats
        # during imports from old-style courses.  Ignore them.
        strip_filenames(initial_course)
        strip_filenames(exported_course)

        self.assertTrue(blocks_are_equivalent(initial_course, exported_course))
        self.assertEquals(initial_course.id, exported_course.id)
        course_id = initial_course.id

        print("Checking key equality")
        self.assertItemsEqual(initial_import.modules[course_id].keys(),
                              second_import.modules[course_id].keys())

        print("Checking module equality")
        for location in initial_import.modules[course_id].keys():
            print("Checking", location)
            self.assertTrue(
                blocks_are_equivalent(
                    initial_import.modules[course_id][location],
                    second_import.modules[course_id][location]))
예제 #13
0
    def test_export_roundtrip(self, course_dir, mock_get):

        # Patch network calls to retrieve the textbook TOC
        mock_get.return_value.text = dedent("""
            <?xml version="1.0"?><table_of_contents>
            <entry page="5" page_label="ii" name="Table of Contents"/>
            </table_of_contents>
        """).strip()

        root_dir = path(self.temp_dir)
        print "Copying test course to temp dir {0}".format(root_dir)

        data_dir = path(DATA_DIR)
        shutil.copytree(data_dir / course_dir, root_dir / course_dir)

        print "Starting import"
        initial_import = XMLModuleStore(root_dir, source_dirs=[course_dir], xblock_mixins=(XModuleMixin,))

        courses = initial_import.get_courses()
        self.assertEquals(len(courses), 1)
        initial_course = courses[0]

        # export to the same directory--that way things like the custom_tags/ folder
        # will still be there.
        print "Starting export"
        file_system = OSFS(root_dir)
        initial_course.runtime.export_fs = file_system.makeopendir(course_dir)
        root = lxml.etree.Element('root')

        initial_course.add_xml_to_node(root)
        with initial_course.runtime.export_fs.open('course.xml', 'w') as course_xml:
            lxml.etree.ElementTree(root).write(course_xml)

        print "Starting second import"
        second_import = XMLModuleStore(root_dir, source_dirs=[course_dir], xblock_mixins=(XModuleMixin,))

        courses2 = second_import.get_courses()
        self.assertEquals(len(courses2), 1)
        exported_course = courses2[0]

        print "Checking course equality"

        # HACK: filenames change when changing file formats
        # during imports from old-style courses.  Ignore them.
        strip_filenames(initial_course)
        strip_filenames(exported_course)

        self.assertTrue(blocks_are_equivalent(initial_course, exported_course))
        self.assertEquals(initial_course.id, exported_course.id)
        course_id = initial_course.id

        print "Checking key equality"
        self.assertItemsEqual(
            initial_import.modules[course_id].keys(),
            second_import.modules[course_id].keys()
        )

        print "Checking module equality"
        for location in initial_import.modules[course_id].keys():
            print("Checking", location)
            self.assertTrue(blocks_are_equivalent(
                initial_import.modules[course_id][location],
                second_import.modules[course_id][location]
            ))
예제 #14
0
def export_to_xml(modulestore, contentstore, course_location, root_dir, course_dir, draft_modulestore=None):
    """
    Export all modules from `modulestore` and content from `contentstore` as xml to `root_dir`.

    `modulestore`: A `ModuleStore` object that is the source of the modules to export
    `contentstore`: A `ContentStore` object that is the source of the content to export, can be None
    `course_location`: The `Location` of the `CourseModuleDescriptor` to export
    `root_dir`: The directory to write the exported xml to
    `course_dir`: The name of the directory inside `root_dir` to write the course content to
    `draft_modulestore`: An optional `DraftModuleStore` that contains draft content, which will be exported
        alongside the public content in the course.
    """

    course_id = course_location.course_id
    course = modulestore.get_course(course_id)

    fs = OSFS(root_dir)
    export_fs = fs.makeopendir(course_dir)

    xml = course.export_to_xml(export_fs)
    with export_fs.open('course.xml', 'w') as course_xml:
        course_xml.write(xml)

    # export the static assets
    policies_dir = export_fs.makeopendir('policies')
    if contentstore:
        contentstore.export_all_for_course(
            course_location,
            root_dir + '/' + course_dir + '/static/',
            root_dir + '/' + course_dir + '/policies/assets.json',
        )

    # export the static tabs
    export_extra_content(export_fs, modulestore, course_id, course_location, 'static_tab', 'tabs', '.html')

    # export the custom tags
    export_extra_content(export_fs, modulestore, course_id, course_location, 'custom_tag_template', 'custom_tags')

    # export the course updates
    export_extra_content(export_fs, modulestore, course_id, course_location, 'course_info', 'info', '.html')

    # export the 'about' data (e.g. overview, etc.)
    export_extra_content(export_fs, modulestore, course_id, course_location, 'about', 'about', '.html')

    # export the grading policy
    course_run_policy_dir = policies_dir.makeopendir(course.location.name)
    with course_run_policy_dir.open('grading_policy.json', 'w') as grading_policy:
        grading_policy.write(dumps(course.grading_policy, cls=EdxJSONEncoder))

    # export all of the course metadata in policy.json
    with course_run_policy_dir.open('policy.json', 'w') as course_policy:
        policy = {'course/' + course.location.name: own_metadata(course)}
        course_policy.write(dumps(policy, cls=EdxJSONEncoder))

    # export draft content
    # NOTE: this code assumes that verticals are the top most draftable container
    # should we change the application, then this assumption will no longer
    # be valid
    if draft_modulestore is not None:
        draft_verticals = draft_modulestore.get_items([None, course_location.org, course_location.course,
                                                       'vertical', None, 'draft'])
        if len(draft_verticals) > 0:
            draft_course_dir = export_fs.makeopendir(DRAFT_DIR)
            for draft_vertical in draft_verticals:
                parent_locs = draft_modulestore.get_parent_locations(draft_vertical.location, course.location.course_id)
                # Don't try to export orphaned items.
                if len(parent_locs) > 0:
                    logging.debug('parent_locs = {0}'.format(parent_locs))
                    draft_vertical.xml_attributes['parent_sequential_url'] = Location(parent_locs[0]).url()
                    sequential = modulestore.get_item(Location(parent_locs[0]))
                    index = sequential.children.index(draft_vertical.location.url())
                    draft_vertical.xml_attributes['index_in_children_list'] = str(index)
                    draft_vertical.export_to_xml(draft_course_dir)
예제 #15
0
def export_to_xml(modulestore,
                  contentstore,
                  course_location,
                  root_dir,
                  course_dir,
                  draft_modulestore=None):
    """
    Export all modules from `modulestore` and content from `contentstore` as xml to `root_dir`.

    `modulestore`: A `ModuleStore` object that is the source of the modules to export
    `contentstore`: A `ContentStore` object that is the source of the content to export, can be None
    `course_location`: The `Location` of the `CourseModuleDescriptor` to export
    `root_dir`: The directory to write the exported xml to
    `course_dir`: The name of the directory inside `root_dir` to write the course content to
    `draft_modulestore`: An optional `DraftModuleStore` that contains draft content, which will be exported
        alongside the public content in the course.
    """

    course_id = course_location.course_id
    course = modulestore.get_course(course_id)

    fs = OSFS(root_dir)
    export_fs = course.runtime.export_fs = fs.makeopendir(course_dir)

    root = lxml.etree.Element('unknown')
    course.add_xml_to_node(root)

    with export_fs.open('course.xml', 'w') as course_xml:
        lxml.etree.ElementTree(root).write(course_xml)

    # export the static assets
    policies_dir = export_fs.makeopendir('policies')
    if contentstore:
        contentstore.export_all_for_course(
            course_location,
            root_dir + '/' + course_dir + '/static/',
            root_dir + '/' + course_dir + '/policies/assets.json',
        )

        # If we are using the default course image, export it to the
        # legacy location to support backwards compatibility.
        if course.course_image == course.fields['course_image'].default:
            try:
                course_image = contentstore.find(
                    StaticContent.compute_location(course.location.org,
                                                   course.location.course,
                                                   course.course_image), )
            except NotFoundError:
                pass
            else:
                output_dir = root_dir + '/' + course_dir + '/static/images/'
                if not os.path.isdir(output_dir):
                    os.makedirs(output_dir)
                with OSFS(output_dir).open('course_image.jpg',
                                           'wb') as course_image_file:
                    course_image_file.write(course_image.data)

    # export the static tabs
    export_extra_content(export_fs, modulestore, course_id, course_location,
                         'static_tab', 'tabs', '.html')

    # export the custom tags
    export_extra_content(export_fs, modulestore, course_id, course_location,
                         'custom_tag_template', 'custom_tags')

    # export the course updates
    export_extra_content(export_fs, modulestore, course_id, course_location,
                         'course_info', 'info', '.html')

    # export the 'about' data (e.g. overview, etc.)
    export_extra_content(export_fs, modulestore, course_id, course_location,
                         'about', 'about', '.html')

    # export the grading policy
    course_run_policy_dir = policies_dir.makeopendir(course.location.name)
    with course_run_policy_dir.open('grading_policy.json',
                                    'w') as grading_policy:
        grading_policy.write(dumps(course.grading_policy, cls=EdxJSONEncoder))

    # export all of the course metadata in policy.json
    with course_run_policy_dir.open('policy.json', 'w') as course_policy:
        policy = {'course/' + course.location.name: own_metadata(course)}
        course_policy.write(dumps(policy, cls=EdxJSONEncoder))

    # export draft content
    # NOTE: this code assumes that verticals are the top most draftable container
    # should we change the application, then this assumption will no longer
    # be valid
    if draft_modulestore is not None:
        draft_verticals = draft_modulestore.get_items([
            None, course_location.org, course_location.course, 'vertical',
            None, 'draft'
        ])
        if len(draft_verticals) > 0:
            draft_course_dir = export_fs.makeopendir(DRAFT_DIR)
            for draft_vertical in draft_verticals:
                parent_locs = draft_modulestore.get_parent_locations(
                    draft_vertical.location, course.location.course_id)
                # Don't try to export orphaned items.
                if len(parent_locs) > 0:
                    logging.debug('parent_locs = {0}'.format(parent_locs))
                    draft_vertical.xml_attributes[
                        'parent_sequential_url'] = Location(
                            parent_locs[0]).url()
                    sequential = modulestore.get_item(Location(parent_locs[0]))
                    index = sequential.children.index(
                        draft_vertical.location.url())
                    draft_vertical.xml_attributes[
                        'index_in_children_list'] = str(index)
                    draft_vertical.runtime.export_fs = draft_course_dir
                    node = lxml.etree.Element('unknown')
                    draft_vertical.add_xml_to_node(node)
예제 #16
0
# Turn on captcha for registration
if int(myconf.take('recaptcha.use')):
    auth.settings.captcha = Recaptcha2(request,
                                       myconf.take('recaptcha.site_key'),
                                       myconf.take('recaptcha.secret_key'))

# -----------------------------------------------------------------------------
# IMPORT the CKEDITOR PLUGIN TO GIVE A WYSIWYG EDITOR FOR BLOGS AND NEWS
# -- OK, so this editor is neat but one issue is that it dumps files into the
#    root of uploads, which is messy
# -- Ordinarily, this would be controlled by the upload_folder setting but
#    this is hardcoded in the module. Could edit it there but you can also use
#    a fs object to provide a folder
# -- You'd think it might be possible to have multiple upload folders but
#    it turns out to be quite hard to switch the settings
# -----------------------------------------------------------------------------

ckeditor = CKEditor(db)

app_root = request.folder
app_root_fs = OSFS(app_root)

if not app_root_fs.exists('uploads/news_and_blogs/'):
    blog_fs = app_root_fs.makeopendir('uploads/news_and_blogs/')
else:
    blog_fs = app_root_fs.opendir('uploads/news_and_blogs/')

ckeditor.settings.uploadfs = blog_fs
ckeditor.settings.table_upload_name = 'ckeditor_uploads'
ckeditor.define_tables(fake_migrate=True)
예제 #17
0
def export_to_xml(modulestore, contentstore, course_key, root_dir, course_dir):
    """
    Export all modules from `modulestore` and content from `contentstore` as xml to `root_dir`.

    `modulestore`: A `ModuleStore` object that is the source of the modules to export
    `contentstore`: A `ContentStore` object that is the source of the content to export, can be None
    `course_key`: The `CourseKey` of the `CourseModuleDescriptor` to export
    `root_dir`: The directory to write the exported xml to
    `course_dir`: The name of the directory inside `root_dir` to write the course content to
    """

    course = modulestore.get_course(course_key)

    fsm = OSFS(root_dir)
    export_fs = course.runtime.export_fs = fsm.makeopendir(course_dir)

    root = lxml.etree.Element('unknown')

    # export only the published content
    with modulestore.branch_setting(ModuleStoreEnum.Branch.published_only,
                                    course_key):
        course.add_xml_to_node(root)

    with export_fs.open('course.xml', 'w') as course_xml:
        lxml.etree.ElementTree(root).write(course_xml)

    # export the static assets
    policies_dir = export_fs.makeopendir('policies')
    if contentstore:
        contentstore.export_all_for_course(
            course_key,
            root_dir + '/' + course_dir + '/static/',
            root_dir + '/' + course_dir + '/policies/assets.json',
        )

        # If we are using the default course image, export it to the
        # legacy location to support backwards compatibility.
        if course.course_image == course.fields['course_image'].default:
            try:
                course_image = contentstore.find(
                    StaticContent.compute_location(course.id,
                                                   course.course_image), )
            except NotFoundError:
                pass
            else:
                output_dir = root_dir + '/' + course_dir + '/static/images/'
                if not os.path.isdir(output_dir):
                    os.makedirs(output_dir)
                with OSFS(output_dir).open('course_image.jpg',
                                           'wb') as course_image_file:
                    course_image_file.write(course_image.data)

    # export the static tabs
    export_extra_content(export_fs, modulestore, course_key, 'static_tab',
                         'tabs', '.html')

    # export the custom tags
    export_extra_content(export_fs, modulestore, course_key,
                         'custom_tag_template', 'custom_tags')

    # export the course updates
    export_extra_content(export_fs, modulestore, course_key, 'course_info',
                         'info', '.html')

    # export the 'about' data (e.g. overview, etc.)
    export_extra_content(export_fs, modulestore, course_key, 'about', 'about',
                         '.html')

    # export the grading policy
    course_run_policy_dir = policies_dir.makeopendir(course.location.name)
    with course_run_policy_dir.open('grading_policy.json',
                                    'w') as grading_policy:
        grading_policy.write(dumps(course.grading_policy, cls=EdxJSONEncoder))

    # export all of the course metadata in policy.json
    with course_run_policy_dir.open('policy.json', 'w') as course_policy:
        policy = {'course/' + course.location.name: own_metadata(course)}
        course_policy.write(dumps(policy, cls=EdxJSONEncoder))

    # NOTE: this code assumes that verticals are the top most draftable container
    # should we change the application, then this assumption will no longer be valid
    # NOTE: we need to explicitly implement the logic for setting the vertical's parent
    # and index here since the XML modulestore cannot load draft modules
    draft_verticals = modulestore.get_items(
        course_key,
        category='vertical',
        revision=ModuleStoreEnum.RevisionOption.draft_only)
    if len(draft_verticals) > 0:
        draft_course_dir = export_fs.makeopendir(DRAFT_DIR)
        for draft_vertical in draft_verticals:
            parent_loc = modulestore.get_parent_location(
                draft_vertical.location,
                revision=ModuleStoreEnum.RevisionOption.draft_preferred)
            # Don't try to export orphaned items.
            if parent_loc is not None:
                logging.debug('parent_loc = {0}'.format(parent_loc))
                if parent_loc.category in DIRECT_ONLY_CATEGORIES:
                    draft_vertical.xml_attributes[
                        'parent_sequential_url'] = parent_loc.to_deprecated_string(
                        )
                    sequential = modulestore.get_item(parent_loc)
                    index = sequential.children.index(draft_vertical.location)
                    draft_vertical.xml_attributes[
                        'index_in_children_list'] = str(index)
                draft_vertical.runtime.export_fs = draft_course_dir
                node = lxml.etree.Element('unknown')
                draft_vertical.add_xml_to_node(node)
예제 #18
0
def export_to_xml(modulestore, contentstore, course_key, root_dir, course_dir):
    """
    Export all modules from `modulestore` and content from `contentstore` as xml to `root_dir`.

    `modulestore`: A `ModuleStore` object that is the source of the modules to export
    `contentstore`: A `ContentStore` object that is the source of the content to export, can be None
    `course_key`: The `CourseKey` of the `CourseModuleDescriptor` to export
    `root_dir`: The directory to write the exported xml to
    `course_dir`: The name of the directory inside `root_dir` to write the course content to
    """

    with modulestore.bulk_operations(course_key):

        course = modulestore.get_course(course_key, depth=None)  # None means infinite
        fsm = OSFS(root_dir)
        export_fs = course.runtime.export_fs = fsm.makeopendir(course_dir)
        root_course_dir = root_dir + '/' + course_dir

        root = lxml.etree.Element('unknown')

        # export only the published content
        with modulestore.branch_setting(ModuleStoreEnum.Branch.published_only, course_key):
            # change all of the references inside the course to use the xml expected key type w/o version & branch
            xml_centric_course_key = CourseLocator(course_key.org, course_key.course, course_key.run, deprecated=True)
            adapt_references(course, xml_centric_course_key, export_fs)

            course.add_xml_to_node(root)

        with export_fs.open('course.xml', 'w') as course_xml:
            lxml.etree.ElementTree(root).write(course_xml)

        # Export the modulestore's asset metadata.
        asset_dir = root_course_dir + '/' + AssetMetadata.EXPORTED_ASSET_DIR + '/'
        if not os.path.isdir(asset_dir):
            os.makedirs(asset_dir)
        asset_root = lxml.etree.Element(AssetMetadata.ALL_ASSETS_XML_TAG)
        course_assets = modulestore.get_all_asset_metadata(course_key, None)
        for asset_md in course_assets:
            # All asset types are exported using the "asset" tag - but their asset type is specified in each asset key.
            asset = lxml.etree.SubElement(asset_root, AssetMetadata.ASSET_XML_TAG)
            asset_md.to_xml(asset)
        with OSFS(asset_dir).open(AssetMetadata.EXPORTED_ASSET_FILENAME, 'w') as asset_xml_file:
            lxml.etree.ElementTree(asset_root).write(asset_xml_file)

        # export the static assets
        policies_dir = export_fs.makeopendir('policies')
        if contentstore:
            contentstore.export_all_for_course(
                course_key,
                root_course_dir + '/static/',
                root_course_dir + '/policies/assets.json',
            )

            # If we are using the default course image, export it to the
            # legacy location to support backwards compatibility.
            if course.course_image == course.fields['course_image'].default:
                try:
                    course_image = contentstore.find(
                        StaticContent.compute_location(
                            course.id,
                            course.course_image
                        ),
                    )
                except NotFoundError:
                    pass
                else:
                    output_dir = root_course_dir + '/static/images/'
                    if not os.path.isdir(output_dir):
                        os.makedirs(output_dir)
                    with OSFS(output_dir).open('course_image.jpg', 'wb') as course_image_file:
                        course_image_file.write(course_image.data)

        # export the static tabs
        export_extra_content(export_fs, modulestore, course_key, xml_centric_course_key, 'static_tab', 'tabs', '.html')

        # export the custom tags
        export_extra_content(export_fs, modulestore, course_key, xml_centric_course_key, 'custom_tag_template', 'custom_tags')

        # export the course updates
        export_extra_content(export_fs, modulestore, course_key, xml_centric_course_key, 'course_info', 'info', '.html')

        # export the 'about' data (e.g. overview, etc.)
        export_extra_content(export_fs, modulestore, course_key, xml_centric_course_key, 'about', 'about', '.html')

        # export the grading policy
        course_run_policy_dir = policies_dir.makeopendir(course.location.name)
        with course_run_policy_dir.open('grading_policy.json', 'w') as grading_policy:
            grading_policy.write(dumps(course.grading_policy, cls=EdxJSONEncoder, sort_keys=True, indent=4))

        # export all of the course metadata in policy.json
        with course_run_policy_dir.open('policy.json', 'w') as course_policy:
            policy = {'course/' + course.location.name: own_metadata(course)}
            course_policy.write(dumps(policy, cls=EdxJSONEncoder, sort_keys=True, indent=4))

        #### DRAFTS ####
        # xml backed courses don't support drafts!
        if course.runtime.modulestore.get_modulestore_type() != ModuleStoreEnum.Type.xml:
            # NOTE: we need to explicitly implement the logic for setting the vertical's parent
            # and index here since the XML modulestore cannot load draft modules
            with modulestore.branch_setting(ModuleStoreEnum.Branch.draft_preferred, course_key):
                draft_modules = modulestore.get_items(
                    course_key,
                    qualifiers={'category': {'$nin': DIRECT_ONLY_CATEGORIES}},
                    revision=ModuleStoreEnum.RevisionOption.draft_only
                )

                if draft_modules:
                    draft_course_dir = export_fs.makeopendir(DRAFT_DIR)

                    # accumulate tuples of draft_modules and their parents in
                    # this list:
                    draft_node_list = []

                    for draft_module in draft_modules:
                        parent_loc = modulestore.get_parent_location(
                            draft_module.location,
                            revision=ModuleStoreEnum.RevisionOption.draft_preferred
                        )

                        # if module has no parent, set its parent_url to `None`
                        parent_url = None
                        if parent_loc is not None:
                            parent_url = parent_loc.to_deprecated_string()

                        draft_node = draft_node_constructor(
                            draft_module,
                            location=draft_module.location,
                            url=draft_module.location.to_deprecated_string(),
                            parent_location=parent_loc,
                            parent_url=parent_url,
                        )

                        draft_node_list.append(draft_node)

                    for draft_node in get_draft_subtree_roots(draft_node_list):
                        # only export the roots of the draft subtrees
                        # since export_from_xml (called by `add_xml_to_node`)
                        # exports a whole tree

                        # ensure module has "xml_attributes" attr
                        if not hasattr(draft_node.module, 'xml_attributes'):
                            draft_node.module.xml_attributes = {}

                        # Don't try to export orphaned items
                        # and their descendents
                        if draft_node.parent_location is None:
                            continue

                        logging.debug('parent_loc = {0}'.format(draft_node.parent_location))

                        draft_node.module.xml_attributes['parent_url'] = draft_node.parent_url
                        parent = modulestore.get_item(draft_node.parent_location)
                        index = parent.children.index(draft_node.module.location)
                        draft_node.module.xml_attributes['index_in_children_list'] = str(index)

                        draft_node.module.runtime.export_fs = draft_course_dir
                        adapt_references(draft_node.module, xml_centric_course_key, draft_course_dir)
                        node = lxml.etree.Element('unknown')

                        draft_node.module.add_xml_to_node(node)
예제 #19
0
def export_to_xml(modulestore, contentstore, course_key, root_dir, course_dir):
    """
    Export all modules from `modulestore` and content from `contentstore` as xml to `root_dir`.

    `modulestore`: A `ModuleStore` object that is the source of the modules to export
    `contentstore`: A `ContentStore` object that is the source of the content to export, can be None
    `course_key`: The `CourseKey` of the `CourseModuleDescriptor` to export
    `root_dir`: The directory to write the exported xml to
    `course_dir`: The name of the directory inside `root_dir` to write the course content to
    """

    with modulestore.bulk_operations(course_key):

        course = modulestore.get_course(course_key, depth=None)  # None means infinite
        fsm = OSFS(root_dir)
        export_fs = course.runtime.export_fs = fsm.makeopendir(course_dir)

        root = lxml.etree.Element('unknown')

        # export only the published content
        with modulestore.branch_setting(ModuleStoreEnum.Branch.published_only, course_key):
            # change all of the references inside the course to use the xml expected key type w/o version & branch
            xml_centric_course_key = CourseLocator(course_key.org, course_key.course, course_key.run, deprecated=True)
            adapt_references(course, xml_centric_course_key, export_fs)

            course.add_xml_to_node(root)

        with export_fs.open('course.xml', 'w') as course_xml:
            lxml.etree.ElementTree(root).write(course_xml)

        # export the static assets
        policies_dir = export_fs.makeopendir('policies')
        if contentstore:
            contentstore.export_all_for_course(
                course_key,
                root_dir + '/' + course_dir + '/static/',
                root_dir + '/' + course_dir + '/policies/assets.json',
            )

            # If we are using the default course image, export it to the
            # legacy location to support backwards compatibility.
            if course.course_image == course.fields['course_image'].default:
                try:
                    course_image = contentstore.find(
                        StaticContent.compute_location(
                            course.id,
                            course.course_image
                        ),
                    )
                except NotFoundError:
                    pass
                else:
                    output_dir = root_dir + '/' + course_dir + '/static/images/'
                    if not os.path.isdir(output_dir):
                        os.makedirs(output_dir)
                    with OSFS(output_dir).open('course_image.jpg', 'wb') as course_image_file:
                        course_image_file.write(course_image.data)

        # export the static tabs
        export_extra_content(export_fs, modulestore, course_key, xml_centric_course_key, 'static_tab', 'tabs', '.html')

        # export the custom tags
        export_extra_content(export_fs, modulestore, course_key, xml_centric_course_key, 'custom_tag_template', 'custom_tags')

        # export the course updates
        export_extra_content(export_fs, modulestore, course_key, xml_centric_course_key, 'course_info', 'info', '.html')

        # export the 'about' data (e.g. overview, etc.)
        export_extra_content(export_fs, modulestore, course_key, xml_centric_course_key, 'about', 'about', '.html')

        # export the grading policy
        course_run_policy_dir = policies_dir.makeopendir(course.location.name)
        with course_run_policy_dir.open('grading_policy.json', 'w') as grading_policy:
            grading_policy.write(dumps(course.grading_policy, cls=EdxJSONEncoder, sort_keys=True, indent=4))

        # export all of the course metadata in policy.json
        with course_run_policy_dir.open('policy.json', 'w') as course_policy:
            policy = {'course/' + course.location.name: own_metadata(course)}
            course_policy.write(dumps(policy, cls=EdxJSONEncoder, sort_keys=True, indent=4))

        #### DRAFTS ####
        # xml backed courses don't support drafts!
        if course.runtime.modulestore.get_modulestore_type() != ModuleStoreEnum.Type.xml:
            # NOTE: this code assumes that verticals are the top most draftable container
            # should we change the application, then this assumption will no longer be valid
            # NOTE: we need to explicitly implement the logic for setting the vertical's parent
            # and index here since the XML modulestore cannot load draft modules
            with modulestore.branch_setting(ModuleStoreEnum.Branch.draft_preferred, course_key):
                draft_verticals = modulestore.get_items(
                    course_key,
                    qualifiers={'category': 'vertical'},
                    revision=ModuleStoreEnum.RevisionOption.draft_only
                )

                if len(draft_verticals) > 0:
                    draft_course_dir = export_fs.makeopendir(DRAFT_DIR)
                    for draft_vertical in draft_verticals:
                        parent_loc = modulestore.get_parent_location(
                            draft_vertical.location,
                            revision=ModuleStoreEnum.RevisionOption.draft_preferred
                        )
                        # Don't try to export orphaned items.
                        if parent_loc is not None:
                            logging.debug('parent_loc = {0}'.format(parent_loc))
                            if parent_loc.category in DIRECT_ONLY_CATEGORIES:
                                draft_vertical.xml_attributes['parent_sequential_url'] = parent_loc.to_deprecated_string()
                                sequential = modulestore.get_item(parent_loc)
                                index = sequential.children.index(draft_vertical.location)
                                draft_vertical.xml_attributes['index_in_children_list'] = str(index)
                            draft_vertical.runtime.export_fs = draft_course_dir
                            adapt_references(draft_vertical, xml_centric_course_key, draft_course_dir)
                            node = lxml.etree.Element('unknown')
                            draft_vertical.add_xml_to_node(node)
예제 #20
0
def export_to_xml(modulestore, contentstore, course_key, root_dir, course_dir):
    """
    Export all modules from `modulestore` and content from `contentstore` as xml to `root_dir`.

    `modulestore`: A `ModuleStore` object that is the source of the modules to export
    `contentstore`: A `ContentStore` object that is the source of the content to export, can be None
    `course_key`: The `CourseKey` of the `CourseModuleDescriptor` to export
    `root_dir`: The directory to write the exported xml to
    `course_dir`: The name of the directory inside `root_dir` to write the course content to
    """

    with modulestore.bulk_operations(course_key):

        course = modulestore.get_course(course_key, depth=None)  # None means infinite
        fsm = OSFS(root_dir)
        export_fs = course.runtime.export_fs = fsm.makeopendir(course_dir)

        root = lxml.etree.Element("unknown")

        # export only the published content
        with modulestore.branch_setting(ModuleStoreEnum.Branch.published_only, course_key):
            # change all of the references inside the course to use the xml expected key type w/o version & branch
            xml_centric_course_key = CourseLocator(course_key.org, course_key.course, course_key.run, deprecated=True)
            adapt_references(course, xml_centric_course_key, export_fs)

            course.add_xml_to_node(root)

        with export_fs.open("course.xml", "w") as course_xml:
            lxml.etree.ElementTree(root).write(course_xml)

        # export the static assets
        policies_dir = export_fs.makeopendir("policies")
        if contentstore:
            contentstore.export_all_for_course(
                course_key,
                root_dir + "/" + course_dir + "/static/",
                root_dir + "/" + course_dir + "/policies/assets.json",
            )

            # If we are using the default course image, export it to the
            # legacy location to support backwards compatibility.
            if course.course_image == course.fields["course_image"].default:
                try:
                    course_image = contentstore.find(StaticContent.compute_location(course.id, course.course_image))
                except NotFoundError:
                    pass
                else:
                    output_dir = root_dir + "/" + course_dir + "/static/images/"
                    if not os.path.isdir(output_dir):
                        os.makedirs(output_dir)
                    with OSFS(output_dir).open("course_image.jpg", "wb") as course_image_file:
                        course_image_file.write(course_image.data)

        # export the static tabs
        export_extra_content(export_fs, modulestore, course_key, xml_centric_course_key, "static_tab", "tabs", ".html")

        # export the custom tags
        export_extra_content(
            export_fs, modulestore, course_key, xml_centric_course_key, "custom_tag_template", "custom_tags"
        )

        # export the course updates
        export_extra_content(export_fs, modulestore, course_key, xml_centric_course_key, "course_info", "info", ".html")

        # export the 'about' data (e.g. overview, etc.)
        export_extra_content(export_fs, modulestore, course_key, xml_centric_course_key, "about", "about", ".html")

        # export the grading policy
        course_run_policy_dir = policies_dir.makeopendir(course.location.name)
        with course_run_policy_dir.open("grading_policy.json", "w") as grading_policy:
            grading_policy.write(dumps(course.grading_policy, cls=EdxJSONEncoder, sort_keys=True, indent=4))

        # export all of the course metadata in policy.json
        with course_run_policy_dir.open("policy.json", "w") as course_policy:
            policy = {"course/" + course.location.name: own_metadata(course)}
            course_policy.write(dumps(policy, cls=EdxJSONEncoder, sort_keys=True, indent=4))

        #### DRAFTS ####
        # xml backed courses don't support drafts!
        if course.runtime.modulestore.get_modulestore_type() != ModuleStoreEnum.Type.xml:
            # NOTE: we need to explicitly implement the logic for setting the vertical's parent
            # and index here since the XML modulestore cannot load draft modules
            with modulestore.branch_setting(ModuleStoreEnum.Branch.draft_preferred, course_key):
                draft_modules = modulestore.get_items(
                    course_key,
                    qualifiers={"category": {"$nin": DIRECT_ONLY_CATEGORIES}},
                    revision=ModuleStoreEnum.RevisionOption.draft_only,
                )

                if draft_modules:
                    draft_course_dir = export_fs.makeopendir(DRAFT_DIR)

                    # accumulate tuples of draft_modules and their parents in
                    # this list:
                    draft_node_list = []

                    for draft_module in draft_modules:
                        parent_loc = modulestore.get_parent_location(
                            draft_module.location, revision=ModuleStoreEnum.RevisionOption.draft_preferred
                        )
                        # Don't try to export orphaned items.
                        if parent_loc is not None:
                            logging.debug("parent_loc = {0}".format(parent_loc))
                            draft_node = draft_node_constructor(
                                draft_module,
                                location=draft_module.location,
                                url=draft_module.location.to_deprecated_string(),
                                parent_location=parent_loc,
                                parent_url=parent_loc.to_deprecated_string(),
                            )

                            draft_node_list.append(draft_node)

                    for draft_node in get_draft_subtree_roots(draft_node_list):
                        # only export the roots of the draft subtrees
                        # since export_from_xml (called by `add_xml_to_node`)
                        # exports a whole tree

                        draft_node.module.xml_attributes["parent_url"] = draft_node.parent_url
                        parent = modulestore.get_item(draft_node.parent_location)
                        index = parent.children.index(draft_node.module.location)
                        draft_node.module.xml_attributes["index_in_children_list"] = str(index)

                        draft_node.module.runtime.export_fs = draft_course_dir
                        adapt_references(draft_node.module, xml_centric_course_key, draft_course_dir)
                        node = lxml.etree.Element("unknown")

                        draft_node.module.add_xml_to_node(node)
예제 #21
0
def export_to_xml(modulestore, contentstore, course_key, root_dir, course_dir):
    """
    Export all modules from `modulestore` and content from `contentstore` as xml to `root_dir`.

    `modulestore`: A `ModuleStore` object that is the source of the modules to export
    `contentstore`: A `ContentStore` object that is the source of the content to export, can be None
    `course_key`: The `CourseKey` of the `CourseModuleDescriptor` to export
    `root_dir`: The directory to write the exported xml to
    `course_dir`: The name of the directory inside `root_dir` to write the course content to
    """

    with modulestore.bulk_operations(course_key):

        course = modulestore.get_course(course_key,
                                        depth=None)  # None means infinite
        fsm = OSFS(root_dir)
        export_fs = course.runtime.export_fs = fsm.makeopendir(course_dir)

        root = lxml.etree.Element('unknown')

        # export only the published content
        with modulestore.branch_setting(ModuleStoreEnum.Branch.published_only,
                                        course_key):
            # change all of the references inside the course to use the xml expected key type w/o version & branch
            xml_centric_course_key = CourseLocator(course_key.org,
                                                   course_key.course,
                                                   course_key.run,
                                                   deprecated=True)
            adapt_references(course, xml_centric_course_key, export_fs)

            course.add_xml_to_node(root)

        with export_fs.open('course.xml', 'w') as course_xml:
            lxml.etree.ElementTree(root).write(course_xml)

        # export the static assets
        policies_dir = export_fs.makeopendir('policies')
        if contentstore:
            contentstore.export_all_for_course(
                course_key,
                root_dir + '/' + course_dir + '/static/',
                root_dir + '/' + course_dir + '/policies/assets.json',
            )

            # If we are using the default course image, export it to the
            # legacy location to support backwards compatibility.
            if course.course_image == course.fields['course_image'].default:
                try:
                    course_image = contentstore.find(
                        StaticContent.compute_location(course.id,
                                                       course.course_image), )
                except NotFoundError:
                    pass
                else:
                    output_dir = root_dir + '/' + course_dir + '/static/images/'
                    if not os.path.isdir(output_dir):
                        os.makedirs(output_dir)
                    with OSFS(output_dir).open('course_image.jpg',
                                               'wb') as course_image_file:
                        course_image_file.write(course_image.data)

        # export the static tabs
        export_extra_content(export_fs, modulestore, course_key,
                             xml_centric_course_key, 'static_tab', 'tabs',
                             '.html')

        # export the custom tags
        export_extra_content(export_fs, modulestore, course_key,
                             xml_centric_course_key, 'custom_tag_template',
                             'custom_tags')

        # export the course updates
        export_extra_content(export_fs, modulestore, course_key,
                             xml_centric_course_key, 'course_info', 'info',
                             '.html')

        # export the 'about' data (e.g. overview, etc.)
        export_extra_content(export_fs, modulestore, course_key,
                             xml_centric_course_key, 'about', 'about', '.html')

        # export the grading policy
        course_run_policy_dir = policies_dir.makeopendir(course.location.name)
        with course_run_policy_dir.open('grading_policy.json',
                                        'w') as grading_policy:
            grading_policy.write(
                dumps(course.grading_policy,
                      cls=EdxJSONEncoder,
                      sort_keys=True,
                      indent=4))

        # export all of the course metadata in policy.json
        with course_run_policy_dir.open('policy.json', 'w') as course_policy:
            policy = {'course/' + course.location.name: own_metadata(course)}
            course_policy.write(
                dumps(policy, cls=EdxJSONEncoder, sort_keys=True, indent=4))

        #### DRAFTS ####
        # xml backed courses don't support drafts!
        if course.runtime.modulestore.get_modulestore_type(
        ) != ModuleStoreEnum.Type.xml:
            # NOTE: we need to explicitly implement the logic for setting the vertical's parent
            # and index here since the XML modulestore cannot load draft modules
            with modulestore.branch_setting(
                    ModuleStoreEnum.Branch.draft_preferred, course_key):
                draft_modules = modulestore.get_items(
                    course_key,
                    qualifiers={'category': {
                        '$nin': DIRECT_ONLY_CATEGORIES
                    }},
                    revision=ModuleStoreEnum.RevisionOption.draft_only)

                if draft_modules:
                    draft_course_dir = export_fs.makeopendir(DRAFT_DIR)

                    # accumulate tuples of draft_modules and their parents in
                    # this list:
                    draft_node_list = []

                    for draft_module in draft_modules:
                        parent_loc = modulestore.get_parent_location(
                            draft_module.location,
                            revision=ModuleStoreEnum.RevisionOption.
                            draft_preferred)

                        # if module has no parent, set its parent_url to `None`
                        parent_url = None
                        if parent_loc is not None:
                            parent_url = parent_loc.to_deprecated_string()

                        draft_node = draft_node_constructor(
                            draft_module,
                            location=draft_module.location,
                            url=draft_module.location.to_deprecated_string(),
                            parent_location=parent_loc,
                            parent_url=parent_url,
                        )

                        draft_node_list.append(draft_node)

                    for draft_node in get_draft_subtree_roots(draft_node_list):
                        # only export the roots of the draft subtrees
                        # since export_from_xml (called by `add_xml_to_node`)
                        # exports a whole tree

                        # ensure module has "xml_attributes" attr
                        if not hasattr(draft_node.module, 'xml_attributes'):
                            draft_node.module.xml_attributes = {}

                        # Don't try to export orphaned items
                        # and their descendents
                        if draft_node.parent_location is None:
                            continue

                        logging.debug('parent_loc = {0}'.format(
                            draft_node.parent_location))

                        draft_node.module.xml_attributes[
                            'parent_url'] = draft_node.parent_url
                        parent = modulestore.get_item(
                            draft_node.parent_location)
                        index = parent.children.index(
                            draft_node.module.location)
                        draft_node.module.xml_attributes[
                            'index_in_children_list'] = str(index)

                        draft_node.module.runtime.export_fs = draft_course_dir
                        adapt_references(draft_node.module,
                                         xml_centric_course_key,
                                         draft_course_dir)
                        node = lxml.etree.Element('unknown')

                        draft_node.module.add_xml_to_node(node)
예제 #22
0
except IndexError:
    src = '~/projects/linkstop/webapp/linkstop/media/faviconsx'
    dst = '~/projects/linkstop/webapp/linkstop/media/favicons'

src_fs = OSFS(src)
dst_fs = OSFS(dst)

count = 0
max_count = 2
for path in src_fs.listdir(dirs_only=True):
    icon_fs = src_fs.opendir(path)
    if icon_fs.isfile('scan.pik'):
        try:
            icon = pickle.load(icon_fs.open('scan.pik'))
        except Exception, e:
            print "%s (%s)" % (str(e), path)
            continue
        normalized_url = icon['normalized_url']
        out_dir = hash_path(normalized_url) + '/' + url_to_filename(normalized_url)
        print out_dir

        dest_dir_fs = dst_fs.makeopendir(out_dir, recursive=True)


        movedir(icon_fs, dest_dir_fs, overwrite=True, ignore_errors=True)

        #count += 1

    if count >= max_count:
        break
예제 #23
0
def export_to_xml(modulestore, contentstore, course_key, root_dir, course_dir, draft_modulestore=None):
    """
    Export all modules from `modulestore` and content from `contentstore` as xml to `root_dir`.

    `modulestore`: A `ModuleStore` object that is the source of the modules to export
    `contentstore`: A `ContentStore` object that is the source of the content to export, can be None
    `course_key`: The `CourseKey` of the `CourseModuleDescriptor` to export
    `root_dir`: The directory to write the exported xml to
    `course_dir`: The name of the directory inside `root_dir` to write the course content to
    `draft_modulestore`: An optional `DraftModuleStore` that contains draft content, which will be exported
        alongside the public content in the course.
    """

    course = modulestore.get_course(course_key)

    fsm = OSFS(root_dir)
    export_fs = course.runtime.export_fs = fsm.makeopendir(course_dir)

    root = lxml.etree.Element("unknown")
    course.add_xml_to_node(root)

    with export_fs.open("course.xml", "w") as course_xml:
        lxml.etree.ElementTree(root).write(course_xml)

    # export the static assets
    policies_dir = export_fs.makeopendir("policies")
    if contentstore:
        contentstore.export_all_for_course(
            course_key, root_dir + "/" + course_dir + "/static/", root_dir + "/" + course_dir + "/policies/assets.json"
        )

        # If we are using the default course image, export it to the
        # legacy location to support backwards compatibility.
        if course.course_image == course.fields["course_image"].default:
            try:
                course_image = contentstore.find(StaticContent.compute_location(course.id, course.course_image))
            except NotFoundError:
                pass
            else:
                output_dir = root_dir + "/" + course_dir + "/static/images/"
                if not os.path.isdir(output_dir):
                    os.makedirs(output_dir)
                with OSFS(output_dir).open("course_image.jpg", "wb") as course_image_file:
                    course_image_file.write(course_image.data)

    # export the static tabs
    export_extra_content(export_fs, modulestore, course_key, "static_tab", "tabs", ".html")

    # export the custom tags
    export_extra_content(export_fs, modulestore, course_key, "custom_tag_template", "custom_tags")

    # export the course updates
    export_extra_content(export_fs, modulestore, course_key, "course_info", "info", ".html")

    # export the 'about' data (e.g. overview, etc.)
    export_extra_content(export_fs, modulestore, course_key, "about", "about", ".html")

    # export the grading policy
    course_run_policy_dir = policies_dir.makeopendir(course.location.name)
    with course_run_policy_dir.open("grading_policy.json", "w") as grading_policy:
        grading_policy.write(dumps(course.grading_policy, cls=EdxJSONEncoder))

    # export all of the course metadata in policy.json
    with course_run_policy_dir.open("policy.json", "w") as course_policy:
        policy = {"course/" + course.location.name: own_metadata(course)}
        course_policy.write(dumps(policy, cls=EdxJSONEncoder))

    # export draft content
    # NOTE: this code assumes that verticals are the top most draftable container
    # should we change the application, then this assumption will no longer
    # be valid
    if draft_modulestore is not None:
        draft_verticals = draft_modulestore.get_items(course_key, category="vertical", revision="draft")
        if len(draft_verticals) > 0:
            draft_course_dir = export_fs.makeopendir(DRAFT_DIR)
            for draft_vertical in draft_verticals:
                parent_locs = draft_modulestore.get_parent_locations(draft_vertical.location)
                # Don't try to export orphaned items.
                if len(parent_locs) > 0:
                    logging.debug("parent_locs = {0}".format(parent_locs))
                    draft_vertical.xml_attributes["parent_sequential_url"] = parent_locs[0].to_deprecated_string()
                    sequential = modulestore.get_item(parent_locs[0])
                    index = sequential.children.index(draft_vertical.location)
                    draft_vertical.xml_attributes["index_in_children_list"] = str(index)
                    draft_vertical.runtime.export_fs = draft_course_dir
                    node = lxml.etree.Element("unknown")
                    draft_vertical.add_xml_to_node(node)
예제 #24
0
from fs.osfs import OSFS
from fs.errors import ResourceNotFoundError
import settings as s
from backend import fetch_repo, create_production, build
from utils import load_repos

root_fs = OSFS(s.root_path)
build_fs = root_fs.makeopendir(s.build_path)
build_fs.makedir(s.sources_path)
build_fs.makedir(s.staging_path)
build_fs.makedir(s.register_path)

# create production directory if needed
try:
    production_fs = OSFS(s.production_path)
except ResourceNotFoundError:
    # grap production dir's parent dir
    path = s.production_path.split('/')[-2]
    print path
    production_fs = OSFS(s.production_path[:len(s.production_path) - (len(path) + 1)]).makeopendir(path)
    print production_fs

if production_fs.exists(s.backups_path) == False:
    production_fs.makedir(s.backups_path)

# fetch repos from GitHub
for repo in load_repos(s.repos_path)[0].values():
    print 'Fetching %s for the first time' % repo['id']
    fetch_repo(root_fs, s.sources_path, repo['id'], repo['url'], s.build_path)
    build(s.sources_path, s.register_path, root_fs, repo['id'])