Turn on bulk operations for xml export
This commit is contained in:
@@ -37,106 +37,108 @@ def export_to_xml(modulestore, contentstore, course_key, root_dir, course_dir):
|
||||
`course_dir`: The name of the directory inside `root_dir` to write the course content to
|
||||
"""
|
||||
|
||||
course = modulestore.get_course(course_key, depth=None) # None means infinite
|
||||
fsm = OSFS(root_dir)
|
||||
export_fs = course.runtime.export_fs = fsm.makeopendir(course_dir)
|
||||
with modulestore.bulk_operations(course_key):
|
||||
|
||||
root = lxml.etree.Element('unknown')
|
||||
course = modulestore.get_course(course_key, depth=None) # None means infinite
|
||||
fsm = OSFS(root_dir)
|
||||
export_fs = course.runtime.export_fs = fsm.makeopendir(course_dir)
|
||||
|
||||
# export only the published content
|
||||
with modulestore.branch_setting(ModuleStoreEnum.Branch.published_only, course_key):
|
||||
# change all of the references inside the course to use the xml expected key type w/o version & branch
|
||||
xml_centric_course_key = CourseLocator(course_key.org, course_key.course, course_key.run, deprecated=True)
|
||||
adapt_references(course, xml_centric_course_key, export_fs)
|
||||
root = lxml.etree.Element('unknown')
|
||||
|
||||
course.add_xml_to_node(root)
|
||||
# export only the published content
|
||||
with modulestore.branch_setting(ModuleStoreEnum.Branch.published_only, course_key):
|
||||
# change all of the references inside the course to use the xml expected key type w/o version & branch
|
||||
xml_centric_course_key = CourseLocator(course_key.org, course_key.course, course_key.run, deprecated=True)
|
||||
adapt_references(course, xml_centric_course_key, export_fs)
|
||||
|
||||
with export_fs.open('course.xml', 'w') as course_xml:
|
||||
lxml.etree.ElementTree(root).write(course_xml)
|
||||
course.add_xml_to_node(root)
|
||||
|
||||
# export the static assets
|
||||
policies_dir = export_fs.makeopendir('policies')
|
||||
if contentstore:
|
||||
contentstore.export_all_for_course(
|
||||
course_key,
|
||||
root_dir + '/' + course_dir + '/static/',
|
||||
root_dir + '/' + course_dir + '/policies/assets.json',
|
||||
)
|
||||
with export_fs.open('course.xml', 'w') as course_xml:
|
||||
lxml.etree.ElementTree(root).write(course_xml)
|
||||
|
||||
# If we are using the default course image, export it to the
|
||||
# legacy location to support backwards compatibility.
|
||||
if course.course_image == course.fields['course_image'].default:
|
||||
try:
|
||||
course_image = contentstore.find(
|
||||
StaticContent.compute_location(
|
||||
course.id,
|
||||
course.course_image
|
||||
),
|
||||
)
|
||||
except NotFoundError:
|
||||
pass
|
||||
else:
|
||||
output_dir = root_dir + '/' + course_dir + '/static/images/'
|
||||
if not os.path.isdir(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
with OSFS(output_dir).open('course_image.jpg', 'wb') as course_image_file:
|
||||
course_image_file.write(course_image.data)
|
||||
|
||||
# export the static tabs
|
||||
export_extra_content(export_fs, modulestore, xml_centric_course_key, 'static_tab', 'tabs', '.html')
|
||||
|
||||
# export the custom tags
|
||||
export_extra_content(export_fs, modulestore, xml_centric_course_key, 'custom_tag_template', 'custom_tags')
|
||||
|
||||
# export the course updates
|
||||
export_extra_content(export_fs, modulestore, xml_centric_course_key, 'course_info', 'info', '.html')
|
||||
|
||||
# export the 'about' data (e.g. overview, etc.)
|
||||
export_extra_content(export_fs, modulestore, xml_centric_course_key, 'about', 'about', '.html')
|
||||
|
||||
# export the grading policy
|
||||
course_run_policy_dir = policies_dir.makeopendir(course.location.name)
|
||||
with course_run_policy_dir.open('grading_policy.json', 'w') as grading_policy:
|
||||
grading_policy.write(dumps(course.grading_policy, cls=EdxJSONEncoder, sort_keys=True, indent=4))
|
||||
|
||||
# export all of the course metadata in policy.json
|
||||
with course_run_policy_dir.open('policy.json', 'w') as course_policy:
|
||||
policy = {'course/' + course.location.name: own_metadata(course)}
|
||||
course_policy.write(dumps(policy, cls=EdxJSONEncoder, sort_keys=True, indent=4))
|
||||
|
||||
#### DRAFTS ####
|
||||
# xml backed courses don't support drafts!
|
||||
if course.runtime.modulestore.get_modulestore_type() != ModuleStoreEnum.Type.xml:
|
||||
# NOTE: this code assumes that verticals are the top most draftable container
|
||||
# should we change the application, then this assumption will no longer be valid
|
||||
# NOTE: we need to explicitly implement the logic for setting the vertical's parent
|
||||
# and index here since the XML modulestore cannot load draft modules
|
||||
with modulestore.branch_setting(ModuleStoreEnum.Branch.draft_preferred, course_key):
|
||||
draft_verticals = modulestore.get_items(
|
||||
# export the static assets
|
||||
policies_dir = export_fs.makeopendir('policies')
|
||||
if contentstore:
|
||||
contentstore.export_all_for_course(
|
||||
course_key,
|
||||
qualifiers={'category': 'vertical'},
|
||||
revision=ModuleStoreEnum.RevisionOption.draft_only
|
||||
root_dir + '/' + course_dir + '/static/',
|
||||
root_dir + '/' + course_dir + '/policies/assets.json',
|
||||
)
|
||||
|
||||
if len(draft_verticals) > 0:
|
||||
draft_course_dir = export_fs.makeopendir(DRAFT_DIR)
|
||||
for draft_vertical in draft_verticals:
|
||||
parent_loc = modulestore.get_parent_location(
|
||||
draft_vertical.location,
|
||||
revision=ModuleStoreEnum.RevisionOption.draft_preferred
|
||||
# If we are using the default course image, export it to the
|
||||
# legacy location to support backwards compatibility.
|
||||
if course.course_image == course.fields['course_image'].default:
|
||||
try:
|
||||
course_image = contentstore.find(
|
||||
StaticContent.compute_location(
|
||||
course.id,
|
||||
course.course_image
|
||||
),
|
||||
)
|
||||
# Don't try to export orphaned items.
|
||||
if parent_loc is not None:
|
||||
logging.debug('parent_loc = {0}'.format(parent_loc))
|
||||
if parent_loc.category in DIRECT_ONLY_CATEGORIES:
|
||||
draft_vertical.xml_attributes['parent_sequential_url'] = parent_loc.to_deprecated_string()
|
||||
sequential = modulestore.get_item(parent_loc)
|
||||
index = sequential.children.index(draft_vertical.location)
|
||||
draft_vertical.xml_attributes['index_in_children_list'] = str(index)
|
||||
draft_vertical.runtime.export_fs = draft_course_dir
|
||||
adapt_references(draft_vertical, xml_centric_course_key, draft_course_dir)
|
||||
node = lxml.etree.Element('unknown')
|
||||
draft_vertical.add_xml_to_node(node)
|
||||
except NotFoundError:
|
||||
pass
|
||||
else:
|
||||
output_dir = root_dir + '/' + course_dir + '/static/images/'
|
||||
if not os.path.isdir(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
with OSFS(output_dir).open('course_image.jpg', 'wb') as course_image_file:
|
||||
course_image_file.write(course_image.data)
|
||||
|
||||
# export the static tabs
|
||||
export_extra_content(export_fs, modulestore, xml_centric_course_key, 'static_tab', 'tabs', '.html')
|
||||
|
||||
# export the custom tags
|
||||
export_extra_content(export_fs, modulestore, xml_centric_course_key, 'custom_tag_template', 'custom_tags')
|
||||
|
||||
# export the course updates
|
||||
export_extra_content(export_fs, modulestore, xml_centric_course_key, 'course_info', 'info', '.html')
|
||||
|
||||
# export the 'about' data (e.g. overview, etc.)
|
||||
export_extra_content(export_fs, modulestore, xml_centric_course_key, 'about', 'about', '.html')
|
||||
|
||||
# export the grading policy
|
||||
course_run_policy_dir = policies_dir.makeopendir(course.location.name)
|
||||
with course_run_policy_dir.open('grading_policy.json', 'w') as grading_policy:
|
||||
grading_policy.write(dumps(course.grading_policy, cls=EdxJSONEncoder, sort_keys=True, indent=4))
|
||||
|
||||
# export all of the course metadata in policy.json
|
||||
with course_run_policy_dir.open('policy.json', 'w') as course_policy:
|
||||
policy = {'course/' + course.location.name: own_metadata(course)}
|
||||
course_policy.write(dumps(policy, cls=EdxJSONEncoder, sort_keys=True, indent=4))
|
||||
|
||||
#### DRAFTS ####
|
||||
# xml backed courses don't support drafts!
|
||||
if course.runtime.modulestore.get_modulestore_type() != ModuleStoreEnum.Type.xml:
|
||||
# NOTE: this code assumes that verticals are the top most draftable container
|
||||
# should we change the application, then this assumption will no longer be valid
|
||||
# NOTE: we need to explicitly implement the logic for setting the vertical's parent
|
||||
# and index here since the XML modulestore cannot load draft modules
|
||||
with modulestore.branch_setting(ModuleStoreEnum.Branch.draft_preferred, course_key):
|
||||
draft_verticals = modulestore.get_items(
|
||||
course_key,
|
||||
qualifiers={'category': 'vertical'},
|
||||
revision=ModuleStoreEnum.RevisionOption.draft_only
|
||||
)
|
||||
|
||||
if len(draft_verticals) > 0:
|
||||
draft_course_dir = export_fs.makeopendir(DRAFT_DIR)
|
||||
for draft_vertical in draft_verticals:
|
||||
parent_loc = modulestore.get_parent_location(
|
||||
draft_vertical.location,
|
||||
revision=ModuleStoreEnum.RevisionOption.draft_preferred
|
||||
)
|
||||
# Don't try to export orphaned items.
|
||||
if parent_loc is not None:
|
||||
logging.debug('parent_loc = {0}'.format(parent_loc))
|
||||
if parent_loc.category in DIRECT_ONLY_CATEGORIES:
|
||||
draft_vertical.xml_attributes['parent_sequential_url'] = parent_loc.to_deprecated_string()
|
||||
sequential = modulestore.get_item(parent_loc)
|
||||
index = sequential.children.index(draft_vertical.location)
|
||||
draft_vertical.xml_attributes['index_in_children_list'] = str(index)
|
||||
draft_vertical.runtime.export_fs = draft_course_dir
|
||||
adapt_references(draft_vertical, xml_centric_course_key, draft_course_dir)
|
||||
node = lxml.etree.Element('unknown')
|
||||
draft_vertical.add_xml_to_node(node)
|
||||
|
||||
|
||||
def adapt_references(subtree, destination_course_key, export_fs):
|
||||
|
||||
Reference in New Issue
Block a user