Commit 578f5b62 by Carlos Andrés Rocha

Merge pull request #5673 from rocha/fix-course-structure-command

Fix dump course structure when element metadata uses opaque keys.
parents d4531201 a1a7504f
...@@ -26,7 +26,7 @@ from xmodule.modulestore.django import modulestore ...@@ -26,7 +26,7 @@ from xmodule.modulestore.django import modulestore
from xmodule.modulestore.inheritance import own_metadata, compute_inherited_metadata from xmodule.modulestore.inheritance import own_metadata, compute_inherited_metadata
from xblock.fields import Scope from xblock.fields import Scope
from opaque_keys import InvalidKeyError from opaque_keys import InvalidKeyError
from opaque_keys.edx.locations import SlashSeparatedCourseKey from opaque_keys.edx.keys import CourseKey
FILTER_LIST = ['xml_attributes', 'checklists'] FILTER_LIST = ['xml_attributes', 'checklists']
INHERITED_FILTER_LIST = ['children', 'xml_attributes', 'checklists'] INHERITED_FILTER_LIST = ['children', 'xml_attributes', 'checklists']
...@@ -59,20 +59,22 @@ class Command(BaseCommand): ...@@ -59,20 +59,22 @@ class Command(BaseCommand):
raise CommandError("course_id not specified") raise CommandError("course_id not specified")
# Get the modulestore # Get the modulestore
store = modulestore() store = modulestore()
# Get the course data # Get the course data
try: try:
course_id = SlashSeparatedCourseKey.from_deprecated_string(args[0]) course_key = CourseKey.from_string(args[0])
except InvalidKeyError: except InvalidKeyError:
raise CommandError("Invalid course_id") raise CommandError("Invalid course_id")
course = store.get_course(course_id) course = store.get_course(course_key)
if course is None: if course is None:
raise CommandError("Invalid course_id") 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']: if options['inherited']:
compute_inherited_metadata(course) compute_inherited_metadata(course)
...@@ -80,7 +82,7 @@ class Command(BaseCommand): ...@@ -80,7 +82,7 @@ class Command(BaseCommand):
info = dump_module(course, inherited=options['inherited'], defaults=options['inherited_defaults']) 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): def dump_module(module, destination=None, inherited=False, defaults=False):
...@@ -92,16 +94,17 @@ 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 {} destination = destination if destination else {}
items = own_metadata(module) items = own_metadata(module)
filtered_metadata = {k: v for k, v in items.iteritems() if k not in FILTER_LIST} 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, '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, 'metadata': filtered_metadata,
} }
if inherited: if inherited:
# when calculating inherited metadata, don't include existing # When calculating inherited metadata, don't include existing
# locally-defined metadata # locally-defined metadata
inherited_metadata_filter_list = list(filtered_metadata.keys()) inherited_metadata_filter_list = list(filtered_metadata.keys())
inherited_metadata_filter_list.extend(INHERITED_FILTER_LIST) inherited_metadata_filter_list.extend(INHERITED_FILTER_LIST)
...@@ -117,7 +120,7 @@ def dump_module(module, destination=None, inherited=False, defaults=False): ...@@ -117,7 +120,7 @@ def dump_module(module, destination=None, inherited=False, defaults=False):
return field.values != field.default return field.values != field.default
inherited_metadata = {field.name: field.read_json(module) for field in module.fields.values() if is_inherited(field)} 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(): for child in module.get_children():
dump_module(child, destination, inherited, defaults) dump_module(child, destination, inherited, defaults)
......
...@@ -57,7 +57,7 @@ class CommandsTestBase(TestCase): ...@@ -57,7 +57,7 @@ class CommandsTestBase(TestCase):
courses = store.get_courses() courses = store.get_courses()
# NOTE: if xml store owns these, it won't import them into mongo # 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]: 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()] return [course.id for course in store.get_courses()]
...@@ -77,6 +77,19 @@ class CommandsTestBase(TestCase): ...@@ -77,6 +77,19 @@ class CommandsTestBase(TestCase):
dumped_ids = set(dumped_courses) dumped_ids = set(dumped_courses)
self.assertEqual(course_ids, dumped_ids) 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): def test_dump_course_structure(self):
args = [TEST_COURSE_ID] args = [TEST_COURSE_ID]
kwargs = {'modulestore': 'default'} 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