def send_to_grader(self, submission, system): """ Send a given submission to the grader, via the xqueue @param submission: The student submission to send to the grader @param system: Modulesystem @return: Boolean true (not useful right now) """ # Prepare xqueue request #------------------------------------------------------------ xqueue = system.get('xqueue') if xqueue is None: return False qinterface = xqueue['interface'] qtime = datetime.strftime(datetime.now(), xqueue_interface.dateformat) anonymous_student_id = system.anonymous_student_id # Generate header queuekey = xqueue_interface.make_hashkey(str(system.seed) + qtime + anonymous_student_id + str(len(self.child_history))) xheader = xqueue_interface.make_xheader( lms_callback_url=xqueue['construct_callback'](), lms_key=queuekey, queue_name=self.queue_name ) contents = self.payload.copy() # Metadata related to the student submission revealed to the external # grader student_info = { 'anonymous_student_id': anonymous_student_id, 'submission_time': qtime, } # Update contents with student response and student info contents.update({ 'student_info': json.dumps(student_info), 'student_response': submission, 'max_score': self.max_score(), }) # Submit request. When successful, 'msg' is the prior length of the # queue qinterface.send_to_queue( header=xheader, body=json.dumps(contents) ) # State associated with the queueing request queuestate = { 'key': queuekey, 'time': qtime, } return True
def send_to_grader(self, submission, system): """ Send a given submission to the grader, via the xqueue @param submission: The student submission to send to the grader @param system: Modulesystem @return: Boolean true (not useful right now) """ # Prepare xqueue request #------------------------------------------------------------ xqueue = system.get('xqueue') if xqueue is None: return False qinterface = xqueue['interface'] qtime = datetime.strftime(datetime.now(UTC), xqueue_interface.dateformat) anonymous_student_id = system.anonymous_student_id # Generate header queuekey = xqueue_interface.make_hashkey(str(system.seed) + qtime + anonymous_student_id + str(len(self.child_history))) xheader = xqueue_interface.make_xheader( lms_callback_url=xqueue['construct_callback'](), lms_key=queuekey, queue_name=self.queue_name ) contents = self.payload.copy() # Metadata related to the student submission revealed to the external grader student_info = { 'anonymous_student_id': anonymous_student_id, 'submission_time': qtime, } # Update contents with student response and student info contents.update({ 'student_info': json.dumps(student_info), 'student_response': submission, 'max_score': self.max_score(), }) # Submit request. When successful, 'msg' is the prior length of the queue qinterface.send_to_queue( header=xheader, body=json.dumps(contents) ) # State associated with the queueing request queuestate = { 'key': queuekey, 'time': qtime, } return True
def _send_to_xqueue(self, contents, key): xheader = make_xheader( "https://{0}/update_certificate?{1}".format(settings.SITE_NAME, key), key, settings.CERT_QUEUE ) (error, msg) = self.xqueue_interface.send_to_queue(header=xheader, body=json.dumps(contents)) if error: logger.critical("Unable to add a request to the queue: {} {}".format(error, msg)) raise Exception("Unable to send queue message")
def _send_to_xqueue(self, contents, key): xheader = make_xheader( 'https://{0}/update_certificate?{1}'.format( settings.SITE_NAME, key), key, settings.CERT_QUEUE) (error, msg) = self.xqueue_interface.send_to_queue( header=xheader, body=json.dumps(contents)) if error: logger.critical('Unable to add a request to the queue') raise Exception('Unable to send queue message')
def _send_to_xqueue(self, contents, key, task_identifier=None, callback_url_path='/update_certificate'): """Create a new task on the XQueue. Arguments: contents (dict): The contents of the XQueue task. key (str): An access key for the task. This will be sent to the callback end-point once the task completes, so that we can validate that the sender is the same entity that received the task. Keyword Arguments: callback_url_path (str): The path of the callback URL. If not provided, use the default end-point for student-generated certificates. """ callback_url = u'{protocol}://{base_url}{path}'.format( protocol=("https" if self.use_https else "http"), base_url=settings.SITE_NAME, path=callback_url_path ) # Append the key to the URL # This is necessary because XQueue assumes that only one # submission is active for a particular URL. # If it receives a second submission with the same callback URL, # it "retires" any other submission with the same URL. # This was a hack that depended on the URL containing the user ID # and courseware location; an assumption that does not apply # to certificate generation. # XQueue also truncates the callback URL to 128 characters, # but since our key lengths are shorter than that, this should # not affect us. callback_url += "?key={key}".format( key=( task_identifier if task_identifier is not None else key ) ) xheader = make_xheader(callback_url, key, settings.CERT_QUEUE) (error, msg) = self.xqueue_interface.send_to_queue( header=xheader, body=json.dumps(contents)) if error: exc = XQueueAddToQueueError(error, msg) LOGGER.critical(unicode(exc)) raise exc
def _send_to_xqueue(self, contents, key): if self.use_https: proto = "https" else: proto = "http" xheader = make_xheader( '{0}://{1}/update_certificate?{2}'.format( proto, settings.SITE_NAME, key), key, settings.CERT_QUEUE) (error, msg) = self.xqueue_interface.send_to_queue( header=xheader, body=json.dumps(contents)) if error: logger.critical('Unable to add a request to the queue: {} {}'.format(error, msg)) raise Exception('Unable to send queue message')
def _send_to_xqueue(self, contents, key): """Create a new task on the XQueue. """ if self.use_https: proto = "https" else: proto = "http" xheader = make_xheader( '{0}://{1}/update_certificate?{2}'.format( proto, settings.SITE_NAME, key), key, settings.CERT_QUEUE) (error, msg) = self.xqueue_interface.send_to_queue( header=xheader, body=json.dumps(contents)) if error: LOGGER.critical(u'Unable to add a request to the queue: %s %s', unicode(error), msg) raise Exception('Unable to send queue message')
def _send_to_xqueue(self, contents, key): """Create a new task on the XQueue. """ if self.use_https: proto = "https" else: proto = "http" xheader = make_xheader( '{0}://{1}/update_certificate?{2}'.format(proto, settings.SITE_NAME, key), key, settings.CERT_QUEUE) (error, msg) = self.xqueue_interface.send_to_queue(header=xheader, body=json.dumps(contents)) if error: LOGGER.critical(u'Unable to add a request to the queue: %s %s', unicode(error), msg) raise Exception('Unable to send queue message')
def send_to_grader(self, submission, system): """ Send a given submission to the grader, via the xqueue @param submission: The student submission to send to the grader @param system: Modulesystem @return: Boolean true (not useful right now) """ # Prepare xqueue request #------------------------------------------------------------ xqueue = system.get('xqueue') if xqueue is None: return False qinterface = xqueue['interface'] qtime = datetime.strftime(datetime.now(UTC), xqueue_interface.dateformat) anonymous_student_id = system.anonymous_student_id # Generate header queuekey = xqueue_interface.make_hashkey(str(system.seed) + qtime + anonymous_student_id + str(len(self.child_history))) xheader = xqueue_interface.make_xheader( lms_callback_url=xqueue['construct_callback'](), lms_key=queuekey, queue_name=self.queue_name ) contents = self.payload.copy() # Metadata related to the student submission revealed to the external grader student_info = { 'anonymous_student_id': anonymous_student_id, 'submission_time': qtime, } # Update contents with student response and student info contents.update({ 'student_info': json.dumps(student_info), 'student_response': submission, 'max_score': self.max_score(), }) # Submit request. When successful, 'msg' is the prior length of the queue error, error_message = qinterface.send_to_queue( header=xheader, body=json.dumps(contents) ) # State associated with the queueing request queuestate = { 'key': queuekey, 'time': qtime, } _ = self.system.service(self, "i18n").ugettext success = True message = _("Successfully saved your submission.") if error: success = False # Translators: the `grader` refers to the grading service open response problems # are sent to, either to be machine-graded, peer-graded, or instructor-graded. message = _('Unable to submit your submission to the grader. Please try again later.') log.error("Unable to submit to grader. location: {0}, error_message: {1}".format( self.location_string, error_message )) return (success, message)
def message_post(self, data, system): """ Handles a student message post (a reaction to the grade they received from an open ended grader type) Returns a boolean success/fail and an error message """ event_info = dict() event_info['problem_id'] = self.location_string event_info['student_id'] = system.anonymous_student_id event_info['survey_responses'] = data _ = self.system.service(self, "i18n").ugettext survey_responses = event_info['survey_responses'] for tag in ['feedback', 'submission_id', 'grader_id', 'score']: if tag not in survey_responses: # This is a student_facing_error return { 'success': False, # Translators: 'tag' is one of 'feedback', 'submission_id', # 'grader_id', or 'score'. They are categories that a student # responds to when filling out a post-assessment survey # of his or her grade from an openended problem. 'msg': _("Could not find needed tag {tag_name} in the " "survey responses. Please try submitting " "again.").format(tag_name=tag) } try: submission_id = int(survey_responses['submission_id']) grader_id = int(survey_responses['grader_id']) feedback = str(survey_responses['feedback'].encode('ascii', 'ignore')) score = int(survey_responses['score']) except: # This is a dev_facing_error error_message = ( "Could not parse submission id, grader id, " "or feedback from message_post ajax call. " "Here is the message data: {0}".format(survey_responses) ) log.exception(error_message) # This is a student_facing_error return { 'success': False, 'msg': _( "There was an error saving your feedback. Please " "contact course staff." ) } xqueue = system.get('xqueue') if xqueue is None: return {'success': False, 'msg': _("Couldn't submit feedback.")} qinterface = xqueue['interface'] qtime = datetime.strftime(datetime.now(UTC), xqueue_interface.dateformat) anonymous_student_id = system.anonymous_student_id queuekey = xqueue_interface.make_hashkey(str(system.seed) + qtime + anonymous_student_id + str(len(self.child_history))) xheader = xqueue_interface.make_xheader( lms_callback_url=xqueue['construct_callback'](), lms_key=queuekey, queue_name=self.message_queue_name ) student_info = { 'anonymous_student_id': anonymous_student_id, 'submission_time': qtime, } contents = { 'feedback': feedback, 'submission_id': submission_id, 'grader_id': grader_id, 'score': score, 'student_info': json.dumps(student_info), } error, error_message = qinterface.send_to_queue( header=xheader, body=json.dumps(contents) ) # Convert error to a success value success = True message = _("Successfully saved your feedback.") if error: success = False message = _("Unable to save your feedback. Please try again later.") log.error("Unable to send feedback to grader. location: {0}, error_message: {1}".format( self.location_string, error_message )) else: self.child_state = self.DONE # This is a student_facing_message return {'success': success, 'msg': message}
def message_post(self, data, system): """ Handles a student message post (a reaction to the grade they received from an open ended grader type) Returns a boolean success/fail and an error message """ event_info = dict() event_info['problem_id'] = self.location_string event_info['student_id'] = system.anonymous_student_id event_info['survey_responses'] = data survey_responses = event_info['survey_responses'] for tag in ['feedback', 'submission_id', 'grader_id', 'score']: if tag not in survey_responses: # This is a student_facing_error return {'success': False, 'msg': "Could not find needed tag {0} in the survey responses. Please try submitting again.".format( tag)} try: submission_id = int(survey_responses['submission_id']) grader_id = int(survey_responses['grader_id']) feedback = str(survey_responses['feedback'].encode('ascii', 'ignore')) score = int(survey_responses['score']) except: # This is a dev_facing_error error_message = ( "Could not parse submission id, grader id, " "or feedback from message_post ajax call. " "Here is the message data: {0}".format(survey_responses) ) log.exception(error_message) # This is a student_facing_error return {'success': False, 'msg': "There was an error saving your feedback. Please contact course staff."} xqueue = system.get('xqueue') if xqueue is None: return {'success': False, 'msg': "Couldn't submit feedback."} qinterface = xqueue['interface'] qtime = datetime.strftime(datetime.now(UTC), xqueue_interface.dateformat) anonymous_student_id = system.anonymous_student_id queuekey = xqueue_interface.make_hashkey(str(system.seed) + qtime + anonymous_student_id + str(len(self.child_history))) xheader = xqueue_interface.make_xheader( lms_callback_url=xqueue['construct_callback'](), lms_key=queuekey, queue_name=self.message_queue_name ) student_info = { 'anonymous_student_id': anonymous_student_id, 'submission_time': qtime, } contents = { 'feedback': feedback, 'submission_id': submission_id, 'grader_id': grader_id, 'score': score, 'student_info': json.dumps(student_info), } (error, msg) = qinterface.send_to_queue( header=xheader, body=json.dumps(contents) ) # Convert error to a success value success = True if error: success = False self.child_state = self.DONE # This is a student_facing_message return {'success': success, 'msg': "Successfully submitted your feedback."}
def send_to_grader(self, submission, system): """ Send a given submission to the grader, via the xqueue @param submission: The student submission to send to the grader @param system: Modulesystem @return: Boolean true (not useful right now) """ # Prepare xqueue request #------------------------------------------------------------ xqueue = system.get('xqueue') if xqueue is None: return False qinterface = xqueue['interface'] qtime = datetime.strftime(datetime.now(UTC), xqueue_interface.dateformat) anonymous_student_id = system.anonymous_student_id # Generate header queuekey = xqueue_interface.make_hashkey( str(system.seed) + qtime + anonymous_student_id + str(len(self.child_history))) xheader = xqueue_interface.make_xheader( lms_callback_url=xqueue['construct_callback'](), lms_key=queuekey, queue_name=self.queue_name) contents = self.payload.copy() # Metadata related to the student submission revealed to the external grader student_info = { 'anonymous_student_id': anonymous_student_id, 'submission_time': qtime, } # Update contents with student response and student info contents.update({ 'student_info': json.dumps(student_info), 'student_response': submission, 'max_score': self.max_score(), }) # Submit request. When successful, 'msg' is the prior length of the queue error, error_message = qinterface.send_to_queue( header=xheader, body=json.dumps(contents)) # State associated with the queueing request queuestate = { 'key': queuekey, 'time': qtime, } _ = self.system.service(self, "i18n").ugettext success = True message = _("Successfully saved your submission.") if error: success = False # Translators: the `grader` refers to the grading service open response problems # are sent to, either to be machine-graded, peer-graded, or instructor-graded. message = _( 'Unable to submit your submission to the grader. Please try again later.' ) log.error( "Unable to submit to grader. location: {0}, error_message: {1}" .format(self.location_string, error_message)) return (success, message)
def message_post(self, data, system): """ Handles a student message post (a reaction to the grade they received from an open ended grader type) Returns a boolean success/fail and an error message """ event_info = dict() event_info['problem_id'] = self.location_string event_info['student_id'] = system.anonymous_student_id event_info['survey_responses'] = data _ = self.system.service(self, "i18n").ugettext survey_responses = event_info['survey_responses'] for tag in ['feedback', 'submission_id', 'grader_id', 'score']: if tag not in survey_responses: # This is a student_facing_error return { 'success': False, # Translators: 'tag' is one of 'feedback', 'submission_id', # 'grader_id', or 'score'. They are categories that a student # responds to when filling out a post-assessment survey # of his or her grade from an openended problem. 'msg': _("Could not find needed tag {tag_name} in the " "survey responses. Please try submitting " "again.").format(tag_name=tag) } try: submission_id = int(survey_responses['submission_id']) grader_id = int(survey_responses['grader_id']) feedback = str(survey_responses['feedback'].encode( 'ascii', 'ignore')) score = int(survey_responses['score']) except: # This is a dev_facing_error error_message = ( "Could not parse submission id, grader id, " "or feedback from message_post ajax call. " "Here is the message data: {0}".format(survey_responses)) log.exception(error_message) # This is a student_facing_error return { 'success': False, 'msg': _("There was an error saving your feedback. Please " "contact course staff.") } xqueue = system.get('xqueue') if xqueue is None: return {'success': False, 'msg': _("Couldn't submit feedback.")} qinterface = xqueue['interface'] qtime = datetime.strftime(datetime.now(UTC), xqueue_interface.dateformat) anonymous_student_id = system.anonymous_student_id queuekey = xqueue_interface.make_hashkey( str(system.seed) + qtime + anonymous_student_id + str(len(self.child_history))) xheader = xqueue_interface.make_xheader( lms_callback_url=xqueue['construct_callback'](), lms_key=queuekey, queue_name=self.message_queue_name) student_info = { 'anonymous_student_id': anonymous_student_id, 'submission_time': qtime, } contents = { 'feedback': feedback, 'submission_id': submission_id, 'grader_id': grader_id, 'score': score, 'student_info': json.dumps(student_info), } error, error_message = qinterface.send_to_queue( header=xheader, body=json.dumps(contents)) # Convert error to a success value success = True message = _("Successfully saved your feedback.") if error: success = False message = _( "Unable to save your feedback. Please try again later.") log.error( "Unable to send feedback to grader. location: {0}, error_message: {1}" .format(self.location_string, error_message)) else: self.child_state = self.DONE # This is a student_facing_message return {'success': success, 'msg': message}