Example #1
0
    def validate(self, new_page_source):
        from courseflow.utils import dict_to_struct
        import yaml

        try:
            page_desc = dict_to_struct(yaml.load(new_page_source))

            from course.validation import validate_flow_page, ValidationContext
            vctx = ValidationContext(
                    # FIXME
                    repo=None,
                    commit_sha=None)

            validate_flow_page(vctx, "submitted page", page_desc)

            if page_desc.type != self.validator_desc.page_type:
                raise ValidationError("page must be of type '%s'"
                        % self.validator_desc.page_type)

        except:
            import sys
            tp, e, _ = sys.exc_info()

            raise forms.ValidationError("%s: %s"
                    % (tp.__name__, str(e)))
Example #2
0
    def validate(self, new_page_source):
        from relate.utils import dict_to_struct
        import yaml

        try:
            page_desc = dict_to_struct(yaml.safe_load(new_page_source))

            from course.validation import (
                    validate_flow_page, ValidationContext)
            vctx = ValidationContext(
                    # FIXME
                    repo=None,
                    commit_sha=None)

            validate_flow_page(vctx, "submitted page", page_desc)

            if page_desc.type != self.validator_desc.page_type:
                raise ValidationError(ugettext("page must be of type '%s'")
                        % self.validator_desc.page_type)

        except Exception:
            tp, e, _ = sys.exc_info()

            raise forms.ValidationError("%(err_type)s: %(err_str)s"
                    % {"err_type": tp.__name__, "err_str": str(e)})
Example #3
0
    def validate(self, new_page_source):
        from relate.utils import dict_to_struct
        import yaml

        try:
            page_desc = dict_to_struct(yaml.load(new_page_source))

            from course.validation import validate_flow_page, ValidationContext
            vctx = ValidationContext(
                # FIXME
                repo=None,
                commit_sha=None)

            validate_flow_page(vctx, "submitted page", page_desc)

            if page_desc.type != self.validator_desc.page_type:
                raise ValidationError("page must be of type '%s'" %
                                      self.validator_desc.page_type)

        except:
            import sys
            tp, e, _ = sys.exc_info()

            raise forms.ValidationError("%s: %s" % (tp.__name__, str(e)))
Example #4
0
def view_page_sandbox(pctx):
    if pctx.role not in [participation_role.instructor, participation_role.teaching_assistant]:
        raise PermissionDenied(ugettext("must be instructor or TA to access sandbox"))

    from course.validation import ValidationError
    from relate.utils import dict_to_struct, Struct
    import yaml

    PAGE_SESSION_KEY = "cf_validated_sandbox_page:" + pctx.course.identifier  # noqa
    ANSWER_DATA_SESSION_KEY = "cf_page_sandbox_answer_data:" + pctx.course.identifier  # noqa

    request = pctx.request
    page_source = pctx.request.session.get(PAGE_SESSION_KEY)

    page_errors = None
    page_warnings = None

    is_preview_post = request.method == "POST" and "preview" in request.POST

    from course.models import get_user_status

    ustatus = get_user_status(request.user)

    def make_form(data=None):
        return SandboxForm(
            page_source, "yaml", ustatus.editor_mode, ugettext("Enter YAML markup for a flow page."), data
        )

    if is_preview_post:
        edit_form = make_form(pctx.request.POST)

        if edit_form.is_valid():
            try:
                new_page_source = edit_form.cleaned_data["content"]
                page_desc = dict_to_struct(yaml.load(new_page_source))

                if not isinstance(page_desc, Struct):
                    raise ValidationError(
                        "Provided page source code is not "
                        "a dictionary. Do you need to remove a leading "
                        "list marker ('-') or some stray indentation?"
                    )

                from course.validation import validate_flow_page, ValidationContext

                vctx = ValidationContext(repo=pctx.repo, commit_sha=pctx.course_commit_sha)

                validate_flow_page(vctx, "sandbox", page_desc)

                page_warnings = vctx.warnings

            except:
                import sys

                tp, e, _ = sys.exc_info()

                page_errors = (
                    ugettext("Page failed to load/validate")
                    + ": "
                    + "%(err_type)s: %(err_str)s" % {"err_type": tp.__name__, "err_str": e}
                )

            else:
                # Yay, it did validate.
                request.session[PAGE_SESSION_KEY] = page_source = new_page_source

            del new_page_source

        edit_form = make_form(pctx.request.POST)

    else:
        edit_form = make_form()

    have_valid_page = page_source is not None
    if have_valid_page:
        page_desc = dict_to_struct(yaml.load(page_source))

        from course.content import instantiate_flow_page

        try:
            page = instantiate_flow_page("sandbox", pctx.repo, page_desc, pctx.course_commit_sha)
        except:
            import sys

            tp, e, _ = sys.exc_info()

            page_errors = (
                ugettext("Page failed to load/validate")
                + ": "
                + "%(err_type)s: %(err_str)s" % {"err_type": tp.__name__, "err_str": e}
            )
            have_valid_page = False

    if have_valid_page:
        page_data = page.make_page_data()

        from course.models import FlowSession
        from course.page import PageContext

        page_context = PageContext(
            course=pctx.course,
            repo=pctx.repo,
            commit_sha=pctx.course_commit_sha,
            # This helps code pages retrieve the editor pref.
            flow_session=FlowSession(course=pctx.course, participation=pctx.participation),
            in_sandbox=True,
        )

        title = page.title(page_context, page_data)
        body = page.body(page_context, page_data)

        # {{{ try to recover answer_data

        answer_data = None

        stored_answer_data_tuple = pctx.request.session.get(ANSWER_DATA_SESSION_KEY)

        # Session storage uses JSON and may turn tuples into lists.
        if isinstance(stored_answer_data_tuple, (list, tuple)) and len(stored_answer_data_tuple) == 3:
            stored_answer_data_page_type, stored_answer_data_page_id, stored_answer_data = stored_answer_data_tuple

            if stored_answer_data_page_type == page_desc.type and stored_answer_data_page_id == page_desc.id:
                answer_data = stored_answer_data

        # }}}

        feedback = None
        page_form_html = None

        if page.expects_answer():
            from course.page.base import PageBehavior

            page_behavior = PageBehavior(show_correctness=True, show_answer=True, may_change_answer=True)

            if request.method == "POST" and not is_preview_post:
                page_form = page.process_form_post(page_context, page_data, request.POST, request.FILES, page_behavior)

                if page_form.is_valid():

                    answer_data = page.answer_data(page_context, page_data, page_form, request.FILES)

                    feedback = page.grade(page_context, page_data, answer_data, grade_data=None)

                    pctx.request.session[ANSWER_DATA_SESSION_KEY] = (page_desc.type, page_desc.id, answer_data)

            else:
                page_form = page.make_form(page_context, page_data, answer_data, page_behavior)

            if page_form is not None:
                page_form.helper.add_input(Submit("submit", ugettext("Submit answer"), accesskey="g"))
                page_form_html = page.form_to_html(pctx.request, page_context, page_form, answer_data)

        correct_answer = page.correct_answer(page_context, page_data, answer_data, grade_data=None)

        return render_course_page(
            pctx,
            "course/sandbox-page.html",
            {
                "edit_form": edit_form,
                "page_errors": page_errors,
                "page_warnings": page_warnings,
                "form": edit_form,  # to placate form.media
                "have_valid_page": True,
                "title": title,
                "body": body,
                "page_form_html": page_form_html,
                "feedback": feedback,
                "correct_answer": correct_answer,
            },
        )

    else:

        return render_course_page(
            pctx,
            "course/sandbox-page.html",
            {
                "edit_form": edit_form,
                "form": edit_form,  # to placate form.media
                "have_valid_page": False,
                "page_errors": page_errors,
                "page_warnings": page_warnings,
            },
        )
Example #5
0
def view_page_sandbox(pctx):
    from courseflow.utils import dict_to_struct
    import yaml

    PAGE_SESSION_KEY = "cf_validated_sandbox_page:" + pctx.course.identifier
    ANSWER_DATA_SESSION_KEY = "cf_page_sandbox_answer_data:" + pctx.course.identifier

    request = pctx.request
    page_source = pctx.request.session.get(PAGE_SESSION_KEY)

    page_errors = None

    is_preview_post = (request.method == "POST" and "preview" in request.POST)

    def make_form(data=None):
        return SandboxForm(
                page_source, "yaml", vim_mode,
                "Enter YAML markup for a flow page.",
                data)

    vim_mode = pctx.request.session.get(CF_SANDBOX_VIM_MODE, False)

    if is_preview_post:
        edit_form = make_form(pctx.request.POST)

        if edit_form.is_valid():
            pctx.request.session[CF_SANDBOX_VIM_MODE] = \
                    vim_mode = edit_form.cleaned_data["vim_mode"]

            try:
                new_page_source = edit_form.cleaned_data["content"]
                page_desc = dict_to_struct(yaml.load(new_page_source))

                from course.validation import validate_flow_page, ValidationContext
                vctx = ValidationContext(
                        repo=pctx.repo,
                        commit_sha=pctx.course_commit_sha)

                validate_flow_page(vctx, "sandbox", page_desc)

            except:
                import sys
                tp, e, _ = sys.exc_info()

                page_errors = (
                        "Page failed to load/validate: "
                        "%s: %s" % (tp.__name__, e))

            else:
                # Yay, it did validate.
                request.session[PAGE_SESSION_KEY] = page_source = new_page_source

            del new_page_source

        edit_form = make_form(pctx.request.POST)

    else:
        edit_form = make_form()

    have_valid_page = page_source is not None
    if have_valid_page:
        page_desc = dict_to_struct(yaml.load(page_source))

        from course.content import instantiate_flow_page
        page = instantiate_flow_page("sandbox", pctx.repo, page_desc,
                pctx.course_commit_sha)

        page_data = page.make_page_data()

        from course.page import PageContext
        page_context = PageContext(
                course=pctx.course,
                repo=pctx.repo,
                commit_sha=pctx.course_commit_sha,
                flow_session=None)

        title = page.title(page_context, page_data)
        body = page.body(page_context, page_data)

        # {{{ try to recover answer_data

        answer_data = None

        stored_answer_data_tuple = \
                pctx.request.session.get(ANSWER_DATA_SESSION_KEY)

        # Session storage uses JSON and may turn tuples into lists.
        if (isinstance(stored_answer_data_tuple, (list, tuple))
                and len(stored_answer_data_tuple) == 2):
            stored_answer_data_page_id, stored_answer_data = \
                    stored_answer_data_tuple

            if stored_answer_data_page_id == page_desc.id:
                answer_data = stored_answer_data

        # }}}

        feedback = None
        page_form_html = None

        if page.expects_answer():
            if request.method == "POST" and not is_preview_post:
                page_form = page.post_form(page_context, page_data,
                        request.POST, request.FILES)

                if page_form.is_valid():

                    answer_data = page.answer_data(page_context, page_data,
                            page_form, request.FILES)

                    feedback = page.grade(page_context, page_data, answer_data,
                            grade_data=None)

                    pctx.request.session[ANSWER_DATA_SESSION_KEY] = (
                            page_desc.id, answer_data)

            else:
                page_form = page.make_form(page_context, page_data,
                        answer_data, answer_is_final=False)

            if page_form is not None:
                page_form.helper.add_input(
                        Submit("submit", "Submit answer", accesskey="g",
                            css_class="col-lg-offset-2"))
                page_form_html = page.form_to_html(
                        pctx.request, page_context, page_form, answer_data)

        correct_answer = page.correct_answer(
                page_context, page_data, answer_data,
                grade_data=None)

        return render_course_page(pctx, "course/sandbox-page.html", {
            "edit_form": edit_form,
            "page_errors": page_errors,
            "form": edit_form,  # to placate form.media
            "have_valid_page": True,
            "title": title,
            "body": body,
            "page_form_html": page_form_html,
            "feedback": feedback,
            "correct_answer": correct_answer,
        })

    else:

        return render_course_page(pctx, "course/sandbox-page.html", {
            "edit_form": edit_form,
            "form": edit_form,  # to placate form.media
            "have_valid_page": False,
            "page_errors": page_errors,
        })
Example #6
0
def view_page_sandbox(pctx):
    # type: (CoursePageContext) -> http.HttpResponse

    if not pctx.has_permission(pperm.use_page_sandbox):
        raise PermissionDenied()

    from course.validation import ValidationError
    from relate.utils import dict_to_struct, Struct
    import yaml

    PAGE_SESSION_KEY = make_sandbox_session_key(  # noqa
        PAGE_SESSION_KEY_PREFIX, pctx.course.identifier)
    ANSWER_DATA_SESSION_KEY = make_sandbox_session_key(  # noqa
        ANSWER_DATA_SESSION_KEY_PREFIX, pctx.course.identifier)
    PAGE_DATA_SESSION_KEY = make_sandbox_session_key(  # noqa
        PAGE_DATA_SESSION_KEY_PREFIX, pctx.course.identifier)

    request = pctx.request
    page_source = pctx.request.session.get(PAGE_SESSION_KEY)

    page_errors = None
    page_warnings = None

    is_clear_post = (request.method == "POST" and "clear" in request.POST)
    is_clear_response_post = (request.method == "POST"
                              and "clear_response" in request.POST)
    is_preview_post = (request.method == "POST" and "preview" in request.POST)

    def make_form(data=None):
        # type: (Optional[Text]) -> PageSandboxForm
        return PageSandboxForm(page_source, "yaml", request.user.editor_mode,
                               ugettext("Enter YAML markup for a flow page."),
                               data)

    if is_preview_post:
        edit_form = make_form(pctx.request.POST)
        new_page_source = None

        if edit_form.is_valid():
            try:
                from pytools.py_codegen import remove_common_indentation
                new_page_source = remove_common_indentation(
                    edit_form.cleaned_data["content"],
                    require_leading_newline=False)
                from course.content import expand_yaml_macros
                new_page_source = expand_yaml_macros(pctx.repo,
                                                     pctx.course_commit_sha,
                                                     new_page_source)

                yaml_data = yaml.load(new_page_source)  # type: ignore
                page_desc = dict_to_struct(yaml_data)

                if not isinstance(page_desc, Struct):
                    raise ValidationError(
                        "Provided page source code is not "
                        "a dictionary. Do you need to remove a leading "
                        "list marker ('-') or some stray indentation?")

                from course.validation import validate_flow_page, ValidationContext
                vctx = ValidationContext(repo=pctx.repo,
                                         commit_sha=pctx.course_commit_sha)

                validate_flow_page(vctx, "sandbox", page_desc)

                page_warnings = vctx.warnings

            except Exception:
                import sys
                tp, e, _ = sys.exc_info()

                page_errors = (ugettext("Page failed to load/validate") +
                               ": " + "%(err_type)s: %(err_str)s" % {
                                   "err_type": tp.__name__,
                                   "err_str": e
                               })  # type: ignore

            else:
                # Yay, it did validate.
                request.session[
                    PAGE_SESSION_KEY] = page_source = new_page_source

            del new_page_source

        edit_form = make_form(pctx.request.POST)

    elif is_clear_post:
        page_source = None
        pctx.request.session[PAGE_DATA_SESSION_KEY] = None
        pctx.request.session[ANSWER_DATA_SESSION_KEY] = None
        del pctx.request.session[PAGE_DATA_SESSION_KEY]
        del pctx.request.session[ANSWER_DATA_SESSION_KEY]
        edit_form = make_form()

    elif is_clear_response_post:
        page_source = None
        pctx.request.session[PAGE_DATA_SESSION_KEY] = None
        pctx.request.session[ANSWER_DATA_SESSION_KEY] = None
        del pctx.request.session[PAGE_DATA_SESSION_KEY]
        del pctx.request.session[ANSWER_DATA_SESSION_KEY]
        edit_form = make_form(pctx.request.POST)

    else:
        edit_form = make_form()

    have_valid_page = page_source is not None
    if have_valid_page:
        yaml_data = yaml.load(page_source)  # type: ignore
        page_desc = cast(FlowPageDesc, dict_to_struct(yaml_data))

        from course.content import instantiate_flow_page
        try:
            page = instantiate_flow_page("sandbox", pctx.repo, page_desc,
                                         pctx.course_commit_sha)
        except Exception:
            import sys
            tp, e, _ = sys.exc_info()

            page_errors = (ugettext("Page failed to load/validate") + ": " +
                           "%(err_type)s: %(err_str)s" % {
                               "err_type": tp.__name__,
                               "err_str": e
                           })  # type: ignore
            have_valid_page = False

    if have_valid_page:
        page_desc = cast(FlowPageDesc, page_desc)

        # Try to recover page_data, answer_data
        page_data = get_sandbox_data_for_page(pctx, page_desc,
                                              PAGE_DATA_SESSION_KEY)

        answer_data = get_sandbox_data_for_page(pctx, page_desc,
                                                ANSWER_DATA_SESSION_KEY)

        from course.models import FlowSession
        from course.page import PageContext
        page_context = PageContext(
            course=pctx.course,
            repo=pctx.repo,
            commit_sha=pctx.course_commit_sha,

            # This helps code pages retrieve the editor pref.
            flow_session=FlowSession(course=pctx.course,
                                     participation=pctx.participation),
            in_sandbox=True)

        if page_data is None:
            page_data = page.initialize_page_data(page_context)
            pctx.request.session[PAGE_DATA_SESSION_KEY] = (page_desc.type,
                                                           page_desc.id,
                                                           page_data)

        title = page.title(page_context, page_data)
        body = page.body(page_context, page_data)

        feedback = None
        page_form_html = None

        if page.expects_answer():
            from course.page.base import PageBehavior
            page_behavior = PageBehavior(show_correctness=True,
                                         show_answer=True,
                                         may_change_answer=True)

            if request.method == "POST" and not is_preview_post:
                page_form = page.process_form_post(page_context, page_data,
                                                   request.POST, request.FILES,
                                                   page_behavior)

                if page_form.is_valid():

                    answer_data = page.answer_data(page_context, page_data,
                                                   page_form, request.FILES)

                    feedback = page.grade(page_context,
                                          page_data,
                                          answer_data,
                                          grade_data=None)

                    pctx.request.session[ANSWER_DATA_SESSION_KEY] = (
                        page_desc.type, page_desc.id, answer_data)

            else:
                try:
                    page_form = page.make_form(page_context, page_data,
                                               answer_data, page_behavior)

                except Exception:
                    import sys
                    tp, e, _ = sys.exc_info()

                    page_errors = (
                        ugettext("Page failed to load/validate "
                                 "(change page ID to clear faults)") + ": " +
                        "%(err_type)s: %(err_str)s" % {
                            "err_type": tp.__name__,
                            "err_str": e
                        })  # type: ignore  # noqa: E501
                    have_valid_page = False

                    page_form = None

            if page_form is not None:
                page_form.helper.add_input(
                    Submit("submit", ugettext("Submit answer"), accesskey="g"))
                page_form_html = page.form_to_html(pctx.request, page_context,
                                                   page_form, answer_data)

        correct_answer = page.correct_answer(page_context,
                                             page_data,
                                             answer_data,
                                             grade_data=None)

        return render_course_page(
            pctx,
            "course/sandbox-page.html",
            {
                "edit_form": edit_form,
                "page_errors": page_errors,
                "page_warnings": page_warnings,
                "form": edit_form,  # to placate form.media
                "have_valid_page": True,
                "title": title,
                "body": body,
                "page_form_html": page_form_html,
                "feedback": feedback,
                "correct_answer": correct_answer,
            })

    else:

        return render_course_page(
            pctx,
            "course/sandbox-page.html",
            {
                "edit_form": edit_form,
                "form": edit_form,  # to placate form.media
                "have_valid_page": False,
                "page_errors": page_errors,
                "page_warnings": page_warnings,
            })
Example #7
0
def view_page_sandbox(pctx):
    if not pctx.has_permission(pperm.use_page_sandbox):
        raise PermissionDenied()

    from course.validation import ValidationError
    from relate.utils import dict_to_struct, Struct
    import yaml

    PAGE_SESSION_KEY = (  # noqa
            "cf_validated_sandbox_page:" + pctx.course.identifier)
    ANSWER_DATA_SESSION_KEY = (  # noqa
        "cf_page_sandbox_answer_data:" + pctx.course.identifier)
    PAGE_DATA_SESSION_KEY = (  # noqa
        "cf_page_sandbox_page_data:" + pctx.course.identifier)

    request = pctx.request
    page_source = pctx.request.session.get(PAGE_SESSION_KEY)

    page_errors = None
    page_warnings = None

    is_clear_post = (request.method == "POST" and "clear" in request.POST)
    is_clear_response_post = (request.method == "POST"
            and "clear_response" in request.POST)
    is_preview_post = (request.method == "POST" and "preview" in request.POST)

    def make_form(data=None):
        return PageSandboxForm(
                page_source, "yaml", request.user.editor_mode,
                ugettext("Enter YAML markup for a flow page."),
                data)

    if is_preview_post:
        edit_form = make_form(pctx.request.POST)
        new_page_source = None

        if edit_form.is_valid():
            try:
                from pytools.py_codegen import remove_common_indentation
                new_page_source = remove_common_indentation(
                        edit_form.cleaned_data["content"],
                        require_leading_newline=False)
                page_desc = dict_to_struct(yaml.load(new_page_source))

                if not isinstance(page_desc, Struct):
                    raise ValidationError("Provided page source code is not "
                            "a dictionary. Do you need to remove a leading "
                            "list marker ('-') or some stray indentation?")

                from course.validation import validate_flow_page, ValidationContext
                vctx = ValidationContext(
                        repo=pctx.repo,
                        commit_sha=pctx.course_commit_sha)

                validate_flow_page(vctx, "sandbox", page_desc)

                page_warnings = vctx.warnings

            except:
                import sys
                tp, e, _ = sys.exc_info()

                page_errors = (
                        ugettext("Page failed to load/validate")
                        + ": "
                        + "%(err_type)s: %(err_str)s" % {
                            "err_type": tp.__name__, "err_str": e})

            else:
                # Yay, it did validate.
                request.session[PAGE_SESSION_KEY] = page_source = new_page_source

            del new_page_source

        edit_form = make_form(pctx.request.POST)

    elif is_clear_post:
        page_source = None
        pctx.request.session[PAGE_DATA_SESSION_KEY] = None
        pctx.request.session[ANSWER_DATA_SESSION_KEY] = None
        del pctx.request.session[PAGE_DATA_SESSION_KEY]
        del pctx.request.session[ANSWER_DATA_SESSION_KEY]
        edit_form = make_form()

    elif is_clear_response_post:
        page_source = None
        pctx.request.session[PAGE_DATA_SESSION_KEY] = None
        pctx.request.session[ANSWER_DATA_SESSION_KEY] = None
        del pctx.request.session[PAGE_DATA_SESSION_KEY]
        del pctx.request.session[ANSWER_DATA_SESSION_KEY]
        edit_form = make_form(pctx.request.POST)

    else:
        edit_form = make_form()

    have_valid_page = page_source is not None
    if have_valid_page:
        page_desc = dict_to_struct(yaml.load(page_source))

        from course.content import instantiate_flow_page
        try:
            page = instantiate_flow_page("sandbox", pctx.repo, page_desc,
                    pctx.course_commit_sha)
        except:
            import sys
            tp, e, _ = sys.exc_info()

            page_errors = (
                    ugettext("Page failed to load/validate")
                    + ": "
                    + "%(err_type)s: %(err_str)s" % {
                        "err_type": tp.__name__, "err_str": e})
            have_valid_page = False

    if have_valid_page:
        # Try to recover page_data, answer_data
        page_data = get_sandbox_data_for_page(
                pctx, page_desc, PAGE_DATA_SESSION_KEY)

        answer_data = get_sandbox_data_for_page(
                pctx, page_desc, ANSWER_DATA_SESSION_KEY)

        from course.models import FlowSession
        from course.page import PageContext
        page_context = PageContext(
                course=pctx.course,
                repo=pctx.repo,
                commit_sha=pctx.course_commit_sha,

                # This helps code pages retrieve the editor pref.
                flow_session=FlowSession(
                    course=pctx.course,
                    participation=pctx.participation),

                in_sandbox=True)

        if page_data is None:
            page_data = page.initialize_page_data(page_context)
            pctx.request.session[PAGE_DATA_SESSION_KEY] = (
                    page_desc.type, page_desc.id, page_data)

        title = page.title(page_context, page_data)
        body = page.body(page_context, page_data)

        feedback = None
        page_form_html = None

        if page.expects_answer():
            from course.page.base import PageBehavior
            page_behavior = PageBehavior(
                    show_correctness=True,
                    show_answer=True,
                    may_change_answer=True)

            if request.method == "POST" and not is_preview_post:
                page_form = page.process_form_post(page_context, page_data,
                        request.POST, request.FILES,
                        page_behavior)

                if page_form.is_valid():

                    answer_data = page.answer_data(page_context, page_data,
                            page_form, request.FILES)

                    feedback = page.grade(page_context, page_data, answer_data,
                            grade_data=None)

                    pctx.request.session[ANSWER_DATA_SESSION_KEY] = (
                            page_desc.type, page_desc.id, answer_data)

            else:
                try:
                    page_form = page.make_form(page_context, page_data,
                            answer_data, page_behavior)

                except:
                    import sys
                    tp, e, _ = sys.exc_info()

                    page_errors = (
                            ugettext("Page failed to load/validate "
                                "(change page ID to clear faults)")
                            + ": "
                            + "%(err_type)s: %(err_str)s" % {
                                "err_type": tp.__name__, "err_str": e})
                    have_valid_page = False

                    page_form = None

            if page_form is not None:
                page_form.helper.add_input(
                        Submit("submit",
                            ugettext("Submit answer"),
                            accesskey="g"))
                page_form_html = page.form_to_html(
                        pctx.request, page_context, page_form, answer_data)

        correct_answer = page.correct_answer(
                page_context, page_data, answer_data,
                grade_data=None)

        return render_course_page(pctx, "course/sandbox-page.html", {
            "edit_form": edit_form,
            "page_errors": page_errors,
            "page_warnings": page_warnings,
            "form": edit_form,  # to placate form.media
            "have_valid_page": True,
            "title": title,
            "body": body,
            "page_form_html": page_form_html,
            "feedback": feedback,
            "correct_answer": correct_answer,
        })

    else:

        return render_course_page(pctx, "course/sandbox-page.html", {
            "edit_form": edit_form,
            "form": edit_form,  # to placate form.media
            "have_valid_page": False,
            "page_errors": page_errors,
            "page_warnings": page_warnings,
        })
Example #8
0
def view_page_sandbox(pctx):
    from relate.utils import dict_to_struct
    import yaml

    PAGE_SESSION_KEY = "cf_validated_sandbox_page:" + pctx.course.identifier
    ANSWER_DATA_SESSION_KEY = "cf_page_sandbox_answer_data:" + pctx.course.identifier

    request = pctx.request
    page_source = pctx.request.session.get(PAGE_SESSION_KEY)

    page_errors = None

    is_preview_post = (request.method == "POST" and "preview" in request.POST)

    def make_form(data=None):
        return SandboxForm(
                page_source, "yaml", vim_mode,
                "Enter YAML markup for a flow page.",
                data)

    vim_mode = pctx.request.session.get(CF_SANDBOX_VIM_MODE, False)

    if is_preview_post:
        edit_form = make_form(pctx.request.POST)

        if edit_form.is_valid():
            pctx.request.session[CF_SANDBOX_VIM_MODE] = \
                    vim_mode = edit_form.cleaned_data["vim_mode"]

            try:
                new_page_source = edit_form.cleaned_data["content"]
                page_desc = dict_to_struct(yaml.load(new_page_source))

                from course.validation import validate_flow_page, ValidationContext
                vctx = ValidationContext(
                        repo=pctx.repo,
                        commit_sha=pctx.course_commit_sha)

                validate_flow_page(vctx, "sandbox", page_desc)

            except:
                import sys
                tp, e, _ = sys.exc_info()

                page_errors = (
                        "Page failed to load/validate: "
                        "%s: %s" % (tp.__name__, e))

            else:
                # Yay, it did validate.
                request.session[PAGE_SESSION_KEY] = page_source = new_page_source

            del new_page_source

        edit_form = make_form(pctx.request.POST)

    else:
        edit_form = make_form()

    have_valid_page = page_source is not None
    if have_valid_page:
        page_desc = dict_to_struct(yaml.load(page_source))

        from course.content import instantiate_flow_page
        page = instantiate_flow_page("sandbox", pctx.repo, page_desc,
                pctx.course_commit_sha)

        page_data = page.make_page_data()

        from course.page import PageContext
        page_context = PageContext(
                course=pctx.course,
                repo=pctx.repo,
                commit_sha=pctx.course_commit_sha,
                flow_session=None)

        title = page.title(page_context, page_data)
        body = page.body(page_context, page_data)

        # {{{ try to recover answer_data

        answer_data = None

        stored_answer_data_tuple = \
                pctx.request.session.get(ANSWER_DATA_SESSION_KEY)

        # Session storage uses JSON and may turn tuples into lists.
        if (isinstance(stored_answer_data_tuple, (list, tuple))
                and len(stored_answer_data_tuple) == 2):
            stored_answer_data_page_id, stored_answer_data = \
                    stored_answer_data_tuple

            if stored_answer_data_page_id == page_desc.id:
                answer_data = stored_answer_data

        # }}}

        feedback = None
        page_form_html = None

        if page.expects_answer():
            if request.method == "POST" and not is_preview_post:
                page_form = page.post_form(page_context, page_data,
                        request.POST, request.FILES)

                if page_form.is_valid():

                    answer_data = page.answer_data(page_context, page_data,
                            page_form, request.FILES)

                    feedback = page.grade(page_context, page_data, answer_data,
                            grade_data=None)

                    pctx.request.session[ANSWER_DATA_SESSION_KEY] = (
                            page_desc.id, answer_data)

            else:
                page_form = page.make_form(page_context, page_data,
                        answer_data, answer_is_final=False)

            if page_form is not None:
                page_form.helper.add_input(
                        Submit("submit", "Submit answer", accesskey="g",
                            css_class="col-lg-offset-2"))
                page_form_html = page.form_to_html(
                        pctx.request, page_context, page_form, answer_data)

        correct_answer = page.correct_answer(
                page_context, page_data, answer_data,
                grade_data=None)

        return render_course_page(pctx, "course/sandbox-page.html", {
            "edit_form": edit_form,
            "page_errors": page_errors,
            "form": edit_form,  # to placate form.media
            "have_valid_page": True,
            "title": title,
            "body": body,
            "page_form_html": page_form_html,
            "feedback": feedback,
            "correct_answer": correct_answer,
        })

    else:

        return render_course_page(pctx, "course/sandbox-page.html", {
            "edit_form": edit_form,
            "form": edit_form,  # to placate form.media
            "have_valid_page": False,
            "page_errors": page_errors,
        })
Example #9
0
def view_page_sandbox(pctx):
    if pctx.role not in [
            participation_role.instructor,
            participation_role.teaching_assistant]:
        raise PermissionDenied(
                ugettext("must be instructor or TA to access sandbox"))

    from course.validation import ValidationError
    from relate.utils import dict_to_struct, Struct
    import yaml

    PAGE_SESSION_KEY = (  # noqa
            "cf_validated_sandbox_page:" + pctx.course.identifier)
    ANSWER_DATA_SESSION_KEY = (  # noqa
        "cf_page_sandbox_answer_data:" + pctx.course.identifier)

    request = pctx.request
    page_source = pctx.request.session.get(PAGE_SESSION_KEY)

    page_errors = None
    page_warnings = None

    is_preview_post = (request.method == "POST" and "preview" in request.POST)

    from course.models import get_user_status
    ustatus = get_user_status(request.user)

    def make_form(data=None):
        return SandboxForm(
                page_source, "yaml", ustatus.editor_mode,
                ugettext("Enter YAML markup for a flow page."),
                data)

    if is_preview_post:
        edit_form = make_form(pctx.request.POST)

        if edit_form.is_valid():
            try:
                new_page_source = edit_form.cleaned_data["content"]
                page_desc = dict_to_struct(yaml.load(new_page_source))

                if not isinstance(page_desc, Struct):
                    raise ValidationError("Provided page source code is not "
                            "a dictionary. Do you need to remove a leading "
                            "list marker ('-') or some stray indentation?")

                from course.validation import validate_flow_page, ValidationContext
                vctx = ValidationContext(
                        repo=pctx.repo,
                        commit_sha=pctx.course_commit_sha)

                validate_flow_page(vctx, "sandbox", page_desc)

                page_warnings = vctx.warnings

            except:
                import sys
                tp, e, _ = sys.exc_info()

                page_errors = (
                        ugettext("Page failed to load/validate")
                        + ": "
                        + "%(err_type)s: %(err_str)s" % {
                            "err_type": tp.__name__, "err_str": e})

            else:
                # Yay, it did validate.
                request.session[PAGE_SESSION_KEY] = page_source = new_page_source

            del new_page_source

        edit_form = make_form(pctx.request.POST)

    else:
        edit_form = make_form()

    have_valid_page = page_source is not None
    if have_valid_page:
        page_desc = dict_to_struct(yaml.load(page_source))

        from course.content import instantiate_flow_page
        try:
            page = instantiate_flow_page("sandbox", pctx.repo, page_desc,
                    pctx.course_commit_sha)
        except:
            import sys
            tp, e, _ = sys.exc_info()

            page_errors = (
                    ugettext("Page failed to load/validate")
                    + ": "
                    + "%(err_type)s: %(err_str)s" % {
                        "err_type": tp.__name__, "err_str": e})
            have_valid_page = False

    if have_valid_page:
        page_data = page.make_page_data()

        from course.models import FlowSession
        from course.page import PageContext
        page_context = PageContext(
                course=pctx.course,
                repo=pctx.repo,
                commit_sha=pctx.course_commit_sha,

                # This helps code pages retrieve the editor pref.
                flow_session=FlowSession(
                    course=pctx.course,
                    participation=pctx.participation),

                in_sandbox=True)

        title = page.title(page_context, page_data)
        body = page.body(page_context, page_data)

        # {{{ try to recover answer_data

        answer_data = None

        stored_answer_data_tuple = \
                pctx.request.session.get(ANSWER_DATA_SESSION_KEY)

        # Session storage uses JSON and may turn tuples into lists.
        if (isinstance(stored_answer_data_tuple, (list, tuple))
                and len(stored_answer_data_tuple) == 3):
            stored_answer_data_page_type, stored_answer_data_page_id, stored_answer_data = \
                    stored_answer_data_tuple

            if (
                    stored_answer_data_page_type == page_desc.type
                    and
                    stored_answer_data_page_id == page_desc.id):
                answer_data = stored_answer_data

        # }}}

        feedback = None
        page_form_html = None

        if page.expects_answer():
            from course.page.base import PageBehavior
            page_behavior = PageBehavior(
                    show_correctness=True,
                    show_answer=True,
                    may_change_answer=True)

            if request.method == "POST" and not is_preview_post:
                page_form = page.process_form_post(page_context, page_data,
                        request.POST, request.FILES,
                        page_behavior)

                if page_form.is_valid():

                    answer_data = page.answer_data(page_context, page_data,
                            page_form, request.FILES)

                    feedback = page.grade(page_context, page_data, answer_data,
                            grade_data=None)

                    pctx.request.session[ANSWER_DATA_SESSION_KEY] = (
                            page_desc.type, page_desc.id, answer_data)

            else:
                page_form = page.make_form(page_context, page_data,
                        answer_data, page_behavior)

            if page_form is not None:
                page_form.helper.add_input(
                        Submit("submit",
                            ugettext("Submit answer"),
                            accesskey="g"))
                page_form_html = page.form_to_html(
                        pctx.request, page_context, page_form, answer_data)

        correct_answer = page.correct_answer(
                page_context, page_data, answer_data,
                grade_data=None)

        return render_course_page(pctx, "course/sandbox-page.html", {
            "edit_form": edit_form,
            "page_errors": page_errors,
            "page_warnings": page_warnings,
            "form": edit_form,  # to placate form.media
            "have_valid_page": True,
            "title": title,
            "body": body,
            "page_form_html": page_form_html,
            "feedback": feedback,
            "correct_answer": correct_answer,
        })

    else:

        return render_course_page(pctx, "course/sandbox-page.html", {
            "edit_form": edit_form,
            "form": edit_form,  # to placate form.media
            "have_valid_page": False,
            "page_errors": page_errors,
            "page_warnings": page_warnings,
        })