Commit bf4ae6b7 by Calen Pennington

Load modules from the mongo modulestore as errordescriptors if creating a…

Load modules from the mongo modulestore as errordescriptors if creating a regular descriptor fails, but leave the location the same
parent d4377d4a
......@@ -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):
# 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()
def _construct(self, system, contents, error_msg, location):
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):
'''
......
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})
......
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