Commit 8ece6632 by Chris Dodge

more drive by violation fixes

parent 6d6b3a59
...@@ -6,7 +6,7 @@ from xmodule.x_module import XModule ...@@ -6,7 +6,7 @@ from xmodule.x_module import XModule
from xmodule.raw_module import RawDescriptor from xmodule.raw_module import RawDescriptor
from xmodule.xml_module import XmlDescriptor from xmodule.xml_module import XmlDescriptor
from xmodule.exceptions import InvalidDefinitionError from xmodule.exceptions import InvalidDefinitionError
from xblock.core import String, Scope, Object, BlockScope from xblock.core import String, Scope, Object
DEFAULT = "_DEFAULT_GROUP" DEFAULT = "_DEFAULT_GROUP"
......
import logging import logging
from lxml import etree from lxml import etree
from pkg_resources import resource_string, resource_listdir from pkg_resources import resource_string
from xmodule.x_module import XModule from xmodule.x_module import XModule
from xmodule.raw_module import RawDescriptor from xmodule.raw_module import RawDescriptor
from xmodule.contentstore.content import StaticContent
from xblock.core import Scope, String from xblock.core import Scope, String
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -25,7 +24,6 @@ class AnnotatableModule(AnnotatableFields, XModule): ...@@ -25,7 +24,6 @@ class AnnotatableModule(AnnotatableFields, XModule):
css = {'scss': [resource_string(__name__, 'css/annotatable/display.scss')]} css = {'scss': [resource_string(__name__, 'css/annotatable/display.scss')]}
icon_class = 'annotatable' icon_class = 'annotatable'
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
XModule.__init__(self, *args, **kwargs) XModule.__init__(self, *args, **kwargs)
......
...@@ -106,10 +106,10 @@ class CombinedOpenEndedModule(CombinedOpenEndedFields, XModule): ...@@ -106,10 +106,10 @@ class CombinedOpenEndedModule(CombinedOpenEndedFields, XModule):
icon_class = 'problem' icon_class = 'problem'
js = {'coffee': js = {'coffee':
[resource_string(__name__, 'js/src/combinedopenended/display.coffee'), [resource_string(__name__, 'js/src/combinedopenended/display.coffee'),
resource_string(__name__, 'js/src/collapsible.coffee'), resource_string(__name__, 'js/src/collapsible.coffee'),
resource_string(__name__, 'js/src/javascript_loader.coffee'), resource_string(__name__, 'js/src/javascript_loader.coffee'),
]} ]}
js_module_name = "CombinedOpenEnded" js_module_name = "CombinedOpenEnded"
css = {'scss': [resource_string(__name__, 'css/combinedopenended/display.scss')]} css = {'scss': [resource_string(__name__, 'css/combinedopenended/display.scss')]}
...@@ -219,5 +219,5 @@ class CombinedOpenEndedDescriptor(CombinedOpenEndedFields, RawDescriptor): ...@@ -219,5 +219,5 @@ class CombinedOpenEndedDescriptor(CombinedOpenEndedFields, RawDescriptor):
stores_state = True stores_state = True
has_score = True has_score = True
always_recalculate_grades=True always_recalculate_grades = True
template_dir_name = "combinedopenended" template_dir_name = "combinedopenended"
...@@ -10,7 +10,7 @@ from pkg_resources import resource_string ...@@ -10,7 +10,7 @@ from pkg_resources import resource_string
from xmodule.x_module import XModule from xmodule.x_module import XModule
from xmodule.modulestore import Location from xmodule.modulestore import Location
from xmodule.seq_module import SequenceDescriptor from xmodule.seq_module import SequenceDescriptor
from xblock.core import String, Scope, List from xblock.core import Scope, List
from xmodule.modulestore.exceptions import ItemNotFoundError from xmodule.modulestore.exceptions import ItemNotFoundError
...@@ -60,8 +60,7 @@ class ConditionalModule(ConditionalFields, XModule): ...@@ -60,8 +60,7 @@ class ConditionalModule(ConditionalFields, XModule):
js = {'coffee': [resource_string(__name__, 'js/src/javascript_loader.coffee'), js = {'coffee': [resource_string(__name__, 'js/src/javascript_loader.coffee'),
resource_string(__name__, 'js/src/conditional/display.coffee'), resource_string(__name__, 'js/src/conditional/display.coffee'),
resource_string(__name__, 'js/src/collapsible.coffee'), resource_string(__name__, 'js/src/collapsible.coffee'),
]}
]}
js_module_name = "Conditional" js_module_name = "Conditional"
css = {'scss': [resource_string(__name__, 'css/capa/display.scss')]} css = {'scss': [resource_string(__name__, 'css/capa/display.scss')]}
...@@ -82,12 +81,11 @@ class ConditionalModule(ConditionalFields, XModule): ...@@ -82,12 +81,11 @@ class ConditionalModule(ConditionalFields, XModule):
xml_value = self.descriptor.xml_attributes.get(xml_attr) xml_value = self.descriptor.xml_attributes.get(xml_attr)
if xml_value: if xml_value:
return xml_value, attr_name return xml_value, attr_name
raise Exception('Error in conditional module: unknown condition "%s"' raise Exception('Error in conditional module: unknown condition "%s"' % xml_attr)
% xml_attr)
def is_condition_satisfied(self): def is_condition_satisfied(self):
self.required_modules = [self.system.get_module(descriptor) for self.required_modules = [self.system.get_module(descriptor) for
descriptor in self.descriptor.get_required_module_descriptors()] descriptor in self.descriptor.get_required_module_descriptors()]
xml_value, attr_name = self._get_condition() xml_value, attr_name = self._get_condition()
...@@ -111,7 +109,7 @@ class ConditionalModule(ConditionalFields, XModule): ...@@ -111,7 +109,7 @@ class ConditionalModule(ConditionalFields, XModule):
def get_html(self): def get_html(self):
# Calculate html ids of dependencies # Calculate html ids of dependencies
self.required_html_ids = [descriptor.location.html_id() for self.required_html_ids = [descriptor.location.html_id() for
descriptor in self.descriptor.get_required_module_descriptors()] descriptor in self.descriptor.get_required_module_descriptors()]
return self.system.render_template('conditional_ajax.html', { return self.system.render_template('conditional_ajax.html', {
'element_id': self.location.html_id(), 'element_id': self.location.html_id(),
...@@ -130,7 +128,7 @@ class ConditionalModule(ConditionalFields, XModule): ...@@ -130,7 +128,7 @@ class ConditionalModule(ConditionalFields, XModule):
context = {'module': self, context = {'module': self,
'message': message} 'message': message}
html = self.system.render_template('conditional_module.html', html = self.system.render_template('conditional_module.html',
context) context)
return json.dumps({'html': [html], 'message': bool(message)}) return json.dumps({'html': [html], 'message': bool(message)})
html = [child.get_html() for child in self.get_display_items()] html = [child.get_html() for child in self.get_display_items()]
...@@ -145,7 +143,7 @@ class ConditionalModule(ConditionalFields, XModule): ...@@ -145,7 +143,7 @@ class ConditionalModule(ConditionalFields, XModule):
class_priority = ['video', 'problem'] class_priority = ['video', 'problem']
child_classes = [self.system.get_module(child_descriptor).get_icon_class() child_classes = [self.system.get_module(child_descriptor).get_icon_class()
for child_descriptor in self.descriptor.get_children()] for child_descriptor in self.descriptor.get_children()]
for c in class_priority: for c in class_priority:
if c in child_classes: if c in child_classes:
new_class = c new_class = c
...@@ -163,7 +161,6 @@ class ConditionalDescriptor(ConditionalFields, SequenceDescriptor): ...@@ -163,7 +161,6 @@ class ConditionalDescriptor(ConditionalFields, SequenceDescriptor):
stores_state = True stores_state = True
has_score = False has_score = False
@staticmethod @staticmethod
def parse_sources(xml_element, system, return_descriptor=False): def parse_sources(xml_element, system, return_descriptor=False):
"""Parse xml_element 'sources' attr and: """Parse xml_element 'sources' attr and:
......
...@@ -60,8 +60,9 @@ class StaticContent(object): ...@@ -60,8 +60,9 @@ class StaticContent(object):
@staticmethod @staticmethod
def get_id_from_location(location): def get_id_from_location(location):
return {'tag': location.tag, 'org': location.org, 'course': location.course, return {'tag': location.tag, 'org': location.org, 'course': location.course,
'category': location.category, 'name': location.name, 'category': location.category, 'name': location.name,
'revision': location.revision} 'revision': location.revision}
@staticmethod @staticmethod
def get_location_from_path(path): def get_location_from_path(path):
# remove leading / character if it is there one # remove leading / character if it is there one
...@@ -80,8 +81,6 @@ class StaticContent(object): ...@@ -80,8 +81,6 @@ class StaticContent(object):
return StaticContent.get_url_path_from_location(loc) return StaticContent.get_url_path_from_location(loc)
class ContentStore(object): class ContentStore(object):
''' '''
Abstraction for all ContentStore providers (e.g. MongoDB) Abstraction for all ContentStore providers (e.g. MongoDB)
...@@ -120,7 +119,7 @@ class ContentStore(object): ...@@ -120,7 +119,7 @@ class ContentStore(object):
thumbnail_name = StaticContent.generate_thumbnail_name(content.location.name) thumbnail_name = StaticContent.generate_thumbnail_name(content.location.name)
thumbnail_file_location = StaticContent.compute_location(content.location.org, content.location.course, thumbnail_file_location = StaticContent.compute_location(content.location.org, content.location.course,
thumbnail_name, is_thumbnail=True) thumbnail_name, is_thumbnail=True)
# if we're uploading an image, then let's generate a thumbnail so that we can # if we're uploading an image, then let's generate a thumbnail so that we can
# serve it up when needed without having to rescale on the fly # serve it up when needed without having to rescale on the fly
......
from __future__ import absolute_import from __future__ import absolute_import
from importlib import import_module from importlib import import_module
from os import environ
from django.conf import settings from django.conf import settings
......
...@@ -6,7 +6,6 @@ from gridfs.errors import NoFile ...@@ -6,7 +6,6 @@ from gridfs.errors import NoFile
from xmodule.modulestore.mongo import location_to_query, Location from xmodule.modulestore.mongo import location_to_query, Location
from xmodule.contentstore.content import XASSET_LOCATION_TAG from xmodule.contentstore.content import XASSET_LOCATION_TAG
import sys
import logging import logging
from .content import StaticContent, ContentStore from .content import StaticContent, ContentStore
...@@ -26,7 +25,6 @@ class MongoContentStore(ContentStore): ...@@ -26,7 +25,6 @@ class MongoContentStore(ContentStore):
self.fs = gridfs.GridFS(_db) self.fs = gridfs.GridFS(_db)
self.fs_files = _db["fs.files"] # the underlying collection GridFS uses self.fs_files = _db["fs.files"] # the underlying collection GridFS uses
def save(self, content): def save(self, content):
id = content.get_id() id = content.get_id()
...@@ -34,7 +32,8 @@ class MongoContentStore(ContentStore): ...@@ -34,7 +32,8 @@ class MongoContentStore(ContentStore):
self.delete(id) self.delete(id)
with self.fs.new_file(_id=id, filename=content.get_url_path(), content_type=content.content_type, with self.fs.new_file(_id=id, filename=content.get_url_path(), content_type=content.content_type,
displayname=content.name, thumbnail_location=content.thumbnail_location, import_path=content.import_path) as fp: displayname=content.name, thumbnail_location=content.thumbnail_location,
import_path=content.import_path) as fp:
fp.write(content.data) fp.write(content.data)
...@@ -49,8 +48,9 @@ class MongoContentStore(ContentStore): ...@@ -49,8 +48,9 @@ class MongoContentStore(ContentStore):
try: try:
with self.fs.get(id) as fp: with self.fs.get(id) as fp:
return StaticContent(location, fp.displayname, fp.content_type, fp.read(), return StaticContent(location, fp.displayname, fp.content_type, fp.read(),
fp.uploadDate, thumbnail_location=fp.thumbnail_location if hasattr(fp, 'thumbnail_location') else None, fp.uploadDate,
import_path=fp.import_path if hasattr(fp, 'import_path') else None) thumbnail_location=fp.thumbnail_location if hasattr(fp, 'thumbnail_location') else None,
import_path=fp.import_path if hasattr(fp, 'import_path') else None)
except NoFile: except NoFile:
raise NotFoundError() raise NotFoundError()
...@@ -102,7 +102,7 @@ class MongoContentStore(ContentStore): ...@@ -102,7 +102,7 @@ class MongoContentStore(ContentStore):
] ]
''' '''
course_filter = Location(XASSET_LOCATION_TAG, category="asset" if not get_thumbnails else "thumbnail", course_filter = Location(XASSET_LOCATION_TAG, category="asset" if not get_thumbnails else "thumbnail",
course=location.course, org=location.org) course=location.course, org=location.org)
# 'borrow' the function 'location_to_query' from the Mongo modulestore implementation # 'borrow' the function 'location_to_query' from the Mongo modulestore implementation
items = self.fs_files.find(location_to_query(course_filter)) items = self.fs_files.find(location_to_query(course_filter))
return list(items) return list(items)
...@@ -211,7 +211,6 @@ class CourseDescriptor(CourseFields, SequenceDescriptor): ...@@ -211,7 +211,6 @@ class CourseDescriptor(CourseFields, SequenceDescriptor):
template_dir_name = 'course' template_dir_name = 'course'
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(CourseDescriptor, self).__init__(*args, **kwargs) super(CourseDescriptor, self).__init__(*args, **kwargs)
...@@ -421,7 +420,6 @@ class CourseDescriptor(CourseFields, SequenceDescriptor): ...@@ -421,7 +420,6 @@ class CourseDescriptor(CourseFields, SequenceDescriptor):
policy['GRADE_CUTOFFS'] = value policy['GRADE_CUTOFFS'] = value
self.grading_policy = policy self.grading_policy = policy
@property @property
def lowest_passing_grade(self): def lowest_passing_grade(self):
return min(self._grading_policy['GRADE_CUTOFFS'].values()) return min(self._grading_policy['GRADE_CUTOFFS'].values())
...@@ -460,7 +458,6 @@ class CourseDescriptor(CourseFields, SequenceDescriptor): ...@@ -460,7 +458,6 @@ class CourseDescriptor(CourseFields, SequenceDescriptor):
else: else:
return self.cohort_config.get("auto_cohort_groups", []) return self.cohort_config.get("auto_cohort_groups", [])
@property @property
def top_level_discussion_topic_ids(self): def top_level_discussion_topic_ids(self):
""" """
...@@ -469,7 +466,6 @@ class CourseDescriptor(CourseFields, SequenceDescriptor): ...@@ -469,7 +466,6 @@ class CourseDescriptor(CourseFields, SequenceDescriptor):
topics = self.discussion_topics topics = self.discussion_topics
return [d["id"] for d in topics.values()] return [d["id"] for d in topics.values()]
@property @property
def cohorted_discussions(self): def cohorted_discussions(self):
""" """
...@@ -483,8 +479,6 @@ class CourseDescriptor(CourseFields, SequenceDescriptor): ...@@ -483,8 +479,6 @@ class CourseDescriptor(CourseFields, SequenceDescriptor):
return set(config.get("cohorted_discussions", [])) return set(config.get("cohorted_discussions", []))
@property @property
def is_newish(self): def is_newish(self):
""" """
...@@ -585,7 +579,6 @@ class CourseDescriptor(CourseFields, SequenceDescriptor): ...@@ -585,7 +579,6 @@ class CourseDescriptor(CourseFields, SequenceDescriptor):
yield module_descriptor yield module_descriptor
for c in self.get_children(): for c in self.get_children():
sections = []
for s in c.get_children(): for s in c.get_children():
if s.lms.graded: if s.lms.graded:
xmoduledescriptors = list(yield_descriptor_descendents(s)) xmoduledescriptors = list(yield_descriptor_descendents(s))
...@@ -601,8 +594,7 @@ class CourseDescriptor(CourseFields, SequenceDescriptor): ...@@ -601,8 +594,7 @@ class CourseDescriptor(CourseFields, SequenceDescriptor):
all_descriptors.append(s) all_descriptors.append(s)
return {'graded_sections': graded_sections, return {'graded_sections': graded_sections,
'all_descriptors': all_descriptors, } 'all_descriptors': all_descriptors, }
@staticmethod @staticmethod
def make_id(org, course, url_name): def make_id(org, course, url_name):
......
from lxml import etree from pkg_resources import resource_string
from pkg_resources import resource_string, resource_listdir
from xmodule.x_module import XModule from xmodule.x_module import XModule
from xmodule.raw_module import RawDescriptor from xmodule.raw_module import RawDescriptor
...@@ -16,12 +15,11 @@ class DiscussionFields(object): ...@@ -16,12 +15,11 @@ class DiscussionFields(object):
class DiscussionModule(DiscussionFields, XModule): class DiscussionModule(DiscussionFields, XModule):
js = {'coffee': js = {'coffee':
[resource_string(__name__, 'js/src/time.coffee'), [resource_string(__name__, 'js/src/time.coffee'),
resource_string(__name__, 'js/src/discussion/display.coffee')] resource_string(__name__, 'js/src/discussion/display.coffee')]
} }
js_module_name = "InlineDiscussion" js_module_name = "InlineDiscussion"
def get_html(self): def get_html(self):
context = { context = {
'discussion_id': self.discussion_id, 'discussion_id': self.discussion_id,
......
...@@ -38,7 +38,7 @@ class ErrorModule(ErrorFields, XModule): ...@@ -38,7 +38,7 @@ class ErrorModule(ErrorFields, XModule):
'staff_access': True, 'staff_access': True,
'data': self.contents, 'data': self.contents,
'error': self.error_msg, 'error': self.error_msg,
}) })
class NonStaffErrorModule(ErrorFields, XModule): class NonStaffErrorModule(ErrorFields, XModule):
...@@ -51,7 +51,7 @@ class NonStaffErrorModule(ErrorFields, XModule): ...@@ -51,7 +51,7 @@ class NonStaffErrorModule(ErrorFields, XModule):
'staff_access': False, 'staff_access': False,
'data': "", 'data': "",
'error': "", 'error': "",
}) })
class ErrorDescriptor(ErrorFields, JSONEditingDescriptor): class ErrorDescriptor(ErrorFields, JSONEditingDescriptor):
......
class InvalidDefinitionError(Exception): class InvalidDefinitionError(Exception):
pass pass
class NotFoundError(Exception): class NotFoundError(Exception):
pass pass
class ProcessingError(Exception): class ProcessingError(Exception):
''' '''
An error occurred while processing a request to the XModule. An error occurred while processing a request to the XModule.
......
...@@ -51,6 +51,8 @@ class Date(ModelType): ...@@ -51,6 +51,8 @@ class Date(ModelType):
TIMEDELTA_REGEX = re.compile(r'^((?P<days>\d+?) day(?:s?))?(\s)?((?P<hours>\d+?) hour(?:s?))?(\s)?((?P<minutes>\d+?) minute(?:s)?)?(\s)?((?P<seconds>\d+?) second(?:s)?)?$') TIMEDELTA_REGEX = re.compile(r'^((?P<days>\d+?) day(?:s?))?(\s)?((?P<hours>\d+?) hour(?:s?))?(\s)?((?P<minutes>\d+?) minute(?:s)?)?(\s)?((?P<seconds>\d+?) second(?:s)?)?$')
class Timedelta(ModelType): class Timedelta(ModelType):
def from_json(self, time_str): def from_json(self, time_str):
""" """
......
...@@ -107,7 +107,7 @@ class FolditModule(FolditFields, XModule): ...@@ -107,7 +107,7 @@ class FolditModule(FolditFields, XModule):
'show_leader': showleader, 'show_leader': showleader,
'folditbasic': self.get_basicpuzzles_html(), 'folditbasic': self.get_basicpuzzles_html(),
'folditchallenge': self.get_challenge_html() 'folditchallenge': self.get_challenge_html()
} }
return self.system.render_template('foldit.html', context) return self.system.render_template('foldit.html', context)
...@@ -124,7 +124,7 @@ class FolditModule(FolditFields, XModule): ...@@ -124,7 +124,7 @@ class FolditModule(FolditFields, XModule):
'success': self.is_complete(), 'success': self.is_complete(),
'goal_level': goal_level, 'goal_level': goal_level,
'completed': self.completed_puzzles(), 'completed': self.completed_puzzles(),
} }
return self.system.render_template('folditbasic.html', context) return self.system.render_template('folditbasic.html', context)
def get_challenge_html(self): def get_challenge_html(self):
...@@ -149,7 +149,6 @@ class FolditModule(FolditFields, XModule): ...@@ -149,7 +149,6 @@ class FolditModule(FolditFields, XModule):
return 1 return 1
class FolditDescriptor(FolditFields, XmlDescriptor, EditingDescriptor): class FolditDescriptor(FolditFields, XmlDescriptor, EditingDescriptor):
""" """
Module for adding Foldit problems to courses Module for adding Foldit problems to courses
......
...@@ -6,7 +6,6 @@ Passes settings.MODULESTORE as kwargs to MongoModuleStore ...@@ -6,7 +6,6 @@ Passes settings.MODULESTORE as kwargs to MongoModuleStore
from __future__ import absolute_import from __future__ import absolute_import
from importlib import import_module from importlib import import_module
from os import environ
from django.conf import settings from django.conf import settings
...@@ -38,7 +37,7 @@ def modulestore(name='default'): ...@@ -38,7 +37,7 @@ def modulestore(name='default'):
for key in FUNCTION_KEYS: for key in FUNCTION_KEYS:
if key in options: if key in options:
options[key] = load_function(options[key]) options[key] = load_function(options[key])
_MODULESTORES[name] = class_( _MODULESTORES[name] = class_(
**options **options
) )
......
...@@ -9,9 +9,10 @@ INHERITABLE_METADATA = ( ...@@ -9,9 +9,10 @@ INHERITABLE_METADATA = (
# intended to be set per-course, but can be overridden in for specific # intended to be set per-course, but can be overridden in for specific
# elements. Can be a float. # elements. Can be a float.
'days_early_for_beta', 'days_early_for_beta',
'giturl' # for git edit link 'giturl' # for git edit link
) )
def compute_inherited_metadata(descriptor): def compute_inherited_metadata(descriptor):
"""Given a descriptor, traverse all of its descendants and do metadata """Given a descriptor, traverse all of its descendants and do metadata
inheritance. Should be called on a CourseDescriptor after importing a inheritance. Should be called on a CourseDescriptor after importing a
......
...@@ -7,7 +7,6 @@ from collections import namedtuple ...@@ -7,7 +7,6 @@ from collections import namedtuple
from fs.osfs import OSFS from fs.osfs import OSFS
from itertools import repeat from itertools import repeat
from path import path from path import path
from datetime import datetime
from operator import attrgetter from operator import attrgetter
from uuid import uuid4 from uuid import uuid4
...@@ -31,11 +30,13 @@ log = logging.getLogger(__name__) ...@@ -31,11 +30,13 @@ log = logging.getLogger(__name__)
# there is only one revision for each item. Once we start versioning inside the CMS, # there is only one revision for each item. Once we start versioning inside the CMS,
# that assumption will have to change # that assumption will have to change
def get_course_id_no_run(location): def get_course_id_no_run(location):
''' '''
''' '''
return "/".join([location.org, location.course]) return "/".join([location.org, location.course])
class MongoKeyValueStore(KeyValueStore): class MongoKeyValueStore(KeyValueStore):
""" """
A KeyValueStore that maps keyed data access to one of the 3 data areas A KeyValueStore that maps keyed data access to one of the 3 data areas
...@@ -130,8 +131,8 @@ class CachingDescriptorSystem(MakoDescriptorSystem): ...@@ -130,8 +131,8 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
render_template: a function for rendering templates, as per render_template: a function for rendering templates, as per
MakoDescriptorSystem MakoDescriptorSystem
""" """
super(CachingDescriptorSystem, self).__init__( super(CachingDescriptorSystem, self).__init__(self.load_item, resources_fs,
self.load_item, resources_fs, error_tracker, render_template) error_tracker, render_template)
self.modulestore = modulestore self.modulestore = modulestore
self.module_data = module_data self.module_data = module_data
self.default_class = default_class self.default_class = default_class
...@@ -140,7 +141,6 @@ class CachingDescriptorSystem(MakoDescriptorSystem): ...@@ -140,7 +141,6 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
self.course_id = None self.course_id = None
self.cached_metadata = cached_metadata self.cached_metadata = cached_metadata
def load_item(self, location): def load_item(self, location):
""" """
Return an XModule instance for the specified location Return an XModule instance for the specified location
...@@ -223,7 +223,7 @@ class MongoModuleStore(ModuleStoreBase): ...@@ -223,7 +223,7 @@ class MongoModuleStore(ModuleStoreBase):
def __init__(self, host, db, collection, fs_root, render_template, def __init__(self, host, db, collection, fs_root, render_template,
port=27017, default_class=None, port=27017, default_class=None,
error_tracker=null_error_tracker, error_tracker=null_error_tracker,
user=None, password=None, request_cache=None, user=None, password=None, request_cache=None,
metadata_inheritance_cache_subsystem=None, **kwargs): metadata_inheritance_cache_subsystem=None, **kwargs):
ModuleStoreBase.__init__(self) ModuleStoreBase.__init__(self)
...@@ -468,7 +468,7 @@ class MongoModuleStore(ModuleStoreBase): ...@@ -468,7 +468,7 @@ class MongoModuleStore(ModuleStoreBase):
# if we are loading a course object, if we're not prefetching children (depth != 0) then don't # if we are loading a course object, if we're not prefetching children (depth != 0) then don't
# bother with the metadata inheritance # bother with the metadata inheritance
return [self._load_item(item, data_cache, return [self._load_item(item, data_cache,
apply_cached_metadata=(item['location']['category']!='course' or depth !=0)) for item in items] apply_cached_metadata=(item['location']['category'] != 'course' or depth != 0)) for item in items]
def get_courses(self): def get_courses(self):
''' '''
...@@ -710,10 +710,9 @@ class MongoModuleStore(ModuleStoreBase): ...@@ -710,10 +710,9 @@ class MongoModuleStore(ModuleStoreBase):
course.tabs = [tab for tab in existing_tabs if tab.get('url_slug') != location.name] course.tabs = [tab for tab in existing_tabs if tab.get('url_slug') != location.name]
self.update_metadata(course.location, own_metadata(course)) self.update_metadata(course.location, own_metadata(course))
self.collection.remove({'_id': Location(location).dict()}, # Must include this to avoid the django debug toolbar (which defines the deprecated "safe=False")
# Must include this to avoid the django debug toolbar (which defines the deprecated "safe=False") # from overriding our default value set in the init method.
# from overriding our default value set in the init method. self.collection.remove({'_id': Location(location).dict()}, safe=self.collection.safe)
safe=self.collection.safe)
# recompute (and update) the metadata inheritance tree which is cached # recompute (and update) the metadata inheritance tree which is cached
self.refresh_cached_metadata_inheritance_tree(Location(location)) self.refresh_cached_metadata_inheritance_tree(Location(location))
self.fire_updated_modulestore_signal(get_course_id_no_run(Location(location)), Location(location)) self.fire_updated_modulestore_signal(get_course_id_no_run(Location(location)), Location(location))
...@@ -724,7 +723,7 @@ class MongoModuleStore(ModuleStoreBase): ...@@ -724,7 +723,7 @@ class MongoModuleStore(ModuleStoreBase):
''' '''
location = Location.ensure_fully_specified(location) location = Location.ensure_fully_specified(location)
items = self.collection.find({'definition.children': location.url()}, items = self.collection.find({'definition.children': location.url()},
{'_id': True}) {'_id': True})
return [i['_id'] for i in items] return [i['_id'] for i in items]
def get_errored_courses(self): def get_errored_courses(self):
......
...@@ -3,7 +3,7 @@ from itertools import repeat ...@@ -3,7 +3,7 @@ from itertools import repeat
from xmodule.course_module import CourseDescriptor from xmodule.course_module import CourseDescriptor
from .exceptions import (ItemNotFoundError, NoPathToItem) from .exceptions import (ItemNotFoundError, NoPathToItem)
from . import ModuleStore, Location from . import Location
def path_to_location(modulestore, course_id, location): def path_to_location(modulestore, course_id, location):
...@@ -106,7 +106,7 @@ def path_to_location(modulestore, course_id, location): ...@@ -106,7 +106,7 @@ def path_to_location(modulestore, course_id, location):
position_list = [] position_list = []
for path_index in range(2, n - 1): for path_index in range(2, n - 1):
category = path[path_index].category category = path[path_index].category
if category == 'sequential' or category == 'videosequence': if category == 'sequential' or category == 'videosequence':
section_desc = modulestore.get_instance(course_id, path[path_index]) section_desc = modulestore.get_instance(course_id, path[path_index])
child_locs = [c.location for c in section_desc.get_children()] child_locs = [c.location for c in section_desc.get_children()]
# positions are 1-indexed, and should be strings to be consistent with # positions are 1-indexed, and should be strings to be consistent with
......
import logging
from xmodule.contentstore.content import StaticContent from xmodule.contentstore.content import StaticContent
from xmodule.modulestore import Location from xmodule.modulestore import Location
from xmodule.modulestore.mongo import MongoModuleStore from xmodule.modulestore.mongo import MongoModuleStore
...@@ -33,11 +32,11 @@ def clone_course(modulestore, contentstore, source_location, dest_location, dele ...@@ -33,11 +32,11 @@ def clone_course(modulestore, contentstore, source_location, dest_location, dele
if original_loc.category != 'course': if original_loc.category != 'course':
module.location = module.location._replace(tag=dest_location.tag, org=dest_location.org, module.location = module.location._replace(tag=dest_location.tag, org=dest_location.org,
course=dest_location.course) course=dest_location.course)
else: else:
# on the course module we also have to update the module name # on the course module we also have to update the module name
module.location = module.location._replace(tag=dest_location.tag, org=dest_location.org, module.location = module.location._replace(tag=dest_location.tag, org=dest_location.org,
course=dest_location.course, name=dest_location.name) course=dest_location.course, name=dest_location.name)
print "Cloning module {0} to {1}....".format(original_loc, module.location) print "Cloning module {0} to {1}....".format(original_loc, module.location)
...@@ -49,9 +48,9 @@ def clone_course(modulestore, contentstore, source_location, dest_location, dele ...@@ -49,9 +48,9 @@ def clone_course(modulestore, contentstore, source_location, dest_location, dele
for child_loc_url in module.children: for child_loc_url in module.children:
child_loc = Location(child_loc_url) child_loc = Location(child_loc_url)
child_loc = child_loc._replace( child_loc = child_loc._replace(
tag=dest_location.tag, tag=dest_location.tag,
org=dest_location.org, org=dest_location.org,
course=dest_location.course course=dest_location.course
) )
new_children.append(child_loc.url()) new_children.append(child_loc.url())
...@@ -67,7 +66,7 @@ def clone_course(modulestore, contentstore, source_location, dest_location, dele ...@@ -67,7 +66,7 @@ def clone_course(modulestore, contentstore, source_location, dest_location, dele
thumb_loc = Location(thumb["_id"]) thumb_loc = Location(thumb["_id"])
content = contentstore.find(thumb_loc) content = contentstore.find(thumb_loc)
content.location = content.location._replace(org=dest_location.org, content.location = content.location._replace(org=dest_location.org,
course=dest_location.course) course=dest_location.course)
print "Cloning thumbnail {0} to {1}".format(thumb_loc, content.location) print "Cloning thumbnail {0} to {1}".format(thumb_loc, content.location)
...@@ -80,12 +79,12 @@ def clone_course(modulestore, contentstore, source_location, dest_location, dele ...@@ -80,12 +79,12 @@ def clone_course(modulestore, contentstore, source_location, dest_location, dele
asset_loc = Location(asset["_id"]) asset_loc = Location(asset["_id"])
content = contentstore.find(asset_loc) content = contentstore.find(asset_loc)
content.location = content.location._replace(org=dest_location.org, content.location = content.location._replace(org=dest_location.org,
course=dest_location.course) course=dest_location.course)
# be sure to update the pointer to the thumbnail # be sure to update the pointer to the thumbnail
if content.thumbnail_location is not None: if content.thumbnail_location is not None:
content.thumbnail_location = content.thumbnail_location._replace(org=dest_location.org, content.thumbnail_location = content.thumbnail_location._replace(org=dest_location.org,
course=dest_location.course) course=dest_location.course)
print "Cloning asset {0} to {1}".format(asset_loc, content.location) print "Cloning asset {0} to {1}".format(asset_loc, content.location)
...@@ -94,7 +93,7 @@ def clone_course(modulestore, contentstore, source_location, dest_location, dele ...@@ -94,7 +93,7 @@ def clone_course(modulestore, contentstore, source_location, dest_location, dele
return True return True
def delete_course(modulestore, contentstore, source_location, commit = False): def delete_course(modulestore, contentstore, source_location, commit=False):
# first check to see if the modulestore is Mongo backed # first check to see if the modulestore is Mongo backed
if not isinstance(modulestore, MongoModuleStore): if not isinstance(modulestore, MongoModuleStore):
raise Exception("Expected a MongoModuleStore in the runtime. Aborting....") raise Exception("Expected a MongoModuleStore in the runtime. Aborting....")
......
...@@ -75,7 +75,7 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem): ...@@ -75,7 +75,7 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):
# tags that really need unique names--they store (or should store) state. # tags that really need unique names--they store (or should store) state.
need_uniq_names = ('problem', 'sequential', 'video', 'course', 'chapter', need_uniq_names = ('problem', 'sequential', 'video', 'course', 'chapter',
'videosequence', 'poll_question', 'timelimit') 'videosequence', 'poll_question', 'timelimit')
attr = xml_data.attrib attr = xml_data.attrib
tag = xml_data.tag tag = xml_data.tag
...@@ -169,7 +169,6 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem): ...@@ -169,7 +169,6 @@ class ImportSystem(XMLParsingSystem, MakoDescriptorSystem):
# Didn't load properly. Fall back on loading as an error # Didn't load properly. Fall back on loading as an error
# descriptor. This should never error due to formatting. # descriptor. This should never error due to formatting.
msg = "Error loading from xml. " + str(err)[:200] msg = "Error loading from xml. " + str(err)[:200]
log.warning(msg) log.warning(msg)
# Normally, we don't want lots of exception traces in our logs from common # Normally, we don't want lots of exception traces in our logs from common
...@@ -367,7 +366,7 @@ class XMLModuleStore(ModuleStoreBase): ...@@ -367,7 +366,7 @@ class XMLModuleStore(ModuleStoreBase):
if org is None: if org is None:
msg = ("No 'org' attribute set for course in {dir}. " msg = ("No 'org' attribute set for course in {dir}. "
"Using default 'edx'".format(dir=course_dir)) "Using default 'edx'".format(dir=course_dir))
log.warning(msg) log.warning(msg)
tracker(msg) tracker(msg)
org = 'edx' org = 'edx'
...@@ -376,10 +375,10 @@ class XMLModuleStore(ModuleStoreBase): ...@@ -376,10 +375,10 @@ class XMLModuleStore(ModuleStoreBase):
if course is None: if course is None:
msg = ("No 'course' attribute set for course in {dir}." msg = ("No 'course' attribute set for course in {dir}."
" Using default '{default}'".format( " Using default '{default}'".format(dir=course_dir,
dir=course_dir, default=course_dir
default=course_dir )
)) )
log.warning(msg) log.warning(msg)
tracker(msg) tracker(msg)
course = course_dir course = course_dir
...@@ -445,7 +444,6 @@ class XMLModuleStore(ModuleStoreBase): ...@@ -445,7 +444,6 @@ class XMLModuleStore(ModuleStoreBase):
log.debug('========> Done with course import from {0}'.format(course_dir)) log.debug('========> Done with course import from {0}'.format(course_dir))
return course_descriptor return course_descriptor
def load_extra_content(self, system, course_descriptor, category, base_dir, course_dir, url_name): def load_extra_content(self, system, course_descriptor, category, base_dir, course_dir, url_name):
self._load_extra_content(system, course_descriptor, category, base_dir, course_dir) self._load_extra_content(system, course_descriptor, category, base_dir, course_dir)
...@@ -453,7 +451,6 @@ class XMLModuleStore(ModuleStoreBase): ...@@ -453,7 +451,6 @@ class XMLModuleStore(ModuleStoreBase):
if os.path.isdir(base_dir / url_name): if os.path.isdir(base_dir / url_name):
self._load_extra_content(system, course_descriptor, category, base_dir / url_name, course_dir) self._load_extra_content(system, course_descriptor, category, base_dir / url_name, course_dir)
def _load_extra_content(self, system, course_descriptor, category, path, course_dir): def _load_extra_content(self, system, course_descriptor, category, path, course_dir):
for filepath in glob.glob(path / '*'): for filepath in glob.glob(path / '*'):
...@@ -480,7 +477,6 @@ class XMLModuleStore(ModuleStoreBase): ...@@ -480,7 +477,6 @@ class XMLModuleStore(ModuleStoreBase):
logging.exception("Failed to load {0}. Skipping... Exception: {1}".format(filepath, str(e))) logging.exception("Failed to load {0}. Skipping... Exception: {1}".format(filepath, str(e)))
system.error_tracker("ERROR: " + str(e)) system.error_tracker("ERROR: " + str(e))
def get_instance(self, course_id, location, depth=0): def get_instance(self, course_id, location, depth=0):
""" """
Returns an XModuleDescriptor instance for the item at Returns an XModuleDescriptor instance for the item at
...@@ -542,7 +538,6 @@ class XMLModuleStore(ModuleStoreBase): ...@@ -542,7 +538,6 @@ class XMLModuleStore(ModuleStoreBase):
return items return items
def get_courses(self, depth=0): def get_courses(self, depth=0):
""" """
Returns a list of course descriptors. If there were errors on loading, Returns a list of course descriptors. If there were errors on loading,
...@@ -567,7 +562,6 @@ class XMLModuleStore(ModuleStoreBase): ...@@ -567,7 +562,6 @@ class XMLModuleStore(ModuleStoreBase):
""" """
raise NotImplementedError("XMLModuleStores are read-only") raise NotImplementedError("XMLModuleStores are read-only")
def update_children(self, location, children): def update_children(self, location, children):
""" """
Set the children for the item specified by the location to Set the children for the item specified by the location to
...@@ -578,7 +572,6 @@ class XMLModuleStore(ModuleStoreBase): ...@@ -578,7 +572,6 @@ class XMLModuleStore(ModuleStoreBase):
""" """
raise NotImplementedError("XMLModuleStores are read-only") raise NotImplementedError("XMLModuleStores are read-only")
def update_metadata(self, location, metadata): def update_metadata(self, location, metadata):
""" """
Set the metadata for the item specified by the location to Set the metadata for the item specified by the location to
......
...@@ -316,7 +316,7 @@ def import_module(module, store, course_data_path, static_content_store, allow_n ...@@ -316,7 +316,7 @@ def import_module(module, store, course_data_path, static_content_store, allow_n
# Note the dropped element closing tag. This causes the LMS to fail when rendering modules - that's # Note the dropped element closing tag. This causes the LMS to fail when rendering modules - that's
# no good, so we have to do this kludge # no good, so we have to do this kludge
if isinstance(module_data, str) or isinstance(module_data, unicode): # some module 'data' fields are non strings which blows up the link traversal code if isinstance(module_data, str) or isinstance(module_data, unicode): # some module 'data' fields are non strings which blows up the link traversal code
lxml_rewrite_links(module_data, lambda link: verify_content_links(module, course_data_path, static_content_store, link, remap_dict)) lxml_rewrite_links(module_data, lambda link: verify_content_links(module, course_data_path, static_content_store, link, remap_dict))
for key in remap_dict.keys(): for key in remap_dict.keys():
module_data = module_data.replace(key, remap_dict[key]) module_data = module_data.replace(key, remap_dict[key])
......
...@@ -28,6 +28,7 @@ def lazyproperty(fn): ...@@ -28,6 +28,7 @@ def lazyproperty(fn):
""" """
attr_name = '_lazy_' + fn.__name__ attr_name = '_lazy_' + fn.__name__
@property @property
def _lazyprop(self): def _lazyprop(self):
if not hasattr(self, attr_name): if not hasattr(self, attr_name):
......
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