Skip to content
Snippets Groups Projects
Commit fd06640d authored by Don Mitchell's avatar Don Mitchell
Browse files

Merge pull request #1091 from edx/assets/persist_lock

Export asset attrs to a policy file
parents 7275f852 20e4d585
No related merge requests found
......@@ -170,6 +170,16 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
resp = self.client.get(reverse('edit_unit', kwargs={'location': descriptor.location.url()}))
self.assertEqual(resp.status_code, 200)
def lockAnAsset(self, content_store, course_location):
"""
Lock an arbitrary asset in the course
:param course_location:
"""
course_assets = content_store.get_all_content_for_course(course_location)
self.assertGreater(len(course_assets), 0, "No assets to lock")
content_store.set_attr(course_assets[0]['_id'], 'locked', True)
return course_assets[0]['_id']
def test_edit_unit_toy(self):
self.check_edit_unit('toy')
......@@ -952,6 +962,11 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
self.assertIn(private_location_no_draft.url(), sequential.children)
locked_asset = self.lockAnAsset(content_store, location)
locked_asset_attrs = content_store.get_attrs(locked_asset)
# the later import will reupload
del locked_asset_attrs['uploadDate']
print 'Exporting to tempdir = {0}'.format(root_dir)
# export out to a tempdir
......@@ -1034,6 +1049,10 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
self.assertGreater(len(course.textbooks), 0)
new_attrs = content_store.get_attrs(locked_asset)
for key, value in locked_asset_attrs.iteritems():
self.assertEqual(value, new_attrs[key])
shutil.rmtree(root_dir)
def test_export_course_with_metadata_only_video(self):
......
......@@ -12,6 +12,7 @@ from .content import StaticContent, ContentStore, StaticContentStream
from xmodule.exceptions import NotFoundError
from fs.osfs import OSFS
import os
import json
class MongoContentStore(ContentStore):
......@@ -103,12 +104,28 @@ class MongoContentStore(ContentStore):
with disk_fs.open(content.name, 'wb') as asset_file:
asset_file.write(content.data)
def export_all_for_course(self, course_location, output_directory):
def export_all_for_course(self, course_location, output_directory, assets_policy_file):
"""
Export all of this course's assets to the output_directory. Export all of the assets'
attributes to the policy file.
:param course_location: the Location of type 'course'
:param output_directory: the directory under which to put all the asset files
:param assets_policy_file: the filename for the policy file which should be in the same
directory as the other policy files.
"""
policy = {}
assets = self.get_all_content_for_course(course_location)
for asset in assets:
asset_location = Location(asset['_id'])
self.export(asset_location, output_directory)
for attr, value in asset.iteritems():
if attr not in ['_id', 'md5', 'uploadDate', 'length', 'chunkSize']:
policy.setdefault(asset_location.url(), {})[attr] = value
with open(assets_policy_file, 'w') as f:
json.dump(policy, f)
def get_all_content_thumbnails_for_course(self, location):
return self._get_all_content_for_course(location, get_thumbnails=True)
......
......@@ -55,8 +55,13 @@ def export_to_xml(modulestore, contentstore, course_location, root_dir, course_d
with export_fs.open('course.xml', 'w') as course_xml:
course_xml.write(xml)
policies_dir = export_fs.makeopendir('policies')
# export the static assets
contentstore.export_all_for_course(course_location, root_dir + '/' + course_dir + '/static/')
contentstore.export_all_for_course(
course_location,
root_dir + '/' + course_dir + '/static/',
root_dir + '/' + course_dir + '/policies/assets.json',
)
# export the static tabs
export_extra_content(export_fs, modulestore, course_location, 'static_tab', 'tabs', '.html')
......@@ -71,7 +76,6 @@ def export_to_xml(modulestore, contentstore, course_location, root_dir, course_d
export_extra_content(export_fs, modulestore, course_location, 'about', 'about', '.html')
# export the grading policy
policies_dir = export_fs.makeopendir('policies')
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))
......
......@@ -2,6 +2,7 @@ import logging
import os
import mimetypes
from path import path
import json
from xblock.fields import Scope
......@@ -22,6 +23,13 @@ def import_static_content(modules, course_loc, course_data_path, static_content_
# now import all static assets
static_dir = course_data_path / subpath
try:
with open(course_data_path / 'policies/assets.json') as f:
policy = json.load(f)
except (IOError, ValueError) as err:
# xml backed courses won't have this file, only exported courses; so, its absence is not
# really an exception.
policy = {}
verbose = True
......@@ -46,10 +54,16 @@ def import_static_content(modules, course_loc, course_data_path, static_content_
if fullname_with_subpath.startswith('/'):
fullname_with_subpath = fullname_with_subpath[1:]
content_loc = StaticContent.compute_location(target_location_namespace.org, target_location_namespace.course, fullname_with_subpath)
mime_type = mimetypes.guess_type(filename)[0]
content = StaticContent(content_loc, filename, mime_type, data, import_path=fullname_with_subpath)
policy_ele = policy.get(content_loc.url(), {})
displayname = policy_ele.get('displayname', filename)
locked = policy_ele.get('locked', False)
mime_type = policy_ele.get('contentType', mimetypes.guess_type(filename)[0])
content = StaticContent(
content_loc, displayname, mime_type, data,
import_path=fullname_with_subpath, locked=locked
)
# first let's save a thumbnail so we can get back a thumbnail location
(thumbnail_content, thumbnail_location) = static_content_store.generate_thumbnail(content)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment