Commit 95c67194 by Chris Dodge

initial commit. Add 'import_path' field to the GridFS so that when we export, we…

initial commit. Add 'import_path' field to the GridFS so that when we export, we know where it originated from
parent c3d7c466
...@@ -12,13 +12,16 @@ from .django import contentstore ...@@ -12,13 +12,16 @@ from .django import contentstore
from PIL import Image from PIL import Image
class StaticContent(object): class StaticContent(object):
def __init__(self, loc, name, content_type, data, last_modified_at=None, thumbnail_location=None): def __init__(self, loc, name, content_type, data, last_modified_at=None, thumbnail_location=None, import_path=None):
self.location = loc self.location = loc
self.name = name #a display string which can be edited, and thus not part of the location which needs to be fixed self.name = name #a display string which can be edited, and thus not part of the location which needs to be fixed
self.content_type = content_type self.content_type = content_type
self.data = data self.data = data
self.last_modified_at = last_modified_at self.last_modified_at = last_modified_at
self.thumbnail_location = thumbnail_location self.thumbnail_location = thumbnail_location
# optional information about where this file was imported from. This is needed to support import/export
# cycles
self.import_path = import_path
@property @property
def is_thumbnail(self): def is_thumbnail(self):
......
...@@ -11,6 +11,7 @@ import logging ...@@ -11,6 +11,7 @@ import logging
from .content import StaticContent, ContentStore from .content import StaticContent, ContentStore
from xmodule.exceptions import NotFoundError from xmodule.exceptions import NotFoundError
from fs.osfs import OSFS
class MongoContentStore(ContentStore): class MongoContentStore(ContentStore):
...@@ -33,7 +34,7 @@ class MongoContentStore(ContentStore): ...@@ -33,7 +34,7 @@ class MongoContentStore(ContentStore):
self.fs.delete(id) self.fs.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) 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)
...@@ -45,10 +46,18 @@ class MongoContentStore(ContentStore): ...@@ -45,10 +46,18 @@ 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 'thumbnail_location' in fp else None) fp.uploadDate, thumbnail_location = fp.thumbnail_location if 'thumbnail_location' in fp else None,
import_path = fp.import_path if 'import_path' in fp else None)
except NoFile: except NoFile:
raise NotFoundError() raise NotFoundError()
def export(self, location, output_directory):
content = self.find(location)
disk_fs = OSFS(output_directory)
with disk_fs.open('course.xml', 'wb') as course_xml:
course_xml.write(content.data)
def get_all_content_thumbnails_for_course(self, location): def get_all_content_thumbnails_for_course(self, location):
return self._get_all_content_for_course(location, get_thumbnails = True) return self._get_all_content_for_course(location, get_thumbnails = True)
......
...@@ -32,7 +32,7 @@ def import_static_content(modules, course_loc, course_data_path, static_content_ ...@@ -32,7 +32,7 @@ def import_static_content(modules, course_loc, course_data_path, static_content_
with open(content_path, 'rb') as f: with open(content_path, 'rb') as f:
data = f.read() data = f.read()
content = StaticContent(content_loc, filename, mime_type, data) content = StaticContent(content_loc, filename, mime_type, data, import_path = fullname_with_subpath)
# first let's save a thumbnail so we can get back a thumbnail location # first let's save a thumbnail so we can get back a thumbnail location
thumbnail_content = static_content_store.generate_thumbnail(content) thumbnail_content = static_content_store.generate_thumbnail(content)
...@@ -66,7 +66,7 @@ def verify_content_links(module, base_dir, static_content_store, link, remap_dic ...@@ -66,7 +66,7 @@ def verify_content_links(module, base_dir, static_content_store, link, remap_dic
with open(static_pathname, 'rb') as f: with open(static_pathname, 'rb') as f:
data = f.read() data = f.read()
content = StaticContent(content_loc, filename, mime_type, data) content = StaticContent(content_loc, filename, mime_type, data, import_path = path)
# first let's save a thumbnail so we can get back a thumbnail location # first let's save a thumbnail so we can get back a thumbnail location
thumbnail_content = static_content_store.generate_thumbnail(content) thumbnail_content = static_content_store.generate_thumbnail(content)
......
...@@ -98,7 +98,7 @@ class XmlDescriptor(XModuleDescriptor): ...@@ -98,7 +98,7 @@ class XmlDescriptor(XModuleDescriptor):
metadata_to_strip = ('data_dir', metadata_to_strip = ('data_dir',
# cdodge: @TODO: We need to figure out a way to export out 'tabs' and 'grading_policy' which is on the course # cdodge: @TODO: We need to figure out a way to export out 'tabs' and 'grading_policy' which is on the course
'tabs', 'grading_policy', 'tabs', 'grading_policy', 'is_draft', 'published_by', 'published_date',
# VS[compat] -- remove the below attrs once everything is in the CMS # VS[compat] -- remove the below attrs once everything is in the CMS
'course', 'org', 'url_name', 'filename') 'course', 'org', 'url_name', 'filename')
......
...@@ -148,7 +148,7 @@ def get_course_about_section(course, section_key): ...@@ -148,7 +148,7 @@ def get_course_about_section(course, section_key):
request = get_request_for_thread() request = get_request_for_thread()
loc = course.location._replace(category='about', name=section_key) loc = course.location._replace(category='about', name=section_key)
course_module = get_module(request.user, request, loc, None, course.id, not_found_ok = True, wrap_xmodule_display = False) course_module = get_module(request.user, request, loc, None, course.id, not_found_ok = True, wrap_xmodule_display = True)
html = '' html = ''
...@@ -186,7 +186,7 @@ def get_course_info_section(request, cache, course, section_key): ...@@ -186,7 +186,7 @@ def get_course_info_section(request, cache, course, section_key):
loc = Location(course.location.tag, course.location.org, course.location.course, 'course_info', section_key) loc = Location(course.location.tag, course.location.org, course.location.course, 'course_info', section_key)
course_module = get_module(request.user, request, loc, cache, course.id, wrap_xmodule_display = False) course_module = get_module(request.user, request, loc, cache, course.id, wrap_xmodule_display = True)
html = '' html = ''
if course_module is not None: if course_module is not None:
......
...@@ -422,6 +422,18 @@ namespace :cms do ...@@ -422,6 +422,18 @@ namespace :cms do
end end
end end
namespace :cms do
desc "Export course data to a tar.gz file"
task :export do
if ENV['COURSE_ID'] and ENV['OUTPUT_PATH']
sh(django_admin(:cms, :dev, :export, ENV['COURSE_ID'], ENV['OUTPUT_PATH']))
else
raise "Please specify a COURSE_ID and OUTPUT_PATH.\n" +
"Example: \`rake cms:export COURSE_ID=MITx/12345/name OUTPUT_PATH=foo.tar.gz\`"
end
end
end
desc "Build a properties file used to trigger autodeploy builds" desc "Build a properties file used to trigger autodeploy builds"
task :autodeploy_properties do task :autodeploy_properties do
File.open("autodeploy.properties", "w") do |file| File.open("autodeploy.properties", "w") do |file|
......
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