refactor: xmodule/capa_module.py -> xmodule/capa_block.py
This commit is contained in:
@@ -24,7 +24,7 @@ from opaque_keys import InvalidKeyError
|
||||
from opaque_keys.edx.keys import AssetKey, CourseKey, UsageKey
|
||||
from opaque_keys.edx.locations import CourseLocator
|
||||
from path import Path as path
|
||||
from xmodule.capa_module import ProblemBlock
|
||||
from xmodule.capa_block import ProblemBlock
|
||||
from xmodule.contentstore.content import StaticContent
|
||||
from xmodule.contentstore.django import contentstore
|
||||
from xmodule.contentstore.utils import empty_asset_trashcan, restore_asset_from_trashcan
|
||||
@@ -1518,7 +1518,7 @@ class ContentStoreTest(ContentStoreTestCase):
|
||||
retarget = str(course.id.make_usage_key('chapter', 'REPLACE')).replace('REPLACE', r'([0-9]|[a-f]){3,}')
|
||||
self.assertRegex(data['locator'], retarget)
|
||||
|
||||
def test_capa_module(self):
|
||||
def test_capa_block(self):
|
||||
"""Test that a problem treats markdown specially."""
|
||||
course = CourseFactory.create()
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
|
||||
from xmodule import templates
|
||||
from xmodule.capa_module import ProblemBlock
|
||||
from xmodule.capa_block import ProblemBlock
|
||||
from xmodule.course_module import CourseBlock
|
||||
from xmodule.html_module import HtmlBlock
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
|
||||
@@ -27,7 +27,7 @@ from xblock.fields import Scope, ScopeIds, String
|
||||
from xblock.runtime import DictKeyValueStore, KvsFieldData
|
||||
from xblock.test.tools import TestRuntime
|
||||
from xblock.validation import ValidationMessage
|
||||
from xmodule.capa_module import ProblemBlock
|
||||
from xmodule.capa_block import ProblemBlock
|
||||
from xmodule.course_module import DEFAULT_START_DATE
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
@@ -8,7 +8,7 @@ from xblock.core import XBlock, XBlockAside
|
||||
from xblock.fields import Dict, Scope
|
||||
|
||||
from common.djangoapps.edxmako.shortcuts import render_to_string
|
||||
from xmodule.capa_module import ProblemBlock # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from xmodule.capa_block import ProblemBlock # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from xmodule.x_module import AUTHOR_VIEW # lint-amnesty, pylint: disable=wrong-import-order
|
||||
|
||||
_ = lambda text: text
|
||||
|
||||
@@ -1 +1 @@
|
||||
These files really should be in the capa module, but we don't have a way to load js from there at the moment. (TODO)
|
||||
These files really should be in the capa block, but we don't have a way to load js from there at the moment. (TODO)
|
||||
|
||||
@@ -131,7 +131,7 @@ capa
|
||||
|
||||
* PR: https://github.com/openedx/edx-platform/pull/30403
|
||||
|
||||
* Notes: Like xmodule, extracting capa from edx-platform would have been difficult. However, updating its import path was feasible; so, to create avoid creating a sixth top-level package, it was decided to move the code within ./xmodule as a sub-packages. ./xmodule was chosen as the parent package because it contains related code, notably ./xmodule/capa_module.py, which defines the ``ProblemBlock`` (formerly the ``CapaModule``).
|
||||
* Notes: Like xmodule, extracting capa from edx-platform would have been difficult. However, updating its import path was feasible; so, to create avoid creating a sixth top-level package, it was decided to move the code within ./xmodule as a sub-packages. ./xmodule was chosen as the parent package because it contains related code, notably ./xmodule/capa_block.py, which defines the ``ProblemBlock`` (formerly the ``CapaModule``).
|
||||
|
||||
xblock_discussion
|
||||
-----------------
|
||||
|
||||
@@ -42,7 +42,7 @@ from xblock.test.tools import TestRuntime # lint-amnesty, pylint: disable=wrong
|
||||
|
||||
from xmodule.capa.tests.response_xml_factory import OptionResponseXMLFactory # lint-amnesty, pylint: disable=reimported
|
||||
from xmodule.capa.xqueue_interface import XQueueInterface
|
||||
from xmodule.capa_module import ProblemBlock
|
||||
from xmodule.capa_block import ProblemBlock
|
||||
from xmodule.contentstore.django import contentstore
|
||||
from xmodule.html_module import AboutBlock, CourseInfoBlock, HtmlBlock, StaticTabBlock
|
||||
from xmodule.lti_module import LTIBlock
|
||||
|
||||
@@ -477,7 +477,7 @@ class TestProblemResponsesReport(TestReportMixin, InstructorTaskModuleTestCase):
|
||||
Temporarily removes the generate_report_data method so we can test
|
||||
report generation when it's absent.
|
||||
"""
|
||||
from xmodule.capa_module import ProblemBlock
|
||||
from xmodule.capa_block import ProblemBlock
|
||||
generate_report_data = ProblemBlock.generate_report_data
|
||||
del ProblemBlock.generate_report_data
|
||||
try:
|
||||
@@ -532,7 +532,7 @@ class TestProblemResponsesReport(TestReportMixin, InstructorTaskModuleTestCase):
|
||||
assert student_data_keys_list == ['username', 'title', 'location', 'block_key', 'state']
|
||||
mock_list_problem_responses.assert_called_with(self.course.id, ANY, ANY)
|
||||
|
||||
@patch('xmodule.capa_module.ProblemBlock.generate_report_data', create=True)
|
||||
@patch('xmodule.capa_block.ProblemBlock.generate_report_data', create=True)
|
||||
def test_build_student_data_for_block_with_mock_generate_report_data(self, mock_generate_report_data):
|
||||
"""
|
||||
Ensure that building student data for a block that supports the
|
||||
@@ -571,7 +571,7 @@ class TestProblemResponsesReport(TestReportMixin, InstructorTaskModuleTestCase):
|
||||
assert student_data[0]['state'] == student_data[1]['state']
|
||||
assert student_data_keys_list == ['username', 'title', 'location', 'more', 'some', 'block_key', 'state']
|
||||
|
||||
@patch('xmodule.capa_module.ProblemBlock.generate_report_data', create=True)
|
||||
@patch('xmodule.capa_block.ProblemBlock.generate_report_data', create=True)
|
||||
def test_build_student_data_for_block_with_ordered_generate_report_data(self, mock_generate_report_data):
|
||||
"""
|
||||
Ensure that building student data for a block that returns OrderedDicts from the
|
||||
@@ -698,7 +698,7 @@ class TestProblemResponsesReport(TestReportMixin, InstructorTaskModuleTestCase):
|
||||
assert len(student_data) == filtered_count
|
||||
|
||||
@patch('lms.djangoapps.instructor_task.tasks_helper.grades.list_problem_responses')
|
||||
@patch('xmodule.capa_module.ProblemBlock.generate_report_data', create=True)
|
||||
@patch('xmodule.capa_block.ProblemBlock.generate_report_data', create=True)
|
||||
def test_build_student_data_for_block_with_generate_report_data_not_implemented(
|
||||
self,
|
||||
mock_generate_report_data,
|
||||
|
||||
@@ -5,7 +5,7 @@ new Show Answer values that remove the Past Due check (keeping the rest intact)
|
||||
|
||||
from lms.djangoapps.courseware.field_overrides import FieldOverrideProvider
|
||||
from openedx.features.course_experience import RELATIVE_DATES_FLAG
|
||||
from xmodule.capa_module import SHOWANSWER # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from xmodule.capa_block import SHOWANSWER # lint-amnesty, pylint: disable=wrong-import-order
|
||||
|
||||
|
||||
class ShowAnswerFieldOverride(FieldOverrideProvider):
|
||||
|
||||
@@ -10,7 +10,7 @@ from lms.djangoapps.ccx.tests.test_overrides import inject_field_overrides
|
||||
from lms.djangoapps.courseware.model_data import FieldDataCache
|
||||
from lms.djangoapps.courseware.module_render import get_module
|
||||
from openedx.features.course_experience import RELATIVE_DATES_FLAG
|
||||
from xmodule.capa_module import SHOWANSWER # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from xmodule.capa_block import SHOWANSWER # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from xmodule.modulestore.tests.factories import CourseFactory # lint-amnesty, pylint: disable=wrong-import-order
|
||||
|
||||
|
||||
2
setup.py
2
setup.py
@@ -25,7 +25,7 @@ XBLOCKS = [
|
||||
"library_sourced = xmodule.library_sourced_block:LibrarySourcedBlock",
|
||||
"lti = xmodule.lti_module:LTIBlock",
|
||||
"poll_question = xmodule.poll_module:PollBlock",
|
||||
"problem = xmodule.capa_module:ProblemBlock",
|
||||
"problem = xmodule.capa_block:ProblemBlock",
|
||||
"randomize = xmodule.randomize_module:RandomizeBlock",
|
||||
"sequential = xmodule.seq_module:SequenceBlock",
|
||||
"slides = xmodule.template_module:TranslateCustomTagBlock",
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"""
|
||||
Main module which shows problems (of "capa" type).
|
||||
|
||||
This is used by capa_module.
|
||||
This is used by capa_block.
|
||||
"""
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ import xmodule.capa.responsetypes as responsetypes
|
||||
import xmodule.capa.xqueue_interface as xqueue_interface
|
||||
from xmodule.capa.correctmap import CorrectMap
|
||||
from xmodule.capa.safe_exec import safe_exec
|
||||
from xmodule.capa.util import contextualize_text, convert_files_to_filenames, get_course_id_from_capa_module
|
||||
from xmodule.capa.util import contextualize_text, convert_files_to_filenames, get_course_id_from_capa_block
|
||||
from openedx.core.djangolib.markup import HTML, Text
|
||||
from openedx.core.lib.edx_six import get_gettext
|
||||
from xmodule.stringify import stringify_children
|
||||
@@ -130,7 +130,7 @@ class LoncapaProblem(object):
|
||||
"""
|
||||
Main class for capa Problems.
|
||||
"""
|
||||
def __init__(self, problem_text, id, capa_system, capa_module, # pylint: disable=redefined-builtin
|
||||
def __init__(self, problem_text, id, capa_system, capa_block, # pylint: disable=redefined-builtin
|
||||
state=None, seed=None, minimal_init=False, extract_tree=True):
|
||||
"""
|
||||
Initializes capa Problem.
|
||||
@@ -141,7 +141,7 @@ class LoncapaProblem(object):
|
||||
id (string): identifier for this problem, often a filename (no spaces).
|
||||
capa_system (LoncapaSystem): LoncapaSystem instance which provides OS,
|
||||
rendering, user context, and other resources.
|
||||
capa_module: instance needed to access runtime/logging
|
||||
capa_block: instance needed to access runtime/logging
|
||||
state (dict): containing the following keys:
|
||||
- `seed` (int) random number generator seed
|
||||
- `student_answers` (dict) maps input id to the stored answer for that input
|
||||
@@ -159,7 +159,7 @@ class LoncapaProblem(object):
|
||||
self.do_reset()
|
||||
self.problem_id = id
|
||||
self.capa_system = capa_system
|
||||
self.capa_module = capa_module
|
||||
self.capa_block = capa_block
|
||||
|
||||
state = state or {}
|
||||
|
||||
@@ -190,12 +190,12 @@ class LoncapaProblem(object):
|
||||
try:
|
||||
self.make_xml_compatible(self.tree)
|
||||
except Exception:
|
||||
capa_module = self.capa_module
|
||||
capa_block = self.capa_block
|
||||
log.exception(
|
||||
"CAPAProblemError: %s, id:%s, data: %s",
|
||||
capa_module.display_name,
|
||||
capa_block.display_name,
|
||||
self.problem_id,
|
||||
capa_module.data
|
||||
capa_block.data
|
||||
)
|
||||
raise
|
||||
|
||||
@@ -421,7 +421,7 @@ class LoncapaProblem(object):
|
||||
|
||||
def grade_answers(self, answers):
|
||||
"""
|
||||
Grade student responses. Called by capa_module.submit_problem.
|
||||
Grade student responses. Called by capa_block.submit_problem.
|
||||
|
||||
`answers` is a dict of all the entries from request.POST, but with the first part
|
||||
of each key removed (the string before the first "_").
|
||||
@@ -501,7 +501,7 @@ class LoncapaProblem(object):
|
||||
Returns a dict of answer_ids to answer values. If we cannot generate
|
||||
an answer (this sometimes happens in customresponses), that answer_id is
|
||||
not included. Called by "show answers" button JSON request
|
||||
(see capa_module)
|
||||
(see capa_block)
|
||||
"""
|
||||
# dict of (id, correct_answer)
|
||||
answer_map = {}
|
||||
@@ -935,8 +935,8 @@ class LoncapaProblem(object):
|
||||
python_path=python_path,
|
||||
extra_files=extra_files,
|
||||
cache=self.capa_system.cache,
|
||||
limit_overrides_context=get_course_id_from_capa_module(
|
||||
self.capa_module
|
||||
limit_overrides_context=get_course_id_from_capa_block(
|
||||
self.capa_block
|
||||
),
|
||||
slug=self.problem_id,
|
||||
unsafely=self.capa_system.can_execute_unsafe_code(),
|
||||
@@ -994,7 +994,7 @@ class LoncapaProblem(object):
|
||||
|
||||
# If we're withholding correctness, don't show adaptive hints either.
|
||||
# Note that regular, "demand" hints will be shown, if the course author has added them to the problem.
|
||||
if not self.capa_module.correctness_available():
|
||||
if not self.capa_block.correctness_available():
|
||||
status = 'submitted'
|
||||
else:
|
||||
# If the the problem has not been saved since the last submit set the status to the
|
||||
@@ -1107,7 +1107,7 @@ class LoncapaProblem(object):
|
||||
# instantiate capa Response
|
||||
responsetype_cls = responsetypes.registry.get_class_for_tag(response.tag)
|
||||
responder = responsetype_cls(
|
||||
response, inputfields, self.context, self.capa_system, self.capa_module, minimal_init
|
||||
response, inputfields, self.context, self.capa_system, self.capa_block, minimal_init
|
||||
)
|
||||
# save in list in self
|
||||
self.responders[response] = responder
|
||||
|
||||
@@ -57,7 +57,7 @@ from .util import (
|
||||
convert_files_to_filenames,
|
||||
default_tolerance,
|
||||
find_with_default,
|
||||
get_course_id_from_capa_module,
|
||||
get_course_id_from_capa_block,
|
||||
get_inner_html_from_xpath,
|
||||
is_list_of_files
|
||||
)
|
||||
@@ -162,7 +162,7 @@ class LoncapaResponse(six.with_metaclass(abc.ABCMeta, object)):
|
||||
# By default, we set this to False, allowing subclasses to override as appropriate.
|
||||
multi_device_support = False
|
||||
|
||||
def __init__(self, xml, inputfields, context, system, capa_module, minimal_init):
|
||||
def __init__(self, xml, inputfields, context, system, capa_block, minimal_init):
|
||||
"""
|
||||
Init is passed the following arguments:
|
||||
|
||||
@@ -170,13 +170,13 @@ class LoncapaResponse(six.with_metaclass(abc.ABCMeta, object)):
|
||||
- inputfields : ordered list of ElementTrees for each input entry field in this Response
|
||||
- context : script processor context
|
||||
- system : LoncapaSystem instance which provides OS, rendering, and user context
|
||||
- capa_module : Capa module, to access runtime
|
||||
- capa_block : Capa block, to access runtime
|
||||
"""
|
||||
self.xml = xml
|
||||
self.inputfields = inputfields
|
||||
self.context = context
|
||||
self.capa_system = system
|
||||
self.capa_module = capa_module # njp, note None
|
||||
self.capa_block = capa_block # njp, note None
|
||||
|
||||
self.id = xml.get('id')
|
||||
|
||||
@@ -373,7 +373,7 @@ class LoncapaResponse(six.with_metaclass(abc.ABCMeta, object)):
|
||||
|
||||
# This is the "feedback hint" event
|
||||
event_info = {}
|
||||
event_info['module_id'] = text_type(self.capa_module.location)
|
||||
event_info['module_id'] = text_type(self.capa_block.location)
|
||||
event_info['problem_part_id'] = self.id
|
||||
event_info['trigger_type'] = 'single' # maybe be overwritten by log_extra
|
||||
event_info['hint_label'] = label
|
||||
@@ -383,7 +383,7 @@ class LoncapaResponse(six.with_metaclass(abc.ABCMeta, object)):
|
||||
event_info['question_type'] = question_tag
|
||||
if log_extra:
|
||||
event_info.update(log_extra)
|
||||
self.capa_module.runtime.publish(self.capa_module, 'edx.problem.hint.feedback_displayed', event_info)
|
||||
self.capa_block.runtime.publish(self.capa_block, 'edx.problem.hint.feedback_displayed', event_info)
|
||||
|
||||
# Form the div-wrapped hint texts
|
||||
hints_wrap = HTML('').join(
|
||||
@@ -486,8 +486,8 @@ class LoncapaResponse(six.with_metaclass(abc.ABCMeta, object)):
|
||||
globals_dict,
|
||||
python_path=self.context['python_path'],
|
||||
extra_files=self.context['extra_files'],
|
||||
limit_overrides_context=get_course_id_from_capa_module(
|
||||
self.capa_module
|
||||
limit_overrides_context=get_course_id_from_capa_block(
|
||||
self.capa_block
|
||||
),
|
||||
slug=self.id,
|
||||
random_seed=self.context['seed'],
|
||||
@@ -985,7 +985,7 @@ class MultipleChoiceResponse(LoncapaResponse):
|
||||
whole software stack works with just the one system of naming.
|
||||
The .has_mask() test on a response checks for masking, implemented by a
|
||||
._has_mask attribute on the response object.
|
||||
The logging functionality in capa_module calls the unmask functions here
|
||||
The logging functionality in capa_block calls the unmask functions here
|
||||
to translate back to choice_0 name style for recording in the logs, so
|
||||
the logging is in terms of the regular names.
|
||||
"""
|
||||
|
||||
@@ -83,9 +83,9 @@ def test_capa_system(render_template=None):
|
||||
return the_system
|
||||
|
||||
|
||||
def mock_capa_module():
|
||||
def mock_capa_block():
|
||||
"""
|
||||
capa response types needs just two things from the capa_module: location and publish.
|
||||
capa response types needs just two things from the capa_block: location and publish.
|
||||
"""
|
||||
def mock_location_text(self): # lint-amnesty, pylint: disable=unused-argument
|
||||
"""
|
||||
@@ -93,21 +93,21 @@ def mock_capa_module():
|
||||
"""
|
||||
return 'i4x://Foo/bar/mock/abc'
|
||||
|
||||
capa_module = Mock()
|
||||
capa_block = Mock()
|
||||
if six.PY2:
|
||||
capa_module.location.__unicode__ = mock_location_text
|
||||
capa_block.location.__unicode__ = mock_location_text
|
||||
else:
|
||||
capa_module.location.__str__ = mock_location_text
|
||||
capa_block.location.__str__ = mock_location_text
|
||||
# The following comes into existence by virtue of being called
|
||||
# capa_module.runtime.publish
|
||||
return capa_module
|
||||
# capa_block.runtime.publish
|
||||
return capa_block
|
||||
|
||||
|
||||
def new_loncapa_problem(xml, problem_id='1', capa_system=None, seed=723, use_capa_render_template=False):
|
||||
"""Construct a `LoncapaProblem` suitable for unit tests."""
|
||||
render_template = capa_render_template if use_capa_render_template else None
|
||||
return LoncapaProblem(xml, id=problem_id, seed=seed, capa_system=capa_system or test_capa_system(render_template),
|
||||
capa_module=mock_capa_module())
|
||||
capa_block=mock_capa_block())
|
||||
|
||||
|
||||
def load_fixture(relpath):
|
||||
|
||||
@@ -359,7 +359,7 @@ class SchematicResponseXMLFactory(ResponseXMLFactory):
|
||||
|
||||
Although <schematic> can have several attributes,
|
||||
(*height*, *width*, *parts*, *analyses*, *submit_analysis*, and *initial_value*),
|
||||
none of them are used in the capa module.
|
||||
none of them are used in the capa block.
|
||||
For testing, we create a bare-bones version of <schematic>."""
|
||||
return etree.Element("schematic")
|
||||
|
||||
|
||||
@@ -48,10 +48,10 @@ class TextInputHintsTest(HintTest):
|
||||
|
||||
def test_tracking_log(self):
|
||||
"""Test that the tracking log comes out right."""
|
||||
self.problem.capa_module.reset_mock()
|
||||
self.problem.capa_block.reset_mock()
|
||||
self.get_hint('1_3_1', 'Blue')
|
||||
self.problem.capa_module.runtime.publish.assert_called_with(
|
||||
self.problem.capa_module,
|
||||
self.problem.capa_block.runtime.publish.assert_called_with(
|
||||
self.problem.capa_block,
|
||||
'edx.problem.hint.feedback_displayed',
|
||||
{'module_id': 'i4x://Foo/bar/mock/abc',
|
||||
'problem_part_id': '1_2',
|
||||
@@ -224,8 +224,8 @@ class NumericInputHintsTest(HintTest):
|
||||
|
||||
def test_tracking_log(self):
|
||||
self.get_hint('1_2_1', '1.141')
|
||||
self.problem.capa_module.runtime.publish.assert_called_with(
|
||||
self.problem.capa_module,
|
||||
self.problem.capa_block.runtime.publish.assert_called_with(
|
||||
self.problem.capa_block,
|
||||
'edx.problem.hint.feedback_displayed',
|
||||
{'module_id': 'i4x://Foo/bar/mock/abc', 'problem_part_id': '1_1', 'trigger_type': 'single',
|
||||
'hint_label': 'Nice',
|
||||
@@ -363,8 +363,8 @@ class CheckboxHintsTestTracking(HintTest):
|
||||
"""Test checkbox tracking log - by far the most complicated case"""
|
||||
# A -> 1 hint
|
||||
self.get_hint('1_2_1', ['choice_0'])
|
||||
self.problem.capa_module.runtime.publish.assert_called_with(
|
||||
self.problem.capa_module,
|
||||
self.problem.capa_block.runtime.publish.assert_called_with(
|
||||
self.problem.capa_block,
|
||||
'edx.problem.hint.feedback_displayed',
|
||||
{'hint_label': 'Incorrect:',
|
||||
'module_id': 'i4x://Foo/bar/mock/abc',
|
||||
@@ -378,10 +378,10 @@ class CheckboxHintsTestTracking(HintTest):
|
||||
)
|
||||
|
||||
# B C -> 2 hints
|
||||
self.problem.capa_module.runtime.publish.reset_mock()
|
||||
self.problem.capa_block.runtime.publish.reset_mock()
|
||||
self.get_hint('1_2_1', ['choice_1', 'choice_2'])
|
||||
self.problem.capa_module.runtime.publish.assert_called_with(
|
||||
self.problem.capa_module,
|
||||
self.problem.capa_block.runtime.publish.assert_called_with(
|
||||
self.problem.capa_block,
|
||||
'edx.problem.hint.feedback_displayed',
|
||||
{'hint_label': 'Incorrect:',
|
||||
'module_id': 'i4x://Foo/bar/mock/abc',
|
||||
@@ -398,10 +398,10 @@ class CheckboxHintsTestTracking(HintTest):
|
||||
)
|
||||
|
||||
# A C -> 1 Compound hint
|
||||
self.problem.capa_module.runtime.publish.reset_mock()
|
||||
self.problem.capa_block.runtime.publish.reset_mock()
|
||||
self.get_hint('1_2_1', ['choice_0', 'choice_2'])
|
||||
self.problem.capa_module.runtime.publish.assert_called_with(
|
||||
self.problem.capa_module,
|
||||
self.problem.capa_block.runtime.publish.assert_called_with(
|
||||
self.problem.capa_block,
|
||||
'edx.problem.hint.feedback_displayed',
|
||||
{'hint_label': 'Correct:',
|
||||
'module_id': 'i4x://Foo/bar/mock/abc',
|
||||
@@ -428,10 +428,10 @@ class MultpleChoiceHintsTest(HintTest):
|
||||
|
||||
def test_tracking_log(self):
|
||||
"""Test that the tracking log comes out right."""
|
||||
self.problem.capa_module.reset_mock()
|
||||
self.problem.capa_block.reset_mock()
|
||||
self.get_hint('1_3_1', 'choice_2')
|
||||
self.problem.capa_module.runtime.publish.assert_called_with(
|
||||
self.problem.capa_module,
|
||||
self.problem.capa_block.runtime.publish.assert_called_with(
|
||||
self.problem.capa_block,
|
||||
'edx.problem.hint.feedback_displayed',
|
||||
{'module_id': 'i4x://Foo/bar/mock/abc', 'problem_part_id': '1_2', 'trigger_type': 'single',
|
||||
'student_answer': ['choice_2'], 'correctness': False, 'question_type': 'multiplechoiceresponse',
|
||||
@@ -469,10 +469,10 @@ class MultpleChoiceHintsWithHtmlTest(HintTest):
|
||||
|
||||
def test_tracking_log(self):
|
||||
"""Test that the tracking log comes out right."""
|
||||
self.problem.capa_module.reset_mock()
|
||||
self.problem.capa_block.reset_mock()
|
||||
self.get_hint('1_2_1', 'choice_0')
|
||||
self.problem.capa_module.runtime.publish.assert_called_with(
|
||||
self.problem.capa_module,
|
||||
self.problem.capa_block.runtime.publish.assert_called_with(
|
||||
self.problem.capa_block,
|
||||
'edx.problem.hint.feedback_displayed',
|
||||
{'module_id': 'i4x://Foo/bar/mock/abc', 'problem_part_id': '1_1', 'trigger_type': 'single',
|
||||
'student_answer': ['choice_0'], 'correctness': False, 'question_type': 'multiplechoiceresponse',
|
||||
@@ -503,10 +503,10 @@ class DropdownHintsTest(HintTest):
|
||||
|
||||
def test_tracking_log(self):
|
||||
"""Test that the tracking log comes out right."""
|
||||
self.problem.capa_module.reset_mock()
|
||||
self.problem.capa_block.reset_mock()
|
||||
self.get_hint('1_3_1', 'FACES')
|
||||
self.problem.capa_module.runtime.publish.assert_called_with(
|
||||
self.problem.capa_module,
|
||||
self.problem.capa_block.runtime.publish.assert_called_with(
|
||||
self.problem.capa_block,
|
||||
'edx.problem.hint.feedback_displayed',
|
||||
{'module_id': 'i4x://Foo/bar/mock/abc', 'problem_part_id': '1_2', 'trigger_type': 'single',
|
||||
'student_answer': ['FACES'], 'correctness': True, 'question_type': 'optionresponse',
|
||||
|
||||
@@ -224,28 +224,28 @@ def remove_markup(html):
|
||||
return HTML(bleach.clean(html, tags=[], strip=True))
|
||||
|
||||
|
||||
def get_course_id_from_capa_module(capa_module):
|
||||
def get_course_id_from_capa_block(capa_block):
|
||||
"""
|
||||
Extract a stringified course run key from a CAPA module (aka ProblemBlock).
|
||||
Extract a stringified course run key from a CAPA block (aka ProblemBlock).
|
||||
|
||||
This is a bit of a hack. Its intended use is to allow us to pass the course id
|
||||
(if available) to `safe_exec`, enabling course-run-specific resource limits
|
||||
in the safe execution environment (codejail).
|
||||
|
||||
Arguments:
|
||||
capa_module (ProblemBlock|None)
|
||||
capa_block (ProblemBlock|None)
|
||||
|
||||
Returns: str|None
|
||||
The stringified course run key of the module.
|
||||
If not available, fall back to None.
|
||||
"""
|
||||
if not capa_module:
|
||||
if not capa_block:
|
||||
return None
|
||||
try:
|
||||
return str(capa_module.scope_ids.usage_id.course_key)
|
||||
return str(capa_block.scope_ids.usage_id.course_key)
|
||||
except (AttributeError, TypeError):
|
||||
# AttributeError:
|
||||
# If the capa module lacks scope ids or has unexpected scope ids, we
|
||||
# If the capa block lacks scope ids or has unexpected scope ids, we
|
||||
# would rather fall back to `None` than let an AttributeError be raised
|
||||
# here.
|
||||
# TypeError:
|
||||
|
||||
@@ -547,7 +547,7 @@ class ProblemBlock(
|
||||
try:
|
||||
tree = etree.XML(self.data)
|
||||
except etree.XMLSyntaxError:
|
||||
log.error(f'Error parsing problem types from xml for capa module {self.display_name}')
|
||||
log.error(f'Error parsing problem types from xml for capa block {self.display_name}')
|
||||
return None # short-term fix to prevent errors (TNL-5057). Will be more properly addressed in TNL-4525.
|
||||
registered_tags = responsetypes.registry.registered_tags()
|
||||
return {node.tag for node in tree.iter() if node.tag in registered_tags}
|
||||
@@ -638,7 +638,7 @@ class ProblemBlock(
|
||||
problem_text=self.data,
|
||||
id=self.location.html_id(),
|
||||
capa_system=capa_system,
|
||||
capa_module=self,
|
||||
capa_block=self,
|
||||
state={},
|
||||
seed=1,
|
||||
minimal_init=True,
|
||||
@@ -708,7 +708,7 @@ class ProblemBlock(
|
||||
id=self.location.html_id(),
|
||||
capa_system=capa_system,
|
||||
# We choose to run without a fully initialized CapaModule
|
||||
capa_module=None,
|
||||
capa_block=None,
|
||||
state={
|
||||
'done': user_state.state.get('done'),
|
||||
'correct_map': user_state.state.get('correct_map'),
|
||||
@@ -849,7 +849,7 @@ class ProblemBlock(
|
||||
state=state,
|
||||
seed=self.get_seed(),
|
||||
capa_system=capa_system,
|
||||
capa_module=self, # njp
|
||||
capa_block=self, # njp
|
||||
)
|
||||
|
||||
def get_state_for_lcp(self):
|
||||
@@ -1070,7 +1070,7 @@ class ProblemBlock(
|
||||
|
||||
if self.debug:
|
||||
msg = HTML(
|
||||
'[courseware.capa.capa_module] '
|
||||
'[courseware.capa.capa_block] '
|
||||
'Failed to generate HTML for problem {url}'
|
||||
).format(
|
||||
url=str(self.location)
|
||||
@@ -1786,7 +1786,7 @@ class ProblemBlock(
|
||||
except (StudentInputError, ResponseError, LoncapaProblemError) as inst:
|
||||
if self.debug:
|
||||
log.warning(
|
||||
"StudentInputError in capa_module:problem_check",
|
||||
"StudentInputError in capa_block:problem_check",
|
||||
exc_info=True
|
||||
)
|
||||
|
||||
@@ -2174,7 +2174,7 @@ class ProblemBlock(
|
||||
self.update_correctness()
|
||||
calculated_score = self.calculate_score()
|
||||
except (StudentInputError, ResponseError, LoncapaProblemError) as inst: # lint-amnesty, pylint: disable=unused-variable
|
||||
log.warning("Input error in capa_module:problem_rescore", exc_info=True)
|
||||
log.warning("Input error in capa_block:problem_rescore", exc_info=True)
|
||||
event_info['failure'] = 'input_error'
|
||||
self.publish_unmasked('problem_rescore_fail', event_info)
|
||||
raise
|
||||
@@ -14,7 +14,7 @@ from openedx.core.djangoapps.content_libraries import api as library_api
|
||||
from openedx.core.djangoapps.xblock.api import load_block
|
||||
from openedx.core.lib import blockstore_api
|
||||
from common.djangoapps.student.auth import has_studio_write_access
|
||||
from xmodule.capa_module import ProblemBlock
|
||||
from xmodule.capa_block import ProblemBlock
|
||||
from xmodule.library_content_module import ANY_CAPA_TYPE_VALUE
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.exceptions import ItemNotFoundError
|
||||
|
||||
@@ -2455,12 +2455,12 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
new_block_info.defaults = new_block_info.fields
|
||||
|
||||
# <workaround>
|
||||
# CAPA modules store their 'markdown' value (an alternate representation of their content)
|
||||
# CAPA blocks store their 'markdown' value (an alternate representation of their content)
|
||||
# in Scope.settings rather than Scope.content :-/
|
||||
# markdown is a field that really should not be overridable - it fundamentally changes the content.
|
||||
# capa modules also use a custom editor that always saves their markdown field to the metadata,
|
||||
# capa blocks also use a custom editor that always saves their markdown field to the metadata,
|
||||
# even if it hasn't changed, which breaks our override system.
|
||||
# So until capa modules are fixed, we special-case them and remove their markdown fields,
|
||||
# So until capa blocks are fixed, we special-case them and remove their markdown fields,
|
||||
# forcing the inherited version to use XML only.
|
||||
if usage_key.block_type == 'problem' and 'markdown' in new_block_info.defaults:
|
||||
del new_block_info.defaults['markdown']
|
||||
|
||||
@@ -59,7 +59,7 @@ class TestSplitCopyTemplate(MixedSplitTestCase):
|
||||
problem_block_course = self.store.get_item(vertical_block_course.children[0])
|
||||
assert problem_block_course.display_name == problem_library_display_name
|
||||
|
||||
# Check that when capa modules are copied, their "markdown" fields (Scope.settings) are removed.
|
||||
# Check that when capa blocks are copied, their "markdown" fields (Scope.settings) are removed.
|
||||
# (See note in split.py:copy_from_template())
|
||||
assert problem_block.markdown is not None
|
||||
assert problem_block_course.markdown is None
|
||||
|
||||
@@ -20,7 +20,7 @@ from docopt import docopt
|
||||
from path import Path as path
|
||||
|
||||
from xmodule.annotatable_block import AnnotatableBlock
|
||||
from xmodule.capa_module import ProblemBlock
|
||||
from xmodule.capa_block import ProblemBlock
|
||||
from xmodule.conditional_module import ConditionalBlock
|
||||
from xmodule.html_module import AboutBlock, CourseInfoBlock, HtmlBlock, StaticTabBlock
|
||||
from xmodule.library_content_module import LibraryContentBlock
|
||||
|
||||
@@ -33,10 +33,10 @@ from xmodule.capa import responsetypes
|
||||
from xmodule.capa.correctmap import CorrectMap
|
||||
from xmodule.capa.responsetypes import LoncapaProblemError, ResponseError, StudentInputError
|
||||
from xmodule.capa.xqueue_interface import XQueueInterface
|
||||
from xmodule.capa_module import ComplexEncoder, ProblemBlock
|
||||
from xmodule.capa_block import ComplexEncoder, ProblemBlock
|
||||
from xmodule.tests import DATA_DIR
|
||||
|
||||
from ..capa_module import RANDOMIZATION, SHOWANSWER
|
||||
from ..capa_block import RANDOMIZATION, SHOWANSWER
|
||||
from . import get_test_system
|
||||
|
||||
|
||||
@@ -218,7 +218,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
|
||||
def test_get_score(self):
|
||||
"""
|
||||
Tests the internals of get_score. In keeping with the ScorableXBlock spec,
|
||||
Capa modules store their score independently of the LCP internals, so it must
|
||||
Capa blocks store their score independently of the LCP internals, so it must
|
||||
be explicitly updated.
|
||||
"""
|
||||
student_answers = {'1_2_1': 'abcd'}
|
||||
@@ -705,7 +705,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
|
||||
# what the input is, by patching CorrectMap.is_correct()
|
||||
# Also simulate rendering the HTML
|
||||
with patch('xmodule.capa.correctmap.CorrectMap.is_correct') as mock_is_correct:
|
||||
with patch('xmodule.capa_module.ProblemBlock.get_problem_html') as mock_html:
|
||||
with patch('xmodule.capa_block.ProblemBlock.get_problem_html') as mock_html:
|
||||
mock_is_correct.return_value = True
|
||||
mock_html.return_value = "Test HTML"
|
||||
|
||||
@@ -749,7 +749,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
|
||||
|
||||
# Problem closed -- cannot submit
|
||||
# Simulate that ProblemBlock.closed() always returns True
|
||||
with patch('xmodule.capa_module.ProblemBlock.closed') as mock_closed:
|
||||
with patch('xmodule.capa_block.ProblemBlock.closed') as mock_closed:
|
||||
mock_closed.return_value = True
|
||||
with pytest.raises(xmodule.exceptions.NotFoundError):
|
||||
get_request_dict = {CapaFactory.input_key(): '3.14'}
|
||||
@@ -902,7 +902,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
|
||||
|
||||
def test_submit_problem_error(self):
|
||||
|
||||
# Try each exception that capa_module should handle
|
||||
# Try each exception that capa_block should handle
|
||||
exception_classes = [StudentInputError,
|
||||
LoncapaProblemError,
|
||||
ResponseError]
|
||||
@@ -929,7 +929,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
|
||||
|
||||
def test_submit_problem_error_with_codejail_exception(self):
|
||||
|
||||
# Try each exception that capa_module should handle
|
||||
# Try each exception that capa_block should handle
|
||||
exception_classes = [StudentInputError,
|
||||
LoncapaProblemError,
|
||||
ResponseError]
|
||||
@@ -999,7 +999,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
|
||||
|
||||
def test_submit_problem_error_nonascii(self):
|
||||
|
||||
# Try each exception that capa_module should handle
|
||||
# Try each exception that capa_block should handle
|
||||
exception_classes = [StudentInputError,
|
||||
LoncapaProblemError,
|
||||
ResponseError]
|
||||
@@ -1026,7 +1026,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
|
||||
|
||||
def test_submit_problem_error_with_staff_user(self):
|
||||
|
||||
# Try each exception that capa module should handle
|
||||
# Try each exception that capa block should handle
|
||||
for exception_class in [StudentInputError,
|
||||
LoncapaProblemError,
|
||||
ResponseError]:
|
||||
@@ -1088,7 +1088,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
|
||||
module.choose_new_seed = Mock(wraps=module.choose_new_seed)
|
||||
|
||||
# Stub out HTML rendering
|
||||
with patch('xmodule.capa_module.ProblemBlock.get_problem_html') as mock_html:
|
||||
with patch('xmodule.capa_block.ProblemBlock.get_problem_html') as mock_html:
|
||||
mock_html.return_value = "<div>Test HTML</div>"
|
||||
|
||||
# Reset the problem
|
||||
@@ -1110,7 +1110,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
|
||||
module = CapaFactory.create(rerandomize=RANDOMIZATION.ALWAYS)
|
||||
|
||||
# Simulate that the problem is closed
|
||||
with patch('xmodule.capa_module.ProblemBlock.closed') as mock_closed:
|
||||
with patch('xmodule.capa_block.ProblemBlock.closed') as mock_closed:
|
||||
mock_closed.return_value = True
|
||||
|
||||
# Try to reset the problem
|
||||
@@ -1302,7 +1302,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
|
||||
module = CapaFactory.create(done=False)
|
||||
|
||||
# Simulate that the problem is closed
|
||||
with patch('xmodule.capa_module.ProblemBlock.closed') as mock_closed:
|
||||
with patch('xmodule.capa_block.ProblemBlock.closed') as mock_closed:
|
||||
mock_closed.return_value = True
|
||||
|
||||
# Try to save the problem
|
||||
@@ -1931,8 +1931,8 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
|
||||
assert 0 <= module.seed < 1000
|
||||
i -= 1
|
||||
|
||||
@patch('xmodule.capa_module.log')
|
||||
@patch('xmodule.capa_module.Progress')
|
||||
@patch('xmodule.capa_block.log')
|
||||
@patch('xmodule.capa_block.Progress')
|
||||
def test_get_progress_error(self, mock_progress, mock_log):
|
||||
"""
|
||||
Check that an exception given in `Progress` produces a `log.exception` call.
|
||||
@@ -1945,7 +1945,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
|
||||
mock_log.exception.assert_called_once_with('Got bad progress')
|
||||
mock_log.reset_mock()
|
||||
|
||||
@patch('xmodule.capa_module.Progress')
|
||||
@patch('xmodule.capa_block.Progress')
|
||||
def test_get_progress_no_error_if_weight_zero(self, mock_progress):
|
||||
"""
|
||||
Check that if the weight is 0 get_progress does not try to create a Progress object.
|
||||
@@ -1957,7 +1957,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
|
||||
assert progress is None
|
||||
assert not mock_progress.called
|
||||
|
||||
@patch('xmodule.capa_module.Progress')
|
||||
@patch('xmodule.capa_block.Progress')
|
||||
def test_get_progress_calculate_progress_fraction(self, mock_progress):
|
||||
"""
|
||||
Check that score and total are calculated correctly for the progress fraction.
|
||||
@@ -3266,7 +3266,7 @@ class ProblemBlockReportGenerationTest(unittest.TestCase):
|
||||
def test_generate_report_data_report_loncapa_error(self):
|
||||
#Test to make sure reports continue despite loncappa errors, and write them into the report.
|
||||
descriptor = self._get_descriptor()
|
||||
with patch('xmodule.capa_module.LoncapaProblem') as mock_LoncapaProblem:
|
||||
with patch('xmodule.capa_block.LoncapaProblem') as mock_LoncapaProblem:
|
||||
mock_LoncapaProblem.side_effect = LoncapaProblemError
|
||||
report_data = list(descriptor.generate_report_data(
|
||||
self._mock_user_state_generator(
|
||||
@@ -1,9 +1,9 @@
|
||||
"""
|
||||
Tests the logic of problems with a delay between attempt submissions.
|
||||
|
||||
Note that this test file is based off of test_capa_module.py and as
|
||||
Note that this test file is based off of test_capa_block.py and as
|
||||
such, uses the same CapaFactory problem setup to test the functionality
|
||||
of the submit_problem method of a capa module when the "delay between quiz
|
||||
of the submit_problem method of a capa block when the "delay between quiz
|
||||
submissions" setting is set to different values
|
||||
"""
|
||||
|
||||
@@ -21,7 +21,7 @@ from xblock.fields import ScopeIds
|
||||
from xblock.scorable import Score
|
||||
|
||||
import xmodule
|
||||
from xmodule.capa_module import ProblemBlock
|
||||
from xmodule.capa_block import ProblemBlock
|
||||
|
||||
from . import get_test_system
|
||||
|
||||
@@ -30,7 +30,7 @@ class CapaFactoryWithDelay:
|
||||
"""
|
||||
Create problem modules class, specialized for delay_between_attempts
|
||||
test cases. This factory seems different enough from the one in
|
||||
test_capa_module that unifying them is unattractive.
|
||||
test_capa_block that unifying them is unattractive.
|
||||
Removed the unused optional arguments.
|
||||
"""
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ from xmodule.modulestore.tests.utils import MixedSplitTestCase
|
||||
from xmodule.tests import get_test_system
|
||||
from xmodule.validation import StudioValidationMessage
|
||||
from xmodule.x_module import AUTHOR_VIEW
|
||||
from xmodule.capa_module import ProblemBlock
|
||||
from xmodule.capa_block import ProblemBlock
|
||||
|
||||
from .test_course_module import DummySystem as TestImportSystem
|
||||
|
||||
|
||||
Reference in New Issue
Block a user