diff --git a/.coveragerc b/.coveragerc
index b48299d3d7..397a19c100 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -4,6 +4,7 @@ data_file = reports/${TEST_SUITE}.coverage
source =
cms
common/djangoapps
+ common/lib/capa
lms
openedx
pavelib
diff --git a/.coveragerc-local b/.coveragerc-local
index f14fdeea9c..a651388835 100644
--- a/.coveragerc-local
+++ b/.coveragerc-local
@@ -4,6 +4,7 @@ data_file = reports/.coverage
source =
cms
common/djangoapps
+ common/lib/capa
common/lib/xmodule
lms
openedx
diff --git a/.eslintignore b/.eslintignore
index 82cdcd00dc..87fc6073da 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -46,10 +46,10 @@ cms/static/js/spec/views/course_info_spec.js
cms/static/js/spec/views/metadata_edit_spec.js
cms/static/js/spec/views/textbook_spec.js
cms/static/js/spec/views/upload_spec.js
-xmodule/capa/tests/test_files/js/test_problem_display.js
-xmodule/capa/tests/test_files/js/test_problem_generator.js
-xmodule/capa/tests/test_files/js/test_problem_grader.js
-xmodule/capa/tests/test_files/js/xproblem.js
+common/lib/capa/capa/tests/test_files/js/test_problem_display.js
+common/lib/capa/capa/tests/test_files/js/test_problem_generator.js
+common/lib/capa/capa/tests/test_files/js/test_problem_grader.js
+common/lib/capa/capa/tests/test_files/js/xproblem.js
lms/static/js/spec/calculator_spec.js
lms/static/js/spec/courseware_spec.js
lms/static/js/spec/feedback_form_spec.js
diff --git a/.github/workflows/unit-test-shards.json b/.github/workflows/unit-test-shards.json
index 1ca3f847fe..81a618f1e6 100644
--- a/.github/workflows/unit-test-shards.json
+++ b/.github/workflows/unit-test-shards.json
@@ -261,6 +261,12 @@
]
},
"common-2": {
+ "settings": "lms.envs.test",
+ "paths": [
+ "common/lib/"
+ ]
+ },
+ "common-3": {
"settings": "cms.envs.test",
"paths": [
"common/djangoapps/"
diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml
index 3b17418e58..dfe2412a24 100644
--- a/.github/workflows/unit-tests.yml
+++ b/.github/workflows/unit-tests.yml
@@ -31,6 +31,7 @@ jobs:
"cms-2",
"common-1",
"common-2",
+ "common-3",
"xmodule-1"
]
@@ -61,7 +62,7 @@ jobs:
- name: install requirements
run: |
sudo pip install -r requirements/pip.txt
- sudo pip install --exists-action='w' -r requirements/edx/testing.txt
+ sudo pip install -r requirements/edx/testing.txt
if [[ "${{ matrix.django-version }}" == "pinned" ]]; then
sudo pip install -r requirements/edx/django.txt
else
diff --git a/.github/workflows/verify-gha-unit-tests-count.yml b/.github/workflows/verify-gha-unit-tests-count.yml
index 8b5701af48..70e2295752 100644
--- a/.github/workflows/verify-gha-unit-tests-count.yml
+++ b/.github/workflows/verify-gha-unit-tests-count.yml
@@ -18,7 +18,7 @@ jobs:
- name: install requirements
run: |
sudo pip install -r requirements/pip.txt
- sudo pip install --exists-action='w' -r requirements/edx/testing.txt
+ sudo pip install -r requirements/edx/testing.txt
- name: verify unit tests count
uses: ./.github/actions/verify-tests-count
diff --git a/cms/envs/common.py b/cms/envs/common.py
index 0e9ec0d20c..7fe7f7ea5c 100644
--- a/cms/envs/common.py
+++ b/cms/envs/common.py
@@ -1112,10 +1112,10 @@ COURSES_WITH_UNSAFE_CODE = []
# Cojail REST service
ENABLE_CODEJAIL_REST_SERVICE = False
# .. setting_name: CODE_JAIL_REST_SERVICE_REMOTE_EXEC
-# .. setting_default: 'xmodule.capa.safe_exec.remote_exec.send_safe_exec_request_v0'
+# .. setting_default: 'capa.safe_exec.remote_exec.send_safe_exec_request_v0'
# .. setting_description: Set the python package.module.function that is reponsible of
# calling the remote service in charge of jailed code execution
-CODE_JAIL_REST_SERVICE_REMOTE_EXEC = 'xmodule.capa.safe_exec.remote_exec.send_safe_exec_request_v0'
+CODE_JAIL_REST_SERVICE_REMOTE_EXEC = 'capa.safe_exec.remote_exec.send_safe_exec_request_v0'
# .. setting_name: CODE_JAIL_REST_SERVICE_HOST
# .. setting_default: 'http://127.0.0.1:8550'
# .. setting_description: Set the codejail remote service host
diff --git a/xmodule/capa/__init__.py b/common/lib/capa/capa/__init__.py
similarity index 100%
rename from xmodule/capa/__init__.py
rename to common/lib/capa/capa/__init__.py
diff --git a/xmodule/capa/capa_problem.py b/common/lib/capa/capa/capa_problem.py
similarity index 99%
rename from xmodule/capa/capa_problem.py
rename to common/lib/capa/capa/capa_problem.py
index 66242b8438..30295b0919 100644
--- a/xmodule/capa/capa_problem.py
+++ b/common/lib/capa/capa/capa_problem.py
@@ -27,13 +27,13 @@ import six
from lxml import etree
from pytz import UTC
-import xmodule.capa.customrender as customrender
-import xmodule.capa.inputtypes as inputtypes
-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
+import capa.customrender as customrender
+import capa.inputtypes as inputtypes
+import capa.responsetypes as responsetypes
+import capa.xqueue_interface as xqueue_interface
+from capa.correctmap import CorrectMap
+from capa.safe_exec import safe_exec
+from capa.util import contextualize_text, convert_files_to_filenames, get_course_id_from_capa_module
from openedx.core.djangolib.markup import HTML, Text
from openedx.core.lib.edx_six import get_gettext
from xmodule.stringify import stringify_children
diff --git a/xmodule/capa/checker.py b/common/lib/capa/capa/checker.py
similarity index 99%
rename from xmodule/capa/checker.py
rename to common/lib/capa/capa/checker.py
index bcbdd85e52..c3873085d9 100755
--- a/xmodule/capa/checker.py
+++ b/common/lib/capa/capa/checker.py
@@ -13,7 +13,7 @@ from calc import UndefinedVariable
from mako.lookup import TemplateLookup
from path import Path as path
-from xmodule.capa.capa_problem import LoncapaProblem
+from capa.capa_problem import LoncapaProblem
logging.basicConfig(format="%(levelname)s %(message)s")
log = logging.getLogger('capa.checker')
diff --git a/xmodule/capa/correctmap.py b/common/lib/capa/capa/correctmap.py
similarity index 100%
rename from xmodule/capa/correctmap.py
rename to common/lib/capa/capa/correctmap.py
diff --git a/xmodule/capa/customrender.py b/common/lib/capa/capa/customrender.py
similarity index 100%
rename from xmodule/capa/customrender.py
rename to common/lib/capa/capa/customrender.py
diff --git a/xmodule/capa/inputtypes.py b/common/lib/capa/capa/inputtypes.py
similarity index 99%
rename from xmodule/capa/inputtypes.py
rename to common/lib/capa/capa/inputtypes.py
index f1817415ca..6adef536a3 100644
--- a/xmodule/capa/inputtypes.py
+++ b/common/lib/capa/capa/inputtypes.py
@@ -57,7 +57,7 @@ from chem import chemcalc
from lxml import etree
from six import text_type
-from xmodule.capa.xqueue_interface import XQUEUE_TIMEOUT
+from capa.xqueue_interface import XQUEUE_TIMEOUT
from openedx.core.djangolib.markup import HTML, Text
from openedx.core.lib import edx_six
from xmodule.stringify import stringify_children
diff --git a/xmodule/capa/registry.py b/common/lib/capa/capa/registry.py
similarity index 100%
rename from xmodule/capa/registry.py
rename to common/lib/capa/capa/registry.py
diff --git a/xmodule/capa/responsetypes.py b/common/lib/capa/capa/responsetypes.py
similarity index 99%
rename from xmodule/capa/responsetypes.py
rename to common/lib/capa/capa/responsetypes.py
index 39000c544a..35cc8eaa1c 100644
--- a/xmodule/capa/responsetypes.py
+++ b/common/lib/capa/capa/responsetypes.py
@@ -43,8 +43,8 @@ from shapely.geometry import MultiPoint, Point
from six import text_type
from six.moves import map, range, zip
-import xmodule.capa.safe_exec as safe_exec
-import xmodule.capa.xqueue_interface as xqueue_interface
+import capa.safe_exec as safe_exec
+import capa.xqueue_interface as xqueue_interface
from openedx.core.djangolib.markup import HTML, Text
from openedx.core.lib import edx_six
from openedx.core.lib.grade_utils import round_away_from_zero
diff --git a/xmodule/capa/safe_exec/README.rst b/common/lib/capa/capa/safe_exec/README.rst
similarity index 100%
rename from xmodule/capa/safe_exec/README.rst
rename to common/lib/capa/capa/safe_exec/README.rst
diff --git a/xmodule/capa/safe_exec/__init__.py b/common/lib/capa/capa/safe_exec/__init__.py
similarity index 100%
rename from xmodule/capa/safe_exec/__init__.py
rename to common/lib/capa/capa/safe_exec/__init__.py
diff --git a/xmodule/capa/safe_exec/exceptions.py b/common/lib/capa/capa/safe_exec/exceptions.py
similarity index 100%
rename from xmodule/capa/safe_exec/exceptions.py
rename to common/lib/capa/capa/safe_exec/exceptions.py
diff --git a/xmodule/capa/safe_exec/lazymod.py b/common/lib/capa/capa/safe_exec/lazymod.py
similarity index 100%
rename from xmodule/capa/safe_exec/lazymod.py
rename to common/lib/capa/capa/safe_exec/lazymod.py
diff --git a/xmodule/capa/safe_exec/remote_exec.py b/common/lib/capa/capa/safe_exec/remote_exec.py
similarity index 100%
rename from xmodule/capa/safe_exec/remote_exec.py
rename to common/lib/capa/capa/safe_exec/remote_exec.py
index a7aa7f8344..8baf0b7108 100644
--- a/xmodule/capa/safe_exec/remote_exec.py
+++ b/common/lib/capa/capa/safe_exec/remote_exec.py
@@ -2,19 +2,19 @@
Helper methods related to safe exec.
"""
+import requests
import json
import logging
-from importlib import import_module
-import requests
from codejail.safe_exec import SafeExecException
from django.conf import settings
from edx_toggles.toggles import SettingToggle
+from importlib import import_module
from requests.exceptions import RequestException, HTTPError
from simplejson import JSONDecodeError
-from django.utils.translation import gettext as _
from .exceptions import CodejailServiceParseError, CodejailServiceStatusError, CodejailServiceUnavailable
+from django.utils.translation import gettext as _
log = logging.getLogger(__name__)
diff --git a/xmodule/capa/safe_exec/safe_exec.py b/common/lib/capa/capa/safe_exec/safe_exec.py
similarity index 100%
rename from xmodule/capa/safe_exec/safe_exec.py
rename to common/lib/capa/capa/safe_exec/safe_exec.py
diff --git a/xmodule/capa/safe_exec/tests/__init__.py b/common/lib/capa/capa/safe_exec/tests/__init__.py
similarity index 100%
rename from xmodule/capa/safe_exec/tests/__init__.py
rename to common/lib/capa/capa/safe_exec/tests/__init__.py
diff --git a/xmodule/capa/safe_exec/tests/test_files/pylib/constant.py b/common/lib/capa/capa/safe_exec/tests/test_files/pylib/constant.py
similarity index 100%
rename from xmodule/capa/safe_exec/tests/test_files/pylib/constant.py
rename to common/lib/capa/capa/safe_exec/tests/test_files/pylib/constant.py
diff --git a/xmodule/capa/safe_exec/tests/test_lazymod.py b/common/lib/capa/capa/safe_exec/tests/test_lazymod.py
similarity index 97%
rename from xmodule/capa/safe_exec/tests/test_lazymod.py
rename to common/lib/capa/capa/safe_exec/tests/test_lazymod.py
index 548422d7c8..fb7bdda28d 100644
--- a/xmodule/capa/safe_exec/tests/test_lazymod.py
+++ b/common/lib/capa/capa/safe_exec/tests/test_lazymod.py
@@ -4,7 +4,7 @@
import sys
import unittest
-from xmodule.capa.safe_exec.lazymod import LazyModule
+from capa.safe_exec.lazymod import LazyModule
class ModuleIsolation(object):
diff --git a/xmodule/capa/safe_exec/tests/test_safe_exec.py b/common/lib/capa/capa/safe_exec/tests/test_safe_exec.py
similarity index 99%
rename from xmodule/capa/safe_exec/tests/test_safe_exec.py
rename to common/lib/capa/capa/safe_exec/tests/test_safe_exec.py
index 3ed60c6914..ea0b9ea67e 100644
--- a/xmodule/capa/safe_exec/tests/test_safe_exec.py
+++ b/common/lib/capa/capa/safe_exec/tests/test_safe_exec.py
@@ -19,7 +19,7 @@ from django.test import override_settings
from six import text_type, unichr
from six.moves import range
-from xmodule.capa.safe_exec import safe_exec, update_hash
+from capa.safe_exec import safe_exec, update_hash
class TestSafeExec(unittest.TestCase): # lint-amnesty, pylint: disable=missing-class-docstring
diff --git a/xmodule/capa/templates/annotationinput.html b/common/lib/capa/capa/templates/annotationinput.html
similarity index 100%
rename from xmodule/capa/templates/annotationinput.html
rename to common/lib/capa/capa/templates/annotationinput.html
diff --git a/xmodule/capa/templates/chemicalequationinput.html b/common/lib/capa/capa/templates/chemicalequationinput.html
similarity index 93%
rename from xmodule/capa/templates/chemicalequationinput.html
rename to common/lib/capa/capa/templates/chemicalequationinput.html
index ca01d3d7c2..3f18a699e6 100644
--- a/xmodule/capa/templates/chemicalequationinput.html
+++ b/common/lib/capa/capa/templates/chemicalequationinput.html
@@ -1,4 +1,4 @@
-<%! from xmodule.capa.util import remove_markup %>
+<%! from capa.util import remove_markup %>
diff --git a/xmodule/capa/templates/choicegroup.html b/common/lib/capa/capa/templates/choicegroup.html
similarity index 100%
rename from xmodule/capa/templates/choicegroup.html
rename to common/lib/capa/capa/templates/choicegroup.html
diff --git a/xmodule/capa/templates/choicetext.html b/common/lib/capa/capa/templates/choicetext.html
similarity index 98%
rename from xmodule/capa/templates/choicetext.html
rename to common/lib/capa/capa/templates/choicetext.html
index 64c4226b08..e2b5480ed4 100644
--- a/xmodule/capa/templates/choicetext.html
+++ b/common/lib/capa/capa/templates/choicetext.html
@@ -1,4 +1,4 @@
-<%! from xmodule.capa.util import remove_markup
+<%! from capa.util import remove_markup
from django.utils.translation import ugettext as _
from openedx.core.djangolib.markup import HTML
%>
diff --git a/xmodule/capa/templates/clarification.html b/common/lib/capa/capa/templates/clarification.html
similarity index 100%
rename from xmodule/capa/templates/clarification.html
rename to common/lib/capa/capa/templates/clarification.html
diff --git a/xmodule/capa/templates/codeinput.html b/common/lib/capa/capa/templates/codeinput.html
similarity index 100%
rename from xmodule/capa/templates/codeinput.html
rename to common/lib/capa/capa/templates/codeinput.html
diff --git a/xmodule/capa/templates/crystallography.html b/common/lib/capa/capa/templates/crystallography.html
similarity index 100%
rename from xmodule/capa/templates/crystallography.html
rename to common/lib/capa/capa/templates/crystallography.html
diff --git a/xmodule/capa/templates/designprotein2dinput.html b/common/lib/capa/capa/templates/designprotein2dinput.html
similarity index 100%
rename from xmodule/capa/templates/designprotein2dinput.html
rename to common/lib/capa/capa/templates/designprotein2dinput.html
diff --git a/xmodule/capa/templates/drag_and_drop_input.html b/common/lib/capa/capa/templates/drag_and_drop_input.html
similarity index 100%
rename from xmodule/capa/templates/drag_and_drop_input.html
rename to common/lib/capa/capa/templates/drag_and_drop_input.html
diff --git a/xmodule/capa/templates/editageneinput.html b/common/lib/capa/capa/templates/editageneinput.html
similarity index 100%
rename from xmodule/capa/templates/editageneinput.html
rename to common/lib/capa/capa/templates/editageneinput.html
diff --git a/xmodule/capa/templates/editamolecule.html b/common/lib/capa/capa/templates/editamolecule.html
similarity index 100%
rename from xmodule/capa/templates/editamolecule.html
rename to common/lib/capa/capa/templates/editamolecule.html
diff --git a/xmodule/capa/templates/filesubmission.html b/common/lib/capa/capa/templates/filesubmission.html
similarity index 100%
rename from xmodule/capa/templates/filesubmission.html
rename to common/lib/capa/capa/templates/filesubmission.html
diff --git a/xmodule/capa/templates/formulaequationinput.html b/common/lib/capa/capa/templates/formulaequationinput.html
similarity index 100%
rename from xmodule/capa/templates/formulaequationinput.html
rename to common/lib/capa/capa/templates/formulaequationinput.html
diff --git a/xmodule/capa/templates/imageinput.html b/common/lib/capa/capa/templates/imageinput.html
similarity index 100%
rename from xmodule/capa/templates/imageinput.html
rename to common/lib/capa/capa/templates/imageinput.html
diff --git a/xmodule/capa/templates/jsinput.html b/common/lib/capa/capa/templates/jsinput.html
similarity index 100%
rename from xmodule/capa/templates/jsinput.html
rename to common/lib/capa/capa/templates/jsinput.html
diff --git a/xmodule/capa/templates/mathstring.html b/common/lib/capa/capa/templates/mathstring.html
similarity index 100%
rename from xmodule/capa/templates/mathstring.html
rename to common/lib/capa/capa/templates/mathstring.html
diff --git a/xmodule/capa/templates/matlabinput.html b/common/lib/capa/capa/templates/matlabinput.html
similarity index 100%
rename from xmodule/capa/templates/matlabinput.html
rename to common/lib/capa/capa/templates/matlabinput.html
diff --git a/xmodule/capa/templates/optioninput.html b/common/lib/capa/capa/templates/optioninput.html
similarity index 100%
rename from xmodule/capa/templates/optioninput.html
rename to common/lib/capa/capa/templates/optioninput.html
diff --git a/xmodule/capa/templates/schematicinput.html b/common/lib/capa/capa/templates/schematicinput.html
similarity index 92%
rename from xmodule/capa/templates/schematicinput.html
rename to common/lib/capa/capa/templates/schematicinput.html
index 9693e0a36d..c0bf6f14c4 100644
--- a/xmodule/capa/templates/schematicinput.html
+++ b/common/lib/capa/capa/templates/schematicinput.html
@@ -1,4 +1,4 @@
-<%! from xmodule.capa.util import remove_markup %>
+<%! from capa.util import remove_markup %>
element
import textwrap
import unittest
-from xmodule.capa.tests.helpers import load_fixture, new_loncapa_problem, test_capa_system
+from capa.tests.helpers import load_fixture, new_loncapa_problem, test_capa_system
class CapaTargetedFeedbackTest(unittest.TestCase):
diff --git a/xmodule/capa/tests/test_util.py b/common/lib/capa/capa/tests/test_util.py
similarity index 98%
rename from xmodule/capa/tests/test_util.py
rename to common/lib/capa/capa/tests/test_util.py
index 38f488a2be..a56567f785 100644
--- a/xmodule/capa/tests/test_util.py
+++ b/common/lib/capa/capa/tests/test_util.py
@@ -9,8 +9,8 @@ import unittest
import ddt
from lxml import etree
-from xmodule.capa.tests.helpers import test_capa_system
-from xmodule.capa.util import (
+from capa.tests.helpers import test_capa_system
+from capa.util import (
compare_with_tolerance,
contextualize_text,
get_inner_html_from_xpath,
diff --git a/xmodule/capa/tests/test_xqueue_interface.py b/common/lib/capa/capa/tests/test_xqueue_interface.py
similarity index 94%
rename from xmodule/capa/tests/test_xqueue_interface.py
rename to common/lib/capa/capa/tests/test_xqueue_interface.py
index 315e0c0b0a..77cd6ccad0 100644
--- a/xmodule/capa/tests/test_xqueue_interface.py
+++ b/common/lib/capa/capa/tests/test_xqueue_interface.py
@@ -6,7 +6,7 @@ Tests the xqueue service interface.
from unittest import TestCase
from django.conf import settings
-from xmodule.capa.xqueue_interface import XQueueInterface, XQueueService
+from capa.xqueue_interface import XQueueInterface, XQueueService
class XQueueServiceTest(TestCase):
diff --git a/xmodule/capa/util.py b/common/lib/capa/capa/util.py
similarity index 100%
rename from xmodule/capa/util.py
rename to common/lib/capa/capa/util.py
diff --git a/xmodule/capa/xqueue_interface.py b/common/lib/capa/capa/xqueue_interface.py
similarity index 100%
rename from xmodule/capa/xqueue_interface.py
rename to common/lib/capa/capa/xqueue_interface.py
diff --git a/common/lib/capa/setup.py b/common/lib/capa/setup.py
new file mode 100644
index 0000000000..d2ea877cb9
--- /dev/null
+++ b/common/lib/capa/setup.py
@@ -0,0 +1,14 @@
+# lint-amnesty, pylint: disable=missing-module-docstring
+
+from setuptools import find_packages, setup
+
+setup(
+ name="capa",
+ version="0.1",
+ packages=find_packages(exclude=["tests"]),
+ install_requires=[
+ "setuptools",
+ "lxml",
+ "pytz"
+ ],
+)
diff --git a/conf/locale/babel_mako.cfg b/conf/locale/babel_mako.cfg
index 5c940572db..d009a4ee4c 100644
--- a/conf/locale/babel_mako.cfg
+++ b/conf/locale/babel_mako.cfg
@@ -11,7 +11,7 @@
# lms/templates
# lms/djangoapps/APPNAME/templates
# openedx/**/templates
-# xmodule/capa/templates
+# common/lib/capa/capa/templates
#
# Don't extract from these directory trees:
# common/test/test_microsites/test_microsite/templates
@@ -25,7 +25,7 @@ input_encoding = utf-8
input_encoding = utf-8
[mako: */templates/emails/**.txt]
input_encoding = utf-8
-[mako: xmodule/capa/templates/**.html]
+[mako: common/lib/capa/capa/templates/**.html]
input_encoding = utf-8
[mako: openedx/**/templates/**.html]
input_encoding = utf-8
diff --git a/docs/guides/conf.py b/docs/guides/conf.py
index fa6e8c3dab..09c64ffabf 100644
--- a/docs/guides/conf.py
+++ b/docs/guides/conf.py
@@ -20,6 +20,7 @@ root = Path('../..').abspath()
# can be successfully imported
sys.path.insert(0, root)
sys.path.append(root / "docs/guides")
+sys.path.append(root / "common/lib/capa")
# Use a settings module that allows all LMS and Studio code to be imported
@@ -220,6 +221,7 @@ autodoc_mock_imports = [
# the generated *.rst files
modules = {
'cms': 'cms',
+ 'common/lib/capa/capa': 'common/lib/capa',
'lms': 'lms',
'openedx': 'openedx',
'xmodule': 'xmodule',
diff --git a/docs/guides/docstrings/common_lib.rst b/docs/guides/docstrings/common_lib.rst
index 725f712db9..dcf884e56f 100644
--- a/docs/guides/docstrings/common_lib.rst
+++ b/docs/guides/docstrings/common_lib.rst
@@ -7,3 +7,5 @@ out from edx-platform into separate packages at some point.
.. toctree::
:maxdepth: 2
+
+ common/lib/capa/modules
diff --git a/docs/guides/testing/testing.rst b/docs/guides/testing/testing.rst
index bd232da231..f7a10787df 100644
--- a/docs/guides/testing/testing.rst
+++ b/docs/guides/testing/testing.rst
@@ -71,7 +71,7 @@ Test Locations
- Python unit and integration tests: Located in subpackages called
``tests``. For example, the tests for the ``capa`` package are
- located in ``xmodule/capa/tests``.
+ located in ``common/lib/capa/capa/tests``.
- Javascript unit tests: Located in ``spec`` folders. For example,
``xmodule/js/spec`` and
@@ -432,7 +432,7 @@ Factories are often implemented using `FactoryBoy`_.
In general, factories should be located close to the code they use. For
example, the factory for creating problem XML definitions is located in
-``xmodule/capa/tests/response_xml_factory.py`` because the
+``common/lib/capa/capa/tests/response_xml_factory.py`` because the
``capa`` package handles problem XML.
.. _FactoryBoy: https://readthedocs.org/projects/factoryboy/
diff --git a/lms/djangoapps/ccx/tests/test_views.py b/lms/djangoapps/ccx/tests/test_views.py
index d556693fb1..c3c3f68a00 100644
--- a/lms/djangoapps/ccx/tests/test_views.py
+++ b/lms/djangoapps/ccx/tests/test_views.py
@@ -19,12 +19,13 @@ from django.utils.translation import gettext as _
from edx_django_utils.cache import RequestCache
from opaque_keys.edx.keys import CourseKey
from pytz import UTC
+from capa.tests.response_xml_factory import StringResponseXMLFactory
+
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, SampleCourseFactory
from xmodule.x_module import XModuleMixin
-from xmodule.capa.tests.response_xml_factory import StringResponseXMLFactory
from common.djangoapps.edxmako.shortcuts import render_to_response
from common.djangoapps.student.models import CourseEnrollment, CourseEnrollmentAllowed
from common.djangoapps.student.roles import CourseCcxCoachRole, CourseInstructorRole, CourseStaffRole
diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py
index 19b3176991..3633ffcc13 100644
--- a/lms/djangoapps/courseware/module_render.py
+++ b/lms/djangoapps/courseware/module_render.py
@@ -48,7 +48,7 @@ from xmodule.services import RebindUserService
from common.djangoapps.static_replace.services import ReplaceURLService
from common.djangoapps.static_replace.wrapper import replace_urls_wrapper
from common.djangoapps.xblock_django.constants import ATTR_KEY_USER_ID
-from xmodule.capa.xqueue_interface import XQueueService # lint-amnesty, pylint: disable=wrong-import-order
+from capa.xqueue_interface import XQueueService # lint-amnesty, pylint: disable=wrong-import-order
from lms.djangoapps.courseware.access import get_user_role, has_access
from lms.djangoapps.courseware.entrance_exams import user_can_skip_entrance_exam, user_has_passed_entrance_exam
from lms.djangoapps.courseware.masquerade import (
diff --git a/lms/djangoapps/courseware/tests/test_entrance_exam.py b/lms/djangoapps/courseware/tests/test_entrance_exam.py
index d45a4b8058..3075bb577c 100644
--- a/lms/djangoapps/courseware/tests/test_entrance_exam.py
+++ b/lms/djangoapps/courseware/tests/test_entrance_exam.py
@@ -7,15 +7,16 @@ from unittest.mock import patch
from crum import set_current_request
from django.urls import reverse
from milestones.tests.utils import MilestonesTestCaseMixin
+from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
from lms.djangoapps.courseware.entrance_exams import (
course_has_entrance_exam,
get_entrance_exam_content,
user_can_skip_entrance_exam,
user_has_passed_entrance_exam
)
+
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
-from xmodule.capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
from lms.djangoapps.courseware.model_data import FieldDataCache
from lms.djangoapps.courseware.module_render import get_module, handle_xblock_callback, toc_for_course
from lms.djangoapps.courseware.tests.helpers import LoginEnrollmentTestCase
diff --git a/lms/djangoapps/courseware/tests/test_masquerade.py b/lms/djangoapps/courseware/tests/test_masquerade.py
index 342aa7c965..dbfdece5d9 100644
--- a/lms/djangoapps/courseware/tests/test_masquerade.py
+++ b/lms/djangoapps/courseware/tests/test_masquerade.py
@@ -16,7 +16,7 @@ from django.urls import reverse
from pytz import UTC
from xblock.runtime import DictKeyValueStore
-from xmodule.capa.tests.response_xml_factory import OptionResponseXMLFactory
+from capa.tests.response_xml_factory import OptionResponseXMLFactory
from lms.djangoapps.courseware.masquerade import (
MASQUERADE_SETTINGS_KEY,
CourseMasquerade,
diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py
index 15b3384479..d01d2e3f45 100644
--- a/lms/djangoapps/courseware/tests/test_module_render.py
+++ b/lms/djangoapps/courseware/tests/test_module_render.py
@@ -39,8 +39,8 @@ from xblock.fields import ScopeIds # lint-amnesty, pylint: disable=wrong-import
from xblock.runtime import DictKeyValueStore, KvsFieldData, Runtime # lint-amnesty, pylint: disable=wrong-import-order
from xblock.test.tools import TestRuntime # lint-amnesty, pylint: disable=wrong-import-order
-from xmodule.capa.tests.response_xml_factory import OptionResponseXMLFactory # lint-amnesty, pylint: disable=reimported
-from xmodule.capa.xqueue_interface import XQueueInterface
+from capa.tests.response_xml_factory import OptionResponseXMLFactory # lint-amnesty, pylint: disable=reimported
+from capa.xqueue_interface import XQueueInterface
from xmodule.capa_module import ProblemBlock
from xmodule.contentstore.django import contentstore
from xmodule.html_module import AboutBlock, CourseInfoBlock, HtmlBlock, StaticTabBlock
diff --git a/lms/djangoapps/courseware/tests/test_submitting_problems.py b/lms/djangoapps/courseware/tests/test_submitting_problems.py
index dc5ff1cc1b..fa9f381160 100644
--- a/lms/djangoapps/courseware/tests/test_submitting_problems.py
+++ b/lms/djangoapps/courseware/tests/test_submitting_problems.py
@@ -22,13 +22,13 @@ from django.urls import reverse
from django.utils.timezone import now
from submissions import api as submissions_api
-from xmodule.capa.tests.response_xml_factory import (
+from capa.tests.response_xml_factory import (
CodeResponseXMLFactory,
CustomResponseXMLFactory,
OptionResponseXMLFactory,
SchematicResponseXMLFactory
)
-from xmodule.capa.xqueue_interface import XQueueInterface
+from capa.xqueue_interface import XQueueInterface
from common.djangoapps.course_modes.models import CourseMode
from lms.djangoapps.courseware.models import BaseStudentModuleHistory, StudentModule
from lms.djangoapps.courseware.tests.helpers import LoginEnrollmentTestCase
diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py
index 17c87108e2..8eea7537e9 100644
--- a/lms/djangoapps/courseware/tests/test_views.py
+++ b/lms/djangoapps/courseware/tests/test_views.py
@@ -12,6 +12,7 @@ from urllib.parse import quote, urlencode
from uuid import uuid4
import ddt
+from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
from completion.test_utils import CompletionWaffleTestMixin
from crum import set_current_request
from django.conf import settings
@@ -30,7 +31,6 @@ from rest_framework import status
from web_fragments.fragment import Fragment
from xblock.core import XBlock
from xblock.fields import Scope, String
-from xmodule.capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
from xmodule.data import CertificatesDisplayBehaviors
from xmodule.graders import ShowCorrectness
from xmodule.modulestore import ModuleStoreEnum
@@ -2207,7 +2207,7 @@ class GenerateUserCertTests(ModuleStoreTestCase):
def test_user_with_passing_grade(self, mock_is_course_passed): # lint-amnesty, pylint: disable=unused-argument
# If user has above passing grading then json will return cert generating message and
# status valid code
- with patch('xmodule.capa.xqueue_interface.XQueueInterface.send_to_queue') as mock_send_to_queue:
+ with patch('capa.xqueue_interface.XQueueInterface.send_to_queue') as mock_send_to_queue:
mock_send_to_queue.return_value = (0, "Successfully queued")
resp = self.client.post(self.url)
diff --git a/lms/djangoapps/grades/rest_api/v1/tests/test_grading_policy_view.py b/lms/djangoapps/grades/rest_api/v1/tests/test_grading_policy_view.py
index a061ef41be..c4ba94d946 100644
--- a/lms/djangoapps/grades/rest_api/v1/tests/test_grading_policy_view.py
+++ b/lms/djangoapps/grades/rest_api/v1/tests/test_grading_policy_view.py
@@ -8,10 +8,11 @@ from datetime import datetime
import ddt
from django.urls import reverse
from pytz import UTC
+from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
+
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_AMNESTY_MODULESTORE, SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
-from xmodule.capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
from common.djangoapps.student.tests.factories import GlobalStaffFactory
from common.djangoapps.student.tests.factories import StaffFactory
from common.djangoapps.student.tests.factories import UserFactory
diff --git a/lms/djangoapps/grades/tests/base.py b/lms/djangoapps/grades/tests/base.py
index 19cf45bfcc..747474a351 100644
--- a/lms/djangoapps/grades/tests/base.py
+++ b/lms/djangoapps/grades/tests/base.py
@@ -4,10 +4,10 @@ Base file for Grades tests
from crum import set_current_request
+from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
+
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
-
-from xmodule.capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
from common.djangoapps.student.models import CourseEnrollment
from common.djangoapps.student.tests.factories import UserFactory
from lms.djangoapps.course_blocks.api import get_course_blocks
diff --git a/lms/djangoapps/grades/tests/integration/test_access.py b/lms/djangoapps/grades/tests/integration/test_access.py
index 9149fe6472..15866c520b 100644
--- a/lms/djangoapps/grades/tests/integration/test_access.py
+++ b/lms/djangoapps/grades/tests/integration/test_access.py
@@ -5,7 +5,7 @@ Test grading with access changes.
from crum import set_current_request
-from xmodule.capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
+from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
from common.djangoapps.student.models import CourseEnrollment
from common.djangoapps.student.tests.factories import UserFactory
from lms.djangoapps.course_blocks.api import get_course_blocks
diff --git a/lms/djangoapps/grades/tests/integration/test_events.py b/lms/djangoapps/grades/tests/integration/test_events.py
index f9b2ba4545..27966f86a3 100644
--- a/lms/djangoapps/grades/tests/integration/test_events.py
+++ b/lms/djangoapps/grades/tests/integration/test_events.py
@@ -6,7 +6,7 @@ from unittest.mock import patch
from crum import set_current_request
-from xmodule.capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
+from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
from common.djangoapps.student.models import CourseEnrollment
from common.djangoapps.student.tests.factories import UserFactory
from lms.djangoapps.courseware.tests.test_submitting_problems import ProblemSubmissionTestMixin
diff --git a/lms/djangoapps/grades/tests/integration/test_problems.py b/lms/djangoapps/grades/tests/integration/test_problems.py
index bb25ea047c..92b6478c83 100644
--- a/lms/djangoapps/grades/tests/integration/test_problems.py
+++ b/lms/djangoapps/grades/tests/integration/test_problems.py
@@ -5,6 +5,8 @@ import itertools
import ddt
import pytz
from crum import set_current_request
+from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
+
from xmodule.graders import ProblemScore
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.tests.django_utils import (
@@ -13,7 +15,6 @@ from xmodule.modulestore.tests.django_utils import (
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
from xmodule.modulestore.tests.utils import TEST_DATA_DIR
from xmodule.modulestore.xml_importer import import_course_from_xml
-from xmodule.capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
from common.djangoapps.student.models import CourseEnrollment
from common.djangoapps.student.tests.factories import UserFactory
from lms.djangoapps.course_blocks.api import get_course_blocks
diff --git a/lms/djangoapps/instructor/tests/test_enrollment.py b/lms/djangoapps/instructor/tests/test_enrollment.py
index ac7ab1749c..c5cc4989bb 100644
--- a/lms/djangoapps/instructor/tests/test_enrollment.py
+++ b/lms/djangoapps/instructor/tests/test_enrollment.py
@@ -9,6 +9,7 @@ from unittest.mock import patch
import ddt
import pytest
+from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
from ccx_keys.locator import CCXLocator
from crum import set_current_request
from django.conf import settings
@@ -19,7 +20,6 @@ from submissions import api as sub_api
from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_AMNESTY_MODULESTORE, SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
-from xmodule.capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
from common.djangoapps.student.models import CourseEnrollment, CourseEnrollmentAllowed, anonymous_id_for_user
from common.djangoapps.student.roles import CourseCcxCoachRole
from common.djangoapps.student.tests.factories import AdminFactory, UserFactory
diff --git a/lms/djangoapps/instructor/tests/test_spoc_gradebook.py b/lms/djangoapps/instructor/tests/test_spoc_gradebook.py
index 1f23ba6807..5b62e67641 100644
--- a/lms/djangoapps/instructor/tests/test_spoc_gradebook.py
+++ b/lms/djangoapps/instructor/tests/test_spoc_gradebook.py
@@ -3,7 +3,7 @@ Tests of the instructor dashboard spoc gradebook
"""
from django.urls import reverse
-from xmodule.capa.tests.response_xml_factory import StringResponseXMLFactory
+from capa.tests.response_xml_factory import StringResponseXMLFactory
from common.djangoapps.student.tests.factories import AdminFactory, CourseEnrollmentFactory, UserFactory
from lms.djangoapps.courseware.tests.factories import StudentModuleFactory
from lms.djangoapps.grades.api import task_compute_all_grades_for_course
diff --git a/lms/djangoapps/instructor_task/tasks_helper/module_state.py b/lms/djangoapps/instructor_task/tasks_helper/module_state.py
index 8095153f00..36ba0107a4 100644
--- a/lms/djangoapps/instructor_task/tasks_helper/module_state.py
+++ b/lms/djangoapps/instructor_task/tasks_helper/module_state.py
@@ -12,7 +12,7 @@ from opaque_keys.edx.keys import UsageKey
from xblock.runtime import KvsFieldData
from xblock.scorable import Score
-from xmodule.capa.responsetypes import LoncapaProblemError, ResponseError, StudentInputError
+from capa.responsetypes import LoncapaProblemError, ResponseError, StudentInputError
from common.djangoapps.student.models import get_user_by_username_or_email
from common.djangoapps.track.event_transaction_utils import create_new_event_transaction_id, set_event_transaction_type
from common.djangoapps.track.views import task_track
diff --git a/lms/djangoapps/instructor_task/tests/test_base.py b/lms/djangoapps/instructor_task/tests/test_base.py
index 75f6eb0b33..14d4b0d040 100644
--- a/lms/djangoapps/instructor_task/tests/test_base.py
+++ b/lms/djangoapps/instructor_task/tests/test_base.py
@@ -13,6 +13,7 @@ from unittest.mock import Mock, patch
from uuid import uuid4
import unicodecsv
+from capa.tests.response_xml_factory import OptionResponseXMLFactory
from celery.states import FAILURE, SUCCESS
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
from django.urls import reverse
@@ -23,7 +24,6 @@ from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_AMNESTY_MODULESTORE, ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
-from xmodule.capa.tests.response_xml_factory import OptionResponseXMLFactory
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
from lms.djangoapps.courseware.model_data import StudentModule
from lms.djangoapps.courseware.tests.tests import LoginEnrollmentTestCase
diff --git a/lms/djangoapps/instructor_task/tests/test_integration.py b/lms/djangoapps/instructor_task/tests/test_integration.py
index db8413046a..72c07e201c 100644
--- a/lms/djangoapps/instructor_task/tests/test_integration.py
+++ b/lms/djangoapps/instructor_task/tests/test_integration.py
@@ -20,8 +20,8 @@ from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imp
from django.test.utils import override_settings
from django.urls import reverse
-from xmodule.capa.responsetypes import StudentInputError
-from xmodule.capa.tests.response_xml_factory import CodeResponseXMLFactory, CustomResponseXMLFactory
+from capa.responsetypes import StudentInputError
+from capa.tests.response_xml_factory import CodeResponseXMLFactory, CustomResponseXMLFactory
from lms.djangoapps.courseware.model_data import StudentModule
from lms.djangoapps.grades.api import CourseGradeFactory
from lms.djangoapps.instructor_task.api import (
@@ -273,7 +273,7 @@ class TestRescoringTask(TestIntegrationTask):
self.submit_student_answer('u1', problem_url_name, [OPTION_1, OPTION_1])
expected_message = "bad things happened"
- with patch('xmodule.capa.capa_problem.LoncapaProblem.get_grade_from_current_answers') as mock_rescore:
+ with patch('capa.capa_problem.LoncapaProblem.get_grade_from_current_answers') as mock_rescore:
mock_rescore.side_effect = ZeroDivisionError(expected_message)
instructor_task = self.submit_rescore_all_student_answers('instructor', problem_url_name)
self._assert_task_failure(
@@ -293,7 +293,7 @@ class TestRescoringTask(TestIntegrationTask):
# return an input error as if it were a numerical response, with an embedded unicode character:
expected_message = "Could not interpret '2/3\u03a9' as a number"
- with patch('xmodule.capa.capa_problem.LoncapaProblem.get_grade_from_current_answers') as mock_rescore:
+ with patch('capa.capa_problem.LoncapaProblem.get_grade_from_current_answers') as mock_rescore:
mock_rescore.side_effect = StudentInputError(expected_message)
instructor_task = self.submit_rescore_all_student_answers('instructor', problem_url_name)
@@ -332,7 +332,7 @@ class TestRescoringTask(TestIntegrationTask):
problem_url_name = 'H1P2'
self.define_code_response_problem(problem_url_name)
# we fully create the CodeResponse problem, but just pretend that we're queuing it:
- with patch('xmodule.capa.xqueue_interface.XQueueInterface.send_to_queue') as mock_send_to_queue:
+ with patch('capa.xqueue_interface.XQueueInterface.send_to_queue') as mock_send_to_queue:
mock_send_to_queue.return_value = (0, "Successfully queued")
self.submit_student_answer('u1', problem_url_name, ["answer1", "answer2"])
diff --git a/lms/djangoapps/instructor_task/tests/test_tasks_helper.py b/lms/djangoapps/instructor_task/tests/test_tasks_helper.py
index 6fbb4834db..1807a8af96 100644
--- a/lms/djangoapps/instructor_task/tests/test_tasks_helper.py
+++ b/lms/djangoapps/instructor_task/tests/test_tasks_helper.py
@@ -24,7 +24,7 @@ from freezegun import freeze_time
from pytz import UTC
import openedx.core.djangoapps.user_api.course_tag.api as course_tag_api
-from xmodule.capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory # lint-amnesty, pylint: disable=wrong-import-order
+from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory # lint-amnesty, pylint: disable=wrong-import-order
from common.djangoapps.course_modes.models import CourseMode
from common.djangoapps.student.models import CourseEnrollment, CourseEnrollmentAllowed
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
@@ -2488,7 +2488,7 @@ class TestCertificateGeneration(InstructorTaskModuleTestCase):
with patch('lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task') as mock_current_task:
mock_current_task.return_value = current_task
- with patch('xmodule.capa.xqueue_interface.XQueueInterface.send_to_queue') as mock_queue:
+ with patch('capa.xqueue_interface.XQueueInterface.send_to_queue') as mock_queue:
mock_queue.return_value = (0, "Successfully queued")
result = generate_students_certificates(
None, None, self.course.id, task_input, 'certificates generated'
diff --git a/lms/envs/common.py b/lms/envs/common.py
index db3db3a3d4..7f7baa99b9 100644
--- a/lms/envs/common.py
+++ b/lms/envs/common.py
@@ -1080,7 +1080,6 @@ PROJECT_ROOT = path(__file__).abspath().dirname().dirname() # /edx-platform/lms
REPO_ROOT = PROJECT_ROOT.dirname()
COMMON_ROOT = REPO_ROOT / "common"
OPENEDX_ROOT = REPO_ROOT / "openedx"
-XMODULE_ROOT = REPO_ROOT / "xmodule"
ENV_ROOT = REPO_ROOT.dirname() # virtualenv dir /edx-platform is in
COURSES_ROOT = ENV_ROOT / "data"
NODE_MODULES_ROOT = REPO_ROOT / "node_modules"
@@ -1212,7 +1211,7 @@ MAKO_MODULE_DIR = os.path.join(tempfile.gettempdir(), 'mako_lms')
MAKO_TEMPLATE_DIRS_BASE = [
PROJECT_ROOT / 'templates',
COMMON_ROOT / 'templates',
- XMODULE_ROOT / 'capa' / 'templates',
+ COMMON_ROOT / 'lib' / 'capa' / 'capa' / 'templates',
COMMON_ROOT / 'djangoapps' / 'pipeline_mako' / 'templates',
OPENEDX_ROOT / 'core' / 'djangoapps' / 'cors_csrf' / 'templates',
OPENEDX_ROOT / 'core' / 'djangoapps' / 'dark_lang' / 'templates',
@@ -1271,7 +1270,7 @@ TEMPLATES = [
'DIRS': [
PROJECT_ROOT / "templates",
COMMON_ROOT / 'templates',
- XMODULE_ROOT / 'capa' / 'templates',
+ COMMON_ROOT / 'lib' / 'capa' / 'capa' / 'templates',
COMMON_ROOT / 'djangoapps' / 'pipeline_mako' / 'templates',
COMMON_ROOT / 'static', # required to statically include common Underscore templates
],
@@ -1703,10 +1702,10 @@ COURSES_WITH_UNSAFE_CODE = []
# Cojail REST service
ENABLE_CODEJAIL_REST_SERVICE = False
# .. setting_name: CODE_JAIL_REST_SERVICE_REMOTE_EXEC
-# .. setting_default: 'xmodule.capa.safe_exec.remote_exec.send_safe_exec_request_v0'
+# .. setting_default: 'common.lib.capa.capa.safe_exec.remote_exec.send_safe_exec_request_v0'
# .. setting_description: Set the python package.module.function that is reponsible of
# calling the remote service in charge of jailed code execution
-CODE_JAIL_REST_SERVICE_REMOTE_EXEC = 'xmodule.capa.safe_exec.remote_exec.send_safe_exec_request_v0'
+CODE_JAIL_REST_SERVICE_REMOTE_EXEC = 'common.lib.capa.capa.safe_exec.remote_exec.send_safe_exec_request_v0'
# .. setting_name: CODE_JAIL_REST_SERVICE_HOST
# .. setting_default: 'http://127.0.0.1:8550'
# .. setting_description: Set the codejail remote service host
diff --git a/openedx/core/djangoapps/content/block_structure/tasks.py b/openedx/core/djangoapps/content/block_structure/tasks.py
index 7c3c2805fb..30628ebe00 100644
--- a/openedx/core/djangoapps/content/block_structure/tasks.py
+++ b/openedx/core/djangoapps/content/block_structure/tasks.py
@@ -12,7 +12,7 @@ from edxval.api import ValInternalError
from lxml.etree import XMLSyntaxError
from opaque_keys.edx.keys import CourseKey
-from xmodule.capa.responsetypes import LoncapaProblemError
+from capa.responsetypes import LoncapaProblemError
from openedx.core.djangoapps.content.block_structure import api
from openedx.core.djangoapps.content.block_structure.config import enable_storage_backing_for_cache_in_request
from xmodule.modulestore.exceptions import ItemNotFoundError # lint-amnesty, pylint: disable=wrong-import-order
diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt
index 81a06194a7..fb13c29cc9 100644
--- a/requirements/edx/base.txt
+++ b/requirements/edx/base.txt
@@ -6,6 +6,8 @@
#
-e git+https://github.com/openedx/blockstore.git@1.2.1#egg=blockstore==1.2.1
# via -r requirements/edx/github.in
+-e common/lib/capa
+ # via -r requirements/edx/local.in
-e git+https://github.com/edx/codejail.git@3.1.3#egg=codejail==3.1.3
# via -r requirements/edx/github.in
-e git+https://github.com/edx/django-wiki.git@1.1.0#egg=django-wiki
diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt
index 48a9cd2228..70b2bfcf94 100644
--- a/requirements/edx/development.txt
+++ b/requirements/edx/development.txt
@@ -6,6 +6,8 @@
#
-e git+https://github.com/openedx/blockstore.git@1.2.1#egg=blockstore==1.2.1
# via -r requirements/edx/testing.txt
+-e common/lib/capa
+ # via -r requirements/edx/testing.txt
-e git+https://github.com/edx/codejail.git@3.1.3#egg=codejail==3.1.3
# via -r requirements/edx/testing.txt
-e git+https://github.com/edx/django-wiki.git@1.1.0#egg=django-wiki
diff --git a/requirements/edx/local.in b/requirements/edx/local.in
index 776e718daa..2e80f24af3 100644
--- a/requirements/edx/local.in
+++ b/requirements/edx/local.in
@@ -1,2 +1,3 @@
# Python libraries to install that are local to the edx-platform repo
-e .
+-e common/lib/capa
diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt
index d689709455..9d6d46b77a 100644
--- a/requirements/edx/testing.txt
+++ b/requirements/edx/testing.txt
@@ -6,6 +6,8 @@
#
-e git+https://github.com/openedx/blockstore.git@1.2.1#egg=blockstore==1.2.1
# via -r requirements/edx/base.txt
+-e common/lib/capa
+ # via -r requirements/edx/base.txt
-e git+https://github.com/edx/codejail.git@3.1.3#egg=codejail==3.1.3
# via -r requirements/edx/base.txt
-e git+https://github.com/edx/django-wiki.git@1.1.0#egg=django-wiki
diff --git a/scripts/verify-dunder-init.sh b/scripts/verify-dunder-init.sh
index 7c88feffc6..907df34bb1 100755
--- a/scripts/verify-dunder-init.sh
+++ b/scripts/verify-dunder-init.sh
@@ -27,7 +27,7 @@ exclude=''
exclude+='^\.$'
# Exclude test data that includes Python (do NOT exclude unit test source code, though).
-exclude+='|^xmodule/capa/safe_exec/tests/test_files/?.*$'
+exclude+='|^common/lib/capa/capa/safe_exec/tests/test_files/?.*$'
exclude+='|^common/test/data/?.*$'
# Exclude common/lib and its immediate child directories.
@@ -38,6 +38,7 @@ exclude+='|^common/test/data/?.*$'
# * common/lib/capa -> EXCLUDE from check.
# * common/lib/capa/capa/safe_exec -> INCLUDE in check.
exclude+='|^common/lib$'
+exclude+='|^common/lib/capa$'
# xmodule data folder
exclude+='|^xmodule/tests/data/xml-course-root/capa$'
diff --git a/xmodule/capa_module.py b/xmodule/capa_module.py
index 9276669396..225d9aa46b 100644
--- a/xmodule/capa_module.py
+++ b/xmodule/capa_module.py
@@ -26,11 +26,11 @@ from xblock.core import XBlock
from xblock.fields import Boolean, Dict, Float, Integer, Scope, String, XMLString
from xblock.scorable import ScorableXBlockMixin, Score
-from xmodule.capa import responsetypes
-from xmodule.capa.capa_problem import LoncapaProblem, LoncapaSystem
-from xmodule.capa.inputtypes import Status
-from xmodule.capa.responsetypes import LoncapaProblemError, ResponseError, StudentInputError
-from xmodule.capa.util import convert_files_to_filenames, get_inner_html_from_xpath
+from capa import responsetypes
+from capa.capa_problem import LoncapaProblem, LoncapaSystem
+from capa.inputtypes import Status
+from capa.responsetypes import LoncapaProblemError, ResponseError, StudentInputError
+from capa.util import convert_files_to_filenames, get_inner_html_from_xpath
from xmodule.contentstore.django import contentstore
from xmodule.editing_module import EditingMixin
from xmodule.exceptions import NotFoundError, ProcessingError
@@ -140,7 +140,7 @@ class ProblemBlock(
An XBlock representing a "problem".
A problem contains zero or more respondable items, such as multiple choice,
- numeric response, true/false, etc. See xmodule/capa/responsetypes.py
+ numeric response, true/false, etc. See common/lib/capa/capa/responsetypes.py
for the full ensemble.
The rendering logic of a problem is largely encapsulated within
@@ -1717,7 +1717,7 @@ class ProblemBlock(
answers_without_files = convert_files_to_filenames(answers)
event_info['answers'] = answers_without_files
- metric_name = 'xmodule.capa.check_problem.{}'.format # lint-amnesty, pylint: disable=unused-variable
+ metric_name = 'capa.check_problem.{}'.format # lint-amnesty, pylint: disable=unused-variable
# Can override current time
current_time = datetime.datetime.now(utc)
if override_time is not False:
diff --git a/xmodule/library_content_module.py b/xmodule/library_content_module.py
index 0d9d4e080f..599656e676 100644
--- a/xmodule/library_content_module.py
+++ b/xmodule/library_content_module.py
@@ -24,7 +24,7 @@ from xblock.completable import XBlockCompletionMode
from xblock.core import XBlock
from xblock.fields import Integer, List, Scope, String, Boolean
-from xmodule.capa.responsetypes import registry
+from capa.responsetypes import registry
from xmodule.mako_module import MakoTemplateBlockBase
from xmodule.studio_editable import StudioEditableBlock
from xmodule.util.xmodule_django import add_webpack_to_fragment
diff --git a/xmodule/tests/__init__.py b/xmodule/tests/__init__.py
index 6ab4105029..385ae3fcaa 100644
--- a/xmodule/tests/__init__.py
+++ b/xmodule/tests/__init__.py
@@ -26,7 +26,7 @@ from xblock.core import XBlock
from xblock.field_data import DictFieldData
from xblock.fields import Reference, ReferenceList, ReferenceValueDict, ScopeIds
-from xmodule.capa.xqueue_interface import XQueueService
+from capa.xqueue_interface import XQueueService
from xmodule.assetstore import AssetMetadata
from xmodule.contentstore.django import contentstore
from xmodule.mako_module import MakoDescriptorSystem
diff --git a/xmodule/tests/test_capa_module.py b/xmodule/tests/test_capa_module.py
index 7513c2b9ed..0f859300b2 100644
--- a/xmodule/tests/test_capa_module.py
+++ b/xmodule/tests/test_capa_module.py
@@ -28,11 +28,11 @@ from xblock.field_data import DictFieldData
from xblock.fields import ScopeIds
from xblock.scorable import Score
+from capa import responsetypes
+from capa.correctmap import CorrectMap
+from capa.responsetypes import LoncapaProblemError, ResponseError, StudentInputError
+from capa.xqueue_interface import XQueueInterface
import xmodule
-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.tests import DATA_DIR
@@ -704,7 +704,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
# Simulate that all answers are marked correct, no matter
# 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('capa.correctmap.CorrectMap.is_correct') as mock_is_correct:
with patch('xmodule.capa_module.ProblemBlock.get_problem_html') as mock_html:
mock_is_correct.return_value = True
mock_html.return_value = "Test HTML"
@@ -729,7 +729,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
module = CapaFactory.create(attempts=0)
# Simulate marking the input incorrect
- with patch('xmodule.capa.correctmap.CorrectMap.is_correct') as mock_is_correct:
+ with patch('capa.correctmap.CorrectMap.is_correct') as mock_is_correct:
mock_is_correct.return_value = False
# Check the problem
@@ -801,7 +801,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
# Simulate that the problem is queued
multipatch = patch.multiple(
- 'xmodule.capa.capa_problem.LoncapaProblem',
+ 'capa.capa_problem.LoncapaProblem',
is_queued=DEFAULT,
get_recentmost_queuetime=DEFAULT
)
@@ -911,7 +911,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
module = CapaFactory.create(attempts=1, user_is_staff=False)
# Simulate answering a problem that raises the exception
- with patch('xmodule.capa.capa_problem.LoncapaProblem.grade_answers') as mock_grade:
+ with patch('capa.capa_problem.LoncapaProblem.grade_answers') as mock_grade:
mock_grade.side_effect = exception_class('test error')
get_request_dict = {CapaFactory.input_key(): '3.14'}
@@ -939,7 +939,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
module = CapaFactory.create(attempts=1, user_is_staff=False)
# Simulate a codejail exception "Exception: Couldn't execute jailed code"
- with patch('xmodule.capa.capa_problem.LoncapaProblem.grade_answers') as mock_grade:
+ with patch('capa.capa_problem.LoncapaProblem.grade_answers') as mock_grade:
try:
raise ResponseError(
'Couldn\'t execute jailed code: stdout: \'\', '
@@ -973,7 +973,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
module = CapaFactory.create(attempts=1, user_is_staff=False)
# Simulate answering a problem that raises the exception
- with patch('xmodule.capa.capa_problem.LoncapaProblem.grade_answers') as mock_grade:
+ with patch('capa.capa_problem.LoncapaProblem.grade_answers') as mock_grade:
error_msg = "Superterrible error happened: ☠"
mock_grade.side_effect = Exception(error_msg)
@@ -1008,7 +1008,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
module = CapaFactory.create(attempts=1, user_is_staff=False)
# Simulate answering a problem that raises the exception
- with patch('xmodule.capa.capa_problem.LoncapaProblem.grade_answers') as mock_grade:
+ with patch('capa.capa_problem.LoncapaProblem.grade_answers') as mock_grade:
mock_grade.side_effect = exception_class("ȧƈƈḗƞŧḗḓ ŧḗẋŧ ƒǿř ŧḗşŧīƞɠ")
get_request_dict = {CapaFactory.input_key(): '3.14'}
@@ -1034,7 +1034,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
module = CapaFactory.create(attempts=1, user_is_staff=True)
# Simulate answering a problem that raises an exception
- with patch('xmodule.capa.capa_problem.LoncapaProblem.grade_answers') as mock_grade:
+ with patch('capa.capa_problem.LoncapaProblem.grade_answers') as mock_grade:
mock_grade.side_effect = exception_class('test error')
get_request_dict = {CapaFactory.input_key(): '3.14'}
@@ -1066,7 +1066,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
correct=is_correct)
# Simulate marking the input correct/incorrect
- with patch('xmodule.capa.correctmap.CorrectMap.is_correct') as mock_is_correct:
+ with patch('capa.correctmap.CorrectMap.is_correct') as mock_is_correct:
mock_is_correct.return_value = is_correct
# Check the problem
@@ -1137,13 +1137,13 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
# Simulate that all answers are marked correct, no matter
# what the input is, by patching LoncapaResponse.evaluate_answers()
- with patch('xmodule.capa.responsetypes.LoncapaResponse.evaluate_answers') as mock_evaluate_answers:
+ with patch('capa.responsetypes.LoncapaResponse.evaluate_answers') as mock_evaluate_answers:
mock_evaluate_answers.return_value = CorrectMap(
answer_id=CapaFactory.answer_key(),
correctness='correct',
npoints=1,
)
- with patch('xmodule.capa.correctmap.CorrectMap.is_correct') as mock_is_correct:
+ with patch('capa.correctmap.CorrectMap.is_correct') as mock_is_correct:
mock_is_correct.return_value = True
# Check the problem
@@ -1183,10 +1183,10 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
# In case of rescore with only_if_higher=True it should update score of module
# if previous score was lower
- with patch('xmodule.capa.correctmap.CorrectMap.is_correct') as mock_is_correct:
+ with patch('capa.correctmap.CorrectMap.is_correct') as mock_is_correct:
mock_is_correct.return_value = True
module.set_score(module.score_from_lcp(module.lcp))
- with patch('xmodule.capa.responsetypes.NumericalResponse.get_staff_ans') as get_staff_ans:
+ with patch('capa.responsetypes.NumericalResponse.get_staff_ans') as get_staff_ans:
get_staff_ans.return_value = 1 + 0j
module.rescore(only_if_higher=True)
@@ -1205,7 +1205,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
# Simulate that all answers are marked incorrect, no matter
# what the input is, by patching LoncapaResponse.evaluate_answers()
- with patch('xmodule.capa.responsetypes.LoncapaResponse.evaluate_answers') as mock_evaluate_answers:
+ with patch('capa.responsetypes.LoncapaResponse.evaluate_answers') as mock_evaluate_answers:
mock_evaluate_answers.return_value = CorrectMap(CapaFactory.answer_key(), 'incorrect')
module.rescore(only_if_higher=False)
@@ -1229,7 +1229,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
module = CapaFactory.create(done=True)
# Try to rescore the problem, and get exception
- with patch('xmodule.capa.capa_problem.LoncapaProblem.supports_rescoring') as mock_supports_rescoring:
+ with patch('capa.capa_problem.LoncapaProblem.supports_rescoring') as mock_supports_rescoring:
mock_supports_rescoring.return_value = False
with pytest.raises(NotImplementedError):
module.rescore(only_if_higher=False)
@@ -1255,7 +1255,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
# When codejail safe_exec fails upon problem creation, a LoncapaProblemError should be raised.
with pytest.raises(LoncapaProblemError):
- with patch('xmodule.capa.capa_problem.safe_exec') as mock_safe_exec:
+ with patch('capa.capa_problem.safe_exec') as mock_safe_exec:
mock_safe_exec.side_effect = SafeExecException()
factory.create()
@@ -1265,7 +1265,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
module = CapaFactory.create(attempts=1, done=True)
# Simulate answering a problem that raises the exception
- with patch('xmodule.capa.capa_problem.LoncapaProblem.get_grade_from_current_answers') as mock_rescore:
+ with patch('capa.capa_problem.LoncapaProblem.get_grade_from_current_answers') as mock_rescore:
mock_rescore.side_effect = exception_class('test error \u03a9')
with pytest.raises(exception_class):
module.rescore(only_if_higher=False)
@@ -1537,7 +1537,7 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
module.should_show_save_button = Mock(return_value=show_save_button)
# Patch the capa problem's HTML rendering
- with patch('xmodule.capa.capa_problem.LoncapaProblem.get_html') as mock_html:
+ with patch('capa.capa_problem.LoncapaProblem.get_html') as mock_html:
mock_html.return_value = "