Commit a1a7504f by Carlos Andrés Rocha

Fix dump course structure when element metadata uses opaque keys.

Make sure that during the serialization, all opaque keys and their
references and serialized using the `unicode` function.

AN-3821
parent 0d36dd72
......@@ -26,7 +26,7 @@ from xmodule.modulestore.django import modulestore
from xmodule.modulestore.inheritance import own_metadata, compute_inherited_metadata
from xblock.fields import Scope
from opaque_keys import InvalidKeyError
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from opaque_keys.edx.keys import CourseKey
FILTER_LIST = ['xml_attributes', 'checklists']
INHERITED_FILTER_LIST = ['children', 'xml_attributes', 'checklists']
......@@ -59,20 +59,22 @@ class Command(BaseCommand):
raise CommandError("course_id not specified")
# Get the modulestore
store = modulestore()
# Get the course data
try:
course_id = SlashSeparatedCourseKey.from_deprecated_string(args[0])
course_key = CourseKey.from_string(args[0])
except InvalidKeyError:
raise CommandError("Invalid course_id")
course = store.get_course(course_id)
course = store.get_course(course_key)
if course is None:
raise CommandError("Invalid course_id")
# precompute inherited metadata at the course level, if needed:
# Precompute inherited metadata at the course level, if needed:
if options['inherited']:
compute_inherited_metadata(course)
......@@ -80,7 +82,7 @@ class Command(BaseCommand):
info = dump_module(course, inherited=options['inherited'], defaults=options['inherited_defaults'])
return json.dumps(info, indent=2, sort_keys=True)
return json.dumps(info, indent=2, sort_keys=True, default=unicode)
def dump_module(module, destination=None, inherited=False, defaults=False):
......@@ -92,16 +94,17 @@ def dump_module(module, destination=None, inherited=False, defaults=False):
destination = destination if destination else {}
items = own_metadata(module)
filtered_metadata = {k: v for k, v in items.iteritems() if k not in FILTER_LIST}
destination[module.location.to_deprecated_string()] = {
destination[unicode(module.location)] = {
'category': module.location.category,
'children': [child.to_deprecated_string() for child in getattr(module, 'children', [])],
'children': [unicode(child) for child in getattr(module, 'children', [])],
'metadata': filtered_metadata,
}
if inherited:
# when calculating inherited metadata, don't include existing
# When calculating inherited metadata, don't include existing
# locally-defined metadata
inherited_metadata_filter_list = list(filtered_metadata.keys())
inherited_metadata_filter_list.extend(INHERITED_FILTER_LIST)
......@@ -117,7 +120,7 @@ def dump_module(module, destination=None, inherited=False, defaults=False):
return field.values != field.default
inherited_metadata = {field.name: field.read_json(module) for field in module.fields.values() if is_inherited(field)}
destination[module.location.to_deprecated_string()]['inherited_metadata'] = inherited_metadata
destination[unicode(module.location)]['inherited_metadata'] = inherited_metadata
for child in module.get_children():
dump_module(child, destination, inherited, defaults)
......
......@@ -57,7 +57,7 @@ class CommandsTestBase(TestCase):
courses = store.get_courses()
# NOTE: if xml store owns these, it won't import them into mongo
if SlashSeparatedCourseKey.from_deprecated_string(TEST_COURSE_ID) not in [c.id for c in courses]:
import_from_xml(store, ModuleStoreEnum.UserID.mgmt_command, DATA_DIR, ['toy', 'simple'])
import_from_xml(store, ModuleStoreEnum.UserID.mgmt_command, DATA_DIR, ['toy', 'simple', 'open_ended'])
return [course.id for course in store.get_courses()]
......@@ -77,6 +77,19 @@ class CommandsTestBase(TestCase):
dumped_ids = set(dumped_courses)
self.assertEqual(course_ids, dumped_ids)
def test_correct_course_structure_metadata(self):
course_id = 'edX/open_ended/2012_Fall'
args = [course_id]
kwargs = {'modulestore': 'default'}
try:
output = self.call_command('dump_course_structure', *args, **kwargs)
except TypeError, exception:
self.fail(exception)
dump = json.loads(output)
self.assertGreater(len(dump.values()), 0)
def test_dump_course_structure(self):
args = [TEST_COURSE_ID]
kwargs = {'modulestore': 'default'}
......
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