From d91676fcb43c9d40720fd6a5a5f617b73c4e63bb Mon Sep 17 00:00:00 2001 From: Kyle McCormick Date: Fri, 17 Oct 2025 17:29:26 -0400 Subject: [PATCH] fix: Don't look for a custom Python ZIP in Content Libs V2 (#37500) Python-evaluated problems were failing to render because they were trying to invoke `course_id.make_asset_key` in order to obtain the asset key of the custom Python ZIP file. Learning Core assets work differently (no asset keys, etc.), and, furthermore, we haven't really thought though how and whether we want to support custom Python ZIPs in libraries. So, this fix punts on supporting Python ZIP files in libraries for now, but enables rendering of advanced CAPA problems which don't rely on a ZIP. This brings us to parity with Legacy Libraries, which didn't support assets at all and thus didn't support Python ZIPs either. Fixes: https://github.com/openedx/edx-platform/issues/37447 --- .../djangoapps/util/tests/test_sandboxing.py | 19 ++++++++++++++++++- xmodule/util/sandboxing.py | 9 +++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/common/djangoapps/util/tests/test_sandboxing.py b/common/djangoapps/util/tests/test_sandboxing.py index a1c06172ed..e544a07e85 100644 --- a/common/djangoapps/util/tests/test_sandboxing.py +++ b/common/djangoapps/util/tests/test_sandboxing.py @@ -7,7 +7,7 @@ import ddt from django.test import TestCase from django.test.utils import override_settings from opaque_keys.edx.keys import CourseKey -from opaque_keys.edx.locator import CourseLocator, LibraryLocator +from opaque_keys.edx.locator import CourseLocator, LibraryLocator, LibraryLocatorV2 from xmodule.contentstore.django import contentstore from xmodule.modulestore.tests.django_utils import upload_file_to_course @@ -114,3 +114,20 @@ class SandboxServiceTest(TestCase): def test_no_python_lib_zip(self): assert self.sandbox_service.get_python_lib_zip() is None + + +class SandboxServiceForLibrariesV2Test(TestCase): + """ + Test SandboxService methods for V2 Content Libraries. + + (Lacks tests for anything other than python_lib_zip) + """ + + @classmethod + def setUpClass(cls): + super().setUpClass() + library_key = LibraryLocatorV2('test', 'sandbox_test') + cls.sandbox_service = SandboxService(course_id=library_key, contentstore=contentstore) + + def test_no_python_lib_zip(self): + assert self.sandbox_service.get_python_lib_zip() is None diff --git a/xmodule/util/sandboxing.py b/xmodule/util/sandboxing.py index 298f421b74..01e897adec 100644 --- a/xmodule/util/sandboxing.py +++ b/xmodule/util/sandboxing.py @@ -3,6 +3,7 @@ import re from django.conf import settings +from opaque_keys.edx.keys import CourseKey, LearningContextKey DEFAULT_PYTHON_LIB_FILENAME = 'python_lib.zip' @@ -39,10 +40,14 @@ def can_execute_unsafe_code(course_id): return False -def get_python_lib_zip(contentstore, course_id): +def get_python_lib_zip(contentstore, context_key: LearningContextKey): """Return the bytes of the course code library file, if it exists.""" + if not isinstance(context_key, CourseKey): + # Although Content Libraries V2 does support python-evaluated capa problems, + # it doesn't yet support supplementary python zip files. + return None python_lib_filename = course_code_library_asset_name() - asset_key = course_id.make_asset_key("asset", python_lib_filename) + asset_key = context_key.make_asset_key("asset", python_lib_filename) zip_lib = contentstore().find(asset_key, throw_on_not_found=False) if zip_lib is not None: return zip_lib.data