Merge pull request #5673 from rocha/fix-course-structure-command
Fix dump course structure when element metadata uses opaque keys.
This commit is contained in:
@@ -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'}
|
||||
|
||||
Reference in New Issue
Block a user