def validate_markup(vctx, location, markup_str): # type: (ValidationContext, Text, Text) -> None def reverse_func(*args, **kwargs): pass from course.content import markup_to_html try: markup_to_html( course=None, repo=vctx.repo, commit_sha=vctx.commit_sha, text=markup_str, reverse_func=reverse_func, validate_only=True) except: from traceback import print_exc print_exc() tp, e, _ = sys.exc_info() assert tp is not None raise ValidationError( "%(location)s: %(err_type)s: %(err_str)s" % { 'location': location, "err_type": tp.__name__, "err_str": str(e)})
def process_choice_string(cls, page_context, s): s = remove_prefix(cls.CORRECT_TAG, s) s = markup_to_html(page_context, s) # allow HTML in option s = mark_safe(s) return s
def grade(self, page_context, page_data, answer_data, grade_data): """This method is appropriate if the grade consists *only* of the feedback provided by humans. If more complicated/combined feedback is desired, a subclass would likely override this. """ if answer_data is None: return AnswerFeedback(correctness=0, feedback=ugettext("No answer provided.")) if grade_data is None: return None if not grade_data["released"]: return None if grade_data["grade_percent"] is not None: correctness = grade_data["grade_percent"]/100 feedback_text = "<p>%s</p>" % get_auto_feedback(correctness) if grade_data["feedback_text"]: feedback_text += ( string_concat( "<p>", _("The following feedback was provided"), ":<p>") + markup_to_html( page_context, grade_data["feedback_text"])) return AnswerFeedback( correctness=correctness, feedback=feedback_text) else: return None
def validate_markup(ctx, location, markup_str): from course.content import markup_to_html try: markup_to_html( course=None, repo=ctx.repo, commit_sha=ctx.commit_sha, text=markup_str) except: from traceback import print_exc print_exc() tp, e, _ = sys.exc_info() raise ValidationError("%s: %s: %s" % ( location, tp.__name__, str(e)))
def grading_form_to_html(self, request, page_context, grading_form, grade_data): ctx = {"form": grading_form, "rubric": markup_to_html(page_context, self.page_desc.rubric)} from django.template import RequestContext from django.template.loader import render_to_string return render_to_string("course/human-feedback-form.html", RequestContext(request, ctx))
def markup_to_html(page_context, text): from course.content import markup_to_html return markup_to_html( page_context.course, page_context.repo, page_context.commit_sha, text)
def validate_markup(ctx, location, markup_str): def reverse_func(*args, **kwargs): pass from course.content import markup_to_html try: markup_to_html(course=None, repo=ctx.repo, commit_sha=ctx.commit_sha, text=markup_str, reverse_func=reverse_func, validate_only=True) except: from traceback import print_exc print_exc() tp, e, _ = sys.exc_info() raise ValidationError("%s: %s: %s" % (location, tp.__name__, str(e)))
def grading_form_to_html(self, request, page_context, grading_form, grade_data): ctx = { "form": grading_form, "rubric": markup_to_html(page_context, self.page_desc.rubric) } from django.template import RequestContext from django.template.loader import render_to_string return render_to_string( "course/human-feedback-form.html", RequestContext(request, ctx))
def validate_markup(ctx, location, markup_str): def reverse_func(*args, **kwargs): pass from course.content import markup_to_html try: markup_to_html( course=None, repo=ctx.repo, commit_sha=ctx.commit_sha, text=markup_str, reverse_func=reverse_func, validate_only=True) except: from traceback import print_exc print_exc() tp, e, _ = sys.exc_info() raise ValidationError("%s: %s: %s" % ( location, tp.__name__, str(e)))
def view_markup_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")) request = pctx.request preview_text = "" from course.models import get_user_status ustatus = get_user_status(request.user) def make_form(data=None): help_text = (ugettext("Enter <a href=\"http://documen.tician.de/" "relate/content.html#relate-markup\">" "RELATE markup</a>.")) return SandboxForm(None, "markdown", ustatus.editor_mode, help_text, data) if request.method == "POST": form = make_form(request.POST) if form.is_valid(): from course.content import markup_to_html try: preview_text = markup_to_html(pctx.course, pctx.repo, pctx.course_commit_sha, form.cleaned_data["content"]) except: import sys tp, e, _ = sys.exc_info() messages.add_message( pctx.request, messages.ERROR, ugettext("Markup failed to render") + ": " + "%(err_type)s: %(err_str)s" % { "err_type": tp.__name__, "err_str": e }) form = make_form(request.POST) else: form = make_form() return render_course_page(pctx, "course/sandbox-markup.html", { "form": form, "preview_text": preview_text, })
def view_markup_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")) request = pctx.request preview_text = "" from course.models import get_user_status ustatus = get_user_status(request.user) def make_form(data=None): help_text = (ugettext("Enter <a href=\"http://documen.tician.de/" "relate/content.html#relate-markup\">" "RELATE markup</a>.")) return SandboxForm( None, "markdown", ustatus.editor_mode, help_text, data) if request.method == "POST": form = make_form(request.POST) if form.is_valid(): from course.content import markup_to_html try: preview_text = markup_to_html( pctx.course, pctx.repo, pctx.course_commit_sha, form.cleaned_data["content"]) except: import sys tp, e, _ = sys.exc_info() messages.add_message(pctx.request, messages.ERROR, ugettext("Markup failed to render") + ": " + "%(err_type)s: %(err_str)s" % { "err_type": tp.__name__, "err_str": e}) form = make_form(request.POST) else: form = make_form() return render_course_page(pctx, "course/sandbox-markup.html", { "form": form, "preview_text": preview_text, })
def view_markup_sandbox(pctx): request = pctx.request preview_text = "" def make_form(data=None): help_text = ("Enter <a href=\"http://documen.tician.de/" "relate/content.html#relate-markup\">" "RELATE markup</a>.") return SandboxForm( None, "markdown", vim_mode, help_text, data) vim_mode = pctx.request.session.get(CF_SANDBOX_VIM_MODE, False) if request.method == "POST": form = make_form(request.POST) if form.is_valid(): pctx.request.session[CF_SANDBOX_VIM_MODE] = \ vim_mode = form.cleaned_data["vim_mode"] from course.content import markup_to_html try: preview_text = markup_to_html( pctx.course, pctx.repo, pctx.course_commit_sha, form.cleaned_data["content"]) except: import sys tp, e, _ = sys.exc_info() messages.add_message(pctx.request, messages.ERROR, "Markup failed to render: " "%s: %s" % (tp.__name__, e)) form = make_form(request.POST) else: form = make_form() return render_course_page(pctx, "course/sandbox-markup.html", { "form": form, "preview_text": preview_text, })
def view_markup_sandbox(pctx): if not pctx.has_permission(pperm.use_markup_sandbox): raise PermissionDenied() request = pctx.request preview_text = "" def make_form(data=None): help_text = (ugettext("Enter <a href=\"http://documen.tician.de/" "relate/content.html#relate-markup\">" "RELATE markup</a>.")) return SandboxForm(None, "markdown", request.user.editor_mode, help_text, data) if request.method == "POST" and "preview" in request.POST: form = make_form(request.POST) if form.is_valid(): from course.content import markup_to_html try: preview_text = markup_to_html(pctx.course, pctx.repo, pctx.course_commit_sha, form.cleaned_data["content"]) except Exception: import sys tp, e, _ = sys.exc_info() messages.add_message( pctx.request, messages.ERROR, ugettext("Markup failed to render") + ": " + "%(err_type)s: %(err_str)s" % { "err_type": tp.__name__, "err_str": e }) form = make_form(request.POST) else: form = make_form() return render_course_page(pctx, "course/sandbox-markup.html", { "form": form, "preview_text": preview_text, })
def view_markup_sandbox(pctx): request = pctx.request preview_text = "" def make_form(data=None): help_text = ("Enter <a href=\"http://documen.tician.de/" "courseflow/content.html#courseflow-markup\">" "CourseFlow markup</a>.") return SandboxForm( None, "markdown", vim_mode, help_text, data) vim_mode = pctx.request.session.get(CF_SANDBOX_VIM_MODE, False) if request.method == "POST": form = make_form(request.POST) if form.is_valid(): pctx.request.session[CF_SANDBOX_VIM_MODE] = \ vim_mode = form.cleaned_data["vim_mode"] from course.content import markup_to_html try: preview_text = markup_to_html( pctx.course, pctx.repo, pctx.course_commit_sha, form.cleaned_data["content"]) except: import sys tp, e, _ = sys.exc_info() messages.add_message(pctx.request, messages.ERROR, "Markup failed to render: " "%s: %s" % (tp.__name__, e)) form = make_form(request.POST) else: form = make_form() return render_course_page(pctx, "course/sandbox-markup.html", { "form": form, "preview_text": preview_text, })
def view_markup_sandbox(pctx): if not pctx.has_permission(pperm.use_markup_sandbox): raise PermissionDenied() request = pctx.request preview_text = "" def make_form(data=None): help_text = (ugettext("Enter <a href=\"http://documen.tician.de/" "relate/content.html#relate-markup\">" "RELATE markup</a>.")) return SandboxForm( None, "markdown", request.user.editor_mode, help_text, data) if request.method == "POST" and "preview" in request.POST: form = make_form(request.POST) if form.is_valid(): from course.content import markup_to_html try: preview_text = markup_to_html( pctx.course, pctx.repo, pctx.course_commit_sha, form.cleaned_data["content"]) except: import sys tp, e, _ = sys.exc_info() messages.add_message(pctx.request, messages.ERROR, ugettext("Markup failed to render") + ": " + "%(err_type)s: %(err_str)s" % { "err_type": tp.__name__, "err_str": e}) form = make_form(request.POST) else: form = make_form() return render_course_page(pctx, "course/sandbox-markup.html", { "form": form, "preview_text": preview_text, })
def view_calendar(pctx): from course.content import markup_to_html events_json = [] from course.content import get_raw_yaml_from_repo try: event_descr = get_raw_yaml_from_repo(pctx.repo, pctx.course.events_file, pctx.course_commit_sha) except ObjectDoesNotExist: event_descr = {} event_kinds_desc = event_descr.get("event_kinds", {}) event_info_desc = event_descr.get("events", {}) event_info_list = [] for event in (Event.objects.filter( course=pctx.course, shown_in_calendar=True).order_by("time")): kind_desc = event_kinds_desc.get(event.kind) human_title = unicode(event) event_json = { "id": event.id, "start": event.time.isoformat(), "allDay": event.all_day, } if event.end_time is not None: event_json["end"] = event.end_time.isoformat() if kind_desc is not None: if "color" in kind_desc: event_json["color"] = kind_desc["color"] if "title" in kind_desc: if event.ordinal is not None: human_title = kind_desc["title"].format(nr=event.ordinal) else: human_title = kind_desc["title"] description = None event_desc = event_info_desc.get(unicode(event)) if event_desc is not None: if "description" in event_desc: description = markup_to_html(pctx.course, pctx.repo, pctx.course_commit_sha, event_desc["description"]) if "title" in event_desc: human_title = event_desc["title"] if "color" in event_desc: human_title = event_desc["color"] event_json["title"] = human_title if description: event_json["url"] = "#event-%d" % event.id start_time = event.time end_time = event.end_time if event.all_day: start_time = start_time.date() end_time = end_time.date() event_info_list.append( EventInfo(id=event.id, human_title=human_title, start_time=start_time, end_time=end_time, description=description)) events_json.append(event_json) from json import dumps return render_course_page(pctx, "course/calendar.html", { "events_json": dumps(events_json), "event_info_list": event_info_list, })
def view_calendar(pctx): from course.content import markup_to_html events_json = [] from course.content import get_yaml_from_repo_as_dict try: event_descr = get_yaml_from_repo_as_dict(pctx.repo, pctx.course.events_file, pctx.course_commit_sha) except ObjectDoesNotExist: event_descr = {} print "ODN" event_kinds_desc = event_descr.get("event_kinds", {}) event_info_desc = event_descr.get("events", {}) event_info_list = [] for event in Event.objects.order_by("time"): kind_desc = event_kinds_desc.get(event.kind) human_title = unicode(event) event_json = { "id": event.id, "start": event.time.isoformat(), } if event.end_time is not None: event_json["end"] = event.end_time.isoformat() if kind_desc is not None: if "color" in kind_desc: event_json["color"] = kind_desc["color"] if "title" in kind_desc: if event.ordinal: human_title = kind_desc["title"].format(nr=event.ordinal) else: human_title = kind_desc["title"] description = None event_desc = event_info_desc.get(unicode(event)) if event_desc is not None: if "description" in event_desc: description = markup_to_html( pctx.course, pctx.repo, pctx.course_commit_sha, event_desc["description"]) if "title" in event_desc: human_title = event_desc["title"] if "color" in event_desc: human_title = event_desc["color"] event_json["title"] = human_title if description: event_json["url"] = "#event-%d" % event.id event_info_list.append( EventInfo( id=event.id, human_title=human_title, start_time=event.time, end_time=event.end_time, description=description )) events_json.append(event_json) from json import dumps return render_course_page(pctx, "course/calendar.html", { "events_json": dumps(events_json), "event_info_list": event_info_list, })
def view_calendar(pctx): from course.content import markup_to_html events_json = [] from course.content import get_raw_yaml_from_repo try: event_descr = get_raw_yaml_from_repo(pctx.repo, pctx.course.events_file, pctx.course_commit_sha) except ObjectDoesNotExist: event_descr = {} event_kinds_desc = event_descr.get("event_kinds", {}) event_info_desc = event_descr.get("events", {}) event_info_list = [] for event in (Event.objects .filter( course=pctx.course, shown_in_calendar=True) .order_by("-time")): kind_desc = event_kinds_desc.get(event.kind) human_title = six.text_type(event) event_json = { "id": event.id, "start": event.time.isoformat(), "allDay": event.all_day, } if event.end_time is not None: event_json["end"] = event.end_time.isoformat() if kind_desc is not None: if "color" in kind_desc: event_json["color"] = kind_desc["color"] if "title" in kind_desc: if event.ordinal is not None: human_title = kind_desc["title"].format(nr=event.ordinal) else: human_title = kind_desc["title"] description = None event_desc = event_info_desc.get(six.text_type(event)) if event_desc is not None: if "description" in event_desc: description = markup_to_html( pctx.course, pctx.repo, pctx.course_commit_sha, event_desc["description"]) if "title" in event_desc: human_title = event_desc["title"] if "color" in event_desc: event_json["color"] = event_desc["color"] event_json["title"] = human_title if description: event_json["url"] = "#event-%d" % event.id start_time = event.time end_time = event.end_time if event.all_day: start_time = start_time.date() end_time = end_time.date() event_info_list.append( EventInfo( id=event.id, human_title=human_title, start_time=start_time, end_time=end_time, description=description )) events_json.append(event_json) from course.views import get_now_or_fake_time default_date = get_now_or_fake_time(pctx.request).date() if pctx.course.end_date is not None and default_date > pctx.course.end_date: default_date = pctx.course.end_date from json import dumps return render_course_page(pctx, "course/calendar.html", { "events_json": dumps(events_json), "event_info_list": event_info_list, "default_date": default_date.isoformat(), })
def correct_answer(self, page_context, page_data, answer_data, grade_data): if hasattr(self.page_desc, "correct_answer"): return markup_to_html(page_context, self.page_desc.correct_answer) else: return None
def finish_flow_session_view(request, course_identifier, flow_identifier): flow_session = find_current_flow_session(request, flow_identifier) if flow_session is None: messages.add_message(request, messages.WARNING, "No session record found for this flow. " "Redirected to flow start page.") return redirect("course.flow.start_flow", course_identifier, flow_identifier) fctx = FlowContext(request, course_identifier, flow_identifier, flow_session=flow_session) answer_visits = assemble_answer_visits(flow_session) from course.content import markup_to_html completion_text = markup_to_html( fctx.course, fctx.repo, fctx.flow_commit_sha, fctx.flow_desc.completion_text) (answered_count, unanswered_count) = count_answered( fctx, fctx.flow_session, answer_visits) def render_finish_response(template, **kwargs): render_args = { "course": fctx.course, "course_desc": fctx.course_desc, "flow_identifier": fctx.flow_identifier, "flow_desc": fctx.flow_desc, "participation": fctx.participation, "role": fctx.role, "participation_role": participation_role, } render_args.update(kwargs) return render(request, template, render_args) if request.method == "POST": if "submit" not in request.POST: raise SuspiciousOperation("odd POST parameters") if not flow_session.in_progress: raise PermissionDenied("Can't end a session that's already ended") # Actually end the flow session request.session["flow_session_id"] = None grade_info = finish_flow_session(fctx, flow_session) if answered_count + unanswered_count: # This is a graded flow. if grade_info is None: messages.add_message(request, messages.INFO, "A grade for your work has not yet been assigned. " "Please check back later for grade information.") return render_finish_response( "course/flow-completion.html", last_page_nr=None, completion_text=completion_text) return render_finish_response( "course/flow-completion-grade.html", completion_text=completion_text, grade_info=grade_info) else: # {{{ no grade return render_finish_response( "course/flow-completion.html", last_page_nr=None, completion_text=completion_text) # }}} if (answered_count + unanswered_count == 0 and fctx.flow_commit_sha == fctx.course_commit_sha): # Not serious--no questions in flow, and no new version available. # No need to end the flow visit. return render_finish_response( "course/flow-completion.html", last_page_nr=fctx.page_count-1, completion_text=completion_text) elif not flow_session.in_progress: # Just reviewing: re-show grades. grade_info = gather_grade_info(fctx, answer_visits) return render_finish_response( "course/flow-completion-grade.html", completion_text=completion_text, grade_info=grade_info) else: # confirm ending flow return render_finish_response( "course/flow-confirm-completion.html", last_page_nr=fctx.page_count-1, answered_count=answered_count, unanswered_count=unanswered_count, total_count=answered_count+unanswered_count)
def finish_flow_session_view(pctx, flow_session_id): now_datetime = get_now_or_fake_time(pctx.request) request = pctx.request flow_session_id = int(flow_session_id) flow_session = get_and_check_flow_session(pctx, flow_session_id) flow_id = flow_session.flow_id fctx = FlowContext(pctx.repo, pctx.course, flow_id, participation=pctx.participation, flow_session=flow_session) access_rule = get_session_access_rule(flow_session, pctx.role, fctx.flow_desc, now_datetime, pctx.remote_address) answer_visits = assemble_answer_visits(flow_session) from course.content import markup_to_html completion_text = markup_to_html(fctx.course, fctx.repo, pctx.course_commit_sha, fctx.flow_desc.completion_text) (answered_count, unanswered_count) = count_answered_gradable(fctx, flow_session, answer_visits) is_graded_flow = bool(answered_count + unanswered_count) if flow_permission.view not in access_rule.permissions: raise PermissionDenied() def render_finish_response(template, **kwargs): render_args = {"flow_identifier": fctx.flow_id, "flow_desc": fctx.flow_desc} render_args.update(kwargs) return render_course_page(pctx, template, render_args, allow_instant_flow_requests=False) if request.method == "POST": if "submit" not in request.POST: raise SuspiciousOperation(_("odd POST parameters")) if not flow_session.in_progress: raise PermissionDenied(_("Can't end a session that's already ended")) if flow_permission.end_session not in access_rule.permissions: raise PermissionDenied(_("not permitted to end session")) grading_rule = get_session_grading_rule(flow_session, pctx.role, fctx.flow_desc, now_datetime) grade_info = finish_flow_session(fctx, flow_session, grading_rule, now_datetime=now_datetime) if is_graded_flow: return render_finish_response( "course/flow-completion-grade.html", completion_text=completion_text, grade_info=grade_info ) else: return render_finish_response( "course/flow-completion.html", last_page_nr=None, flow_session=flow_session, completion_text=completion_text, ) if not is_graded_flow or (flow_session.in_progress and flow_permission.end_session not in access_rule.permissions): # No ability to end--just show completion page. return render_finish_response( "course/flow-completion.html", last_page_nr=flow_session.page_count - 1, flow_session=flow_session, completion_text=completion_text, ) elif not flow_session.in_progress: # Just reviewing: re-show grades. grade_info = gather_grade_info(fctx, flow_session, answer_visits) return render_finish_response( "course/flow-completion-grade.html", completion_text=completion_text, grade_info=grade_info ) else: # confirm ending flow return render_finish_response( "course/flow-confirm-completion.html", last_page_nr=flow_session.page_count - 1, flow_session=flow_session, answered_count=answered_count, unanswered_count=unanswered_count, total_count=answered_count + unanswered_count, )
def view_calendar(pctx): from course.content import markup_to_html, parse_date_spec from course.views import get_now_or_fake_time now = get_now_or_fake_time(pctx.request) if not pctx.has_permission(pperm.view_calendar): raise PermissionDenied(_("may not view calendar")) events_json = [] from course.content import get_raw_yaml_from_repo try: event_descr = get_raw_yaml_from_repo(pctx.repo, pctx.course.events_file, pctx.course_commit_sha) except ObjectDoesNotExist: event_descr = {} event_kinds_desc = event_descr.get("event_kinds", {}) event_info_desc = event_descr.get("events", {}) event_info_list = [] events = sorted( Event.objects .filter( course=pctx.course, shown_in_calendar=True), key=lambda evt: ( -evt.time.year, -evt.time.month, -evt.time.day, evt.time.hour, evt.time.minute, evt.time.second)) for event in events: kind_desc = event_kinds_desc.get(event.kind) human_title = six.text_type(event) event_json = { "id": event.id, "start": event.time.isoformat(), "allDay": event.all_day, } if event.end_time is not None: event_json["end"] = event.end_time.isoformat() if kind_desc is not None: if "color" in kind_desc: event_json["color"] = kind_desc["color"] if "title" in kind_desc: if event.ordinal is not None: human_title = kind_desc["title"].format(nr=event.ordinal) else: human_title = kind_desc["title"] description = None show_description = True event_desc = event_info_desc.get(six.text_type(event)) if event_desc is not None: if "description" in event_desc: description = markup_to_html( pctx.course, pctx.repo, pctx.course_commit_sha, event_desc["description"]) if "title" in event_desc: human_title = event_desc["title"] if "color" in event_desc: event_json["color"] = event_desc["color"] if "show_description_from" in event_desc: ds = parse_date_spec( pctx.course, event_desc["show_description_from"]) if now < ds: show_description = False if "show_description_until" in event_desc: ds = parse_date_spec( pctx.course, event_desc["show_description_until"]) if now > ds: show_description = False event_json["title"] = human_title if show_description and description: event_json["url"] = "#event-%d" % event.id start_time = event.time end_time = event.end_time if event.all_day: start_time = start_time.date() if end_time is not None: local_end_time = as_local_time(end_time) end_midnight = datetime.time(tzinfo=local_end_time.tzinfo) if local_end_time.time() == end_midnight: end_time = (end_time - datetime.timedelta(days=1)).date() else: end_time = end_time.date() event_info_list.append( EventInfo( id=event.id, human_title=human_title, start_time=start_time, end_time=end_time, description=description )) events_json.append(event_json) default_date = now.date() if pctx.course.end_date is not None and default_date > pctx.course.end_date: default_date = pctx.course.end_date from json import dumps return render_course_page(pctx, "course/calendar.html", { "events_json": dumps(events_json), "event_info_list": event_info_list, "default_date": default_date.isoformat(), })
def batch_issue_exam_tickets(pctx): if pctx.role not in [ participation_role.instructor, ]: raise PermissionDenied( _("must be instructor or TA to batch-issue tickets")) form_text = "" request = pctx.request if request.method == "POST": form = BatchIssueTicketsForm(pctx.course, request.user.editor_mode, request.POST) if form.is_valid(): exam = form.cleaned_data["exam"] from jinja2 import TemplateSyntaxError from course.content import markup_to_html try: with transaction.atomic(): if form.cleaned_data["revoke_prior"]: ExamTicket.objects.filter( exam=exam, state__in=( exam_ticket_states.valid, exam_ticket_states.used, ) ).update(state=exam_ticket_states.revoked) tickets = [] for participation in ( Participation.objects.filter( course=pctx.course, status=participation_status.active) .order_by("user__last_name") ): ticket = ExamTicket() ticket.exam = exam ticket.participation = participation ticket.creator = request.user ticket.state = exam_ticket_states.valid ticket.code = gen_ticket_code() ticket.save() tickets.append(ticket) checkin_uri = pctx.request.build_absolute_uri( reverse("relate-check_in_for_exam")) form_text = markup_to_html( pctx.course, pctx.repo, pctx.course_commit_sha, form.cleaned_data["format"], jinja_env={ "tickets": tickets, "checkin_uri": checkin_uri, }) except TemplateSyntaxError as e: messages.add_message(request, messages.ERROR, string_concat( _("Template rendering failed"), ": line %(lineno)d: %(err_str)s") % { "lineno": e.lineno, "err_str": e.message.decode("utf-8")}) except Exception as e: messages.add_message(request, messages.ERROR, string_concat( _("Template rendering failed"), ": %(err_type)s: %(err_str)s") % {"err_type": type(e).__name__, "err_str": str(e)}) else: messages.add_message(request, messages.SUCCESS, _("%d tickets issued.") % len(tickets)) else: form = BatchIssueTicketsForm(pctx.course, request.user.editor_mode) return render_course_page(pctx, "course/batch-exam-tickets-form.html", { "form": form, "form_text": form_text, "form_description": ugettext("Batch-Issue Exam Tickets") })
def batch_issue_exam_tickets(pctx): if not pctx.has_permission(pperm.batch_issue_exam_ticket): raise PermissionDenied(_("may not batch-issue tickets")) form_text = "" request = pctx.request if request.method == "POST": form = BatchIssueTicketsForm(pctx.course, request.user.editor_mode, request.POST) if form.is_valid(): exam = form.cleaned_data["exam"] from jinja2 import TemplateSyntaxError from course.content import markup_to_html try: with transaction.atomic(): if form.cleaned_data["revoke_prior"]: ExamTicket.objects.filter( exam=exam, state__in=( exam_ticket_states.valid, exam_ticket_states.used, )).update(state=exam_ticket_states.revoked) tickets = [] for participation in (Participation.objects.filter( course=pctx.course, status=participation_status.active).order_by( "user__last_name")): ticket = ExamTicket() ticket.exam = exam ticket.participation = participation ticket.creator = request.user ticket.state = exam_ticket_states.valid ticket.code = gen_ticket_code() ticket.valid_start_time = \ form.cleaned_data["valid_start_time"] ticket.valid_end_time = form.cleaned_data[ "valid_end_time"] ticket.restrict_to_facility = \ form.cleaned_data["restrict_to_facility"] ticket.save() tickets.append(ticket) checkin_uri = pctx.request.build_absolute_uri( reverse("relate-check_in_for_exam")) form_text = markup_to_html(pctx.course, pctx.repo, pctx.course_commit_sha, form.cleaned_data["format"], jinja_env={ "tickets": tickets, "checkin_uri": checkin_uri, }) except TemplateSyntaxError as e: messages.add_message( request, messages.ERROR, string_concat(_("Template rendering failed"), ": line %(lineno)d: %(err_str)s") % { "lineno": e.lineno, "err_str": e.message.decode("utf-8") }) except Exception as e: messages.add_message( request, messages.ERROR, string_concat(_("Template rendering failed"), ": %(err_type)s: %(err_str)s") % { "err_type": type(e).__name__, "err_str": str(e) }) else: messages.add_message(request, messages.SUCCESS, _("%d tickets issued.") % len(tickets)) else: form = BatchIssueTicketsForm(pctx.course, request.user.editor_mode) return render_course_page( pctx, "course/batch-exam-tickets-form.html", { "form": form, "form_text": form_text, "form_description": gettext("Batch-Issue Exam Tickets") })
def finish_flow_session_view(pctx, flow_identifier): request = pctx.request flow_session = find_current_flow_session( request, pctx.course, flow_identifier) if flow_session is None: messages.add_message(request, messages.WARNING, "No session record found for this flow. " "Redirected to flow start page.") return redirect("course.flow.start_flow", pctx.course.identifier, flow_identifier) fctx = FlowContext(pctx.repo, pctx.course, flow_identifier, participation=pctx.participation, flow_session=flow_session) current_access_rule = fctx.get_current_access_rule( flow_session, pctx.role, pctx.participation, get_now_or_fake_time(request)) answer_visits = assemble_answer_visits(flow_session) from course.content import markup_to_html completion_text = markup_to_html( fctx.course, fctx.repo, fctx.flow_commit_sha, fctx.flow_desc.completion_text) (answered_count, unanswered_count) = count_answered( fctx, flow_session, answer_visits) is_graded_flow = bool(answered_count + unanswered_count) if flow_permission.view not in current_access_rule.permissions: raise PermissionDenied() def render_finish_response(template, **kwargs): render_args = { "flow_identifier": fctx.flow_identifier, "flow_desc": fctx.flow_desc, } render_args.update(kwargs) return render_course_page( pctx, template, render_args, allow_instant_flow_requests=False) if request.method == "POST": if "submit" not in request.POST: raise SuspiciousOperation("odd POST parameters") if not flow_session.in_progress: raise PermissionDenied("Can't end a session that's already ended") # Actually end the flow session request.session["flow_session_id"] = None grade_info = finish_flow_session(fctx, flow_session, current_access_rule) if is_graded_flow: return render_finish_response( "course/flow-completion-grade.html", completion_text=completion_text, grade_info=grade_info) else: return render_finish_response( "course/flow-completion.html", last_page_nr=None, completion_text=completion_text) # }}} if (not is_graded_flow and fctx.flow_commit_sha == fctx.course_commit_sha): # Not serious--no questions in flow, and no new version available. # No need to end the flow visit. return render_finish_response( "course/flow-completion.html", last_page_nr=flow_session.page_count-1, completion_text=completion_text) elif not flow_session.in_progress: # Just reviewing: re-show grades. grade_info = gather_grade_info(flow_session, answer_visits) return render_finish_response( "course/flow-completion-grade.html", completion_text=completion_text, grade_info=grade_info) else: # confirm ending flow return render_finish_response( "course/flow-confirm-completion.html", last_page_nr=flow_session.page_count-1, answered_count=answered_count, unanswered_count=unanswered_count, total_count=answered_count+unanswered_count)
def body(self, page_context, page_data): return markup_to_html(page_context, self.page_desc.prompt)
def view_calendar(pctx): from course.content import markup_to_html, parse_date_spec from course.views import get_now_or_fake_time now = get_now_or_fake_time(pctx.request) if not pctx.has_permission(pperm.view_calendar): raise PermissionDenied(_("may not view calendar")) events_json = [] from course.content import get_raw_yaml_from_repo try: event_descr = get_raw_yaml_from_repo(pctx.repo, pctx.course.events_file, pctx.course_commit_sha) except ObjectDoesNotExist: event_descr = {} event_kinds_desc = event_descr.get("event_kinds", {}) event_info_desc = event_descr.get("events", {}) event_info_list = [] for event in Event.objects.filter(course=pctx.course, shown_in_calendar=True).order_by("-time"): kind_desc = event_kinds_desc.get(event.kind) human_title = six.text_type(event) event_json = {"id": event.id, "start": event.time.isoformat(), "allDay": event.all_day} if event.end_time is not None: event_json["end"] = event.end_time.isoformat() if kind_desc is not None: if "color" in kind_desc: event_json["color"] = kind_desc["color"] if "title" in kind_desc: if event.ordinal is not None: human_title = kind_desc["title"].format(nr=event.ordinal) else: human_title = kind_desc["title"] description = None show_description = True event_desc = event_info_desc.get(six.text_type(event)) if event_desc is not None: if "description" in event_desc: description = markup_to_html(pctx.course, pctx.repo, pctx.course_commit_sha, event_desc["description"]) if "title" in event_desc: human_title = event_desc["title"] if "color" in event_desc: event_json["color"] = event_desc["color"] if "show_description_from" in event_desc: ds = parse_date_spec(pctx.course, event_desc["show_description_from"]) if now < ds: show_description = False if "show_description_until" in event_desc: ds = parse_date_spec(pctx.course, event_desc["show_description_until"]) if now > ds: show_description = False event_json["title"] = human_title if show_description and description: event_json["url"] = "#event-%d" % event.id start_time = event.time end_time = event.end_time if event.all_day: start_time = start_time.date() local_end_time = as_local_time(end_time) end_midnight = datetime.time(tzinfo=local_end_time.tzinfo) if local_end_time.time() == end_midnight: end_time = (end_time - datetime.timedelta(days=1)).date() else: end_time = end_time.date() event_info_list.append( EventInfo( id=event.id, human_title=human_title, start_time=start_time, end_time=end_time, description=description, ) ) events_json.append(event_json) default_date = now.date() if pctx.course.end_date is not None and default_date > pctx.course.end_date: default_date = pctx.course.end_date from json import dumps return render_course_page( pctx, "course/calendar.html", { "events_json": dumps(events_json), "event_info_list": event_info_list, "default_date": default_date.isoformat(), }, )