Commit f1fff439 by Jonathan Piacenti

Add clearer error message for library content blocks on incompatible modulestores.

parent f203651a
...@@ -847,3 +847,27 @@ class TestOverrides(LibraryTestCase): ...@@ -847,3 +847,27 @@ class TestOverrides(LibraryTestCase):
self.assertEqual(self.problem_in_course.display_name, new_display_name) self.assertEqual(self.problem_in_course.display_name, new_display_name)
self.assertEqual(self.problem_in_course.weight, new_weight) self.assertEqual(self.problem_in_course.weight, new_weight)
self.assertEqual(self.problem_in_course.data, new_data_value) self.assertEqual(self.problem_in_course.data, new_data_value)
class TestIncompatibleModuleStore(LibraryTestCase):
"""
Tests for proper validation errors with an incompatible course modulestore.
"""
def setUp(self):
super(TestIncompatibleModuleStore, self).setUp()
# Create a course in an incompatible modulestore.
with modulestore().default_store(ModuleStoreEnum.Type.mongo):
self.course = CourseFactory.create()
# Add a LibraryContent block to the course:
self.lc_block = self._add_library_content_block(self.course, self.lib_key)
def test_incompatible_modulestore(self):
"""
Verifies that, if a user is using a modulestore that doesn't support libraries,
a validation error will be produced.
"""
validation = self.lc_block.validate()
self.assertEqual(validation.summary.type, validation.summary.ERROR)
self.assertIn(
"This course does not support content libraries.", validation.summary.text)
...@@ -434,6 +434,18 @@ class LibraryContentDescriptor(LibraryContentFields, MakoModuleDescriptor, XmlDe ...@@ -434,6 +434,18 @@ class LibraryContentDescriptor(LibraryContentFields, MakoModuleDescriptor, XmlDe
validation = super(LibraryContentDescriptor, self).validate() validation = super(LibraryContentDescriptor, self).validate()
if not isinstance(validation, StudioValidation): if not isinstance(validation, StudioValidation):
validation = StudioValidation.copy(validation) validation = StudioValidation.copy(validation)
library_tools = self.runtime.service(self, "library_tools")
if not (library_tools and library_tools.can_use_library_content(self)):
validation.set_summary(
StudioValidationMessage(
StudioValidationMessage.ERROR,
_(
u"This course does not support content libraries. "
u"Contact your system administrator for more information."
)
)
)
return validation
if not self.source_libraries: if not self.source_libraries:
validation.set_summary( validation.set_summary(
StudioValidationMessage( StudioValidationMessage(
......
...@@ -96,6 +96,12 @@ class LibraryToolsService(object): ...@@ -96,6 +96,12 @@ class LibraryToolsService(object):
assert isinstance(descriptor, CapaDescriptor) assert isinstance(descriptor, CapaDescriptor)
return capa_type in descriptor.problem_types return capa_type in descriptor.problem_types
def can_use_library_content(self, block):
"""
Determines whether a modulestore holding a course_id supports libraries.
"""
return self.store.check_supports(block.location.course_key, 'copy_from_template')
def update_children(self, dest_block, user_id, user_perms=None): def update_children(self, dest_block, user_id, user_perms=None):
""" """
This method is to be used when any of the libraries that a LibraryContentModule This method is to be used when any of the libraries that a LibraryContentModule
......
...@@ -441,6 +441,17 @@ class ModuleStoreAssetBase(object): ...@@ -441,6 +441,17 @@ class ModuleStoreAssetBase(object):
ret_assets.append(new_asset) ret_assets.append(new_asset)
return ret_assets return ret_assets
# pylint: disable=unused-argument
def check_supports(self, course_key, method):
"""
Verifies that a modulestore supports a particular method.
Some modulestores may differ based on the course_key, such
as mixed (since it has to find the underlying modulestore),
so it's required as part of the method signature.
"""
return hasattr(self, method)
class ModuleStoreAssetWriteInterface(ModuleStoreAssetBase): class ModuleStoreAssetWriteInterface(ModuleStoreAssetBase):
""" """
......
...@@ -850,6 +850,17 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase): ...@@ -850,6 +850,17 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
store = self._verify_modulestore_support(xblock.location.course_key, 'has_changes') store = self._verify_modulestore_support(xblock.location.course_key, 'has_changes')
return store.has_changes(xblock) return store.has_changes(xblock)
def check_supports(self, course_key, method):
"""
Verifies that the modulestore for a particular course supports a feature.
Returns True/false based on this.
"""
try:
self._verify_modulestore_support(course_key, method)
return True
except NotImplementedError:
return False
def _verify_modulestore_support(self, course_key, method): def _verify_modulestore_support(self, course_key, method):
""" """
Finds and returns the store that contains the course for the given location, and verifying Finds and returns the store that contains the course for the given location, and verifying
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment