def get(self, request, exam_id=None, course_id=None, content_id=None): # pylint: disable=unused-argument """ HTTP GET handler. Scenarios: by exam_id: calls get_exam_by_id() by course_id, content_id: get_exam_by_content_id() """ if exam_id: data = get_exam_by_id(exam_id) elif course_id is not None: if content_id is not None: # get by course_id & content_id data = get_exam_by_content_id(course_id, content_id) else: data = get_all_exams_for_course(course_id=course_id, active_only=True) return Response(data)
def get(self, request, exam_id=None, course_id=None, content_id=None): # pylint: disable=unused-argument """ HTTP GET handler. Scenarios: by exam_id: calls get_exam_by_id() by course_id, content_id: get_exam_by_content_id() """ if exam_id: data = get_exam_by_id(exam_id) elif course_id is not None: if content_id is not None: # get by course_id & content_id data = get_exam_by_content_id(course_id, content_id) else: data = get_all_exams_for_course( course_id=course_id, active_only=True ) return Response(data)
""" if exam_id: try: return Response(data=get_exam_by_id(exam_id), status=status.HTTP_200_OK) except ProctoredExamNotFoundException, ex: LOG.exception(ex) return Response(status=status.HTTP_400_BAD_REQUEST, data={"detail": "The exam_id does not exist."}) else: if course_id is not None: if content_id is not None: # get by course_id & content_id try: return Response(data=get_exam_by_content_id( course_id, content_id), status=status.HTTP_200_OK) except ProctoredExamNotFoundException, ex: LOG.exception(ex) return Response( status=status.HTTP_400_BAD_REQUEST, data={ "detail": "The exam with course_id, content_id does not exist." }) else: timed_exams_only = not request.user.is_staff result_set = get_all_exams_for_course( course_id=course_id, timed_exams_only=timed_exams_only, active_only=True)
def register_special_exams(course_key): """ This is typically called on a course published signal. The course is examined for sequences that are marked as timed exams. Then these are registered with the edx-proctoring subsystem. Likewise, if formerly registered exams are unmarked, then those registered exams are marked as inactive """ if not settings.FEATURES.get('ENABLE_SPECIAL_EXAMS'): # if feature is not enabled then do a quick exit return course = modulestore().get_course(course_key) if not course.enable_proctored_exams and not course.enable_timed_exams: # likewise if course does not have these features turned on # then quickly exit return # get all sequences, since they can be marked as timed/proctored exams _timed_exams = modulestore().get_items(course_key, qualifiers={ 'category': 'sequential', }, settings={ 'is_time_limited': True, }) # filter out any potential dangling sequences timed_exams = [ timed_exam for timed_exam in _timed_exams if is_item_in_course_tree(timed_exam) ] # enumerate over list of sequences which are time-limited and # add/update any exam entries in edx-proctoring for timed_exam in timed_exams: msg = ( 'Found {location} as a timed-exam in course structure. Inspecting...' .format(location=unicode(timed_exam.location))) log.info(msg) try: exam = get_exam_by_content_id(unicode(course_key), unicode(timed_exam.location)) # update case, make sure everything is synced exam_id = update_exam( exam_id=exam['id'], exam_name=timed_exam.display_name, time_limit_mins=timed_exam.default_time_limit_minutes, due_date=timed_exam.due, is_proctored=timed_exam.is_proctored_exam, is_practice_exam=timed_exam.is_practice_exam, is_active=True, hide_after_due=timed_exam.hide_after_due, ) msg = 'Updated timed exam {exam_id}'.format(exam_id=exam['id']) log.info(msg) except ProctoredExamNotFoundException: exam_id = create_exam( course_id=unicode(course_key), content_id=unicode(timed_exam.location), exam_name=timed_exam.display_name, time_limit_mins=timed_exam.default_time_limit_minutes, due_date=timed_exam.due, is_proctored=timed_exam.is_proctored_exam, is_practice_exam=timed_exam.is_practice_exam, is_active=True, hide_after_due=timed_exam.hide_after_due, ) msg = 'Created new timed exam {exam_id}'.format(exam_id=exam_id) log.info(msg) # only create/update exam policy for the proctored exams if timed_exam.is_proctored_exam and not timed_exam.is_practice_exam: try: update_review_policy( exam_id=exam_id, set_by_user_id=timed_exam.edited_by, review_policy=timed_exam.exam_review_rules) except ProctoredExamReviewPolicyNotFoundException: if timed_exam.exam_review_rules: # won't save an empty rule. create_exam_review_policy( exam_id=exam_id, set_by_user_id=timed_exam.edited_by, review_policy=timed_exam.exam_review_rules) msg = 'Created new exam review policy with exam_id {exam_id}'.format( exam_id=exam_id) log.info(msg) else: try: # remove any associated review policy remove_review_policy(exam_id=exam_id) except ProctoredExamReviewPolicyNotFoundException: pass # then see which exams we have in edx-proctoring that are not in # our current list. That means the the user has disabled it exams = get_all_exams_for_course(course_key) for exam in exams: if exam['is_active']: # try to look up the content_id in the sequences location search = [ timed_exam for timed_exam in timed_exams if unicode(timed_exam.location) == exam['content_id'] ] if not search: # This means it was turned off in Studio, we need to mark # the exam as inactive (we don't delete!) msg = 'Disabling timed exam {exam_id}'.format( exam_id=exam['id']) log.info(msg) update_exam( exam_id=exam['id'], is_proctored=False, is_active=False, )
def register_special_exams(course_key): """ This is typically called on a course published signal. The course is examined for sequences that are marked as timed exams. Then these are registered with the edx-proctoring subsystem. Likewise, if formerly registered exams are unmarked, then those registered exams are marked as inactive """ if not settings.FEATURES.get('ENABLE_SPECIAL_EXAMS'): # if feature is not enabled then do a quick exit return course = modulestore().get_course(course_key) if course is None: raise ItemNotFoundError(u"Course {} does not exist", unicode(course_key)) if not course.enable_proctored_exams and not course.enable_timed_exams: # likewise if course does not have these features turned on # then quickly exit return # get all sequences, since they can be marked as timed/proctored exams _timed_exams = modulestore().get_items( course_key, qualifiers={ 'category': 'sequential', }, settings={ 'is_time_limited': True, } ) # filter out any potential dangling sequences timed_exams = [ timed_exam for timed_exam in _timed_exams if is_item_in_course_tree(timed_exam) ] # enumerate over list of sequences which are time-limited and # add/update any exam entries in edx-proctoring for timed_exam in timed_exams: msg = ( u'Found {location} as a timed-exam in course structure. Inspecting...'.format( location=unicode(timed_exam.location) ) ) log.info(msg) exam_metadata = { 'exam_name': timed_exam.display_name, 'time_limit_mins': timed_exam.default_time_limit_minutes, 'due_date': timed_exam.due, 'is_proctored': timed_exam.is_proctored_exam, # backends that support onboarding exams will treat onboarding exams as practice 'is_practice_exam': timed_exam.is_practice_exam or timed_exam.is_onboarding_exam, 'is_active': True, 'hide_after_due': timed_exam.hide_after_due, 'backend': course.proctoring_provider, } try: exam = get_exam_by_content_id(unicode(course_key), unicode(timed_exam.location)) # update case, make sure everything is synced exam_metadata['exam_id'] = exam['id'] exam_id = update_exam(**exam_metadata) msg = u'Updated timed exam {exam_id}'.format(exam_id=exam['id']) log.info(msg) except ProctoredExamNotFoundException: exam_metadata['course_id'] = unicode(course_key) exam_metadata['content_id'] = unicode(timed_exam.location) exam_id = create_exam(**exam_metadata) msg = u'Created new timed exam {exam_id}'.format(exam_id=exam_id) log.info(msg) exam_review_policy_metadata = { 'exam_id': exam_id, 'set_by_user_id': timed_exam.edited_by, 'review_policy': timed_exam.exam_review_rules, } # only create/update exam policy for the proctored exams if timed_exam.is_proctored_exam and not timed_exam.is_practice_exam and not timed_exam.is_onboarding_exam: try: update_review_policy(**exam_review_policy_metadata) except ProctoredExamReviewPolicyNotFoundException: if timed_exam.exam_review_rules: # won't save an empty rule. create_exam_review_policy(**exam_review_policy_metadata) msg = u'Created new exam review policy with exam_id {exam_id}'.format(exam_id=exam_id) log.info(msg) else: try: # remove any associated review policy remove_review_policy(exam_id=exam_id) except ProctoredExamReviewPolicyNotFoundException: pass # then see which exams we have in edx-proctoring that are not in # our current list. That means the the user has disabled it exams = get_all_exams_for_course(course_key) for exam in exams: if exam['is_active']: # try to look up the content_id in the sequences location search = [ timed_exam for timed_exam in timed_exams if unicode(timed_exam.location) == exam['content_id'] ] if not search: # This means it was turned off in Studio, we need to mark # the exam as inactive (we don't delete!) msg = u'Disabling timed exam {exam_id}'.format(exam_id=exam['id']) log.info(msg) update_exam( exam_id=exam['id'], is_proctored=False, is_active=False, )
data=get_exam_by_id(exam_id), status=status.HTTP_200_OK ) except ProctoredExamNotFoundException, ex: LOG.exception(ex) return Response( status=status.HTTP_400_BAD_REQUEST, data={"detail": "The exam_id does not exist."} ) else: if course_id is not None: if content_id is not None: # get by course_id & content_id try: return Response( data=get_exam_by_content_id(course_id, content_id), status=status.HTTP_200_OK ) except ProctoredExamNotFoundException, ex: LOG.exception(ex) return Response( status=status.HTTP_400_BAD_REQUEST, data={"detail": "The exam with course_id, content_id does not exist."} ) else: result_set = get_all_exams_for_course( course_id=course_id ) return Response(result_set)
by course_id, content_id: get_exam_by_content_id() """ if exam_id: try: return Response(data=get_exam_by_id(exam_id), status=status.HTTP_200_OK) except ProctoredExamNotFoundException, ex: LOG.exception(ex) return Response(status=status.HTTP_400_BAD_REQUEST, data={"detail": "The exam_id does not exist."}) else: if course_id is not None: if content_id is not None: # get by course_id & content_id try: return Response(data=get_exam_by_content_id(course_id, content_id), status=status.HTTP_200_OK) except ProctoredExamNotFoundException, ex: LOG.exception(ex) return Response( status=status.HTTP_400_BAD_REQUEST, data={"detail": "The exam with course_id, content_id does not exist."}, ) else: timed_exams_only = not request.user.is_staff result_set = get_all_exams_for_course( course_id=course_id, timed_exams_only=timed_exams_only, active_only=True ) return Response(result_set) class StudentProctoredExamAttempt(AuthenticatedAPIView):
data=get_exam_by_id(exam_id), status=status.HTTP_200_OK ) except ProctoredExamNotFoundException, ex: LOG.exception(ex) return Response( status=status.HTTP_400_BAD_REQUEST, data={"detail": "The exam_id does not exist."} ) else: if course_id is not None: if content_id is not None: # get by course_id & content_id try: return Response( data=get_exam_by_content_id(course_id, content_id), status=status.HTTP_200_OK ) except ProctoredExamNotFoundException, ex: LOG.exception(ex) return Response( status=status.HTTP_400_BAD_REQUEST, data={"detail": "The exam with course_id, content_id does not exist."} ) else: timed_exams_only = not request.user.is_staff result_set = get_all_exams_for_course( course_id=course_id, timed_exams_only=timed_exams_only, active_only=True )
def register_special_exams(course_key): """ This is typically called on a course published signal. The course is examined for sequences that are marked as timed exams. Then these are registered with the edx-proctoring subsystem. Likewise, if formerly registered exams are unmarked, then those registered exams are marked as inactive """ if not settings.FEATURES.get('ENABLE_SPECIAL_EXAMS'): # if feature is not enabled then do a quick exit return course = modulestore().get_course(course_key) if course is None: raise ItemNotFoundError(u"Course {} does not exist", six.text_type(course_key)) # lint-amnesty, pylint: disable=raising-format-tuple if not course.enable_proctored_exams and not course.enable_timed_exams: # likewise if course does not have these features turned on # then quickly exit return # get all sequences, since they can be marked as timed/proctored exams _timed_exams = modulestore().get_items(course_key, qualifiers={ 'category': 'sequential', }, settings={ 'is_time_limited': True, }) # filter out any potential dangling sequences timed_exams = [ timed_exam for timed_exam in _timed_exams if is_item_in_course_tree(timed_exam) ] # enumerate over list of sequences which are time-limited and # add/update any exam entries in edx-proctoring for timed_exam in timed_exams: msg = ( u'Found {location} as a timed-exam in course structure. Inspecting...' .format(location=six.text_type(timed_exam.location))) log.info(msg) exam_metadata = { 'exam_name': timed_exam.display_name, 'time_limit_mins': timed_exam.default_time_limit_minutes, 'due_date': timed_exam.due if not course.self_paced else None, 'is_proctored': timed_exam.is_proctored_exam, # backends that support onboarding exams will treat onboarding exams as practice 'is_practice_exam': timed_exam.is_practice_exam or timed_exam.is_onboarding_exam, 'is_active': True, 'hide_after_due': timed_exam.hide_after_due, 'backend': course.proctoring_provider, } try: exam = get_exam_by_content_id(six.text_type(course_key), six.text_type(timed_exam.location)) # update case, make sure everything is synced exam_metadata['exam_id'] = exam['id'] exam_id = update_exam(**exam_metadata) msg = u'Updated timed exam {exam_id}'.format(exam_id=exam['id']) log.info(msg) except ProctoredExamNotFoundException: exam_metadata['course_id'] = six.text_type(course_key) exam_metadata['content_id'] = six.text_type(timed_exam.location) exam_id = create_exam(**exam_metadata) msg = u'Created new timed exam {exam_id}'.format(exam_id=exam_id) log.info(msg) exam_review_policy_metadata = { 'exam_id': exam_id, 'set_by_user_id': timed_exam.edited_by, 'review_policy': timed_exam.exam_review_rules, } # only create/update exam policy for the proctored exams if timed_exam.is_proctored_exam and not timed_exam.is_practice_exam and not timed_exam.is_onboarding_exam: try: update_review_policy(**exam_review_policy_metadata) except ProctoredExamReviewPolicyNotFoundException: if timed_exam.exam_review_rules: # won't save an empty rule. create_exam_review_policy(**exam_review_policy_metadata) msg = u'Created new exam review policy with exam_id {exam_id}'.format( exam_id=exam_id) log.info(msg) else: try: # remove any associated review policy remove_review_policy(exam_id=exam_id) except ProctoredExamReviewPolicyNotFoundException: pass # then see which exams we have in edx-proctoring that are not in # our current list. That means the the user has disabled it exams = get_all_exams_for_course(course_key) for exam in exams: if exam['is_active']: # try to look up the content_id in the sequences location search = [ timed_exam for timed_exam in timed_exams if six.text_type(timed_exam.location) == exam['content_id'] ] if not search: # This means it was turned off in Studio, we need to mark # the exam as inactive (we don't delete!) msg = u'Disabling timed exam {exam_id}'.format( exam_id=exam['id']) log.info(msg) update_exam( exam_id=exam['id'], is_proctored=False, is_active=False, )
def register_special_exams(course_key): """ This is typically called on a course published signal. The course is examined for sequences that are marked as timed exams. Then these are registered with the edx-proctoring subsystem. Likewise, if formerly registered exams are unmarked, then those registered exams are marked as inactive """ if not settings.FEATURES.get("ENABLE_SPECIAL_EXAMS"): # if feature is not enabled then do a quick exit return course = modulestore().get_course(course_key) if not course.enable_proctored_exams and not course.enable_timed_exams: # likewise if course does not have these features turned on # then quickly exit return # get all sequences, since they can be marked as timed/proctored exams _timed_exams = modulestore().get_items( course_key, qualifiers={"category": "sequential"}, settings={"is_time_limited": True} ) # filter out any potential dangling sequences timed_exams = [timed_exam for timed_exam in _timed_exams if is_item_in_course_tree(timed_exam)] # enumerate over list of sequences which are time-limited and # add/update any exam entries in edx-proctoring for timed_exam in timed_exams: msg = "Found {location} as a timed-exam in course structure. Inspecting...".format( location=unicode(timed_exam.location) ) log.info(msg) try: exam = get_exam_by_content_id(unicode(course_key), unicode(timed_exam.location)) # update case, make sure everything is synced update_exam( exam_id=exam["id"], exam_name=timed_exam.display_name, time_limit_mins=timed_exam.default_time_limit_minutes, due_date=timed_exam.due, is_proctored=timed_exam.is_proctored_exam, is_practice_exam=timed_exam.is_practice_exam, is_active=True, ) msg = "Updated timed exam {exam_id}".format(exam_id=exam["id"]) log.info(msg) except ProctoredExamNotFoundException: exam_id = create_exam( course_id=unicode(course_key), content_id=unicode(timed_exam.location), exam_name=timed_exam.display_name, time_limit_mins=timed_exam.default_time_limit_minutes, due_date=timed_exam.due, is_proctored=timed_exam.is_proctored_exam, is_practice_exam=timed_exam.is_practice_exam, is_active=True, ) msg = "Created new timed exam {exam_id}".format(exam_id=exam_id) log.info(msg) # then see which exams we have in edx-proctoring that are not in # our current list. That means the the user has disabled it exams = get_all_exams_for_course(course_key) for exam in exams: if exam["is_active"]: # try to look up the content_id in the sequences location search = [timed_exam for timed_exam in timed_exams if unicode(timed_exam.location) == exam["content_id"]] if not search: # This means it was turned off in Studio, we need to mark # the exam as inactive (we don't delete!) msg = "Disabling timed exam {exam_id}".format(exam_id=exam["id"]) log.info(msg) update_exam(exam_id=exam["id"], is_proctored=False, is_active=False)