Commit 96b4914f by cahrens Committed by Chris Dodge

Make our deserializing consistent with serializing.

Also fixes problems with double-quoted strings (historical artifact).

STUD-640

Conflicts:

	common/lib/xmodule/xmodule/video_module.py
parent f27ed073
......@@ -264,6 +264,62 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
'data': ''
})
def test_from_xml_double_quotes(self):
"""
Make sure we can handle the double-quoted string format (which was used for exporting for
a few weeks).
"""
module_system = DummySystem(load_error_modules=True)
xml_data ='''
<video display_name="&quot;display_name&quot;"
html5_sources="[&quot;source_1&quot;, &quot;source_2&quot;]"
show_captions="false"
source="&quot;http://download_video&quot;"
sub="&quot;html5_subtitles&quot;"
track="&quot;http://download_track&quot;"
youtube_id_0_75="&quot;OEoXaMPEzf65&quot;"
youtube_id_1_25="&quot;OEoXaMPEzf125&quot;"
youtube_id_1_5="&quot;OEoXaMPEzf15&quot;"
youtube_id_1_0="&quot;OEoXaMPEzf10&quot;"
/>
'''
output = VideoDescriptor.from_xml(xml_data, module_system)
self.assert_attributes_equal(output, {
'youtube_id_0_75': 'OEoXaMPEzf65',
'youtube_id_1_0': 'OEoXaMPEzf10',
'youtube_id_1_25': 'OEoXaMPEzf125',
'youtube_id_1_5': 'OEoXaMPEzf15',
'show_captions': False,
'start_time': 0.0,
'end_time': 0.0,
'track': 'http://download_track',
'source': 'http://download_video',
'html5_sources': ["source_1", "source_2"],
'data': ''
})
def test_from_xml_double_quote_concatenated_youtube(self):
module_system = DummySystem(load_error_modules=True)
xml_data = '''
<video display_name="Test Video"
youtube="1.0:&quot;p2Q6BrNhdh8&quot;,1.25:&quot;1EeWXzPdhSA&quot;">
</video>
'''
output = VideoDescriptor.from_xml(xml_data, module_system)
self.assert_attributes_equal(output, {
'youtube_id_0_75': '',
'youtube_id_1_0': 'p2Q6BrNhdh8',
'youtube_id_1_25': '1EeWXzPdhSA',
'youtube_id_1_5': '',
'show_captions': True,
'start_time': 0.0,
'end_time': 0.0,
'track': '',
'source': '',
'html5_sources': [],
'data': ''
})
def test_old_video_format(self):
"""
Test backwards compatibility with VideoModule's XML format.
......
......@@ -291,19 +291,19 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
XML-based courses.
"""
ret = {'0.75': '', '1.00': '', '1.25': '', '1.50': ''}
if data == '':
return ret
videos = data.split(',')
for video in videos:
pieces = video.split(':')
# HACK
# To elaborate somewhat: in many LMS tests, the keys for
# Youtube IDs are inconsistent. Sometimes a particular
# speed isn't present, and formatting is also inconsistent
# ('1.0' versus '1.00'). So it's necessary to either do
# something like this or update all the tests to work
# properly.
ret['%.2f' % float(pieces[0])] = pieces[1]
try:
speed = '%.2f' % float(pieces[0]) # normalize speed
# Handle the fact that youtube IDs got double-quoted for a period of time.
# Note: we pass in "VideoFields.youtube_id_1_0" so we deserialize as a String--
# it doesn't matter what the actual speed is for the purposes of deserializing.
youtube_id = VideoDescriptor._deserialize(VideoFields.youtube_id_1_0.name, pieces[1])
ret[speed] = youtube_id
except (ValueError, IndexError):
log.warning('Invalid YouTube ID: %s' % video)
return ret
@staticmethod
......@@ -316,7 +316,6 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
model_data = {}
conversions = {
'show_captions': json.loads,
'start_time': VideoDescriptor._parse_time,
'end_time': VideoDescriptor._parse_time
}
......@@ -355,10 +354,21 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
# Convert XML attrs into Python values.
if attr in conversions:
value = conversions[attr](value)
else:
# We export values with json.dumps (well, except for Strings, but
# for about a month we did it for Strings also).
value = VideoDescriptor._deserialize(attr, value)
model_data[attr] = value
return model_data
@classmethod
def _deserialize(cls, attr, value):
"""
Handles deserializing values that may have been encoded with json.dumps.
"""
return cls.get_map_for_field(attr).from_xml(value)
@staticmethod
def _parse_time(str_time):
"""Converts s in '12:34:45' format to seconds. If s is
......
......@@ -167,6 +167,11 @@ class XmlDescriptor(XModuleDescriptor):
@classmethod
def get_map_for_field(cls, attr):
"""
Returns a serialize/deserialize AttrMap for the given field of a class.
Searches through fields defined by cls to find one named attr.
"""
for field in set(cls.fields + cls.lms.fields):
if field.name == attr:
from_xml = lambda val: deserialize_field(field, val)
......
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