fix: TNL-8233: Change exception raised at problem creation failure from generic exception to LoncapaProblemError. (#27361)

Raising this specific exception will cause the failure to be handled more gracefully by problem rescoring code.
This commit is contained in:
Julia Eskew
2021-04-21 16:13:23 -04:00
committed by GitHub
parent a1fe3d58dc
commit efa13ff1d2
4 changed files with 40 additions and 3 deletions

View File

@@ -298,7 +298,7 @@ class CapaMixin(ScorableXBlockMixin, CapaFields):
except Exception as err: # pylint: disable=broad-except
msg = 'cannot create LoncapaProblem {loc}: {err}'.format(
loc=str(self.location), err=err)
raise Exception(msg).with_traceback(sys.exc_info()[2])
raise LoncapaProblemError(msg).with_traceback(sys.exc_info()[2])
if self.score is None:
self.set_score(self.score_from_lcp(lcp))

View File

@@ -132,7 +132,7 @@ def get_test_system(
replace_urls=str,
user=user,
get_real_user=lambda __: user,
filestore=Mock(name='get_test_system.filestore'),
filestore=Mock(name='get_test_system.filestore', root_path='.'),
debug=True,
hostname="edx.org",
xqueue={

View File

@@ -16,6 +16,7 @@ import pytest
import ddt
import requests
import webob
from codejail.safe_exec import SafeExecException
from django.utils.encoding import smart_text
from edx_user_state_client.interface import XBlockUserState
from lxml import etree
@@ -1231,6 +1232,31 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
with pytest.raises(NotImplementedError):
module.rescore(only_if_higher=False)
def capa_factory_for_problem_xml(self, xml): # lint-amnesty, pylint: disable=missing-function-docstring
class CustomCapaFactory(CapaFactory):
"""
A factory for creating a Capa problem with arbitrary xml.
"""
sample_problem_xml = textwrap.dedent(xml)
return CustomCapaFactory
def test_codejail_error_upon_problem_creation(self):
# Simulate a codejail safe_exec failure upon problem creation.
# Create a problem with some script attached.
xml_str = textwrap.dedent("""
<problem>
<script>test=True</script>
</problem>
""")
factory = self.capa_factory_for_problem_xml(xml_str)
# When codejail safe_exec fails upon problem creation, a LoncapaProblemError should be raised.
with pytest.raises(LoncapaProblemError):
with patch('capa.capa_problem.safe_exec') as mock_safe_exec:
mock_safe_exec.side_effect = SafeExecException()
factory.create()
def _rescore_problem_error_helper(self, exception_class):
"""Helper to allow testing all errors that rescoring might return."""
# Create the module

View File

@@ -170,7 +170,18 @@ def rescore_problem_module_state(xmodule_instance_args, module_descriptor, stude
# specific events from CAPA are not propagated up the stack. Do we want this?
try:
instance.rescore(only_if_higher=task_input['only_if_higher'])
except (LoncapaProblemError, StudentInputError, ResponseError):
except (LoncapaProblemError, ResponseError):
# Capture a backtrace for these errors, but only a warning below for student input errors.
TASK_LOG.exception(
"error processing rescore call for course %(course)s, problem %(loc)s "
"and student %(student)s",
dict(
course=course_id,
loc=usage_key,
student=student
)
)
except StudentInputError:
TASK_LOG.warning(
"error processing rescore call for course %(course)s, problem %(loc)s "
"and student %(student)s",