Ejemplo n.º 1
0
def _render_rst_to_jinja_templating(course, page_path, content):
    cache_pages = syllabus.get_config()["caching"]["cache_pages"]
    toc = syllabus.get_toc(course)
    print_mode = session.get("print_mode", False)
    # look if we have a cached version of this content
    if cache_pages and toc.has_cached_content(content, print_mode):
        with open(
                safe_join(syllabus.get_pages_path(course),
                          content.cached_path(print_mode)), "r") as f:
            rendered = f.read()
    else:
        # render the content
        with open(safe_join(syllabus.get_pages_path(course), page_path),
                  "r") as f:
            rendered = publish_string(f.read(),
                                      writer_name='html',
                                      settings_overrides=default_rst_opts)
        if cache_pages:  # cache the content if needed
            if type(content) is Page:
                parent = toc.get_parent_of(content)
                os.makedirs(safe_join(
                    toc.cached_path(print_mode),
                    parent.path if parent is not None else ""),
                            exist_ok=True)
            else:
                os.makedirs(safe_join(toc.cached_path(print_mode),
                                      content.path),
                            exist_ok=True)
            with open(
                    safe_join(syllabus.get_pages_path(course),
                              content.cached_path(print_mode)),
                    "w") as cached_content:
                cached_content.write(rendered)
    return rendered
Ejemplo n.º 2
0
def edit_content(course, content_path, TOC: TableOfContent):
    try:
        content = TOC.get_page_from_path("%s.rst" % content_path)
    except ContentNotFoundError:
        content = TOC.get_content_from_path(content_path)
    if request.method == "POST":
        inpt = request.form
        if "new_content" not in inpt:
            return seeother(request.path)
        else:
            if type(content) is Chapter:
                with open(
                        safe_join(syllabus.get_pages_path(course),
                                  content.path, "chapter_introduction.rst"),
                        "w") as f:
                    f.write(inpt["new_content"])
            else:
                with open(
                        safe_join(syllabus.get_pages_path(course),
                                  content.path), "w") as f:
                    f.write(inpt["new_content"])
            return seeother(request.path)
    elif request.method == "GET":
        return render_template("edit_page.html",
                               content_data=get_content_data(course, content),
                               content=content,
                               TOC=TOC)
Ejemplo n.º 3
0
def toc_edition(course):
    if not course in syllabus.get_config()["courses"].keys():
        abort(404)
    toc = syllabus.get_toc(course)
    if toc.ignored and not has_feedback(session):
        set_feedback(
            session,
            Feedback(feedback_type="warning",
                     message="The following contents have not been found :\n" +
                     "<pre>" + "\n".join(toc.ignored) + "</pre>"))
    if request.method == "POST":
        inpt = request.form
        if "new_content" in inpt:
            try:
                # check YAML validity
                toc_dict = yaml.load(inpt["new_content"],
                                     OrderedDictYAMLLoader)
                if not TableOfContent.is_toc_dict_valid(
                        syllabus.get_pages_path(course), toc_dict):
                    set_feedback(
                        session,
                        Feedback(feedback_type="error",
                                 message="The submitted table of contents "
                                 "is not consistent with the files "
                                 "located in the pages directory."))
                    return seeother(request.path)
            except yaml.YAMLError:
                set_feedback(
                    session,
                    Feedback(feedback_type="error",
                             message="The submitted table of contents is not "
                             "written in valid YAML."))
                return seeother(request.path)
            # the YAML is valid, write it in the ToC
            with open(
                    os.path.join(syllabus.get_pages_path(course), "toc.yaml"),
                    "w") as f:
                f.write(inpt["new_content"])
            syllabus.get_toc(course, force=True)
        set_feedback(
            session,
            Feedback(feedback_type="success",
                     message="The table of contents has been modified "
                     "successfully !"))
        return seeother(request.path)
    else:
        with open(os.path.join(syllabus.get_pages_path(course), "toc.yaml"),
                  "r") as f:
            try:
                return render_template(
                    'edit_table_of_content.html',
                    active_element=sidebar['active_element'],
                    sidebar_elements=sidebar['elements'],
                    content=f.read(),
                    feedback=pop_feeback(session))
            except TemplateNotFound:
                abort(404)
Ejemplo n.º 4
0
def render_rst_file(course, page_path, **kwargs):
    with open(safe_join(syllabus.get_pages_path(course), page_path), "r") as f:
        # TODO: cache the return value of publish_string, it should not change per user
        return render_template_string(
            publish_string(f.read(),
                           writer_name='html',
                           settings_overrides=default_rst_opts), **kwargs)
Ejemplo n.º 5
0
def delete_content(course, inpt, TOC):
    pages_path = syllabus.get_pages_path(course)
    content_path = inpt["content-path"]
    path = os.path.join(pages_path, content_path)

    content_to_delete = TOC.get_content_from_path(content_path)
    TOC.remove_content_from_toc(content_to_delete)

    # dump the TOC and reload it
    syllabus.save_toc(course, TOC)
    syllabus.get_toc(course, force=True)

    # remove the files if asked
    if inpt.get("delete-files", None) == "on":
        if type(content_to_delete) is Chapter:
            # delete a chapter
            shutil.rmtree(os.path.join(path))
        else:
            # delete a page
            os.remove(path)

    set_feedback(
        session,
        Feedback(feedback_type="success",
                 message="The content has been successfully deleted"))
    return seeother(request.path)
Ejemplo n.º 6
0
def init_and_sync_repo(course, force_sync=False):
    """
    Initializes a git repository in the pages folder if no repository already exists, then
    synchronizes it with the remote specified in the configuration file if the
    origin didn't exist before or if force_sync is True.
    Warning: the local changes will be overwritten.
    :return:
    """
    path = os.path.join(syllabus.get_root_path(),
                        syllabus.get_pages_path(course))
    git_config = syllabus.get_config()['courses'][course]['pages']['git']
    try:
        if not os.path.exists(path):
            os.makedirs(path)
        repo = Repo(path)
    except InvalidGitRepositoryError:
        # this is currently not a git repo
        repo = Repo.init(path)
    try:
        origin = repo.remote("origin").set_url(git_config['remote'])
    except:
        origin = repo.create_remote("origin", git_config['remote'])
        # sync the repo if the origin wasn't already there
        force_sync = True
    if force_sync:
        git_force_sync(course, origin, repo)
        syllabus.get_toc(course, True)
Ejemplo n.º 7
0
def get_content_data(course, content: Content):
    # TODO: use the same attr for chapter and page to get the file path
    path = content.description_path if type(content) is Chapter else content.path
    try:
        with open(safe_join(syllabus.get_pages_path(course), path), "r") as f:
            return f.read()
    except FileNotFoundError:
        return ""
Ejemplo n.º 8
0
def get_content_data(content: Content):
    path = content.path if type(content) is Page else safe_join(
        content.path, "chapter_introduction.rst")
    try:
        with open(safe_join(syllabus.get_pages_path(), path), "r") as f:
            return f.read()
    except FileNotFoundError:
        return ""
Ejemplo n.º 9
0
 def __init__(self, path, title, description=None, pages_path=None):
     pages_path = pages_path if pages_path is not None else syllabus.get_pages_path(
     )
     file_path = os.path.join(pages_path, path)
     if not os.path.isdir(file_path):
         raise ContentNotFoundError(file_path)
     super().__init__(path, title)
     self.description = description
Ejemplo n.º 10
0
 def __init__(self, path, title, pages_path=None):
     pages_path = pages_path if pages_path is not None else syllabus.get_pages_path(
     )
     # a page should be an rST file, and should have the .rst extension, for security purpose
     file_path = os.path.join(pages_path, path)
     if path[-4:] != ".rst" or not os.path.isfile(file_path):
         raise ContentNotFoundError(file_path)
     super().__init__(path, title)
Ejemplo n.º 11
0
def get_chapter_intro(course, chapter):
    try:
        with open(safe_join(syllabus.get_pages_path(course), chapter.path,
                            "chapter_introduction.rst"),
                  'r',
                  encoding="utf-8") as f:
            return f.read()
    except FileNotFoundError:
        return ""
Ejemplo n.º 12
0
def render_footer(course):
    try:
        with open(safe_join(syllabus.get_pages_path(course),
                            "footer.rst")) as f:
            return publish_string(f.read(),
                                  writer_name='html',
                                  settings_overrides=default_rst_opts)
    except FileNotFoundError as e:
        return ""
Ejemplo n.º 13
0
    def __init__(self, course, toc_file=None, ignore_not_found=True):
        """

        :param toc_file: the yaml file used to describe the toc
        :param ignore_not_found: if set to True, simply ignore chapters and pages that are in the toc file
        but not on the file system. Raises a ContentNotFoundError otherwise
        """
        self.toc_path = get_pages_path(course)
        toc_file = toc_file if toc_file is not None else safe_join(self.toc_path, "toc.yaml")
        with open(toc_file, "r") as f:
            toc_dict = yaml.load(f, OrderedDictYAMLLoader)
            self._init_from_dict(toc_dict, ignore_not_found)
Ejemplo n.º 14
0
def generate_toc_yaml(course):
    def create_dict(path, name):
        retval = {"title": name, "content": {}}
        for entry in os.listdir(path):
            if entry[0] != ".":
                if os.path.isdir(os.path.join(path, entry)):
                    retval["content"][entry] = create_dict(os.path.join(path, entry), entry)
                elif entry[-4:] == ".rst" and entry not in ["chapter_introduction.rst"]:
                    retval["content"][entry] = {"title": entry[:-4]}
        return retval

    path = syllabus.get_pages_path(course)
    result = {}
    for dir in [d for d in os.listdir(path) if os.path.isdir(os.path.join(path, d))]:
        result[dir] = create_dict(os.path.join(path, dir), dir)
    return str(yaml.dump(result))
Ejemplo n.º 15
0
 def __init__(self, toc_file=None):
     toc_file = toc_file if toc_file is not None else os.path.join(
         get_pages_path(), "toc.yaml")
     with open(toc_file, "r") as f:
         toc_dict = yaml.load(f, OrderedDictYAMLLoader)
         self._init_from_dict(toc_dict)
Ejemplo n.º 16
0
def content_edition(course):
    if not course in syllabus.get_config()["courses"].keys():
        abort(404)
    TOC = syllabus.get_toc(course)
    if TOC.ignored and not has_feedback(session):
        set_feedback(
            session,
            Feedback(feedback_type="warning",
                     message="The following contents have not been found :\n" +
                     "<pre>" + "\n".join(TOC.ignored) + "</pre>"))
    if request.method == "POST":
        inpt = request.form
        if inpt["action"] == "delete_content":
            return delete_content(course, inpt, TOC)
        containing_chapter = None
        try:
            if inpt["containing-chapter"] != "":
                containing_chapter = TOC.get_chapter_from_path(
                    inpt["containing-chapter"])

        except ContentNotFoundError:
            set_feedback(
                session,
                Feedback(feedback_type="error",
                         message="The containing chapter for this page "
                         "does not exist"))
            return seeother(request.path)

        # sanity checks on the filename: refuse empty filenames of filenames with spaces
        if len(inpt["name"]) == 0 or len(re.sub(
                r'\s+', '', inpt["name"])) != len(inpt["name"]):
            set_feedback(
                session,
                Feedback(
                    feedback_type="error",
                    message='The file name cannot be empty or contain spaces.')
            )
            return seeother(request.path)

        if os.sep in inpt["name"]:
            set_feedback(
                session,
                Feedback(
                    feedback_type="error",
                    message=
                    'The file name cannot contain the "%s" forbidden character.'
                    % os.sep))
            return seeother(request.path)

        pages_path = syllabus.get_pages_path()
        content_path = os.path.join(
            containing_chapter.path,
            inpt["name"]) if containing_chapter is not None else inpt["name"]
        path = os.path.join(pages_path, content_path)

        # ensure that we do not create a page at the top level
        if containing_chapter is None and inpt["action"] == "create_page":
            set_feedback(
                session,
                Feedback(feedback_type="error",
                         message="Pages cannot be at the top level of the "
                         "syllabus."))
            return seeother(request.path)

        # check that there is no chapter with the same title in the containing chapter
        if containing_chapter is None:
            for content in TOC.get_top_level_content():
                if content.title == inpt["title"]:
                    set_feedback(
                        session,
                        Feedback(feedback_type="error",
                                 message="There is already a top level "
                                 "chapter with this title."))
                    return seeother(request.path)
        else:
            for content in TOC.get_direct_content_of(containing_chapter):
                if content.title == inpt["title"]:
                    set_feedback(
                        session,
                        Feedback(feedback_type="error",
                                 message="There is already a chapter/page "
                                 "with this title in this chapter."))
                    return seeother(request.path)

        if inpt["action"] == "create_page":

            # add the extension to the page filename
            content_path += ".rst"
            path += ".rst"

            # when file/directory already exists
            if os.path.isdir(path) or os.path.isfile(path):
                set_feedback(
                    session,
                    Feedback(feedback_type="error",
                             message="A file or directory with this name "
                             "already exists."))
                return seeother(request.path)

            # create a new page
            open(path, "w").close()
            page = Page(path=content_path,
                        title=inpt["title"],
                        pages_path=syllabus.get_pages_path(course))
            TOC.add_content_in_toc(page)
        elif inpt["action"] == "create_chapter":
            # creating a new chapter
            try:
                os.mkdir(path)
            except FileExistsError:
                set_feedback(
                    session,
                    Feedback(feedback_type="error",
                             message="A file or directory with this name "
                             "already exists."))
                return seeother(request.path)
            chapter = Chapter(path=content_path,
                              title=inpt["title"],
                              pages_path=syllabus.get_pages_path(course))
            TOC.add_content_in_toc(chapter)

        # dump the TOC and reload it
        syllabus.save_toc(course, TOC)
        syllabus.get_toc(course, force=True)
        return seeother(request.path)
    try:
        return render_template('content_edition.html',
                               active_element=sidebar['active_element'],
                               course_str=course,
                               sidebar_elements=sidebar['elements'],
                               TOC=TOC,
                               feedback=pop_feeback(session))
    except TemplateNotFound:
        abort(404)
Ejemplo n.º 17
0
def render_rst_file(page_path, **kwargs):
    with open(safe_join(syllabus.get_pages_path(), page_path), "r") as f:
        return publish_string(render_template_string(f.read(), **kwargs),
                              writer_name='html',
                              settings_overrides=default_rst_opts)