Commit 82988972 by Chris Dodge

WIP: added a get_modulestore_type. Added some unit tests. changed over the…

WIP: added a get_modulestore_type. Added some unit tests. changed over the isinstance() with respect to modulestores to use this get_modulestore_type()
parent b5253b52
...@@ -6,7 +6,7 @@ from staticfiles import finders ...@@ -6,7 +6,7 @@ from staticfiles import finders
from django.conf import settings from django.conf import settings
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.modulestore.xml import XMLModuleStore from xmodule.modulestore import XML_MODULESTORE_TYPE
from xmodule.contentstore.content import StaticContent from xmodule.contentstore.content import StaticContent
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -90,7 +90,7 @@ def replace_course_urls(text, course_id): ...@@ -90,7 +90,7 @@ def replace_course_urls(text, course_id):
return re.sub(_url_replace_regex('/course/'), replace_course_url, text) return re.sub(_url_replace_regex('/course/'), replace_course_url, text)
def replace_static_urls(text, data_directory, course_namespace=None): def replace_static_urls(text, data_directory, course_id=None):
""" """
Replace /static/$stuff urls either with their correct url as generated by collectstatic, Replace /static/$stuff urls either with their correct url as generated by collectstatic,
(/static/$md5_hashed_stuff) or by the course-specific content static url (/static/$md5_hashed_stuff) or by the course-specific content static url
...@@ -99,7 +99,7 @@ def replace_static_urls(text, data_directory, course_namespace=None): ...@@ -99,7 +99,7 @@ def replace_static_urls(text, data_directory, course_namespace=None):
text: The source text to do the substitution in text: The source text to do the substitution in
data_directory: The directory in which course data is stored data_directory: The directory in which course data is stored
course_namespace: The course identifier used to distinguish static content for this course in studio course_id: The course identifier used to distinguish static content for this course in studio
""" """
def replace_static_url(match): def replace_static_url(match):
...@@ -116,7 +116,7 @@ def replace_static_urls(text, data_directory, course_namespace=None): ...@@ -116,7 +116,7 @@ def replace_static_urls(text, data_directory, course_namespace=None):
if settings.DEBUG and finders.find(rest, True): if settings.DEBUG and finders.find(rest, True):
return original return original
# if we're running with a MongoBacked store course_namespace is not None, then use studio style urls # if we're running with a MongoBacked store course_namespace is not None, then use studio style urls
elif course_namespace is not None and not isinstance(modulestore(), XMLModuleStore): elif course_id and modulestore().get_modulestore_type(course_id) != XML_MODULESTORE_TYPE:
# first look in the static file pipeline and see if we are trying to reference # first look in the static file pipeline and see if we are trying to reference
# a piece of static content which is in the mitx repo (e.g. JS associated with an xmodule) # a piece of static content which is in the mitx repo (e.g. JS associated with an xmodule)
if staticfiles_storage.exists(rest): if staticfiles_storage.exists(rest):
...@@ -124,7 +124,7 @@ def replace_static_urls(text, data_directory, course_namespace=None): ...@@ -124,7 +124,7 @@ def replace_static_urls(text, data_directory, course_namespace=None):
else: else:
# if not, then assume it's courseware specific content and then look in the # if not, then assume it's courseware specific content and then look in the
# Mongo-backed database # Mongo-backed database
url = StaticContent.convert_legacy_static_url(rest, course_namespace) url = StaticContent.convert_legacy_static_url(rest, course_id)
# Otherwise, look the file up in staticfiles_storage, and append the data directory if needed # Otherwise, look the file up in staticfiles_storage, and append the data directory if needed
else: else:
course_path = "/".join((data_directory, rest)) course_path = "/".join((data_directory, rest))
......
...@@ -14,6 +14,8 @@ from bson.son import SON ...@@ -14,6 +14,8 @@ from bson.son import SON
log = logging.getLogger('mitx.' + 'modulestore') log = logging.getLogger('mitx.' + 'modulestore')
MONGO_MODULESTORE_TYPE = 'mongo'
XML_MODULESTORE_TYPE = 'xml'
URL_RE = re.compile(""" URL_RE = re.compile("""
(?P<tag>[^:]+)://? (?P<tag>[^:]+)://?
...@@ -391,6 +393,13 @@ class ModuleStore(object): ...@@ -391,6 +393,13 @@ class ModuleStore(object):
''' '''
raise NotImplementedError raise NotImplementedError
def get_modulestore_type(self, course_id):
"""
Returns a type which identifies which modulestore is servicing the given
course_id. The return can be either "xml" (for XML based courses) or "mongo" for MongoDB backed courses
"""
raise NotImplementedError
class ModuleStoreBase(ModuleStore): class ModuleStoreBase(ModuleStore):
''' '''
......
...@@ -118,3 +118,10 @@ class MixedModuleStore(ModuleStoreBase): ...@@ -118,3 +118,10 @@ class MixedModuleStore(ModuleStoreBase):
""" """
for store in self.modulestores.values(): for store in self.modulestores.values():
store.set_modulestore_configuration(config_dict) store.set_modulestore_configuration(config_dict)
def get_modulestore_type(self, course_id):
"""
Returns a type which identifies which modulestore is servicing the given
course_id. The return can be either "xml" (for XML based courses) or "mongo" for MongoDB backed courses
"""
return self._get_modulestore_for_courseid(course_id).get_modulestore_type(course_id)
...@@ -32,7 +32,7 @@ from xmodule.error_module import ErrorDescriptor ...@@ -32,7 +32,7 @@ from xmodule.error_module import ErrorDescriptor
from xblock.runtime import DbModel, KeyValueStore, InvalidScopeError from xblock.runtime import DbModel, KeyValueStore, InvalidScopeError
from xblock.core import Scope from xblock.core import Scope
from xmodule.modulestore import ModuleStoreBase, Location, namedtuple_to_son from xmodule.modulestore import ModuleStoreBase, Location, namedtuple_to_son, MONGO_MODULESTORE_TYPE
from xmodule.modulestore.exceptions import ItemNotFoundError from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.modulestore.inheritance import own_metadata, INHERITABLE_METADATA, inherit_metadata from xmodule.modulestore.inheritance import own_metadata, INHERITABLE_METADATA, inherit_metadata
...@@ -841,6 +841,13 @@ class MongoModuleStore(ModuleStoreBase): ...@@ -841,6 +841,13 @@ class MongoModuleStore(ModuleStoreBase):
{'_id': True}) {'_id': True})
return [i['_id'] for i in items] return [i['_id'] for i in items]
def get_modulestore_type(self, course_id):
"""
Returns a type which identifies which modulestore is servicing the given
course_id. The return can be either "xml" (for XML based courses) or "mongo" for MongoDB backed courses
"""
return MONGO_MODULESTORE_TYPE
def _create_new_model_data(self, category, location, definition_data, metadata): def _create_new_model_data(self, category, location, definition_data, metadata):
""" """
To instantiate a new xmodule which will be saved latter, set up the dbModel and kvs To instantiate a new xmodule which will be saved latter, set up the dbModel and kvs
...@@ -854,9 +861,9 @@ class MongoModuleStore(ModuleStoreBase): ...@@ -854,9 +861,9 @@ class MongoModuleStore(ModuleStoreBase):
) )
class_ = XModuleDescriptor.load_class( class_ = XModuleDescriptor.load_class(
category, category,
self.default_class self.default_class
) )
model_data = DbModel(kvs, class_, None, MongoUsage(None, location)) model_data = DbModel(kvs, class_, None, MongoUsage(None, location))
model_data['category'] = category model_data['category'] = category
model_data['location'] = location model_data['location'] = location
......
...@@ -45,8 +45,7 @@ class TestMongoModuleStore(object): ...@@ -45,8 +45,7 @@ class TestMongoModuleStore(object):
@staticmethod @staticmethod
def initdb(): def initdb():
# connect to the db # connect to the db
store = MongoModuleStore(HOST, DB, COLLECTION, FS_ROOT, RENDER_TEMPLATE, store = MongoModuleStore(HOST, DB, COLLECTION, FS_ROOT, RENDER_TEMPLATE, default_class=DEFAULT_CLASS)
default_class=DEFAULT_CLASS)
# Explicitly list the courses to load (don't want the big one) # Explicitly list the courses to load (don't want the big one)
courses = ['toy', 'simple'] courses = ['toy', 'simple']
import_from_xml(store, DATA_DIR, courses) import_from_xml(store, DATA_DIR, courses)
...@@ -71,6 +70,10 @@ class TestMongoModuleStore(object): ...@@ -71,6 +70,10 @@ class TestMongoModuleStore(object):
pprint([Location(i['_id']).url() for i in ids]) pprint([Location(i['_id']).url() for i in ids])
def test_mongo_modulestore_type(self):
store = MongoModuleStore(HOST, DB, COLLECTION, FS_ROOT, RENDER_TEMPLATE, default_class=DEFAULT_CLASS)
assert_equals(store.get_modulestore_type('foo/bar/baz'), 'mongo')
def test_get_courses(self): def test_get_courses(self):
'''Make sure the course objects loaded properly''' '''Make sure the course objects loaded properly'''
courses = self.store.get_courses() courses = self.store.get_courses()
...@@ -117,6 +120,7 @@ class TestMongoModuleStore(object): ...@@ -117,6 +120,7 @@ class TestMongoModuleStore(object):
'{0} is a template course'.format(course) '{0} is a template course'.format(course)
) )
class TestMongoKeyValueStore(object): class TestMongoKeyValueStore(object):
def setUp(self): def setUp(self):
......
import os.path import os.path
from nose.tools import assert_raises from nose.tools import assert_raises, assert_equals
from xmodule.course_module import CourseDescriptor from xmodule.course_module import CourseDescriptor
from xmodule.modulestore.xml import XMLModuleStore from xmodule.modulestore.xml import XMLModuleStore
from xmodule.modulestore import XML_MODULESTORE_TYPE
from xmodule.tests import DATA_DIR from .test_modulestore import check_path_to_location
from xmodule.modulestore.tests.test_modulestore import check_path_to_location from . import DATA_DIR
class TestXMLModuleStore(object): class TestXMLModuleStore(object):
...@@ -19,6 +20,10 @@ class TestXMLModuleStore(object): ...@@ -19,6 +20,10 @@ class TestXMLModuleStore(object):
check_path_to_location(modulestore) check_path_to_location(modulestore)
def test_xml_modulestore_type(self):
store = XMLModuleStore(DATA_DIR, course_dirs=['toy', 'simple'])
assert_equals(store.get_modulestore_type('foo/bar/baz'), XML_MODULESTORE_TYPE)
def test_unicode_chars_in_xml_content(self): def test_unicode_chars_in_xml_content(self):
# edX/full/6.002_Spring_2012 has non-ASCII chars, and during # edX/full/6.002_Spring_2012 has non-ASCII chars, and during
# uniquification of names, would raise a UnicodeError. It no longer does. # uniquification of names, would raise a UnicodeError. It no longer does.
......
...@@ -21,7 +21,7 @@ from xmodule.x_module import XModuleDescriptor, XMLParsingSystem ...@@ -21,7 +21,7 @@ from xmodule.x_module import XModuleDescriptor, XMLParsingSystem
from xmodule.html_module import HtmlDescriptor from xmodule.html_module import HtmlDescriptor
from . import ModuleStoreBase, Location from . import ModuleStoreBase, Location, XML_MODULESTORE_TYPE
from .exceptions import ItemNotFoundError from .exceptions import ItemNotFoundError
from .inheritance import compute_inherited_metadata from .inheritance import compute_inherited_metadata
...@@ -601,3 +601,10 @@ class XMLModuleStore(ModuleStoreBase): ...@@ -601,3 +601,10 @@ class XMLModuleStore(ModuleStoreBase):
raise ItemNotFoundError("{0} not in {1}".format(location, course_id)) raise ItemNotFoundError("{0} not in {1}".format(location, course_id))
return self.parent_trackers[course_id].parents(location) return self.parent_trackers[course_id].parents(location)
def get_modulestore_type(self, course_id):
"""
Returns a type which identifies which modulestore is servicing the given
course_id. The return can be either "xml" (for XML based courses) or "mongo" for MongoDB backed courses
"""
return XML_MODULESTORE_TYPE
...@@ -161,12 +161,7 @@ class VideoModule(VideoFields, XModule): ...@@ -161,12 +161,7 @@ class VideoModule(VideoFields, XModule):
return json.dumps({'position': self.position}) return json.dumps({'position': self.position})
def get_html(self): def get_html(self):
if isinstance(modulestore(), MongoModuleStore): caption_asset_path = "/static/subs/"
caption_asset_path = StaticContent.get_base_url_path_for_course_assets(self.location) + '/subs_'
else:
# VS[compat]
# cdodge: filesystem static content support.
caption_asset_path = "/static/subs/"
get_ext = lambda filename: filename.rpartition('.')[-1] get_ext = lambda filename: filename.rpartition('.')[-1]
sources = {get_ext(src): src for src in self.html5_sources} sources = {get_ext(src): src for src in self.html5_sources}
......
...@@ -8,7 +8,7 @@ from django.http import Http404 ...@@ -8,7 +8,7 @@ from django.http import Http404
from .module_render import get_module from .module_render import get_module
from xmodule.course_module import CourseDescriptor from xmodule.course_module import CourseDescriptor
from xmodule.modulestore import Location from xmodule.modulestore import Location, MONGO_MODULESTORE_TYPE
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.contentstore.content import StaticContent from xmodule.contentstore.content import StaticContent
from xmodule.modulestore.xml import XMLModuleStore from xmodule.modulestore.xml import XMLModuleStore
...@@ -82,7 +82,7 @@ def get_opt_course_with_access(user, course_id, action): ...@@ -82,7 +82,7 @@ def get_opt_course_with_access(user, course_id, action):
def course_image_url(course): def course_image_url(course):
"""Try to look up the image url for the course. If it's not found, """Try to look up the image url for the course. If it's not found,
log an error and return the dead link""" log an error and return the dead link"""
if isinstance(modulestore(), XMLModuleStore): if modulestore().get_modulestore_type(course.course_id) == MONGO_MODULESTORE_TYPE:
return '/static/' + course.data_dir + "/images/course_image.jpg" return '/static/' + course.data_dir + "/images/course_image.jpg"
else: else:
loc = course.location._replace(tag='c4x', category='asset', name='images_course_image.jpg') loc = course.location._replace(tag='c4x', category='asset', name='images_course_image.jpg')
......
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