diff --git a/openassessment/__init__.py b/openassessment/__init__.py index 531ac82993..a47c086f88 100644 --- a/openassessment/__init__.py +++ b/openassessment/__init__.py @@ -2,4 +2,4 @@ Initialization Information for Open Assessment Module """ -__version__ = '6.12.3' +__version__ = '6.13.0' diff --git a/openassessment/xblock/load_static.py b/openassessment/xblock/load_static.py index 766a75ce55..b6abac2e04 100644 --- a/openassessment/xblock/load_static.py +++ b/openassessment/xblock/load_static.py @@ -5,8 +5,8 @@ import logging from urllib.parse import urlparse -from pkg_resources import resource_string from django.conf import settings +from xblock.utils.resources import ResourceLoader logger = logging.getLogger(__name__) # pylint: disable=invalid-name @@ -31,6 +31,8 @@ class LoadStatic: _base_url = '' _is_loaded = False + resource_loader = ResourceLoader(__name__) + @staticmethod def reload_manifest(): """ @@ -45,7 +47,7 @@ def reload_manifest(): logger.error('LMS_ROOT_URL is undefined') try: - json_data = resource_string(__name__, 'static/dist/manifest.json').decode("utf8") + json_data = LoadStatic.resource_loader.load_unicode('static/dist/manifest.json') LoadStatic._manifest = json.loads(json_data) base_url_override = LoadStatic._manifest.get('base_url', None) LoadStatic._is_loaded = True diff --git a/openassessment/xblock/openassessmentblock.py b/openassessment/xblock/openassessmentblock.py index f950a7909d..19f6b3e397 100644 --- a/openassessment/xblock/openassessmentblock.py +++ b/openassessment/xblock/openassessmentblock.py @@ -7,8 +7,8 @@ import logging import re -import pkg_resources import pytz +from xblock.utils.resources import ResourceLoader from django.conf import settings from django.contrib.auth import get_user_model @@ -72,12 +72,12 @@ from openassessment.xblock.apis.ora_data_accessor import ORADataAccessor logger = logging.getLogger(__name__) # pylint: disable=invalid-name +resource_loader = ResourceLoader(__name__) def load(path): """Handy helper for getting resources from our kit.""" - data = pkg_resources.resource_string(__name__, path) - return data.decode("utf8") + return resource_loader.load_unicode(path) @XBlock.needs("i18n") diff --git a/openassessment/xblock/test/test_load_static.py b/openassessment/xblock/test/test_load_static.py index c722fc14e5..08a6f61b45 100644 --- a/openassessment/xblock/test/test_load_static.py +++ b/openassessment/xblock/test/test_load_static.py @@ -65,24 +65,24 @@ def test_get_url_absolute_base_url(self): self.assertEqual(LoadStatic.get_url(key_url), urljoin( absolute_base_url, loaded_key_url)) - @patch('pkg_resources.resource_string') - def test_get_url_file_not_found(self, resource_string): + @patch('xblock.utils.resources.ResourceLoader.load_unicode') + def test_get_url_file_not_found(self, load_unicode): key_url = 'some_url.js' - resource_string.side_effect = IOError() + load_unicode.side_effect = IOError() self.assertEqual(LoadStatic.get_url(key_url), urljoin( self.default_base_url, 'some_url.js')) @override_settings(LMS_ROOT_URL='localhost/') - @patch('pkg_resources.resource_string') - def test_get_url_file_not_found_with_root_url(self, resource_string): + @patch('xblock.utils.resources.ResourceLoader.load_unicode') + def test_get_url_file_not_found_with_root_url(self, load_unicode): key_url = 'some_url.js' - resource_string.side_effect = IOError() + load_unicode.side_effect = IOError() self.assertEqual(LoadStatic.get_url(key_url), urljoin( 'localhost/', self.default_base_url, 'some_url.js')) - @patch('pkg_resources.resource_string') - def test_get_url_with_manifest(self, resource_string): - resource_string.return_value = None + @patch('xblock.utils.resources.ResourceLoader.load_unicode') + def test_get_url_with_manifest(self, load_unicode): + load_unicode.return_value = None key_url = 'some_url.js' with patch('json.loads') as jsondata: jsondata.return_value = { @@ -92,9 +92,9 @@ def test_get_url_with_manifest(self, resource_string): self.default_base_url, 'some_url.hashchunk.js')) @override_settings(LMS_ROOT_URL='localhost/') - @patch('pkg_resources.resource_string') - def test_get_url_with_manifest_and_root_url(self, resource_string): - resource_string.return_value = None + @patch('xblock.utils.resources.ResourceLoader.load_unicode') + def test_get_url_with_manifest_and_root_url(self, load_unicode): + load_unicode.return_value = None key_url = 'some_url.js' with patch('json.loads') as jsondata: jsondata.return_value = { diff --git a/openassessment/xblock/test/test_openassessment.py b/openassessment/xblock/test/test_openassessment.py index aacf70d0c2..b9af7e50d8 100644 --- a/openassessment/xblock/test/test_openassessment.py +++ b/openassessment/xblock/test/test_openassessment.py @@ -5,6 +5,7 @@ import datetime as dt from io import StringIO import json +import unittest from unittest import mock from unittest.mock import MagicMock, Mock, PropertyMock, patch from django.test.utils import override_settings @@ -16,6 +17,7 @@ from lxml import etree from openassessment.workflow.errors import AssessmentWorkflowError from openassessment.xblock import openassessmentblock +from openassessment.xblock.openassessmentblock import load from openassessment.xblock.utils import defaults from openassessment.xblock.utils.resolve_dates import DateValidationError, DISTANT_FUTURE, DISTANT_PAST from openassessment.xblock.openassesment_template_mixin import UI_MODELS @@ -113,6 +115,23 @@ def test_load_student_view(self, xblock): self.assertIsNotNone(grade_response) self.assertIn("step--grade", grade_response.body.decode('utf-8')) + @scenario("data/basic_scenario.xml") + def test_load_author_view(self, xblock): + """OA XBlock returns some HTML to the author in Studio. + + View basic test for verifying we're returned some HTML about the + Open Assessment XBlock for authoring purposes. + """ + xblock.xmodule_runtime = self._create_mock_runtime( + xblock.scope_ids.usage_id, True, False, "Author" + ) + xblock.mfe_views_enabled = True + xblock_fragment = self.runtime.render(xblock, "author_view") + + # Validate that the author view renders and contains expected content. + self.assertIn("OpenAssessmentBlock", xblock_fragment.body_html()) + self.assertIn("IS_STUDIO", xblock_fragment.body_html()) + def _staff_assessment_view_helper(self, xblock): """ Helper for "staff_assessment_view" tests @@ -1422,3 +1441,23 @@ def test_ora_indexibility_with_multiple_html_prompt(self, xblock): self.assertEqual(content["display_name"], "Open Response Assessment") self.assertEqual(content["prompt_0"], "What is computer? It is a machine") self.assertEqual(content["prompt_1"], "Is it a calculator? Or is it a microwave") + + +class TestLoadFunction(unittest.TestCase): + """Test case for the load function in openassessmentblock.py.""" + + @patch("openassessment.xblock.openassessmentblock.resource_loader.load_unicode") + def test_load_function(self, mock_load_unicode): + """ + Test that load calls resource_loader.load_unicode with the correct path. + """ + mock_load_unicode.return_value = "Sample content" + test_path = "sample/path/to/resource.html" + + result = load(test_path) + + # Check that resource_loader.load_unicode was called with the correct path + mock_load_unicode.assert_called_once_with(test_path) + + # Verify that load() returns the expected value + self.assertEqual(result, "Sample content") diff --git a/requirements/common_constraints.txt b/requirements/common_constraints.txt index ba76d81f3c..d302ebe595 100644 --- a/requirements/common_constraints.txt +++ b/requirements/common_constraints.txt @@ -1,4 +1,3 @@ - # A central location for most common version constraints # (across edx repos) for pip-installation. # diff --git a/setup.py b/setup.py index a6ccd76700..3d971c5a32 100644 --- a/setup.py +++ b/setup.py @@ -68,8 +68,8 @@ def get_version(*file_paths): 'License :: OSI Approved :: GNU Affero General Public License v3', 'Operating System :: OS Independent', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', ], packages=find_packages(include=['openassessment*'], exclude=['*.test', '*.tests']), include_package_data=True,