Load modules from the mongo modulestore as errordescriptors if creating a regular descriptor fails, but leave the location the same
This commit is contained in:
@@ -7,6 +7,7 @@ from lxml import etree
|
||||
from xmodule.x_module import XModule
|
||||
from xmodule.editing_module import JSONEditingDescriptor
|
||||
from xmodule.errortracker import exc_info_to_str
|
||||
from xmodule.modulestore import Location
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -52,14 +53,18 @@ class ErrorDescriptor(JSONEditingDescriptor):
|
||||
module_class = ErrorModule
|
||||
|
||||
@classmethod
|
||||
def _construct(self, system, contents, error_msg, org=None, course=None):
|
||||
def _construct(self, system, contents, error_msg, location):
|
||||
|
||||
# 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,
|
||||
# it will be written out with the original url_name.
|
||||
url_name = hashlib.sha1(contents).hexdigest()
|
||||
if location.name is None:
|
||||
location = location._replace(
|
||||
category='error',
|
||||
# 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,
|
||||
# it will be written out with the original url_name.
|
||||
name=hashlib.sha1(contents).hexdigest()
|
||||
)
|
||||
|
||||
definition = {
|
||||
'data': {
|
||||
@@ -68,12 +73,8 @@ class ErrorDescriptor(JSONEditingDescriptor):
|
||||
}
|
||||
}
|
||||
|
||||
# TODO (vshnayder): Do we need a unique slug here? Just pick a random
|
||||
# 64-bit num?
|
||||
location = ['i4x', org, course, 'error', url_name]
|
||||
|
||||
# real metadata stays in the content, but add a display name
|
||||
metadata = {'display_name': 'Error ' + url_name}
|
||||
metadata = {'display_name': 'Error: ' + location.name}
|
||||
super(ErrorDescriptor, self).__init__(
|
||||
system,
|
||||
definition,
|
||||
@@ -81,6 +82,21 @@ class ErrorDescriptor(JSONEditingDescriptor):
|
||||
metadata=metadata
|
||||
)
|
||||
|
||||
def get_context(self):
|
||||
return {
|
||||
'module': self,
|
||||
'data': self.definition['data']['contents'],
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, json_data, system, error_msg='Error not available'):
|
||||
return cls(
|
||||
system,
|
||||
json.dumps(json_data, indent=4),
|
||||
error_msg,
|
||||
location=Location(json_data['location']),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_descriptor(cls, descriptor, error_msg='Error not available'):
|
||||
return cls._construct(
|
||||
@@ -89,7 +105,8 @@ class ErrorDescriptor(JSONEditingDescriptor):
|
||||
'definition': descriptor.definition,
|
||||
'metadata': descriptor.metadata,
|
||||
}, indent=4),
|
||||
error_msg
|
||||
error_msg,
|
||||
location=descriptor.location,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@@ -119,7 +136,7 @@ class ErrorDescriptor(JSONEditingDescriptor):
|
||||
# Save the error to display later--overrides other problems
|
||||
error_msg = exc_info_to_str(sys.exc_info())
|
||||
|
||||
return cls._construct(system, xml_data, error_msg, org=org, course=course)
|
||||
return cls._construct(system, xml_data, error_msg, location=Location('i4x', org, course, None, None))
|
||||
|
||||
def export_to_xml(self, resource_fs):
|
||||
'''
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import pymongo
|
||||
import sys
|
||||
|
||||
from bson.son import SON
|
||||
from fs.osfs import OSFS
|
||||
@@ -6,13 +7,14 @@ from itertools import repeat
|
||||
from path import path
|
||||
|
||||
from importlib import import_module
|
||||
from xmodule.errortracker import null_error_tracker
|
||||
from xmodule.errortracker import null_error_tracker, exc_info_to_str
|
||||
from xmodule.x_module import XModuleDescriptor
|
||||
from xmodule.mako_module import MakoDescriptorSystem
|
||||
from xmodule.error_module import ErrorDescriptor
|
||||
|
||||
from . import ModuleStoreBase, Location
|
||||
from .exceptions import (ItemNotFoundError,
|
||||
NoPathToItem, DuplicateItemError)
|
||||
DuplicateItemError)
|
||||
|
||||
# TODO (cpennington): This code currently operates under the assumption that
|
||||
# there is only one revision for each item. Once we start versioning inside the CMS,
|
||||
@@ -57,7 +59,14 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
|
||||
# TODO (vshnayder): metadata inheritance is somewhat broken because mongo, doesn't
|
||||
# always load an entire course. We're punting on this until after launch, and then
|
||||
# will build a proper course policy framework.
|
||||
return XModuleDescriptor.load_from_json(json_data, self, self.default_class)
|
||||
try:
|
||||
return XModuleDescriptor.load_from_json(json_data, self, self.default_class)
|
||||
except:
|
||||
return ErrorDescriptor.from_json(
|
||||
json_data,
|
||||
self,
|
||||
error_msg=exc_info_to_str(sys.exc_info())
|
||||
)
|
||||
|
||||
|
||||
def location_to_query(location):
|
||||
@@ -154,7 +163,7 @@ class MongoModuleStore(ModuleStoreBase):
|
||||
"""
|
||||
data_dir = item.get('metadata', {}).get('data_dir', item['location']['course'])
|
||||
root = self.fs_root / data_dir
|
||||
|
||||
|
||||
if not root.isdir():
|
||||
root.mkdir()
|
||||
|
||||
@@ -267,7 +276,6 @@ class MongoModuleStore(ModuleStoreBase):
|
||||
if result['n'] == 0:
|
||||
raise ItemNotFoundError(location)
|
||||
|
||||
|
||||
def update_item(self, location, data):
|
||||
"""
|
||||
Set the data in the item specified by the location to
|
||||
@@ -313,7 +321,7 @@ class MongoModuleStore(ModuleStoreBase):
|
||||
'''
|
||||
location = Location.ensure_fully_specified(location)
|
||||
# Check that it's actually in this modulestore.
|
||||
item = self._find_one(location)
|
||||
self._find_one(location)
|
||||
# now get the parents
|
||||
items = self.collection.find({'definition.children': location.url()},
|
||||
{'_id': True})
|
||||
|
||||
Reference in New Issue
Block a user