Convert ErrorModule and NonStaffErrorModule to XBlocks. (#25570)

This commit is contained in:
Usman Khalid
2021-01-07 20:51:33 +05:00
committed by GitHub
parent 50bb70298c
commit 9e38b17202
22 changed files with 139 additions and 135 deletions

View File

@@ -72,7 +72,7 @@ from common.djangoapps.util.string_utils import _has_non_ascii_characters
from common.djangoapps.xblock_django.api import deprecated_xblocks
from xmodule.contentstore.content import StaticContent
from xmodule.course_module import DEFAULT_START_DATE, CourseFields
from xmodule.error_module import ErrorDescriptor
from xmodule.error_module import ErrorBlock
from xmodule.modulestore import EdxJSONEncoder
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import DuplicateCourseError, ItemNotFoundError
@@ -412,7 +412,7 @@ def _accessible_courses_iter(request):
"""
Filter out unusable and inaccessible courses
"""
if isinstance(course, ErrorDescriptor):
if isinstance(course, ErrorBlock):
return False
# Custom Courses for edX (CCX) is an edX feature for re-using course content.
@@ -499,7 +499,7 @@ def _accessible_libraries_iter(user, org=None):
libraries = [] if org == '' else modulestore().get_libraries(org=org)
else:
libraries = modulestore().get_library_summaries()
# No need to worry about ErrorDescriptors - split's get_libraries() never returns them.
# No need to worry about ErrorBlocks - split's get_libraries() never returns them.
return (lib for lib in libraries if has_studio_read_access(user, lib.location.library_key))
@@ -751,7 +751,7 @@ def _process_courses_list(courses_iter, in_process_course_actions, split_archive
archived_courses = []
for course in courses_iter:
if isinstance(course, ErrorDescriptor) or (course.id in in_process_action_course_keys):
if isinstance(course, ErrorBlock) or (course.id in in_process_action_course_keys):
continue
formatted_course = format_course_for_view(course)

View File

@@ -32,7 +32,7 @@ from openedx.core.lib.xblock_utils import (
)
from common.djangoapps.xblock_django.user_service import DjangoXBlockUserService
from xmodule.contentstore.django import contentstore
from xmodule.error_module import ErrorDescriptor
from xmodule.error_module import ErrorBlock
from xmodule.exceptions import NotFoundError, ProcessingError
from xmodule.modulestore.django import ModuleI18nService, modulestore
from xmodule.partitions.partitions_service import PartitionService
@@ -209,7 +209,7 @@ def _preview_module_system(request, descriptor, field_data):
# Set up functions to modify the fragment produced by student_view
wrappers=wrappers,
wrappers_asides=wrappers_asides,
error_descriptor_class=ErrorDescriptor,
error_descriptor_class=ErrorBlock,
get_user_role=lambda: get_user_role(request.user, course_id),
# Get the raw DescriptorSystem, not the CombinedSystem
descriptor_runtime=descriptor._runtime, # pylint: disable=protected-access

View File

@@ -18,7 +18,7 @@ from common.djangoapps.student.roles import GlobalStaff
from common.djangoapps.student.tests.factories import UserFactory
from common.djangoapps.student.views import get_course_enrollments
from common.djangoapps.util.milestones_helpers import get_pre_requisite_courses_not_completed, set_prerequisite_courses
from xmodule.error_module import ErrorDescriptor
from xmodule.error_module import ErrorBlock
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
@@ -104,7 +104,7 @@ class TestCourseListing(ModuleStoreTestCase, MilestonesTestCaseMixin):
def test_errored_course_regular_access(self):
"""
Test the course list for regular staff when get_course returns an ErrorDescriptor
Test the course list for regular staff when get_course returns an ErrorBlock
"""
# pylint: disable=protected-access
mongo_store = modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.mongo)
@@ -112,7 +112,7 @@ class TestCourseListing(ModuleStoreTestCase, MilestonesTestCaseMixin):
self._create_course_with_access_groups(course_key, default_store=ModuleStoreEnum.Type.mongo)
with mock.patch('xmodule.modulestore.mongo.base.MongoKeyValueStore', mock.Mock(side_effect=Exception)):
self.assertIsInstance(modulestore().get_course(course_key), ErrorDescriptor)
self.assertIsInstance(modulestore().get_course(course_key), ErrorBlock)
# Invalidate (e.g., delete) the corresponding CourseOverview, forcing get_course to be called.
CourseOverview.objects.filter(id=course_key).delete()

View File

@@ -9,8 +9,6 @@ XMODULES = [
"customtag = xmodule.template_module:CustomTagDescriptor",
"discuss = xmodule.backcompat_module:TranslateCustomTagDescriptor",
"image = xmodule.backcompat_module:TranslateCustomTagDescriptor",
"error = xmodule.error_module:ErrorDescriptor",
"nonstaff_error = xmodule.error_module:NonStaffErrorDescriptor",
"poll_question = xmodule.poll_module:PollDescriptor",
"problemset = xmodule.seq_module:SequenceDescriptor",
"section = xmodule.backcompat_module:SemanticSectionDescriptor",
@@ -28,10 +26,12 @@ XBLOCKS = [
"annotatable = xmodule.annotatable_module:AnnotatableBlock",
"conditional = xmodule.conditional_module:ConditionalBlock",
"course_info = xmodule.html_module:CourseInfoBlock",
"error = xmodule.error_module:ErrorBlock",
"html = xmodule.html_module:HtmlBlock",
"library = xmodule.library_root_xblock:LibraryRoot",
"library_content = xmodule.library_content_module:LibraryContentBlock",
"library_sourced = xmodule.library_sourced_block:LibrarySourcedBlock",
"nonstaff_error = xmodule.error_module:NonStaffErrorBlock",
"problem = xmodule.capa_module:ProblemBlock",
"randomize = xmodule.randomize_module:RandomizeBlock",
"split_test = xmodule.split_test_module:SplitTestBlock",

View File

@@ -216,7 +216,7 @@ class ConditionalBlock(
if not hasattr(module, attr_name):
# We don't throw an exception here because it is possible for
# the descriptor of a required module to have a property but
# for the resulting module to be a (flavor of) ErrorModule.
# for the resulting module to be a (flavor of) ErrorBlock.
# So just log and return false.
if module is not None:
# We do not want to log when module is None, and it is when requester

View File

@@ -11,18 +11,25 @@ import sys
import six
from lxml import etree
from web_fragments.fragment import Fragment
from xblock.field_data import DictFieldData
from xblock.fields import Scope, ScopeIds, String
from xmodule.errortracker import exc_info_to_str
from xmodule.modulestore import EdxJSONEncoder
from xmodule.x_module import XModule, XModuleDescriptor
from xmodule.x_module import (
HTMLSnippet,
ResourceTemplates,
XModuleMixin,
XModuleDescriptorToXBlockMixin,
XModuleToXBlockMixin,
)
log = logging.getLogger(__name__)
# NOTE: This is not the most beautiful design in the world, but there's no good
# way to tell if the module is being used in a staff context or not. Errors that get discovered
# at course load time are turned into ErrorDescriptor objects, and automatically hidden from students.
# at course load time are turned into ErrorBlock objects, and automatically hidden from students.
# Unfortunately, we can also have errors when loading modules mid-request, and then we need to decide
# what to show, and the logic for that belongs in the LMS (e.g. in get_module), so the error handler
# decides whether to create a staff or not-staff module.
@@ -30,62 +37,49 @@ log = logging.getLogger(__name__)
class ErrorFields(object):
"""
XBlock fields used by the ErrorModules
XBlock fields used by the ErrorBlocks
"""
contents = String(scope=Scope.content)
error_msg = String(scope=Scope.content)
display_name = String(scope=Scope.settings)
class ErrorModule(ErrorFields, XModule):
class ErrorBlock(
ErrorFields,
XModuleDescriptorToXBlockMixin,
XModuleToXBlockMixin,
HTMLSnippet,
ResourceTemplates,
XModuleMixin,
): # pylint: disable=abstract-method
"""
Module that gets shown to staff when there has been an error while
loading or rendering other modules
"""
def get_html(self):
'''Show an error to staff.
TODO (vshnayder): proper style, divs, etc.
'''
# staff get to see all the details
return self.system.render_template('module-error.html', {
resources_dir = None
def student_view(self, _context):
"""
Return a fragment that contains the html for the student view.
"""
fragment = Fragment(self.system.render_template('module-error.html', {
'staff_access': True,
'data': self.contents,
'error': self.error_msg,
})
}))
return fragment
class NonStaffErrorModule(ErrorFields, XModule):
"""
Module that gets shown to students when there has been an error while
loading or rendering other modules
"""
def get_html(self):
'''Show an error to a student.
TODO (vshnayder): proper style, divs, etc.
'''
# staff get to see all the details
return self.system.render_template('module-error.html', {
'staff_access': False,
'data': "",
'error': "",
})
class ErrorDescriptor(ErrorFields, XModuleDescriptor):
"""
Module that provides a raw editing view of broken xml.
"""
module_class = ErrorModule
resources_dir = None
def get_html(self):
return u''
def studio_view(self, _context):
"""
Show empty edit view since this is not editable.
"""
return Fragment('')
@classmethod
def _construct(cls, system, contents, error_msg, location, for_parent=None):
"""
Build a new ErrorDescriptor. using ``system``.
Build a new ErrorBlock using ``system``.
Arguments:
system (:class:`DescriptorSystem`): The :class:`DescriptorSystem` used
@@ -106,7 +100,7 @@ class ErrorDescriptor(ErrorFields, XModuleDescriptor):
# Pick a unique url_name -- the sha1 hash of the contents.
# NOTE: We could try to pull out the url_name of the errored descriptor,
# but url_names aren't guaranteed to be unique between descriptor types,
# and ErrorDescriptor can wrap any type. When the wrapped module is fixed,
# and ErrorBlock can wrap any type. When the wrapped module is fixed,
# it will be written out with the original url_name.
name=hashlib.sha1(contents.encode('utf8')).hexdigest()
)
@@ -207,8 +201,18 @@ class ErrorDescriptor(ErrorFields, XModuleDescriptor):
return etree.tostring(root, encoding='unicode')
class NonStaffErrorDescriptor(ErrorDescriptor):
class NonStaffErrorBlock(ErrorBlock): # pylint: disable=abstract-method
"""
Module that provides non-staff error messages.
Block that gets shown to students when there has been an error while
loading or rendering other blocks.
"""
module_class = NonStaffErrorModule
def student_view(self, _context):
"""
Return a fragment that contains the html for the student view.
"""
fragment = Fragment(self.system.render_template('module-error.html', {
'staff_access': False,
'data': '',
'error': '',
}))
return fragment

View File

@@ -38,7 +38,7 @@ from xblock.runtime import KvsFieldData
from xmodule.assetstore import AssetMetadata, CourseAssetsFromStorage
from xmodule.course_module import CourseSummary
from xmodule.error_module import ErrorDescriptor
from xmodule.error_module import ErrorBlock
from xmodule.errortracker import exc_info_to_str, null_error_tracker
from xmodule.exceptions import HeartbeatFailure
from xmodule.mako_module import MakoDescriptorSystem
@@ -330,7 +330,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin):
return module
except Exception: # pylint: disable=broad-except
log.warning("Failed to load descriptor from %s", json_data, exc_info=True)
return ErrorDescriptor.from_json(
return ErrorBlock.from_json(
json_data,
self,
location,
@@ -1071,7 +1071,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
],
[]
)
return [course for course in base_list if not isinstance(course, ErrorDescriptor)]
return [course for course in base_list if not isinstance(course, ErrorBlock)]
@autoretry_read()
def _find_one(self, location):

View File

@@ -12,7 +12,7 @@ from xblock.core import XBlock
from xblock.fields import ScopeIds
from xblock.runtime import KeyValueStore, KvsFieldData
from xmodule.error_module import ErrorDescriptor
from xmodule.error_module import ErrorBlock
from xmodule.errortracker import exc_info_to_str
from xmodule.library_tools import LibraryToolsService
from xmodule.mako_module import MakoDescriptorSystem
@@ -258,7 +258,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin):
)
except Exception: # pylint: disable=broad-except
log.warning("Failed to load descriptor", exc_info=True)
return ErrorDescriptor.from_json(
return ErrorBlock.from_json(
block_data,
self,
course_entry_override.course_key.make_usage_key(

View File

@@ -83,7 +83,7 @@ from xblock.fields import Reference, ReferenceList, ReferenceValueDict, Scope
from xmodule.assetstore import AssetMetadata
from xmodule.course_module import CourseSummary
from xmodule.error_module import ErrorDescriptor
from xmodule.error_module import ErrorBlock
from xmodule.errortracker import null_error_tracker
from xmodule.library_content_module import LibrarySummary
from xmodule.modulestore import (
@@ -988,7 +988,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
envelope = CourseEnvelope(locator, entry)
root = entry['root']
structures_list = self._load_items(envelope, [root], depth=0, **kwargs)
if not isinstance(structures_list[0], ErrorDescriptor):
if not isinstance(structures_list[0], ErrorBlock):
result.append(structures_list[0])
return result

View File

@@ -27,7 +27,7 @@ from xblock.field_data import DictFieldData
from xblock.fields import ScopeIds
from xblock.runtime import DictKeyValueStore
from xmodule.error_module import ErrorDescriptor
from xmodule.error_module import ErrorBlock
from xmodule.errortracker import exc_info_to_str, make_error_tracker
from xmodule.mako_module import MakoDescriptorSystem
from xmodule.modulestore import COURSE_ROOT, LIBRARY_ROOT, ModuleStoreEnum, ModuleStoreReadBase
@@ -194,7 +194,7 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):
self.error_tracker(msg)
err_msg = msg + "\n" + exc_info_to_str(sys.exc_info())
descriptor = ErrorDescriptor.from_xml(
descriptor = ErrorBlock.from_xml(
xml,
self,
id_manager,
@@ -390,7 +390,7 @@ class XMLModuleStore(ModuleStoreReadBase):
if course_descriptor is None:
pass
elif isinstance(course_descriptor, ErrorDescriptor):
elif isinstance(course_descriptor, ErrorBlock):
# Didn't load course. Instead, save the errors elsewhere.
self.errored_courses[course_dir] = errorlog
else:
@@ -529,7 +529,7 @@ class XMLModuleStore(ModuleStoreReadBase):
)
course_descriptor = system.process_xml(etree.tostring(course_data, encoding='unicode'))
# If we fail to load the course, then skip the rest of the loading steps
if isinstance(course_descriptor, ErrorDescriptor):
if isinstance(course_descriptor, ErrorBlock):
return course_descriptor
self.content_importers(system, course_descriptor, course_dir, url_name)
@@ -783,7 +783,7 @@ class XMLModuleStore(ModuleStoreReadBase):
def get_courses(self, **kwargs):
"""
Returns a list of course descriptors. If there were errors on loading,
some of these may be ErrorDescriptors instead.
some of these may be ErrorBlock instead.
"""
return list(self.courses.values())

View File

@@ -29,7 +29,7 @@ from xblock.field_data import DictFieldData
from xblock.fields import Reference, ReferenceList, ReferenceValueDict, ScopeIds
from xmodule.assetstore import AssetMetadata
from xmodule.error_module import ErrorDescriptor
from xmodule.error_module import ErrorBlock
from xmodule.mako_module import MakoDescriptorSystem
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.draft_and_published import ModuleStoreDraftAndPublished
@@ -146,7 +146,7 @@ def get_test_system(
node_path=os.environ.get("NODE_PATH", "/usr/local/lib/node_modules"),
anonymous_student_id='student',
course_id=course_id,
error_descriptor_class=ErrorDescriptor,
error_descriptor_class=ErrorBlock,
get_user_role=Mock(name='get_test_system.get_user_role', is_staff=False),
user_location=Mock(name='get_test_system.user_location'),
descriptor_runtime=descriptor_system,

View File

@@ -14,7 +14,7 @@ from xblock.field_data import DictFieldData
from xblock.fields import ScopeIds
from xmodule.conditional_module import ConditionalBlock
from xmodule.error_module import NonStaffErrorDescriptor
from xmodule.error_module import NonStaffErrorBlock
from xmodule.modulestore.xml import CourseLocationManager, ImportSystem, XMLModuleStore
from xmodule.tests import DATA_DIR, get_test_descriptor_system, get_test_system
from xmodule.tests.xml import XModuleXmlImportTest
@@ -63,7 +63,7 @@ class ConditionalFactory(object):
return a dict of modules: the conditional with a single source and a single child.
Keys are 'cond_module', 'source_module', and 'child_module'.
if the source_is_error_module flag is set, create a real ErrorModule for the source.
if the source_is_error_module flag is set, create a real ErrorBlock for the source.
"""
descriptor_system = get_test_descriptor_system()
@@ -72,7 +72,7 @@ class ConditionalFactory(object):
"problem", "SampleProblem", deprecated=True)
if source_is_error_module:
# Make an error descriptor and module
source_descriptor = NonStaffErrorDescriptor.from_xml(
source_descriptor = NonStaffErrorBlock.from_xml(
'some random xml data',
system,
id_generator=CourseLocationManager(source_location.course_key),
@@ -192,7 +192,7 @@ class ConditionalBlockBasicTest(unittest.TestCase):
def test_error_as_source(self):
'''
Check that handle_ajax works properly if the source is really an ErrorModule,
Check that handle_ajax works properly if the source is really an ErrorBlock,
and that the condition is not satisfied.
'''
modules = ConditionalFactory.create(self.test_system, source_is_error_module=True)

View File

@@ -1,5 +1,5 @@
"""
Tests for ErrorModule and NonStaffErrorModule
Tests for ErrorBlock and NonStaffErrorBlock
"""
@@ -12,17 +12,17 @@ from xblock.fields import ScopeIds
from xblock.runtime import IdReader, Runtime
from xblock.test.tools import unabc
from xmodule.error_module import ErrorDescriptor, ErrorModule, NonStaffErrorDescriptor
from xmodule.error_module import ErrorBlock, NonStaffErrorBlock
from xmodule.modulestore.xml import CourseLocationManager
from xmodule.tests import get_test_system
from xmodule.x_module import STUDENT_VIEW, XModule, XModuleDescriptor
class SetupTestErrorModules(unittest.TestCase):
"""Common setUp for use in ErrorModule tests."""
class SetupTestErrorBlock(unittest.TestCase):
"""Common setUp for use in ErrorBlock tests."""
def setUp(self):
super(SetupTestErrorModules, self).setUp()
super().setUp()
self.system = get_test_system()
self.course_id = CourseLocator('org', 'course', 'run')
self.location = self.course_id.make_usage_key('foo', 'bar')
@@ -30,55 +30,55 @@ class SetupTestErrorModules(unittest.TestCase):
self.error_msg = "Error"
class TestErrorModule(SetupTestErrorModules):
class TestErrorBlock(SetupTestErrorBlock):
"""
Tests for ErrorModule and ErrorDescriptor
Tests for ErrorBlock
"""
def test_error_module_xml_rendering(self):
descriptor = ErrorDescriptor.from_xml(
def test_error_block_xml_rendering(self):
descriptor = ErrorBlock.from_xml(
self.valid_xml,
self.system,
CourseLocationManager(self.course_id),
self.error_msg
)
self.assertIsInstance(descriptor, ErrorDescriptor)
self.assertIsInstance(descriptor, ErrorBlock)
descriptor.xmodule_runtime = self.system
context_repr = self.system.render(descriptor, STUDENT_VIEW).content
self.assertIn(self.error_msg, context_repr)
self.assertIn(repr(self.valid_xml), context_repr)
def test_error_module_from_descriptor(self):
def test_error_block_from_descriptor(self):
descriptor = MagicMock(
spec=XModuleDescriptor,
runtime=self.system,
location=self.location,
)
error_descriptor = ErrorDescriptor.from_descriptor(
error_descriptor = ErrorBlock.from_descriptor(
descriptor, self.error_msg)
self.assertIsInstance(error_descriptor, ErrorDescriptor)
self.assertIsInstance(error_descriptor, ErrorBlock)
error_descriptor.xmodule_runtime = self.system
context_repr = self.system.render(error_descriptor, STUDENT_VIEW).content
self.assertIn(self.error_msg, context_repr)
self.assertIn(repr(descriptor), context_repr)
class TestNonStaffErrorModule(SetupTestErrorModules):
class TestNonStaffErrorBlock(SetupTestErrorBlock):
"""
Tests for NonStaffErrorModule and NonStaffErrorDescriptor
Tests for NonStaffErrorBlock.
"""
def test_non_staff_error_module_create(self):
descriptor = NonStaffErrorDescriptor.from_xml(
def test_non_staff_error_block_create(self):
descriptor = NonStaffErrorBlock.from_xml(
self.valid_xml,
self.system,
CourseLocationManager(self.course_id)
)
self.assertIsInstance(descriptor, NonStaffErrorDescriptor)
self.assertIsInstance(descriptor, NonStaffErrorBlock)
def test_from_xml_render(self):
descriptor = NonStaffErrorDescriptor.from_xml(
descriptor = NonStaffErrorBlock.from_xml(
self.valid_xml,
self.system,
CourseLocationManager(self.course_id)
@@ -88,16 +88,16 @@ class TestNonStaffErrorModule(SetupTestErrorModules):
self.assertNotIn(self.error_msg, context_repr)
self.assertNotIn(repr(self.valid_xml), context_repr)
def test_error_module_from_descriptor(self):
def test_error_block_from_descriptor(self):
descriptor = MagicMock(
spec=XModuleDescriptor,
runtime=self.system,
location=self.location,
)
error_descriptor = NonStaffErrorDescriptor.from_descriptor(
error_descriptor = NonStaffErrorBlock.from_descriptor(
descriptor, self.error_msg)
self.assertIsInstance(error_descriptor, ErrorDescriptor)
self.assertIsInstance(error_descriptor, ErrorBlock)
error_descriptor.xmodule_runtime = self.system
context_repr = self.system.render(error_descriptor, STUDENT_VIEW).content
self.assertNotIn(self.error_msg, context_repr)
@@ -124,14 +124,14 @@ class TestRuntime(Runtime):
pass
class TestErrorModuleConstruction(unittest.TestCase):
class TestErrorBlockConstruction(unittest.TestCase):
"""
Test that error module construction happens correctly
Test that error block construction happens correctly
"""
def setUp(self):
# pylint: disable=abstract-class-instantiated
super(TestErrorModuleConstruction, self).setUp()
super().setUp()
field_data = DictFieldData({})
self.descriptor = BrokenDescriptor(
TestRuntime(Mock(spec=IdReader), field_data),
@@ -140,29 +140,29 @@ class TestErrorModuleConstruction(unittest.TestCase):
BlockUsageLocator(CourseLocator('org', 'course', 'run'), 'broken', 'name'))
)
self.descriptor.xmodule_runtime = TestRuntime(Mock(spec=IdReader), field_data)
self.descriptor.xmodule_runtime.error_descriptor_class = ErrorDescriptor
self.descriptor.xmodule_runtime.error_descriptor_class = ErrorBlock
self.descriptor.xmodule_runtime.xmodule_instance = None
def test_broken_module(self):
def test_broken_block(self):
"""
Test that when an XModule throws an error during __init__, we
get an ErrorModule back from XModuleDescriptor._xmodule
Test that when an XModule throws an block during __init__, we
get an ErrorBlock back from XModuleDescriptor._xmodule
"""
module = self.descriptor._xmodule
self.assertIsInstance(module, ErrorModule)
self.assertIsInstance(module, ErrorBlock)
@patch.object(ErrorDescriptor, '__init__', Mock(side_effect=TestException))
@patch.object(ErrorBlock, '__init__', Mock(side_effect=TestException))
def test_broken_error_descriptor(self):
"""
Test that a broken error descriptor doesn't cause an infinite loop
Test that a broken block descriptor doesn't cause an infinite loop
"""
with self.assertRaises(TestException):
module = self.descriptor._xmodule
@patch.object(ErrorModule, '__init__', Mock(side_effect=TestException))
def test_broken_error_module(self):
@patch.object(ErrorBlock, '__init__', Mock(side_effect=TestException))
def test_broken_error_block(self):
"""
Test that a broken error module doesn't cause an infinite loop
Test that a broken block module doesn't cause an infinite loop
"""
with self.assertRaises(TestException):
module = self.descriptor._xmodule

View File

@@ -122,7 +122,7 @@ class ImportTestCase(BaseCourseTestCase):
date = Date()
def test_fallback(self):
'''Check that malformed xml loads as an ErrorDescriptor.'''
'''Check that malformed xml loads as an ErrorBlock.'''
# Use an exotic character to also flush out Unicode issues.
bad_xml = u'''<sequential display_name="oops\N{SNOWMAN}"><video url="hi"></sequential>'''
@@ -130,7 +130,7 @@ class ImportTestCase(BaseCourseTestCase):
descriptor = system.process_xml(bad_xml)
self.assertEqual(descriptor.__class__.__name__, 'ErrorDescriptorWithMixins')
self.assertEqual(descriptor.__class__.__name__, 'ErrorBlockWithMixins')
def test_unique_url_names(self):
'''Check that each error gets its very own url_name'''
@@ -164,7 +164,7 @@ class ImportTestCase(BaseCourseTestCase):
descriptor.add_xml_to_node(node)
re_import_descriptor = system.process_xml(etree.tostring(node))
self.assertEqual(re_import_descriptor.__class__.__name__, 'ErrorDescriptorWithMixins')
self.assertEqual(re_import_descriptor.__class__.__name__, 'ErrorBlockWithMixins')
self.assertEqual(descriptor.contents, re_import_descriptor.contents)
self.assertEqual(descriptor.error_msg, re_import_descriptor.error_msg)
@@ -627,7 +627,7 @@ class ImportTestCase(BaseCourseTestCase):
)
def test_error_on_import(self):
'''Check that when load_error_module is false, an exception is raised, rather than returning an ErrorModule'''
'''Check that when load_error_module is false, an exception is raised, rather than returning an ErrorBlock'''
bad_xml = '''<sequential display_name="oops"><video url="hi"></sequential>'''
system = self.get_system(False)

View File

@@ -1304,11 +1304,11 @@ class XModuleDescriptor(XModuleDescriptorToXBlockMixin, HTMLSnippet, ResourceTem
self.xmodule_runtime.xmodule_instance.save()
except Exception: # pylint: disable=broad-except
# xmodule_instance is set by the XModule.__init__. If we had an error after that,
# we need to clean it out so that we can set up the ErrorModule instead
# we need to clean it out so that we can set up the ErrorBlock instead
self.xmodule_runtime.xmodule_instance = None
if isinstance(self, self.xmodule_runtime.error_descriptor_class):
log.exception('Error creating an ErrorModule from an ErrorDescriptor')
log.exception('Error creating an ErrorBlock from an ErrorBlock')
raise
log.exception('Error creating xmodule')
@@ -1317,7 +1317,7 @@ class XModuleDescriptor(XModuleDescriptorToXBlockMixin, HTMLSnippet, ResourceTem
error_msg=exc_info_to_str(sys.exc_info())
)
descriptor.xmodule_runtime = self.xmodule_runtime
self.xmodule_runtime.xmodule_instance = descriptor._xmodule # pylint: disable=protected-access
self.xmodule_runtime.xmodule_instance = descriptor
return self.xmodule_runtime.xmodule_instance
course_id = module_attr('course_id')

View File

@@ -15,7 +15,7 @@ from lazy import lazy
from opaque_keys.edx.django.models import CourseKeyField, UsageKeyField
from pytz import utc
from xmodule.error_module import ErrorDescriptor
from xmodule.error_module import ErrorBlock
from xmodule.modulestore.django import modulestore
log = logging.getLogger("edx.ccx")
@@ -43,7 +43,7 @@ class CustomCourseForEdX(models.Model):
store = modulestore()
with store.bulk_operations(self.course_id):
course = store.get_course(self.course_id)
if not course or isinstance(course, ErrorDescriptor):
if not course or isinstance(course, ErrorBlock):
log.error("CCX {0} from {2} course {1}".format( # pylint: disable=logging-format-interpolation
self.display_name, self.course_id, "broken" if course else "non-existent"
))

View File

@@ -65,7 +65,7 @@ from common.djangoapps.util.milestones_helpers import (
is_prerequisite_courses_enabled
)
from xmodule.course_module import CATALOG_VISIBILITY_ABOUT, CATALOG_VISIBILITY_CATALOG_AND_ABOUT, CourseDescriptor
from xmodule.error_module import ErrorDescriptor
from xmodule.error_module import ErrorBlock
from xmodule.partitions.partitions import NoSuchUserPartitionError, NoSuchUserPartitionGroupError
from xmodule.x_module import XModule
@@ -149,7 +149,7 @@ def has_access(user, action, obj, course_key=None):
if isinstance(obj, CourseOverview):
return _has_access_course(user, action, obj)
if isinstance(obj, ErrorDescriptor):
if isinstance(obj, ErrorBlock):
return _has_access_error_desc(user, action, obj, course_key)
if isinstance(obj, XModule):

View File

@@ -94,7 +94,7 @@ from common.djangoapps.util import milestones_helpers
from common.djangoapps.util.json_request import JsonResponse
from common.djangoapps.xblock_django.user_service import DjangoXBlockUserService
from xmodule.contentstore.django import contentstore
from xmodule.error_module import ErrorDescriptor, NonStaffErrorDescriptor
from xmodule.error_module import ErrorBlock, NonStaffErrorBlock
from xmodule.exceptions import NotFoundError, ProcessingError
from xmodule.lti_module import LTIModule
from xmodule.modulestore.django import modulestore
@@ -322,7 +322,7 @@ def get_module(user, request, usage_key, field_data_cache,
to the user.
Returns: xmodule instance, or None if the user does not have access to the
module. If there's an error, will try to return an instance of ErrorModule
module. If there's an error, will try to return an instance of ErrorBlock
if possible. If not possible, return None.
"""
try:
@@ -845,11 +845,11 @@ def get_module_system_for_user(
system.set(u'user_is_beta_tester', CourseBetaTesterRole(course_id).has_user(user))
system.set(u'days_early_for_beta', descriptor.days_early_for_beta)
# make an ErrorDescriptor -- assuming that the descriptor's system is ok
# make an ErrorBlock -- assuming that the descriptor's system is ok
if has_access(user, u'staff', descriptor.location, course_id):
system.error_descriptor_class = ErrorDescriptor
system.error_descriptor_class = ErrorBlock
else:
system.error_descriptor_class = NonStaffErrorDescriptor
system.error_descriptor_class = NonStaffErrorBlock
return system, field_data

View File

@@ -21,7 +21,7 @@ from openedx.core.djangoapps.content.course_overviews.models import CourseOvervi
from common.djangoapps.student.models import CourseAccessRole, CourseEnrollment
from common.djangoapps.student.roles import CourseRole, OrgRole
from xmodule.course_module import CourseDescriptor
from xmodule.error_module import ErrorDescriptor
from xmodule.error_module import ErrorBlock
from xmodule.x_module import XModule
@@ -113,7 +113,7 @@ class HasStaffAccessToContent(Rule):
# (start with more specific types, then get more general)
if isinstance(instance, (CourseDescriptor, CourseOverview)):
course_key = instance.id
elif isinstance(instance, (ErrorDescriptor, XModule, XBlock)):
elif isinstance(instance, (ErrorBlock, XModule, XBlock)):
course_key = instance.scope_ids.usage_id.course_key
elif isinstance(instance, CourseKey):
course_key = instance
@@ -171,7 +171,7 @@ class HasRolesRule(Rule):
course_key = instance
elif isinstance(instance, (CourseDescriptor, CourseOverview)):
course_key = instance.id
elif isinstance(instance, (ErrorDescriptor, XModule, XBlock)):
elif isinstance(instance, (ErrorBlock, XModule, XBlock)):
course_key = instance.scope_ids.usage_id.course_key
else:
course_key = CourseKey.from_string(str(instance))

View File

@@ -13,7 +13,7 @@ from six import text_type
from lms.djangoapps.courseware.tests.helpers import LoginEnrollmentTestCase
from lms.djangoapps.lms_xblock.field_data import LmsFieldData
from xmodule.error_module import ErrorDescriptor
from xmodule.error_module import ErrorBlock
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_MODULESTORE, ModuleStoreTestCase
from xmodule.modulestore.tests.factories import ToyCourseFactory
@@ -119,7 +119,7 @@ class PageLoaderTestCase(LoginEnrollmentTestCase):
if check_content:
self.assertNotContains(response, "this module is temporarily unavailable")
self.assertNotIsInstance(descriptor, ErrorDescriptor)
self.assertNotIsInstance(descriptor, ErrorBlock)
class TestMongoCoursesLoad(ModuleStoreTestCase, PageLoaderTestCase):

View File

@@ -32,7 +32,7 @@ from openedx.core.lib.cache_utils import request_cached, RequestCache
from common.djangoapps.static_replace.models import AssetBaseUrlConfig
from xmodule import block_metadata_utils, course_metadata_utils
from xmodule.course_module import DEFAULT_START_DATE, CourseDescriptor
from xmodule.error_module import ErrorDescriptor
from xmodule.error_module import ErrorBlock
from xmodule.modulestore.django import modulestore
from xmodule.tabs import CourseTab
@@ -310,7 +310,7 @@ class CourseOverview(TimeStampedModel):
"Error while loading CourseOverview for course {} "
"from the module store: {}",
six.text_type(course_id),
course.error_msg if isinstance(course, ErrorDescriptor) else six.text_type(course)
course.error_msg if isinstance(course, ErrorBlock) else six.text_type(course)
)
else:
log.info(

View File

@@ -36,7 +36,7 @@ from xmodule.course_module import (
CATALOG_VISIBILITY_CATALOG_AND_ABOUT,
CATALOG_VISIBILITY_NONE
)
from xmodule.error_module import ErrorDescriptor
from xmodule.error_module import ErrorBlock
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
@@ -356,13 +356,13 @@ class CourseOverviewTestCase(CatalogIntegrationMixin, ModuleStoreTestCase, Cache
def test_get_errored_course(self):
"""
Test that getting an ErrorDescriptor back from the module store causes
Test that getting an ErrorBlock back from the module store causes
load_from_module_store to raise an IOError.
"""
mock_get_course = mock.Mock(return_value=ErrorDescriptor)
mock_get_course = mock.Mock(return_value=ErrorBlock)
with mock.patch('xmodule.modulestore.mixed.MixedModuleStore.get_course', mock_get_course):
# This mock makes it so when the module store tries to load course data,
# an exception is thrown, which causes get_course to return an ErrorDescriptor,
# an exception is thrown, which causes get_course to return an ErrorBlock,
# which causes get_from_id to raise an IOError.
with self.assertRaises(IOError):
CourseOverview.load_from_module_store(self.store.make_course_key('Non', 'Existent', 'Course'))