diff --git a/common/lib/xmodule/xmodule/fields.py b/common/lib/xmodule/xmodule/fields.py index e33bc02b0f..878505722f 100644 --- a/common/lib/xmodule/xmodule/fields.py +++ b/common/lib/xmodule/xmodule/fields.py @@ -150,7 +150,7 @@ class IsoTime(Field): try: obj_time = time.strptime(value, '%H:%M:%S') except ValueError as e: - raise e( + raise ValueError( "Incorrect IsoTime value {} was set in XML or serialized." "Original parse message is {}".format(value, e.message) ) @@ -174,7 +174,11 @@ class IsoTime(Field): if isinstance(value, float): return datetime.timedelta(seconds=value) - return self._isotime_to_timedelta(value) + if isinstance(value, basestring): + return self._isotime_to_timedelta(value) + + msg = "IsoTime Field {0} has bad value '{1}'".format(self._name, value) + raise TypeError(msg) def to_json(self, value): """ @@ -194,9 +198,12 @@ class IsoTime(Field): value = 86400 return str(datetime.timedelta(seconds=value)) - if value.total_seconds() > 86400: # sanity check - raise ValueError( - "IsoTime max value is 23:59:59=86400 seconds" - "but {} seconds is passed".format(value.total_seconds()) - ) - return str(value) + if isinstance(value, datetime.timedelta): + if value.total_seconds() > 86400: # sanity check + raise ValueError( + "IsoTime max value is 23:59:59=86400.0 seconds, " + "but {} seconds is passed".format(value.total_seconds()) + ) + return str(value) + + raise TypeError("IsoTime: cannot convert {!r} to json".format(value)) diff --git a/common/lib/xmodule/xmodule/tests/test_fields.py b/common/lib/xmodule/xmodule/tests/test_fields.py index 8453adaa20..99fc1b9626 100644 --- a/common/lib/xmodule/xmodule/tests/test_fields.py +++ b/common/lib/xmodule/xmodule/tests/test_fields.py @@ -2,7 +2,7 @@ import datetime import unittest from django.utils.timezone import UTC -from xmodule.fields import Date, Timedelta +from xmodule.fields import Date, Timedelta, IsoTime from xmodule.timeinfo import TimeInfo import time @@ -116,3 +116,54 @@ class TimeInfoTest(unittest.TestCase): timeinfo = TimeInfo(due_date, grace_pd_string) self.assertEqual(timeinfo.close_date, due_date + Timedelta().from_json(grace_pd_string)) + + +class IsoTimeTest(unittest.TestCase): + + delta = IsoTime() + + def test_from_json(self): + self.assertEqual( + IsoTimeTest.delta.from_json('0:05:07'), + datetime.timedelta(seconds=307) + ) + + self.assertEqual( + IsoTimeTest.delta.from_json(100.0), + datetime.timedelta(seconds=100) + ) + self.assertEqual( + IsoTimeTest.delta.from_json(None), + datetime.timedelta(seconds=0) + ) + + with self.assertRaises(TypeError): + IsoTimeTest.delta.from_json(1234) # int + + with self.assertRaises(ValueError): + IsoTimeTest.delta.from_json("77:77:77") + + def test_to_json(self): + self.assertEqual( + "1:02:03", + IsoTimeTest.delta.to_json(datetime.timedelta(seconds=3723)) + ) + self.assertEqual( + "00:00:00", + IsoTimeTest.delta.to_json(None) + ) + self.assertEqual( + "0:01:40", + IsoTimeTest.delta.to_json(100.0) + ) + + with self.assertRaises(ValueError) as cm: + IsoTimeTest.delta.to_json(datetime.timedelta(seconds=90000)) + + self.assertEqual( + cm.exception.message, + "IsoTime max value is 23:59:59=86400.0 seconds, but 90000.0 seconds is passed" + ) + + with self.assertRaises(TypeError): + IsoTimeTest.delta.to_json("123")