Commit e6e290f5 by Victor Shnayder Committed by Calen Pennington

Make initial import-export tests pass.

TODO:
* need unique slugs for errors so they don't overwrite each other on export.
  - try to preserve origin slug.  If not possible, generate random one.

* figure out what metadata to strip.  e.g.
 ({'data': '<problem><p><h1>Finger Exercise 1...'},
    {'data': '<problem points="1" type="lecture"><p><h1>Finger Exercise 1...'},
    False)
  - where did points and type come from?  Do we want them there?


* separate broken and non-broken test courses
parent b091dcab
...@@ -36,7 +36,6 @@ class HtmlDescriptor(XmlDescriptor, EditingDescriptor): ...@@ -36,7 +36,6 @@ class HtmlDescriptor(XmlDescriptor, EditingDescriptor):
# are being edited in the cms # are being edited in the cms
@classmethod @classmethod
def backcompat_paths(cls, path): def backcompat_paths(cls, path):
origpath = path
if path.endswith('.html.xml'): if path.endswith('.html.xml'):
path = path[:-9] + '.html' #backcompat--look for html instead of xml path = path[:-9] + '.html' #backcompat--look for html instead of xml
candidates = [] candidates = []
...@@ -45,9 +44,11 @@ class HtmlDescriptor(XmlDescriptor, EditingDescriptor): ...@@ -45,9 +44,11 @@ class HtmlDescriptor(XmlDescriptor, EditingDescriptor):
_, _, path = path.partition(os.sep) _, _, path = path.partition(os.sep)
# also look for .html versions instead of .xml # also look for .html versions instead of .xml
if origpath.endswith('.xml'): nc = []
candidates.append(origpath[:-4] + '.html') for candidate in candidates:
return candidates if candidate.endswith('.xml'):
nc.append(candidate[:-4] + '.html')
return candidates + nc
# NOTE: html descriptors are special. We do not want to parse and # NOTE: html descriptors are special. We do not want to parse and
# export them ourselves, because that can break things (e.g. lxml # export them ourselves, because that can break things (e.g. lxml
...@@ -80,7 +81,7 @@ class HtmlDescriptor(XmlDescriptor, EditingDescriptor): ...@@ -80,7 +81,7 @@ class HtmlDescriptor(XmlDescriptor, EditingDescriptor):
# online and has imported all current (fall 2012) courses from xml # online and has imported all current (fall 2012) courses from xml
if not system.resources_fs.exists(filepath): if not system.resources_fs.exists(filepath):
candidates = cls.backcompat_paths(filepath) candidates = cls.backcompat_paths(filepath)
#log.debug("candidates = {0}".format(candidates)) log.debug("candidates = {0}".format(candidates))
for candidate in candidates: for candidate in candidates:
if system.resources_fs.exists(candidate): if system.resources_fs.exists(candidate):
filepath = candidate filepath = candidate
......
import unittest
from fs.osfs import OSFS from fs.osfs import OSFS
from nose.tools import assert_equals, assert_true from nose.tools import assert_equals, assert_true
from nose import SkipTest
from path import path from path import path
from tempfile import mkdtemp from tempfile import mkdtemp
...@@ -18,10 +19,7 @@ DATA_DIR = TEST_DIR / 'data' ...@@ -18,10 +19,7 @@ DATA_DIR = TEST_DIR / 'data'
def strip_metadata(descriptor, key): def strip_metadata(descriptor, key):
""" """
HACK: data_dir metadata tags break equality because they aren't real metadata Recursively strips tag from all children.
remove them.
Recursively strips same tag from all children.
""" """
print "strip {key} from {desc}".format(key=key, desc=descriptor.location.url()) print "strip {key} from {desc}".format(key=key, desc=descriptor.location.url())
descriptor.metadata.pop(key, None) descriptor.metadata.pop(key, None)
...@@ -35,50 +33,66 @@ def check_gone(descriptor, key): ...@@ -35,50 +33,66 @@ def check_gone(descriptor, key):
for d in descriptor.get_children(): for d in descriptor.get_children():
check_gone(d, key) check_gone(d, key)
def check_export_roundtrip(data_dir, course_dir):
print "Starting import"
initial_import = XMLModuleStore(data_dir, eager=True, course_dirs=[course_dir])
courses = initial_import.get_courses()
assert_equals(len(courses), 1)
initial_course = courses[0]
print "Starting export" class RoundTripTestCase(unittest.TestCase):
export_dir = mkdtemp() '''Check that our test courses roundtrip properly'''
print "export_dir: {0}".format(export_dir) def check_export_roundtrip(self, data_dir, course_dir):
fs = OSFS(export_dir) print "Starting import"
export_course_dir = 'export' initial_import = XMLModuleStore(data_dir, eager=True, course_dirs=[course_dir])
export_fs = fs.makeopendir(export_course_dir)
courses = initial_import.get_courses()
self.assertEquals(len(courses), 1)
initial_course = courses[0]
print "Starting export"
export_dir = mkdtemp()
print "export_dir: {0}".format(export_dir)
fs = OSFS(export_dir)
export_course_dir = 'export'
export_fs = fs.makeopendir(export_course_dir)
xml = initial_course.export_to_xml(export_fs)
with export_fs.open('course.xml', 'w') as course_xml:
course_xml.write(xml)
print "Starting second import"
second_import = XMLModuleStore(export_dir, eager=True,
course_dirs=[export_course_dir])
courses2 = second_import.get_courses()
self.assertEquals(len(courses2), 1)
exported_course = courses2[0]
xml = initial_course.export_to_xml(export_fs) print "Checking course equality"
with export_fs.open('course.xml', 'w') as course_xml: # HACK: data_dir metadata tags break equality because they
course_xml.write(xml) # aren't real metadata, and depend on paths. Remove them.
strip_metadata(initial_course, 'data_dir')
strip_metadata(exported_course, 'data_dir')
print "Starting second import" self.assertEquals(initial_course, exported_course)
second_import = XMLModuleStore(export_dir, eager=True,
course_dirs=[export_course_dir])
courses2 = second_import.get_courses() print "Checking key equality"
assert_equals(len(courses2), 1) self.assertEquals(sorted(initial_import.modules.keys()),
exported_course = courses2[0] sorted(second_import.modules.keys()))
print "Checking course equality" print "Checking module equality"
strip_metadata(initial_course, 'data_dir') for location in initial_import.modules.keys():
strip_metadata(exported_course, 'data_dir') print "Checking", location
if location.category == 'html':
print ("Skipping html modules--they can't import in"
" final form without writing files...")
continue
self.assertEquals(initial_import.modules[location],
second_import.modules[location])
assert_equals(initial_course, exported_course)
print "Checking key equality" def setUp(self):
assert_equals(initial_import.modules.keys(), second_import.modules.keys()) self.maxDiff = None
print "Checking module equality" def test_toy_roundtrip(self):
for location in initial_import.modules.keys(): self.check_export_roundtrip(DATA_DIR, "toy")
print "Checking", location
assert_equals(initial_import.modules[location], second_import.modules[location])
def test_toy_roundtrip(): def test_full_roundtrip(self):
dir = "" self.check_export_roundtrip(DATA_DIR, "full")
# TODO: add paths and make this run.
raise SkipTest()
check_export_roundtrip(dir)
...@@ -51,8 +51,6 @@ class DummySystem(XMLParsingSystem): ...@@ -51,8 +51,6 @@ class DummySystem(XMLParsingSystem):
class ImportTestCase(unittest.TestCase): class ImportTestCase(unittest.TestCase):
'''Make sure module imports work properly, including for malformed inputs''' '''Make sure module imports work properly, including for malformed inputs'''
@staticmethod @staticmethod
def get_system(): def get_system():
'''Get a dummy system''' '''Get a dummy system'''
......
...@@ -76,7 +76,7 @@ class XmlDescriptor(XModuleDescriptor): ...@@ -76,7 +76,7 @@ class XmlDescriptor(XModuleDescriptor):
metadata_to_strip = ('data_dir', metadata_to_strip = ('data_dir',
# 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') 'course', 'org', 'url_name', 'filename')
# A dictionary mapping xml attribute names AttrMaps that describe how # A dictionary mapping xml attribute names AttrMaps that describe how
# to import and export them # to import and export them
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<chapter name="Overview"> <chapter name="Overview">
<video name="Welcome" youtube="0.75:izygArpw-Qo,1.0:p2Q6BrNhdh8,1.25:1EeWXzPdhSA,1.50:rABDYkeK0x8"/> <video name="Welcome" youtube="0.75:izygArpw-Qo,1.0:p2Q6BrNhdh8,1.25:1EeWXzPdhSA,1.50:rABDYkeK0x8"/>
<videosequence format="Lecture Sequence" name="A simple sequence"> <videosequence format="Lecture Sequence" name="A simple sequence">
<html id="toylab" filename="toylab"/> <html name="toylab" filename="toylab"/>
<video name="S0V1: Video Resources" youtube="0.75:EuzkdzfR0i8,1.0:1bK-WdDi6Qw,1.25:0v1VzoDVUTM,1.50:Bxk_-ZJb240"/> <video name="S0V1: Video Resources" youtube="0.75:EuzkdzfR0i8,1.0:1bK-WdDi6Qw,1.25:0v1VzoDVUTM,1.50:Bxk_-ZJb240"/>
</videosequence> </videosequence>
<section name="Lecture 2"> <section name="Lecture 2">
......
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