PROD-448: Gracefully handle exceptions from user-supplied code in
advanced problems so that they do not become uneditable.
This commit is contained in:
@@ -387,8 +387,11 @@ class CapaMixin(ScorableXBlockMixin, CapaFields):
|
||||
"""
|
||||
For now, just return weighted earned / weighted possible
|
||||
"""
|
||||
raw_earned = self.score.raw_earned
|
||||
raw_possible = self.score.raw_possible
|
||||
if self.score:
|
||||
raw_earned = self.score.raw_earned
|
||||
raw_possible = self.score.raw_possible
|
||||
else:
|
||||
raw_earned = raw_possible = 0
|
||||
|
||||
if raw_possible > 0:
|
||||
if self.weight is not None:
|
||||
@@ -439,6 +442,18 @@ class CapaMixin(ScorableXBlockMixin, CapaFields):
|
||||
'graded': self.graded,
|
||||
})
|
||||
|
||||
def handle_fatal_lcp_error(self, error):
|
||||
if error:
|
||||
return(
|
||||
HTML(u'<p>Error formatting HTML for problem:</p><p><pre style="color:red">{msg}</pre></p>').format(
|
||||
msg=text_type(error))
|
||||
)
|
||||
else:
|
||||
return HTML(
|
||||
u'<p>Could not format HTML for problem. '
|
||||
u'Contact course staff in the discussion forum for assistance.</p>'
|
||||
)
|
||||
|
||||
def submit_button_name(self):
|
||||
"""
|
||||
Determine the name for the "submit" button.
|
||||
@@ -549,8 +564,8 @@ class CapaMixin(ScorableXBlockMixin, CapaFields):
|
||||
# TODO (vshnayder): another switch on DEBUG.
|
||||
if self.runtime.DEBUG:
|
||||
msg = HTML(
|
||||
u'[courseware.capa.capa_module] <font size="+1" color="red">'
|
||||
u'Failed to generate HTML for problem {url}</font>'
|
||||
u'[courseware.capa.capa_module] '
|
||||
u'Failed to generate HTML for problem {url}'
|
||||
).format(
|
||||
url=text_type(self.location)
|
||||
)
|
||||
@@ -564,6 +579,7 @@ class CapaMixin(ScorableXBlockMixin, CapaFields):
|
||||
|
||||
# Presumably, student submission has corrupted LoncapaProblem HTML.
|
||||
# First, pull down all student answers
|
||||
|
||||
student_answers = self.lcp.student_answers
|
||||
answer_ids = list(student_answers.keys())
|
||||
|
||||
|
||||
@@ -103,13 +103,18 @@ class ProblemBlock(
|
||||
if 'lcp' in self.__dict__:
|
||||
del self.__dict__['lcp']
|
||||
|
||||
def student_view(self, _context):
|
||||
def student_view(self, _context, show_detailed_errors=False):
|
||||
"""
|
||||
Return the student view.
|
||||
"""
|
||||
# self.score is initialized in self.lcp but in this method is accessed before self.lcp so just call it first.
|
||||
self.lcp
|
||||
fragment = Fragment(self.get_html())
|
||||
try:
|
||||
self.lcp
|
||||
except Exception as err:
|
||||
html = self.handle_fatal_lcp_error(err if show_detailed_errors else None)
|
||||
else:
|
||||
html = self.get_html()
|
||||
fragment = Fragment(html)
|
||||
add_webpack_to_fragment(fragment, 'ProblemBlockPreview')
|
||||
shim_xmodule_js(fragment, 'Problem')
|
||||
return fragment
|
||||
@@ -118,7 +123,7 @@ class ProblemBlock(
|
||||
"""
|
||||
Renders the Studio preview view.
|
||||
"""
|
||||
return self.student_view(context)
|
||||
return self.student_view(context, show_detailed_errors=True)
|
||||
|
||||
def studio_view(self, _context):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user