Merge branch 'master' of github.com:MITx/mitx into fix/cdodge/export-draft-modules
Conflicts: common/lib/xmodule/xmodule/modulestore/xml_importer.py
This commit is contained in:
@@ -7,18 +7,16 @@ from path import path
|
||||
from xblock.core import Scope
|
||||
|
||||
from .xml import XMLModuleStore, ImportSystem, ParentTracker
|
||||
from .exceptions import DuplicateItemError
|
||||
from xmodule.modulestore import Location
|
||||
from xmodule.contentstore.content import StaticContent, XASSET_SRCREF_PREFIX
|
||||
from xmodule.contentstore.content import StaticContent
|
||||
from .inheritance import own_metadata
|
||||
from xmodule.errortracker import make_error_tracker
|
||||
from collections import defaultdict
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def import_static_content(modules, course_loc, course_data_path, static_content_store, target_location_namespace,
|
||||
subpath='static', verbose=False):
|
||||
subpath='static', verbose=False):
|
||||
|
||||
remap_dict = {}
|
||||
|
||||
@@ -109,10 +107,10 @@ def import_module_from_xml(modulestore, static_content_store, course_data_path,
|
||||
# the caller passed in
|
||||
if module.location.category != 'course':
|
||||
module.location = module.location._replace(tag=target_location_namespace.tag, org=target_location_namespace.org,
|
||||
course=target_location_namespace.course)
|
||||
course=target_location_namespace.course)
|
||||
else:
|
||||
module.location = module.location._replace(tag=target_location_namespace.tag, org=target_location_namespace.org,
|
||||
course=target_location_namespace.course, name=target_location_namespace.name)
|
||||
course=target_location_namespace.course, name=target_location_namespace.name)
|
||||
|
||||
# then remap children pointers since they too will be re-namespaced
|
||||
if module.has_children:
|
||||
@@ -121,7 +119,7 @@ def import_module_from_xml(modulestore, static_content_store, course_data_path,
|
||||
for child in children_locs:
|
||||
child_loc = Location(child)
|
||||
new_child_loc = child_loc._replace(tag=target_location_namespace.tag, org=target_location_namespace.org,
|
||||
course=target_location_namespace.course)
|
||||
course=target_location_namespace.course)
|
||||
|
||||
new_locs.append(new_child_loc.url())
|
||||
|
||||
@@ -141,8 +139,7 @@ def import_module_from_xml(modulestore, static_content_store, course_data_path,
|
||||
# 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
|
||||
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():
|
||||
module.data = module.data.replace(key, remap_dict[key])
|
||||
@@ -165,9 +162,9 @@ def import_course_from_xml(modulestore, static_content_store, course_data_path,
|
||||
# if there is *any* tabs - then there at least needs to be some predefined ones
|
||||
if module.tabs is None or len(module.tabs) == 0:
|
||||
module.tabs = [{"type": "courseware"},
|
||||
{"type": "course_info", "name": "Course Info"},
|
||||
{"type": "discussion", "name": "Discussion"},
|
||||
{"type": "wiki", "name": "Wiki"}] # note, add 'progress' when we can support it on Edge
|
||||
{"type": "course_info", "name": "Course Info"},
|
||||
{"type": "discussion", "name": "Discussion"},
|
||||
{"type": "wiki", "name": "Wiki"}] # note, add 'progress' when we can support it on Edge
|
||||
|
||||
# a bit of a hack, but typically the "course image" which is shown on marketing pages is hard coded to /images/course_image.jpg
|
||||
# so let's make sure we import in case there are no other references to it in the modules
|
||||
@@ -177,7 +174,7 @@ def import_course_from_xml(modulestore, static_content_store, course_data_path,
|
||||
|
||||
def import_from_xml(store, data_dir, course_dirs=None,
|
||||
default_class='xmodule.raw_module.RawDescriptor',
|
||||
load_error_modules=True, static_content_store=None, target_location_namespace=None,
|
||||
load_error_modules=True, static_content_store=None, target_location_namespace=None,
|
||||
verbose=False, draft_store=None):
|
||||
"""
|
||||
Import the specified xml data_dir into the "store" modulestore,
|
||||
@@ -238,9 +235,9 @@ def import_from_xml(store, data_dir, course_dirs=None,
|
||||
# if there is *any* tabs - then there at least needs to be some predefined ones
|
||||
if module.tabs is None or len(module.tabs) == 0:
|
||||
module.tabs = [{"type": "courseware"},
|
||||
{"type": "course_info", "name": "Course Info"},
|
||||
{"type": "discussion", "name": "Discussion"},
|
||||
{"type": "wiki", "name": "Wiki"}] # note, add 'progress' when we can support it on Edge
|
||||
{"type": "course_info", "name": "Course Info"},
|
||||
{"type": "discussion", "name": "Discussion"},
|
||||
{"type": "wiki", "name": "Wiki"}] # note, add 'progress' when we can support it on Edge
|
||||
|
||||
import_module(module, store, course_data_path, static_content_store)
|
||||
|
||||
@@ -250,14 +247,13 @@ def import_from_xml(store, data_dir, course_dirs=None,
|
||||
|
||||
course_items.append(module)
|
||||
|
||||
|
||||
# then import all the static content
|
||||
if static_content_store is not None:
|
||||
_namespace_rename = target_location_namespace if target_location_namespace is not None else course_location
|
||||
|
||||
# first pass to find everything in /static/
|
||||
import_static_content(xml_module_store.modules[course_id], course_location, course_data_path, static_content_store,
|
||||
_namespace_rename, subpath='static', verbose=verbose)
|
||||
_namespace_rename, subpath='static', verbose=verbose)
|
||||
|
||||
# finally loop through all the modules
|
||||
for module in xml_module_store.modules[course_id].itervalues():
|
||||
@@ -278,19 +274,20 @@ def import_from_xml(store, data_dir, course_dirs=None,
|
||||
|
||||
# now import any 'draft' items
|
||||
if draft_store is not None:
|
||||
import_course_draft(xml_module_store, draft_store, course_data_path,
|
||||
static_content_store, target_location_namespace if target_location_namespace is not None
|
||||
else course_location)
|
||||
import_course_draft(xml_module_store, draft_store, course_data_path,
|
||||
static_content_store, target_location_namespace if target_location_namespace is not None
|
||||
else course_location)
|
||||
|
||||
finally:
|
||||
# turn back on all write signalling
|
||||
if pseudo_course_id in store.ignore_write_events_on_courses:
|
||||
if pseudo_course_id in store.ignore_write_events_on_courses:
|
||||
store.ignore_write_events_on_courses.remove(pseudo_course_id)
|
||||
store.refresh_cached_metadata_inheritance_tree(target_location_namespace if
|
||||
target_location_namespace is not None else course_location)
|
||||
store.refresh_cached_metadata_inheritance_tree(target_location_namespace if
|
||||
target_location_namespace is not None else course_location)
|
||||
|
||||
return xml_module_store, course_items
|
||||
|
||||
|
||||
def import_module(module, store, course_data_path, static_content_store, allow_not_found=False):
|
||||
content = {}
|
||||
for field in module.fields:
|
||||
@@ -319,8 +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
|
||||
# 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
|
||||
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():
|
||||
module_data = module_data.replace(key, remap_dict[key])
|
||||
@@ -340,7 +336,7 @@ def import_module(module, store, course_data_path, static_content_store, allow_n
|
||||
|
||||
# NOTE: It's important to use own_metadata here to avoid writing
|
||||
# inherited metadata everywhere.
|
||||
store.update_metadata(module.location, dict(own_metadata(module)))
|
||||
store.update_metadata(module.location, dict(own_metadata(module)))
|
||||
|
||||
|
||||
def import_course_draft(xml_module_store, store, course_data_path, static_content_store, target_location_namespace):
|
||||
@@ -406,7 +402,7 @@ def import_course_draft(xml_module_store, store, course_data_path, static_conten
|
||||
|
||||
# HACK: since we are doing partial imports of drafts
|
||||
# the vertical doesn't have the 'url-name' set in the attributes (they are normally in the parent
|
||||
# object, aka sequential), so we have to replace the location.name with the XML filename
|
||||
# object, aka sequential), so we have to replace the location.name with the XML filename
|
||||
# that is part of the pack
|
||||
fn, fileExtension = os.path.splitext(filename)
|
||||
descriptor.location = descriptor.location._replace(name=fn)
|
||||
@@ -469,7 +465,6 @@ def check_module_metadata_editability(module):
|
||||
|
||||
allowed = allowed + ['xml_attributes', 'display_name']
|
||||
err_cnt = 0
|
||||
my_metadata = dict(own_metadata(module))
|
||||
illegal_keys = set(own_metadata(module).keys()) - set(allowed)
|
||||
|
||||
if len(illegal_keys) > 0:
|
||||
@@ -512,7 +507,7 @@ def validate_data_source_path_existence(path, is_err=True, extra_msg=None):
|
||||
_cnt = 0
|
||||
if not os.path.exists(path):
|
||||
print ("{0}: Expected folder at {1}. {2}".format('ERROR' if is_err == True else 'WARNING', path, extra_msg if
|
||||
extra_msg is not None else ''))
|
||||
extra_msg is not None else ''))
|
||||
_cnt = 1
|
||||
return _cnt
|
||||
|
||||
@@ -524,13 +519,13 @@ def validate_data_source_paths(data_dir, course_dir):
|
||||
warn_cnt = 0
|
||||
err_cnt += validate_data_source_path_existence(course_path / 'static')
|
||||
warn_cnt += validate_data_source_path_existence(course_path / 'static/subs', is_err=False,
|
||||
extra_msg='Video captions (if they are used) will not work unless they are static/subs.')
|
||||
extra_msg='Video captions (if they are used) will not work unless they are static/subs.')
|
||||
return err_cnt, warn_cnt
|
||||
|
||||
|
||||
def perform_xlint(data_dir, course_dirs,
|
||||
default_class='xmodule.raw_module.RawDescriptor',
|
||||
load_error_modules=True):
|
||||
default_class='xmodule.raw_module.RawDescriptor',
|
||||
load_error_modules=True):
|
||||
err_cnt = 0
|
||||
warn_cnt = 0
|
||||
|
||||
@@ -586,7 +581,6 @@ def perform_xlint(data_dir, course_dirs,
|
||||
print "WARN: Missing course marketing video. It is recommended that every course have a marketing video."
|
||||
warn_cnt += 1
|
||||
|
||||
|
||||
print "\n\n------------------------------------------\nVALIDATION SUMMARY: {0} Errors {1} Warnings\n".format(err_cnt, warn_cnt)
|
||||
|
||||
if err_cnt > 0:
|
||||
|
||||
@@ -199,8 +199,8 @@ class PeerGradingModule(PeerGradingFields, XModule):
|
||||
self.student_data_for_location = response
|
||||
|
||||
score_dict = {
|
||||
'score': int(count_graded >= count_required),
|
||||
'total': self.max_grade,
|
||||
'score': int(count_graded >= count_required and count_graded>0) * int(self.weight),
|
||||
'total': self.max_grade * int(self.weight),
|
||||
}
|
||||
|
||||
return score_dict
|
||||
|
||||
@@ -24,6 +24,11 @@ def strip_filenames(descriptor):
|
||||
"""
|
||||
print "strip filename from {desc}".format(desc=descriptor.location.url())
|
||||
descriptor._model_data.pop('filename', None)
|
||||
|
||||
if hasattr(descriptor, 'xml_attributes'):
|
||||
if 'filename' in descriptor.xml_attributes:
|
||||
del descriptor.xml_attributes['filename']
|
||||
|
||||
for d in descriptor.get_children():
|
||||
strip_filenames(d)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user