def get_current_repo_file(request, course_identifier, path): course = get_object_or_404(Course, identifier=course_identifier) role, participation = get_role_and_participation(request, course) from course.views import check_course_state check_course_state(course, role) from course.content import get_course_commit_sha commit_sha = get_course_commit_sha(course, participation) role, participation = get_role_and_participation(request, course) repo = get_course_repo(course) from course.content import is_repo_file_public if not is_repo_file_public(repo, commit_sha, path): raise PermissionDenied() from course.content import get_repo_blob_data_cached try: data = get_repo_blob_data_cached(repo, path, commit_sha.encode()) except ObjectDoesNotExist: raise http.Http404() from mimetypes import guess_type content_type, _ = guess_type(path) return http.HttpResponse(data, content_type=content_type)
def __init__(self, repo, course, flow_id, participation=None, flow_session=None): """*participation* and *flow_session* are not stored and only used to figure out versioning of the flow content. """ self.repo = repo self.course = course self.flow_id = flow_id from django.core.exceptions import ObjectDoesNotExist self.course_commit_sha = get_course_commit_sha( self.course, participation) try: self.flow_desc = get_flow_desc(self.repo, self.course, flow_id, self.course_commit_sha) except ObjectDoesNotExist: raise http.Http404() if flow_session is not None: from course.content import adjust_flow_session_page_data adjust_flow_session_page_data(repo, flow_session, course.identifier, self.flow_desc)
def __init__(self, repo, course, flow_id, participation=None, flow_session=None): """*participation* and *flow_session* are not stored and only used to figure out versioning of the flow content. """ self.repo = repo self.course = course self.flow_id = flow_id from django.core.exceptions import ObjectDoesNotExist self.course_commit_sha = get_course_commit_sha(self.course, participation) try: self.flow_desc = get_flow_desc(self.repo, self.course, flow_id, self.course_commit_sha) except ObjectDoesNotExist: raise http.Http404() if flow_session is not None: from course.content import adjust_flow_session_page_data adjust_flow_session_page_data(repo, flow_session, course.identifier, self.flow_desc)
def __init__(self, request, course_identifier): # type: (http.HttpRequest, Text) -> None self.request = request self.course_identifier = course_identifier self._permissions_cache = None # type: Optional[FrozenSet[Tuple[Text, Optional[Text]]]] # noqa self._role_identifiers_cache = None # type: Optional[List[Text]] self.old_language = None # using this to prevent nested using as context manager self._is_in_context_manager = False from course.models import Course # noqa self.course = get_object_or_404(Course, identifier=course_identifier) from course.enrollment import get_participation_for_request self.participation = get_participation_for_request( request, self.course) from course.views import check_course_state check_course_state(self.course, self.participation) self.course_commit_sha = get_course_commit_sha(self.course, self.participation) self.repo = get_course_repo(self.course) # logic duplicated in course.content.get_course_commit_sha sha = self.course.active_git_commit_sha.encode() if self.participation is not None: if self.participation.preview_git_commit_sha: preview_sha = self.participation.preview_git_commit_sha.encode( ) with get_course_repo(self.course) as repo: from relate.utils import SubdirRepoWrapper if isinstance(repo, SubdirRepoWrapper): true_repo = repo.repo else: true_repo = cast(dulwich.repo.Repo, repo) try: true_repo[preview_sha] except KeyError: from django.contrib import messages messages.add_message( request, messages.ERROR, _("Preview revision '%s' does not exist--" "showing active course content instead.") % preview_sha.decode()) preview_sha = None finally: true_repo.close() if preview_sha is not None: sha = preview_sha self.course_commit_sha = sha
def get_current_repo_file(request, course_identifier, path): course = get_object_or_404(Course, identifier=course_identifier) role, participation = get_role_and_participation( request, course) from course.views import check_course_state check_course_state(course, role) from course.content import get_course_commit_sha commit_sha = get_course_commit_sha(course, participation) role, participation = get_role_and_participation(request, course) repo = get_course_repo(course) from course.content import is_repo_file_public if not is_repo_file_public(repo, commit_sha, path): raise PermissionDenied() from course.content import get_repo_blob_data_cached try: data = get_repo_blob_data_cached( repo, path, commit_sha.encode()) except ObjectDoesNotExist: raise http.Http404() from mimetypes import guess_type content_type, _ = guess_type(path) return http.HttpResponse(data, content_type=content_type)
def __init__(self, request, course_identifier): # type: (http.HttpRequest, Text) -> None self.request = request self.course_identifier = course_identifier self._permissions_cache = None # type: Optional[FrozenSet[Tuple[Text, Optional[Text]]]] # noqa self._role_identifiers_cache = None # type: Optional[List[Text]] self.old_language = None # using this to prevent nested using as context manager self._is_in_context_manager = False from course.models import Course # noqa self.course = get_object_or_404(Course, identifier=course_identifier) from course.enrollment import get_participation_for_request self.participation = get_participation_for_request( request, self.course) from course.views import check_course_state check_course_state(self.course, self.participation) self.course_commit_sha = get_course_commit_sha( self.course, self.participation) self.repo = get_course_repo(self.course) # logic duplicated in course.content.get_course_commit_sha sha = self.course.active_git_commit_sha.encode() if self.participation is not None: if self.participation.preview_git_commit_sha: preview_sha = self.participation.preview_git_commit_sha.encode() with get_course_repo(self.course) as repo: from relate.utils import SubdirRepoWrapper if isinstance(repo, SubdirRepoWrapper): true_repo = repo.repo else: true_repo = cast(dulwich.repo.Repo, repo) try: true_repo[preview_sha] except KeyError: from django.contrib import messages messages.add_message(request, messages.ERROR, _("Preview revision '%s' does not exist--" "showing active course content instead.") % preview_sha.decode()) preview_sha = None finally: true_repo.close() if preview_sha is not None: sha = preview_sha self.course_commit_sha = sha
def get_current_repo_file(request, course_identifier, path): course = get_object_or_404(Course, identifier=course_identifier) role, participation = get_role_and_participation(request, course) from course.content import get_course_commit_sha commit_sha = get_course_commit_sha(course, participation) return get_repo_file_backend(request, course, role, participation, commit_sha, path)
def get_current_repo_file(request, course_identifier, path): course = get_object_or_404(Course, identifier=course_identifier) role, participation = get_role_and_participation( request, course) from course.content import get_course_commit_sha commit_sha = get_course_commit_sha(course, participation) return get_repo_file_backend( request, course, role, participation, commit_sha, path)
def get_current_repo_file(request, course_identifier, path): # type: (http.HttpRequest, str, str) -> http.HttpResponse course = get_object_or_404(Course, identifier=course_identifier) participation = get_participation_for_request(request, course) from course.content import get_course_commit_sha commit_sha = get_course_commit_sha(course, participation) return get_repo_file_backend( request, course, participation, commit_sha, path)
def current_repo_file_etag_func(request, course_identifier, path): course = get_object_or_404(Course, identifier=course_identifier) role, participation = get_role_and_participation(request, course) from course.views import check_course_state check_course_state(course, role) from course.content import get_course_commit_sha commit_sha = get_course_commit_sha(course, participation) return ":".join([course_identifier, commit_sha, path])
def current_repo_file_etag_func(request, course_identifier, path): # type: (http.HttpRequest, str, str) -> str course = get_object_or_404(Course, identifier=course_identifier) participation = get_participation_for_request(request, course) check_course_state(course, participation) from course.content import get_course_commit_sha commit_sha = get_course_commit_sha(course, participation) return ":".join([course_identifier, commit_sha.decode(), path])
def get_current_repo_file(request, course_identifier, path): # type: (http.HttpRequest, str, str) -> http.HttpResponse course = get_object_or_404(Course, identifier=course_identifier) participation = get_participation_for_request(request, course) from course.content import get_course_commit_sha commit_sha = get_course_commit_sha(course, participation) return get_repo_file_backend(request, course, participation, commit_sha, path)
def current_repo_file_etag_func(request, course_identifier, path): course = get_object_or_404(Course, identifier=course_identifier) role, participation = get_role_and_participation( request, course) from course.views import check_course_state check_course_state(course, role) from course.content import get_course_commit_sha commit_sha = get_course_commit_sha(course, participation) return ":".join([course_identifier, commit_sha.decode(), path])
def set_course_metadata(apps, schema_editor): Course = apps.get_model("course", "Course") # noqa for course in Course.objects.all(): from course.content import get_course_repo, get_course_desc, get_course_commit_sha repo = get_course_repo(course) course_desc = get_course_desc(repo, course, get_course_commit_sha(course, participation=None)) course.name = course_desc.name course.number = course_desc.number course.time_period = course_desc.run repo.close() course.save()
def clean(self): super(FlowRuleException, self).clean() if (self.kind == flow_rule_kind.grading and self.expiration is not None): raise ValidationError(_("grading rules may not expire")) from course.validation import ( ValidationError as ContentValidationError, validate_session_start_rule, validate_session_access_rule, validate_session_grading_rule, ValidationContext) from course.content import (get_course_repo, get_course_commit_sha, get_flow_desc) from relate.utils import dict_to_struct rule = dict_to_struct(self.rule) repo = get_course_repo(self.participation.course) commit_sha = get_course_commit_sha( self.participation.course, self.participation) ctx = ValidationContext( repo=repo, commit_sha=commit_sha) flow_desc = get_flow_desc(repo, self.participation.course, self.flow_id, commit_sha) tags = None if hasattr(flow_desc, "rules"): tags = getattr(flow_desc.rules, "tags", None) try: if self.kind == flow_rule_kind.start: validate_session_start_rule(ctx, unicode(self), rule, tags) elif self.kind == flow_rule_kind.access: validate_session_access_rule(ctx, unicode(self), rule, tags) elif self.kind == flow_rule_kind.grading: validate_session_grading_rule(ctx, unicode(self), rule, tags) else: # the rule refers to FlowRuleException rule raise ValidationError(_("invalid rule kind: ")+self.kind) except ContentValidationError as e: # the rule refers to FlowRuleException rule raise ValidationError(_("invalid existing_session_rules: ")+str(e))
def __init__(self, request, course_identifier): self.request = request self.course_identifier = course_identifier self.course = get_object_or_404(Course, identifier=course_identifier) self.role, self.participation = get_role_and_participation( request, self.course) from course.views import check_course_state check_course_state(self.course, self.role) self.course_commit_sha = get_course_commit_sha(self.course, self.participation) self.repo = get_course_repo(self.course)
def __init__(self, request, course_identifier): self.request = request self.course_identifier = course_identifier self.course = get_object_or_404(Course, identifier=course_identifier) self.role, self.participation = get_role_and_participation( request, self.course) from course.views import check_course_state check_course_state(self.course, self.role) self.course_commit_sha = get_course_commit_sha( self.course, self.participation) self.repo = get_course_repo(self.course)
def __init__(self, request, course_identifier): self.request = request self.course_identifier = course_identifier from course.models import Course self.course = get_object_or_404(Course, identifier=course_identifier) from course.views import get_role_and_participation self.role, self.participation = get_role_and_participation( request, self.course) from course.views import check_course_state check_course_state(self.course, self.role) self.course_commit_sha = get_course_commit_sha( self.course, self.participation) self.repo = get_course_repo(self.course) # logic duplicated in course.content.get_course_commit_sha sha = self.course.active_git_commit_sha.encode() if (self.participation is not None and self.participation.preview_git_commit_sha): preview_sha = self.participation.preview_git_commit_sha.encode() repo = get_course_repo(self.course) from course.content import SubdirRepoWrapper if isinstance(repo, SubdirRepoWrapper): repo = repo.repo try: repo[preview_sha] except KeyError: from django.contrib import messages messages.add_message(request, messages.ERROR, _("Preview revision '%s' does not exist--" "showing active course content instead.") % preview_sha.decode()) preview_sha = None if preview_sha is not None: sha = preview_sha self.course_commit_sha = sha
def set_course_metadata(apps, schema_editor): Course = apps.get_model("course", "Course") # noqa for course in Course.objects.all(): from course.content import ( get_course_repo, get_course_desc, get_course_commit_sha) repo = get_course_repo(course) course_desc = get_course_desc( repo, course, get_course_commit_sha(course, participation=None)) course.name = course_desc.name course.number = course_desc.number course.time_period = course_desc.run repo.close() course.save()
def start_flow(repo, course, participation, flow_id, flow_desc, access_rules_tag, now_datetime): from course.content import get_course_commit_sha course_commit_sha = get_course_commit_sha(course, participation) session = FlowSession( course=course, participation=participation, active_git_commit_sha=course_commit_sha.decode(), flow_id=flow_id, in_progress=True, expiration_mode=flow_session_expiration_mode.end, access_rules_tag=access_rules_tag, ) session.save() # Create flow grading opportunity. This makes the flow # show up in the grade book. from course.utils import get_flow_rules from course.models import get_flow_grading_opportunity for grading_rule in get_flow_rules( flow_desc, flow_rule_kind.grading, participation, flow_id, now_datetime, consider_exceptions=False ): identifier = getattr(grading_rule, "grade_identifier", None) if identifier is not None: get_flow_grading_opportunity( course, flow_id, flow_desc, FlowSessionGradingRule( grade_identifier=identifier, grade_aggregation_strategy=getattr(grading_rule, "grade_aggregation_strategy"), ), ) # will implicitly modify and save the session if there are changes from course.content import adjust_flow_session_page_data adjust_flow_session_page_data(repo, session, course.identifier, flow_desc, course_commit_sha) return session
def __init__(self, repo, course, flow_identifier, participation=None, flow_session=None): """*participation* and *flow_session* are not stored and only used to figure out versioning of the flow content. """ self.repo = repo self.course = course self.flow_identifier = flow_identifier from course.content import get_flow_commit_sha from django.core.exceptions import ObjectDoesNotExist # Fetch 'current' version of the flow to compute permissions # and versioning rules. # Fall back to 'old' version if current git version does not # contain this flow any more. self.course_commit_sha = get_course_commit_sha( self.course, participation) try: current_flow_desc_sha = self.course_commit_sha self.current_flow_desc = get_flow_desc(self.repo, self.course, flow_identifier, current_flow_desc_sha) except ObjectDoesNotExist: if flow_session is None: raise http.Http404() current_flow_desc_sha = flow_session.active_git_commit_sha.encode() self.current_flow_desc = get_flow_desc(self.repo, self.course, flow_identifier, current_flow_desc_sha) self.flow_commit_sha = get_flow_commit_sha( self.course, participation, self.current_flow_desc, flow_session) if self.flow_commit_sha == current_flow_desc_sha: self.flow_desc = self.current_flow_desc else: self.flow_desc = get_flow_desc(self.repo, self.course, flow_identifier, self.flow_commit_sha)
def __init__(self, repo, course, flow_id, participation=None): # type: (Repo_ish, Course, Text, Optional[Participation]) -> None """*participation* and *flow_session* are not stored and only used to figure out versioning of the flow content. """ self.repo = repo self.course = course self.flow_id = flow_id from django.core.exceptions import ObjectDoesNotExist self.course_commit_sha = get_course_commit_sha(self.course, participation) try: self.flow_desc = get_flow_desc(self.repo, self.course, flow_id, self.course_commit_sha) except ObjectDoesNotExist: raise http.Http404()
def clean(self): if (self.kind == flow_rule_kind.grading and self.expiration is not None): raise ValidationError("grading rules may not expire") from course.validation import (ValidationError as ContentValidationError, validate_session_start_rule, validate_session_access_rule, validate_session_grading_rule, ValidationContext) from course.content import (get_course_repo, get_course_commit_sha, get_flow_desc) from relate.utils import dict_to_struct rule = dict_to_struct(self.rule) repo = get_course_repo(self.participation.course) commit_sha = get_course_commit_sha(self.participation.course, self.participation) ctx = ValidationContext(repo=repo, commit_sha=commit_sha) flow_desc = get_flow_desc(repo, self.participation.course, self.flow_id, commit_sha) tags = None if hasattr(flow_desc, "rules"): tags = getattr(flow_desc.rules, "tags", None) try: if self.kind == flow_rule_kind.start: validate_session_start_rule(ctx, unicode(self), rule, tags) elif self.kind == flow_rule_kind.access: validate_session_access_rule(ctx, unicode(self), rule, tags) elif self.kind == flow_rule_kind.grading: validate_session_grading_rule(ctx, unicode(self), rule, tags) else: raise ValidationError("invalid rule kind: " + self.kind) except ContentValidationError as e: raise ValidationError("invalid existing_session_rules: " + str(e))
def __init__(self, repo, course, flow_id, participation=None): # type: (Repo_ish, Course, Text, Optional[Participation]) -> None """*participation* and *flow_session* are not stored and only used to figure out versioning of the flow content. """ self.repo = repo self.course = course self.flow_id = flow_id from django.core.exceptions import ObjectDoesNotExist self.course_commit_sha = get_course_commit_sha( self.course, participation) try: self.flow_desc = get_flow_desc(self.repo, self.course, flow_id, self.course_commit_sha) except ObjectDoesNotExist: raise http.Http404()
def __init__(self, request, course_identifier): # type: (http.HttpRequest, Text) -> None self.request = request self.course_identifier = course_identifier self._permissions_cache = None # type: Optional[FrozenSet[Tuple[Text, Optional[Text]]]] # noqa self._role_identifiers_cache = None # type: Optional[List[Text]] self.old_language = None # using this to prevent nested using as context manager self._is_in_context_manager = False from course.models import Course # noqa self.course = get_object_or_404(Course, identifier=course_identifier) from course.enrollment import get_participation_for_request self.participation = get_participation_for_request( request, self.course) from course.views import check_course_state check_course_state(self.course, self.participation) self.repo = get_course_repo(self.course) try: sha = get_course_commit_sha( self.course, self.participation, repo=self.repo, raise_on_nonexistent_preview_commit=True) except CourseCommitSHADoesNotExist as e: from django.contrib import messages messages.add_message(request, messages.ERROR, str(e)) sha = self.course.active_git_commit_sha.encode() self.course_commit_sha = sha
def _get_current_access_rule(participation, flow_id): course = participation.course from course.content import ( get_course_repo, get_course_commit_sha, get_flow_desc) repo = get_course_repo(course) course_commit_sha = get_course_commit_sha(course, participation) try: flow_desc = get_flow_desc(repo, course, flow_id.encode(), course_commit_sha) except ObjectDoesNotExist: return None else: from course.utils import get_current_flow_access_rule from django.utils.timezone import now return get_current_flow_access_rule(course, participation, participation.role, flow_id, flow_desc, now(), rule_id=None, use_exceptions=False)
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 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()