Commit 26713e07 by Vik Paruchuri

Work on fixing and documenting error messages shown to students

parent aca73d21
...@@ -251,8 +251,9 @@ def upload_to_s3(file_to_upload, keyname, s3_interface): ...@@ -251,8 +251,9 @@ def upload_to_s3(file_to_upload, keyname, s3_interface):
return True, public_url return True, public_url
except: except:
error_message = "Could not connect to S3." #This is a dev_facing_error
log.exception(error_message) error_message = "Could not connect to S3 to upload peer grading image. Trying to utilize bucket: {0}".format(bucketname.lower())
log.error(error_message)
return False, error_message return False, error_message
......
...@@ -59,12 +59,14 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -59,12 +59,14 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
self.submission_id = None self.submission_id = None
self.grader_id = None self.grader_id = None
error_message = "No {0} found in problem xml for open ended problem."
if oeparam is None: if oeparam is None:
raise ValueError("No oeparam found in problem xml.") #This is a staff_facing_error
raise ValueError(error_message.format('oeparam'))
if self.prompt is None: if self.prompt is None:
raise ValueError("No prompt found in problem xml.") raise ValueError(error_message.format('prompt'))
if self.rubric is None: if self.rubric is None:
raise ValueError("No rubric found in problem xml.") raise ValueError(error_message.format('rubric'))
self._parse(oeparam, self.prompt, self.rubric, system) self._parse(oeparam, self.prompt, self.rubric, system)
...@@ -99,7 +101,8 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -99,7 +101,8 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
# __init__ adds it (easiest way to get problem location into # __init__ adds it (easiest way to get problem location into
# response types) # response types)
except TypeError, ValueError: except TypeError, ValueError:
log.exception("Grader payload %r is not a json object!", grader_payload) #This is a dev_facing_error
log.exception("Grader payload from external open ended grading server is not a json object! Object: {0}".format(grader_payload))
self.initial_display = find_with_default(oeparam, 'initial_display', '') self.initial_display = find_with_default(oeparam, 'initial_display', '')
self.answer = find_with_default(oeparam, 'answer_display', 'No answer given.') self.answer = find_with_default(oeparam, 'answer_display', 'No answer given.')
...@@ -142,17 +145,20 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -142,17 +145,20 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
survey_responses = event_info['survey_responses'] survey_responses = event_info['survey_responses']
for tag in ['feedback', 'submission_id', 'grader_id', 'score']: for tag in ['feedback', 'submission_id', 'grader_id', 'score']:
if tag not in survey_responses: if tag not in survey_responses:
return {'success': False, 'msg': "Could not find needed tag {0}".format(tag)} #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: try:
submission_id = int(survey_responses['submission_id']) submission_id = int(survey_responses['submission_id'])
grader_id = int(survey_responses['grader_id']) grader_id = int(survey_responses['grader_id'])
feedback = str(survey_responses['feedback'].encode('ascii', 'ignore')) feedback = str(survey_responses['feedback'].encode('ascii', 'ignore'))
score = int(survey_responses['score']) score = int(survey_responses['score'])
except: except:
#This is a dev_facing_error
error_message = ("Could not parse submission id, grader id, " error_message = ("Could not parse submission id, grader id, "
"or feedback from message_post ajax call. Here is the message data: {0}".format( "or feedback from message_post ajax call. Here is the message data: {0}".format(
survey_responses)) survey_responses))
log.exception(error_message) 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."} return {'success': False, 'msg': "There was an error saving your feedback. Please contact course staff."}
qinterface = system.xqueue['interface'] qinterface = system.xqueue['interface']
...@@ -189,6 +195,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -189,6 +195,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
self.state = self.DONE self.state = self.DONE
#This is a student_facing_message
return {'success': success, 'msg': "Successfully submitted your feedback."} return {'success': success, 'msg': "Successfully submitted your feedback."}
def send_to_grader(self, submission, system): def send_to_grader(self, submission, system):
...@@ -338,18 +345,22 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -338,18 +345,22 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
for tag in ['success', 'feedback', 'submission_id', 'grader_id']: for tag in ['success', 'feedback', 'submission_id', 'grader_id']:
if tag not in response_items: if tag not in response_items:
return format_feedback('errors', 'Error getting feedback') #This is a student_facing_error
return format_feedback('errors', 'Error getting feedback from grader.')
feedback_items = response_items['feedback'] feedback_items = response_items['feedback']
try: try:
feedback = json.loads(feedback_items) feedback = json.loads(feedback_items)
except (TypeError, ValueError): except (TypeError, ValueError):
log.exception("feedback_items have invalid json %r", feedback_items) #This is a dev_facing_error
return format_feedback('errors', 'Could not parse feedback') log.exception("feedback_items from external open ended grader have invalid json {0}".format(feedback_items))
#This is a student_facing_error
return format_feedback('errors', 'Error getting feedback from grader.')
if response_items['success']: if response_items['success']:
if len(feedback) == 0: if len(feedback) == 0:
return format_feedback('errors', 'No feedback available') #This is a student_facing_error
return format_feedback('errors', 'No feedback available from grader.')
for tag in do_not_render: for tag in do_not_render:
if tag in feedback: if tag in feedback:
...@@ -358,6 +369,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -358,6 +369,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
feedback_lst = sorted(feedback.items(), key=get_priority) feedback_lst = sorted(feedback.items(), key=get_priority)
feedback_list_part1 = u"\n".join(format_feedback(k, v) for k, v in feedback_lst) feedback_list_part1 = u"\n".join(format_feedback(k, v) for k, v in feedback_lst)
else: else:
#This is a student_facing_error
feedback_list_part1 = format_feedback('errors', response_items['feedback']) feedback_list_part1 = format_feedback('errors', response_items['feedback'])
feedback_list_part2 = (u"\n".join([format_feedback_hidden(feedback_type, value) feedback_list_part2 = (u"\n".join([format_feedback_hidden(feedback_type, value)
...@@ -433,14 +445,16 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -433,14 +445,16 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
try: try:
score_result = json.loads(score_msg) score_result = json.loads(score_msg)
except (TypeError, ValueError): except (TypeError, ValueError):
error_message = ("External grader message should be a JSON-serialized dict." #This is a dev_facing_error
error_message = ("External open ended grader message should be a JSON-serialized dict."
" Received score_msg = {0}".format(score_msg)) " Received score_msg = {0}".format(score_msg))
log.error(error_message) log.error(error_message)
fail['feedback'] = error_message fail['feedback'] = error_message
return fail return fail
if not isinstance(score_result, dict): if not isinstance(score_result, dict):
error_message = ("External grader message should be a JSON-serialized dict." #This is a dev_facing_error
error_message = ("External open ended grader message should be a JSON-serialized dict."
" Received score_result = {0}".format(score_result)) " Received score_result = {0}".format(score_result))
log.error(error_message) log.error(error_message)
fail['feedback'] = error_message fail['feedback'] = error_message
...@@ -448,7 +462,8 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -448,7 +462,8 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
for tag in ['score', 'feedback', 'grader_type', 'success', 'grader_id', 'submission_id']: for tag in ['score', 'feedback', 'grader_type', 'success', 'grader_id', 'submission_id']:
if tag not in score_result: if tag not in score_result:
error_message = ("External grader message is missing required tag: {0}" #This is a dev_facing_error
error_message = ("External open ended grader message is missing required tag: {0}"
.format(tag)) .format(tag))
log.error(error_message) log.error(error_message)
fail['feedback'] = error_message fail['feedback'] = error_message
...@@ -565,7 +580,10 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -565,7 +580,10 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
} }
if dispatch not in handlers: if dispatch not in handlers:
return 'Error' #This is a dev_facing_error
log.error("Cannot find {0} in handlers in handle_ajax function for open_ended_module.py".format(dispatch))
#This is a dev_facing_error
return json.dumps({'error': 'Error handling action. Please try again.', 'success' : False})
before = self.get_progress() before = self.get_progress()
d = handlers[dispatch](get, system) d = handlers[dispatch](get, system)
...@@ -616,6 +634,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -616,6 +634,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
#Error message already defined #Error message already defined
success = False success = False
else: else:
#This is a student_facing_error
error_message = "There was a problem saving the image in your submission. Please try a different image, or try pasting a link to an image into the answer box." error_message = "There was a problem saving the image in your submission. Please try a different image, or try pasting a link to an image into the answer box."
return { return {
...@@ -696,6 +715,7 @@ class OpenEndedDescriptor(XmlDescriptor, EditingDescriptor): ...@@ -696,6 +715,7 @@ class OpenEndedDescriptor(XmlDescriptor, EditingDescriptor):
""" """
for child in ['openendedparam']: for child in ['openendedparam']:
if len(xml_object.xpath(child)) != 1: if len(xml_object.xpath(child)) != 1:
#This is a staff_facing_error
raise ValueError("Open Ended definition must include exactly one '{0}' tag".format(child)) raise ValueError("Open Ended definition must include exactly one '{0}' tag".format(child))
def parse(k): def parse(k):
......
...@@ -130,12 +130,14 @@ class OpenEndedChild(object): ...@@ -130,12 +130,14 @@ class OpenEndedChild(object):
if self.closed(): if self.closed():
return True, { return True, {
'success': False, 'success': False,
'error': 'This problem is now closed.' #This is a student_facing_error
'error': 'The problem close date has passed, and this problem is now closed.'
} }
elif self.attempts > self.max_attempts: elif self.attempts > self.max_attempts:
return True, { return True, {
'success': False, 'success': False,
'error': 'Too many attempts.' #This is a student_facing_error
'error': 'You have attempted this problem {0} times. You are allowed {1} attempts.'.format(self.attempts, self.max_attempts)
} }
else: else:
return False, {} return False, {}
...@@ -254,7 +256,8 @@ class OpenEndedChild(object): ...@@ -254,7 +256,8 @@ class OpenEndedChild(object):
try: try:
return Progress(self.get_score()['score'], self._max_score) return Progress(self.get_score()['score'], self._max_score)
except Exception as err: except Exception as err:
log.exception("Got bad progress") #This is a dev_facing_error
log.exception("Got bad progress from open ended child module. Max Score: {1}".format(self._max_score))
return None return None
return None return None
...@@ -262,10 +265,12 @@ class OpenEndedChild(object): ...@@ -262,10 +265,12 @@ class OpenEndedChild(object):
""" """
return dict out-of-sync error message, and also log. return dict out-of-sync error message, and also log.
""" """
log.warning("Assessment module state out sync. state: %r, get: %r. %s", #This is a dev_facing_error
log.warning("Open ended child state out sync. state: %r, get: %r. %s",
self.state, get, msg) self.state, get, msg)
#This is a student_facing_error
return {'success': False, return {'success': False,
'error': 'The problem state got out-of-sync'} 'error': 'The problem state got out-of-sync. Please try reloading the page.'}
def get_html(self): def get_html(self):
""" """
...@@ -418,6 +423,7 @@ class OpenEndedChild(object): ...@@ -418,6 +423,7 @@ class OpenEndedChild(object):
success = False success = False
allowed_to_submit = True allowed_to_submit = True
response = {} response = {}
#This is a student_facing_error
error_string = ("You need to peer grade {0} more in order to make another submission. " error_string = ("You need to peer grade {0} more in order to make another submission. "
"You have graded {1}, and {2} are required. You have made {3} successful peer grading submissions.") "You have graded {1}, and {2} are required. You have made {3} successful peer grading submissions.")
try: try:
...@@ -427,7 +433,10 @@ class OpenEndedChild(object): ...@@ -427,7 +433,10 @@ class OpenEndedChild(object):
student_sub_count = response['student_sub_count'] student_sub_count = response['student_sub_count']
success = True success = True
except: except:
error_message = "Could not contact the grading controller." #This is a dev_facing_error
log.error("Could not contact external open ended graders for location {0} and student {1}".format(location,student_id))
#This is a student_facing_error
error_message = "Could not contact the graders. Please notify course staff."
return success, allowed_to_submit, error_message return success, allowed_to_submit, error_message
if count_graded>=count_required: if count_graded>=count_required:
return success, allowed_to_submit, "" return success, allowed_to_submit, ""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment