Esempio n. 1
0
def lesson(lesson, page, solution=None):
    """Render the html of the given lesson page."""

    lesson_url, subpage_url, static_url = relative_url_functions(
        request.path, None, lesson)

    page = lesson.pages[page]

    content = page_content(lesson,
                           page,
                           solution=solution,
                           lesson_url=lesson_url,
                           subpage_url=subpage_url,
                           static_url=static_url)

    content = content["content"]
    allowed_elements_parser.reset_and_feed(content)

    kwargs = {}
    if solution is not None:
        kwargs["solution_number"] = int(solution)

    return render_template("lesson.html",
                           content=content,
                           page=page,
                           lesson=lesson,
                           edit_info=get_edit_info(page.edit_path),
                           title=page.title,
                           **kwargs)
Esempio n. 2
0
def course_calendar_ics(course):
    if not course.start_date:
        abort(404)

    if course.is_link():
        naucse.utils.routes.forks_raise_if_disabled()

        try:
            data_from_fork = course.render_calendar_ics(
                request_url=request.path)
        except POSSIBLE_FORK_EXCEPTIONS as e:
            if raise_errors_from_forks():
                raise

            logger.error("There was an error rendering url %s for course '%s'",
                         request.path, course.slug)
            logger.exception(e)
            return render_template(
                "error_in_fork.html",
                malfunctioning_course=course,
                edit_info=get_edit_info(course.edit_path),
                faulty_page="calendar",
                root_slug=model.meta.slug,
                travis_build_id=os.environ.get("TRAVIS_BUILD_ID"),
            )

        calendar = data_from_fork["calendar"]
    else:
        try:
            calendar = generate_calendar_ics(course)
        except ValueError:
            abort(404)

    return Response(str(calendar), mimetype="text/calendar")
Esempio n. 3
0
def course_calendar(course):
    if course.is_link():
        naucse.utils.routes.forks_raise_if_disabled()

        try:
            data_from_fork = course.render_calendar(request_url=request.path)

            course = process_course_data(data_from_fork.get("course"),
                                         slug=course.slug)
            edit_info = links.process_edit_info(
                data_from_fork.get("edit_info"))
        except POSSIBLE_FORK_EXCEPTIONS as e:
            if raise_errors_from_forks():
                raise

            logger.error("There was an error rendering url %s for course '%s'",
                         request.path, course.slug)
            logger.exception(e)
            return render_template(
                "error_in_fork.html",
                malfunctioning_course=course,
                edit_info=get_edit_info(course.edit_path),
                faulty_page="calendar",
                root_slug=model.meta.slug,
                travis_build_id=os.environ.get("TRAVIS_BUILD_ID"),
            )

        kwargs = {
            "course": course,
            "edit_info": edit_info,
            "content": data_from_fork.get("content")
        }
    else:
        if not course.start_date:
            abort(404)

        content = course_calendar_content(course)
        allowed_elements_parser.reset_and_feed(content)

        kwargs = {
            "course": course,
            "edit_info": get_edit_info(course.edit_path),
            "content": content
        }

    return render_template('course_calendar.html', **kwargs)
Esempio n. 4
0
def course(course):
    if course.is_link():
        naucse.utils.routes.forks_raise_if_disabled()

        try:
            data_from_fork = course.render_course(request_url=request.path)
        except POSSIBLE_FORK_EXCEPTIONS as e:
            if raise_errors_from_forks():
                raise

            # there's no way to replace this page, render an error page instead
            logger.error("There was an error rendering url %s for course '%s'",
                         request.path, course.slug)
            logger.exception(e)
            return render_template(
                "error_in_fork.html",
                malfunctioning_course=course,
                edit_info=get_edit_info(course.edit_path),
                faulty_page="course",
                root_slug=model.meta.slug,
                travis_build_id=os.environ.get("TRAVIS_BUILD_ID"),
            )
        kwargs = {
            "course_content": data_from_fork.get("content"),
            "edit_info":
            links.process_edit_info(data_from_fork.get("edit_info")),
        }
    else:
        content = course_content(course)
        allowed_elements_parser.reset_and_feed(content)

        kwargs = {
            "course_content": content,
            "edit_info": get_edit_info(course.edit_path),
        }

    recent_runs = get_recent_runs(course)

    try:
        return render_template("course.html",
                               course=course,
                               title=course.title,
                               recent_runs=recent_runs,
                               **kwargs)
    except TemplateNotFound:
        abort(404)
Esempio n. 5
0
def runs(year=None, all=None):
    today = datetime.date.today()

    # List of years to show in the pagination
    # If the current year is not there (no runs that start in the current year
    # yet), add it manually
    all_years = model.safe_run_years.keys()
    if today.year not in all_years:
        all_years.append(today.year)
    first_year, last_year = min(all_years), max(all_years)

    if year is not None:
        if year > last_year:
            # Instead of showing a future year, redirect to the 'Current' page
            return redirect(url_for('runs'))
        if year not in all_years:
            # Otherwise, if there are no runs in requested year, return 404.
            abort(404)

    if all is not None:
        run_data = model.safe_run_years

        paginate_prev = {'year': first_year}
        paginate_next = {'all': 'all'}
    elif year is None:
        run_data = model.ongoing_and_recent_runs

        paginate_prev = {'year': None}
        paginate_next = {'year': last_year}
    else:
        run_data = model.runs_from_year(year)

        past_years = [y for y in all_years if y < year]
        if past_years:
            paginate_next = {'year': max(past_years)}
        else:
            paginate_next = {'all': 'all'}

        future_years = [y for y in all_years if y > year]
        if future_years:
            paginate_prev = {'year': min(future_years)}
        else:
            paginate_prev = {'year': None}

    return render_template("run_list.html",
                           run_data=run_data,
                           title="Seznam offline kurzů Pythonu",
                           today=datetime.date.today(),
                           year=year,
                           all=all,
                           all_years=all_years,
                           paginate_next=paginate_next,
                           paginate_prev=paginate_prev,
                           edit_info=get_edit_info(model.runs_edit_path))
Esempio n. 6
0
def courses():
    # since even the basic info about the forked courses can be broken, we need to make sure the required info
    # is provided. If ``RAISE_FORK_ERRORS`` is set, exceptions are raised here, otherwise the course is
    # ignored completely.
    safe_courses = []

    for course in model.courses.values():
        if not course.is_link():
            safe_courses.append(course)
        elif naucse.utils.routes.forks_enabled() and does_course_return_info(
                course):
            safe_courses.append(course)

    return render_template("course_list.html",
                           courses=safe_courses,
                           title="Seznam online kurzů Pythonu",
                           edit_info=get_edit_info(model.courses_edit_path))
Esempio n. 7
0
def render(page_type: str, slug: str, *args, **kwargs) -> Dict[str, Any]:
    """ Returns a rendered page for a course, based on page_type and slug.
    """
    course = get_course_from_slug(slug)

    if course.is_link():
        raise ValueError("Circular dependency.")

    path = []
    if kwargs.get("request_url"):
        path = [kwargs["request_url"]]

    logger = UrlForLogger(routes.app)
    with routes.app.test_request_context(*path):
        with logger:

            info = {
                "course": {
                    "title": course.title,
                    "url": routes.course_url(course),
                    "vars": course.vars,
                    "canonical": course.canonical,
                    "is_derived": course.is_derived,
                },
            }

            if page_type == "course":
                info["content"] = routes.course_content(course)
                info["edit_info"] = get_edit_info(course.edit_path)

            elif page_type == "calendar":
                info["content"] = routes.course_calendar_content(course)
                info["edit_info"] = get_edit_info(course.edit_path)

            elif page_type == "calendar_ics":
                info["calendar"] = str(routes.generate_calendar_ics(course))
                info["edit_info"] = get_edit_info(course.edit_path)

            elif page_type == "course_page":
                lesson_slug, page, solution, *_ = args
                lesson = routes.model.get_lesson(lesson_slug)

                content_offer_key = kwargs.get("content_key")

                not_processed = object()
                content = not_processed

                if content_offer_key is not None:
                    # the base repository has a cached version of the content
                    content_key = page_content_cache_key(
                        Repo("."), lesson_slug, page, solution, course.vars)

                    # if the key matches what would be produced here, let's not return anything
                    # and the cached version will be used
                    if content_offer_key == content_key:
                        content = None

                request_url = kwargs.get("request_url")
                if request_url is None:
                    request_url = url_for('course_page',
                                          course=course,
                                          lesson=lesson,
                                          page=page,
                                          solution=solution)

                lesson_url, subpage_url, static_url = routes.relative_url_functions(
                    request_url, course, lesson)
                page, session, prv, nxt = routes.get_page(course, lesson, page)

                # if content isn't cached or the version was refused, let's render
                # the content here (but just the content and not the whole page with headers, menus etc)
                if content is not_processed:
                    content = routes.page_content(lesson,
                                                  page,
                                                  solution,
                                                  course,
                                                  lesson_url=lesson_url,
                                                  subpage_url=subpage_url,
                                                  static_url=static_url,
                                                  without_cache=True)

                if content is None:
                    info["content"] = None
                    info["content_urls"] = []
                else:
                    info["content"] = content["content"]
                    info["content_urls"] = content["urls"]

                info.update({
                    "page": {
                        "title": page.title,
                        "css": page.info.get(
                            "css"
                        ),  # not page.css since we want the css without limitation
                        "latex": page.latex,
                        "attributions": page.attributions,
                        "license": serialize_license(page.license),
                        "license_code": serialize_license(page.license_code)
                    },
                    "edit_info": get_edit_info(page.edit_path)
                })

                if session is not None:
                    info["session"] = {
                        "title":
                        session.title,
                        "url":
                        url_for("session_coverpage",
                                course=course.slug,
                                session=session.slug),
                        "slug":
                        session.slug,
                    }

                prev_link, session_link, next_link = routes.get_footer_links(
                    course, session, prv, nxt, lesson_url)
                info["footer"] = {
                    "prev_link": prev_link,
                    "session_link": session_link,
                    "next_link": next_link
                }

            elif page_type == "session_coverpage":
                session_slug, coverpage, *_ = args

                session = course.sessions.get(session_slug)

                info.update({
                    "session": {
                        "title":
                        session.title,
                        "url":
                        url_for("session_coverpage",
                                course=course.slug,
                                session=session.slug),
                    },
                    "content":
                    routes.session_coverpage_content(course, session,
                                                     coverpage),
                    "edit_info":
                    get_edit_info(session.get_edit_path(course, coverpage)),
                })
            else:
                raise ValueError("Invalid page type.")

        # generate list of absolute urls which need to be frozen further
        urls = set()
        for endpoint, values in logger.iter_calls():
            url = url_for(endpoint, **values)
            if url.startswith(
                    f"/{slug}"
            ):  # this is checked once again in main repo, but let's save cache space
                urls.add(url)

        info["urls"] = list(urls)

    return info
Esempio n. 8
0
def session_coverpage(course, session, coverpage):
    """Render the session coverpage.

    Args:
        course      course where the session belongs
        session     name of the session
        coverpage   coverpage of the session, front is default

    Returns:
        rendered session coverpage
    """
    if course.is_link():
        naucse.utils.routes.forks_raise_if_disabled()

        try:
            data_from_fork = course.render_session_coverpage(
                session, coverpage, request_url=request.path)

            kwargs = {
                "course":
                process_course_data(data_from_fork.get("course"),
                                    slug=course.slug),
                "session":
                process_session_data(data_from_fork.get("session"),
                                     slug=session),
                "edit_info":
                links.process_edit_info(data_from_fork.get("edit_info")),
                "content":
                data_from_fork["content"]
            }
        except POSSIBLE_FORK_EXCEPTIONS as e:
            if raise_errors_from_forks():
                raise

            # there's no way to replace this page, render an error page instead
            logger.error("There was an error rendering url %s for course '%s'",
                         request.path, course.slug)
            logger.exception(e)
            return render_template(
                "error_in_fork.html",
                malfunctioning_course=course,
                edit_info=get_edit_info(course.edit_path),
                faulty_page=f"session_{coverpage}",
                session=session,
                root_slug=model.meta.slug,
                travis_build_id=os.environ.get("TRAVIS_BUILD_ID"),
            )
    else:
        session = course.sessions.get(session)

        content = session_coverpage_content(course, session, coverpage)
        allowed_elements_parser.reset_and_feed(content)

        kwargs = {
            "course": course,
            "session": session,
            "edit_info":
            get_edit_info(session.get_edit_path(course, coverpage)),
            "content": content
        }

    return render_template("coverpage.html", **kwargs)
Esempio n. 9
0
def course_page(course, lesson, page, solution=None):
    lesson_slug = lesson
    page_slug = page

    try:
        lesson = model.get_lesson(lesson_slug)
        canonical_url = url_for('lesson', lesson=lesson, _external=True)
    except LookupError:
        lesson = canonical_url = None

    kwargs = {}
    prev_link = session_link = next_link = session = None

    if course.is_link():
        naucse.utils.routes.forks_raise_if_disabled()

        fork_kwargs = {"request_url": request.path}

        try:
            # checks if the rendered page content is in cache locally to offer it to the fork
            # ``course.vars`` calls ``course_info`` so it has to be in the try block
            # the function can also raise FileNotFoundError if the lesson doesn't exist in repo
            content_key = page_content_cache_key(
                arca.get_repo(course.repo, course.branch), lesson_slug, page,
                solution, course.vars)
            content_offer = arca.region.get(content_key)

            # we've got the fragment in cache, let's offer it to the fork;
            if content_offer:
                fork_kwargs["content_key"] = content_key

            data_from_fork = course.render_page(lesson_slug, page, solution,
                                                **fork_kwargs)

            content = data_from_fork["content"]

            if content is None:  # if a offer was accepted
                content = content_offer["content"]
                absolute_urls_to_freeze.extend([
                    get_absolute_url(request.path, x)
                    for x in content_offer["urls"]
                ])
            else:  # if the offer was rejected or the the fragment was not in cache
                arca.region.set(content_key, {
                    "content": content,
                    "urls": data_from_fork["content_urls"]
                })
                absolute_urls_to_freeze.extend([
                    get_absolute_url(request.path, x)
                    for x in data_from_fork["content_urls"]
                ])

            # compatability
            page = process_page_data(data_from_fork.get("page"))
            course = process_course_data(data_from_fork.get("course"),
                                         slug=course.slug)
            session = process_session_data(data_from_fork.get("session"))
            kwargs["edit_info"] = links.process_edit_info(
                data_from_fork.get("edit_info"))
            prev_link, session_link, next_link = process_footer_data(
                data_from_fork.get("footer"))

            title = '{}: {}'.format(course["title"], page["title"])
        except POSSIBLE_FORK_EXCEPTIONS as e:
            if raise_errors_from_forks():
                raise

            rendered_replacement = False

            logger.error("There was an error rendering url %s for course '%s'",
                         request.path, course.slug)
            if lesson is not None:
                try:
                    logger.error(
                        "Rendering the canonical version with a warning.")

                    lesson_url, subpage_url, static_url = relative_url_functions(
                        request.path, course, lesson)
                    page = lesson.pages[page]
                    content = page_content(lesson,
                                           page,
                                           solution,
                                           course,
                                           lesson_url=lesson_url,
                                           subpage_url=subpage_url,
                                           static_url=static_url)["content"]
                    title = '{}: {}'.format(course.title, page.title)

                    try:
                        prev_link, session_link, next_link = course.get_footer_links(
                            lesson.slug, page_slug, request_url=request.path)
                    except POSSIBLE_FORK_EXCEPTIONS as e:
                        if raise_errors_from_forks():
                            raise

                        # the fork is failing spectacularly, the footer links aren't that important
                        logger.error(
                            "Could not retrieve even footer links from the fork at page %s",
                            request.path)
                        logger.exception(e)

                    rendered_replacement = True
                    kwargs["edit_info"] = get_edit_info(page.edit_path)
                    kwargs["error_in_fork"] = True
                    kwargs["travis_build_id"] = os.environ.get(
                        "TRAVIS_BUILD_ID")

                except Exception as canonical_error:
                    logger.error("Rendering the canonical version failed.")
                    logger.exception(canonical_error)

            if not rendered_replacement:
                logger.exception(e)
                return render_template(
                    "error_in_fork.html",
                    malfunctioning_course=course,
                    edit_info=get_edit_info(course.edit_path),
                    faulty_page="lesson",
                    lesson=lesson_slug,
                    pg=page_slug,  # avoid name conflict
                    solution=solution,
                    root_slug=model.meta.slug,
                    travis_build_id=os.environ.get("TRAVIS_BUILD_ID"),
                )
    else:
        if lesson is None:
            abort(404)

        lesson_url, subpage_url, static_url = relative_url_functions(
            request.path, course, lesson)
        page, session, prv, nxt = get_page(course, lesson, page)
        prev_link, session_link, next_link = get_footer_links(
            course, session, prv, nxt, lesson_url)

        content = page_content(lesson,
                               page,
                               solution,
                               course=course,
                               lesson_url=lesson_url,
                               subpage_url=subpage_url,
                               static_url=static_url)
        content = content["content"]
        allowed_elements_parser.reset_and_feed(content)
        title = '{}: {}'.format(course.title, page.title)

        kwargs["edit_info"] = get_edit_info(page.edit_path)

    if solution is not None:
        kwargs["solution_number"] = int(solution)

    return render_template("lesson.html",
                           canonical_url=canonical_url,
                           title=title,
                           content=content,
                           prev_link=prev_link,
                           session_link=session_link,
                           next_link=next_link,
                           root_slug=model.meta.slug,
                           course=course,
                           lesson=lesson,
                           page=page,
                           solution=solution,
                           session=session,
                           **kwargs)
Esempio n. 10
0
def index():
    return render_template("index.html", edit_info=get_edit_info(Path(".")))