From cff93d324bc932cd5f6ee3448f6dcfef29d11251 Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Thu, 25 Jul 2013 00:50:42 -0400 Subject: [PATCH] WIP --- cms/djangoapps/contentstore/views/preview.py | 4 ++-- common/djangoapps/contentserver/middleware.py | 5 +++++ common/djangoapps/static_replace/__init__.py | 2 +- common/djangoapps/student/views.py | 1 + common/djangoapps/xmodule_modifiers.py | 4 ++-- .../xmodule/xmodule/contentstore/content.py | 6 ++++++ .../lib/xmodule/xmodule/modulestore/mixed.py | 21 +++++++++++++++++-- lms/djangoapps/branding/__init__.py | 5 +++-- lms/djangoapps/courseware/courses.py | 11 +++++----- lms/djangoapps/courseware/module_render.py | 8 ++++++- lms/djangoapps/staticbook/views.py | 2 +- lms/envs/cms/mixed_dev.py | 3 +-- 12 files changed, 53 insertions(+), 19 deletions(-) diff --git a/cms/djangoapps/contentstore/views/preview.py b/cms/djangoapps/contentstore/views/preview.py index 0591ff0dc4..bbbf3d5f0a 100644 --- a/cms/djangoapps/contentstore/views/preview.py +++ b/cms/djangoapps/contentstore/views/preview.py @@ -116,7 +116,7 @@ def preview_module_system(request, preview_id, descriptor): get_module=partial(load_preview_module, request, preview_id), render_template=render_from_lms, debug=True, - replace_urls=partial(static_replace.replace_static_urls, data_directory=None, course_namespace=descriptor.location), + replace_urls=partial(static_replace.replace_static_urls, data_directory=None, course_id=course_id), user=request.user, xblock_model_data=preview_model_data, can_execute_unsafe_code=(lambda: can_execute_unsafe_code(course_id)), @@ -158,7 +158,7 @@ def load_preview_module(request, preview_id, descriptor): module.get_html = replace_static_urls( module.get_html, getattr(module, 'data_dir', module.location.course), - course_namespace=Location([module.location.tag, module.location.org, module.location.course, None, None]) + course_id=module.location.org+'/'+module.location.course+'/REPLACE_WITH_RUN' ) module.get_html = save_module( diff --git a/common/djangoapps/contentserver/middleware.py b/common/djangoapps/contentserver/middleware.py index d89e3fdd23..733e1c30e3 100644 --- a/common/djangoapps/contentserver/middleware.py +++ b/common/djangoapps/contentserver/middleware.py @@ -6,11 +6,14 @@ from xmodule.modulestore import InvalidLocationError from cache_toolbox.core import get_cached_content, set_cached_content from xmodule.exceptions import NotFoundError +import logging + class StaticContentServer(object): def process_request(self, request): # look to see if the request is prefixed with 'c4x' tag if request.path.startswith('/' + XASSET_LOCATION_TAG + '/'): + logging.debug('**** path = {0}'.format(request.path)) try: loc = StaticContent.get_location_from_path(request.path) except InvalidLocationError: @@ -24,8 +27,10 @@ class StaticContentServer(object): if content is None: # nope, not in cache, let's fetch from DB try: + logging.debug('!!!! loc = {0}'.format(loc)) content = contentstore().find(loc, as_stream=True) except NotFoundError: + logging.debug('**** NOT FOUND') response = HttpResponse() response.status_code = 404 return response diff --git a/common/djangoapps/static_replace/__init__.py b/common/djangoapps/static_replace/__init__.py index c08db34349..63c576cdd2 100644 --- a/common/djangoapps/static_replace/__init__.py +++ b/common/djangoapps/static_replace/__init__.py @@ -124,7 +124,7 @@ def replace_static_urls(text, data_directory, course_id=None): else: # if not, then assume it's courseware specific content and then look in the # Mongo-backed database - url = StaticContent.convert_legacy_static_url(rest, course_id) + url = StaticContent.convert_legacy_static_url_with_course_id(rest, course_id) # Otherwise, look the file up in staticfiles_storage, and append the data directory if needed else: course_path = "/".join((data_directory, rest)) diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index 7795a13c47..4d59b5cc66 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -95,6 +95,7 @@ def index(request, extra_context={}, user=None): courses = sort_by_announcement(courses) context = {'courses': courses} + context.update(extra_context) return render_to_response('index.html', context) diff --git a/common/djangoapps/xmodule_modifiers.py b/common/djangoapps/xmodule_modifiers.py index dd40b5139d..6b73395599 100644 --- a/common/djangoapps/xmodule_modifiers.py +++ b/common/djangoapps/xmodule_modifiers.py @@ -76,7 +76,7 @@ def replace_course_urls(get_html, course_id): return _get_html -def replace_static_urls(get_html, data_dir, course_namespace=None): +def replace_static_urls(get_html, data_dir, course_id=None): """ Updates the supplied module with a new get_html function that wraps the old get_html function and substitutes urls of the form /static/... @@ -85,7 +85,7 @@ def replace_static_urls(get_html, data_dir, course_namespace=None): @wraps(get_html) def _get_html(): - return static_replace.replace_static_urls(get_html(), data_dir, course_namespace) + return static_replace.replace_static_urls(get_html(), data_dir, course_id) return _get_html diff --git a/common/lib/xmodule/xmodule/contentstore/content.py b/common/lib/xmodule/xmodule/contentstore/content.py index eaf3f48dea..cdecfd1af5 100644 --- a/common/lib/xmodule/xmodule/contentstore/content.py +++ b/common/lib/xmodule/xmodule/contentstore/content.py @@ -100,6 +100,12 @@ class StaticContent(object): loc = StaticContent.compute_location(course_namespace.org, course_namespace.course, path) return StaticContent.get_url_path_from_location(loc) + @staticmethod + def convert_legacy_static_url_with_course_id(path, course_id): + org, course_num, run = course_id.split("/") + loc = StaticContent.compute_location(org, course_num, path) + return StaticContent.get_url_path_from_location(loc) + def stream_data(self): yield self._data diff --git a/common/lib/xmodule/xmodule/modulestore/mixed.py b/common/lib/xmodule/xmodule/modulestore/mixed.py index 253852d1db..85ba95af48 100644 --- a/common/lib/xmodule/xmodule/modulestore/mixed.py +++ b/common/lib/xmodule/xmodule/modulestore/mixed.py @@ -8,6 +8,9 @@ IMPORTANT: This modulestore is experimental AND INCOMPLETE. Therefore this shoul from . import ModuleStoreBase from django import create_modulestore_instance +import logging + +log = logging.getLogger(__name__) class MixedModuleStore(ModuleStoreBase): @@ -23,6 +26,9 @@ class MixedModuleStore(ModuleStoreBase): self.modulestores = {} self.mappings = mappings + if 'default' not in stores: + raise Exception('Missing a default modulestore in the MixedModuleStore __init__ method.') + for key in stores: self.modulestores[key] = create_modulestore_instance(stores[key]['ENGINE'], stores[key]['OPTIONS']) @@ -32,7 +38,8 @@ class MixedModuleStore(ModuleStoreBase): For a given course_id, look in the mapping table and see if it has been pinned to a particular modulestore """ - return self.mappings.get(course_id, self.mappings['default']) + mapping = self.mappings.get(course_id, 'default') + return self.modulestores[mapping] def has_item(self, course_id, location): return self._get_modulestore_for_courseid(course_id).has_item(course_id, location) @@ -96,7 +103,8 @@ class MixedModuleStore(ModuleStoreBase): ''' courses = [] for key in self.modulestores: - courses.append(self.modulestores[key].get_courses) + courses = courses + (self.modulestores[key].get_courses()) + return courses def get_course(self, course_id): @@ -125,3 +133,12 @@ class MixedModuleStore(ModuleStoreBase): 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) + + def get_errored_courses(self): + """ + Return a dictionary of course_dir -> [(msg, exception_str)], for each + course_dir where course loading failed. + """ + errs = {} + for store in self.modulestores.values(): + errs.update(store.get_errored_courses()) diff --git a/lms/djangoapps/branding/__init__.py b/lms/djangoapps/branding/__init__.py index b2ac874020..0bdc69bd0d 100644 --- a/lms/djangoapps/branding/__init__.py +++ b/lms/djangoapps/branding/__init__.py @@ -1,4 +1,3 @@ - from xmodule.modulestore.django import modulestore from xmodule.course_module import CourseDescriptor from django.conf import settings @@ -15,7 +14,9 @@ def get_visible_courses(domain=None): """ Return the set of CourseDescriptors that should be visible in this branded instance """ - courses = [c for c in modulestore().get_courses() + _courses = modulestore().get_courses() + + courses = [c for c in _courses if isinstance(c, CourseDescriptor)] courses = sorted(courses, key=lambda course: course.number) diff --git a/lms/djangoapps/courseware/courses.py b/lms/djangoapps/courseware/courses.py index 34de2eb958..5f31658cf2 100644 --- a/lms/djangoapps/courseware/courses.py +++ b/lms/djangoapps/courseware/courses.py @@ -8,10 +8,9 @@ from django.http import Http404 from .module_render import get_module from xmodule.course_module import CourseDescriptor -from xmodule.modulestore import Location, MONGO_MODULESTORE_TYPE +from xmodule.modulestore import Location, XML_MODULESTORE_TYPE from xmodule.modulestore.django import modulestore from xmodule.contentstore.content import StaticContent -from xmodule.modulestore.xml import XMLModuleStore from xmodule.modulestore.exceptions import ItemNotFoundError, InvalidLocationError from courseware.model_data import ModelDataCache from static_replace import replace_static_urls @@ -82,12 +81,12 @@ def get_opt_course_with_access(user, course_id, action): def course_image_url(course): """Try to look up the image url for the course. If it's not found, log an error and return the dead link""" - if modulestore().get_modulestore_type(course.course_id) == MONGO_MODULESTORE_TYPE: + if modulestore().get_modulestore_type(course.location.course_id) == XML_MODULESTORE_TYPE: return '/static/' + course.data_dir + "/images/course_image.jpg" else: loc = course.location._replace(tag='c4x', category='asset', name='images_course_image.jpg') - path = StaticContent.get_url_path_from_location(loc) - return path + _path = StaticContent.get_url_path_from_location(loc) + return _path def find_file(fs, dirs, filename): @@ -243,7 +242,7 @@ def get_course_syllabus_section(course, section_key): return replace_static_urls( htmlFile.read().decode('utf-8'), getattr(course, 'data_dir', None), - course_namespace=course.location + course_id=course.location.course_id ) except ResourceNotFoundError: log.exception("Missing syllabus section {key} in course {url}".format( diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index 0a48c56f87..a851a6d8f4 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -332,6 +332,7 @@ def get_module_for_descriptor_internal(user, descriptor, model_data_cache, cours # TODO (cpennington): When modules are shared between courses, the static # prefix is going to have to be specific to the module, not the directory # that the xml was loaded from + system = ModuleSystem( track_function=track_function, render_template=render_to_string, @@ -347,7 +348,7 @@ def get_module_for_descriptor_internal(user, descriptor, model_data_cache, cours replace_urls=partial( static_replace.replace_static_urls, data_directory=getattr(descriptor, 'data_dir', None), - course_namespace=descriptor.location._replace(category=None, name=None), + course_id=course_id, ), replace_course_urls=partial( static_replace.replace_course_urls, @@ -368,6 +369,7 @@ def get_module_for_descriptor_internal(user, descriptor, model_data_cache, cours cache=cache, can_execute_unsafe_code=(lambda: can_execute_unsafe_code(course_id)), ) + # pass position specified in URL to module through ModuleSystem system.set('position', position) system.set('DEBUG', settings.DEBUG) @@ -405,8 +407,12 @@ def get_module_for_descriptor_internal(user, descriptor, model_data_cache, cours module.get_html = replace_static_urls( _get_html, getattr(descriptor, 'data_dir', None), +<<<<<<< HEAD course_namespace=module.location._replace(category=None, name=None) ) +======= + course_id=course_id) +>>>>>>> WIP # Allow URLs of the form '/course/' refer to the root of multicourse directory # hierarchy of this course diff --git a/lms/djangoapps/staticbook/views.py b/lms/djangoapps/staticbook/views.py index 9ed14bfb6c..25475eb36a 100644 --- a/lms/djangoapps/staticbook/views.py +++ b/lms/djangoapps/staticbook/views.py @@ -50,7 +50,7 @@ def remap_static_url(original_url, course): output_url = replace_static_urls( input_url, getattr(course, 'data_dir', None), - course_namespace=course.location, + coures_id=course.location.course_id, ) # strip off the quotes again... return output_url[1:-1] diff --git a/lms/envs/cms/mixed_dev.py b/lms/envs/cms/mixed_dev.py index 22fd5eeb0e..9a1a3a4cb8 100644 --- a/lms/envs/cms/mixed_dev.py +++ b/lms/envs/cms/mixed_dev.py @@ -9,8 +9,7 @@ MODULESTORE = { 'ENGINE': 'xmodule.modulestore.mixed.MixedModuleStore', 'OPTIONS': { 'mappings': { - '6.002/a/a': 'xml', - '6.002/b/b': 'xml' + 'MITx/2.01x/2013_Spring': 'xml' }, 'stores': { 'xml': {