def instantiate_flow_page_with_ctx(fctx, page_data): from course.content import get_flow_page_desc page_desc = get_flow_page_desc(fctx.flow_id, fctx.flow_desc, page_data.group_id, page_data.page_id) from course.content import instantiate_flow_page return instantiate_flow_page( "course '%s', flow '%s', page '%s/%s'" % (fctx.course.identifier, fctx.flow_id, page_data.group_id, page_data.page_id), fctx.repo, page_desc, fctx.course_commit_sha)
def instantiate_flow_page_with_ctx(fctx, page_data): from course.content import get_flow_page_desc page_desc = get_flow_page_desc( fctx.flow_session, fctx.flow_desc, page_data.group_id, page_data.page_id) from course.content import instantiate_flow_page return instantiate_flow_page( "course '%s', flow '%s', page '%s/%s'" % (fctx.course_identifier, fctx.flow_identifier, page_data.group_id, page_data.page_id), fctx.repo, page_desc, fctx.flow_commit_sha)
def instantiate_flow_page_with_ctx(fctx, page_data): # type: (FlowContext, FlowPageData) -> PageBase from course.content import get_flow_page_desc page_desc = get_flow_page_desc( fctx.flow_id, fctx.flow_desc, page_data.group_id, page_data.page_id) from course.content import instantiate_flow_page return instantiate_flow_page( "course '%s', flow '%s', page '%s/%s'" % (fctx.course.identifier, fctx.flow_id, page_data.group_id, page_data.page_id), fctx.repo, page_desc, fctx.course_commit_sha)
def get_page(self, group_id, page_id, commit_sha): key = (group_id, page_id, commit_sha) try: return self.page_cache[key] except KeyError: from course.content import get_flow_page_desc, instantiate_flow_page page_desc = get_flow_page_desc( self.flow_id, self.get_flow_desc_from_cache(commit_sha), group_id, page_id) page = instantiate_flow_page( location="flow '%s', group, '%s', page '%s'" % (self.flow_id, group_id, page_id), repo=self.repo, page_desc=page_desc, commit_sha=commit_sha) self.page_cache[key] = page return page
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, }, )
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, })
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, })
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, })
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, })
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, })
def grade_page_visit(visit, visit_grade_model=FlowPageVisitGrade, grade_data=None, graded_at_git_commit_sha=None): if not visit.is_graded_answer: raise RuntimeError("cannot grade ungraded answer") flow_session = visit.flow_session course = flow_session.course page_data = visit.page_data from course.content import ( get_course_repo, get_course_commit_sha, get_flow_commit_sha, get_flow_desc, get_flow_page_desc, instantiate_flow_page) repo = get_course_repo(course) course_commit_sha = get_course_commit_sha( course, flow_session.participation) flow_desc_pre = get_flow_desc(repo, course, flow_session.flow_id, course_commit_sha) flow_commit_sha = get_flow_commit_sha( course, flow_session.participation, flow_desc_pre, visit.flow_session) flow_desc = get_flow_desc(repo, course, flow_session.flow_id, flow_commit_sha) page_desc = get_flow_page_desc( flow_session.flow_id, flow_desc, page_data.group_id, page_data.page_id) page = instantiate_flow_page( location="flow '%s', group, '%s', page '%s'" % (flow_session.flow_id, page_data.group_id, page_data.page_id), repo=repo, page_desc=page_desc, commit_sha=flow_commit_sha) from course.page import PageContext grading_page_context = PageContext( course=course, repo=repo, commit_sha=flow_commit_sha) answer_feedback = page.grade( grading_page_context, visit.page_data.data, visit.answer, grade_data=grade_data) grade = visit_grade_model() grade.visit = visit grade.grade_data = grade_data grade.max_points = page.max_points(visit.page_data) grade.graded_at_git_commit_sha = graded_at_git_commit_sha if answer_feedback is not None: grade.correctness = answer_feedback.correctness grade.feedback = answer_feedback.as_json() grade.save()
def grade_page_visit(visit, visit_grade_model=FlowPageVisitGrade, grade_data=None, graded_at_git_commit_sha=None): if not visit.is_submitted_answer: raise RuntimeError(_("cannot grade ungraded answer")) flow_session = visit.flow_session course = flow_session.course page_data = visit.page_data most_recent_grade = visit.get_most_recent_grade() if most_recent_grade is not None and grade_data is None: grade_data = most_recent_grade.grade_data from course.content import ( get_course_repo, get_course_commit_sha, get_flow_desc, get_flow_page_desc, instantiate_flow_page, ) repo = get_course_repo(course) course_commit_sha = get_course_commit_sha(course, flow_session.participation) flow_desc = get_flow_desc(repo, course, flow_session.flow_id, course_commit_sha) page_desc = get_flow_page_desc(flow_session.flow_id, flow_desc, page_data.group_id, page_data.page_id) page = instantiate_flow_page( location="flow '%s', group, '%s', page '%s'" % (flow_session.flow_id, page_data.group_id, page_data.page_id), repo=repo, page_desc=page_desc, commit_sha=course_commit_sha, ) assert page.expects_answer() if not page.is_answer_gradable(): return from course.page import PageContext grading_page_context = PageContext( course=course, repo=repo, commit_sha=course_commit_sha, flow_session=flow_session ) answer_feedback = page.grade(grading_page_context, visit.page_data.data, visit.answer, grade_data=grade_data) grade = visit_grade_model() grade.visit = visit grade.grade_data = grade_data grade.max_points = page.max_points(visit.page_data) grade.graded_at_git_commit_sha = graded_at_git_commit_sha bulk_feedback_json = None if answer_feedback is not None: grade.correctness = answer_feedback.correctness grade.feedback, bulk_feedback_json = answer_feedback.as_json() grade.save() update_bulk_feedback(page_data, grade, bulk_feedback_json)
def convert_flow_page_visit(stderr, fpv): course = fpv.flow_session.course from course.content import (get_course_repo, get_flow_desc, get_flow_page_desc, instantiate_flow_page) repo = get_course_repo(course) flow_id = fpv.flow_session.flow_id commit_sha = course.active_git_commit_sha.encode() try: flow_desc = get_flow_desc(repo, course, flow_id, commit_sha, tolerate_tabs=True) except ObjectDoesNotExist: stderr.write("warning: no flow yaml file found for '%s' in '%s'" % (flow_id, course.identifier)) return try: page_desc = get_flow_page_desc(fpv.flow_session.flow_id, flow_desc, fpv.page_data.group_id, fpv.page_data.page_id) except ObjectDoesNotExist: stderr.write( f"warning: flow page visit {fpv.id}: no page yaml desc " "found for " f"'{flow_id}:{fpv.page_data.group_id}/{fpv.page_data.page_id}' " f"in '{course.identifier}'") return page = instantiate_flow_page( location="flow '%s', group, '%s', page '%s'" % (flow_id, fpv.page_data.group_id, fpv.page_data.page_id), repo=repo, page_desc=page_desc, commit_sha=commit_sha) from course.page.base import PageContext pctx = PageContext(course=course, repo=repo, commit_sha=commit_sha, flow_session=fpv.flow_session, page_uri=None) from course.page.upload import FileUploadQuestion from course.page.code import CodeQuestion if isinstance(page, FileUploadQuestion): content, mime_type = page.get_content_from_answer_data(fpv.answer) from django.core.files.base import ContentFile answer_data = page.file_to_answer_data(pctx, ContentFile(content), mime_type) fpv.answer = answer_data fpv.save() return True elif isinstance(page, CodeQuestion): code = page.get_code_from_answer_data(fpv.answer) answer_data = page.code_to_answer_data(pctx, code) fpv.answer = answer_data fpv.save() return True else: return False assert False