diff --git a/requirements.txt b/requirements.txt index 7ae82855..48e5e5d2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ pbr>=0.5.21,<1.0 Babel>=1.3 PyYAML>=3.1.0 +python_dateutil>=2.4.0 diff --git a/translator/toscalib/dataentity.py b/translator/toscalib/dataentity.py index 06151b4e..a59b5baf 100644 --- a/translator/toscalib/dataentity.py +++ b/translator/toscalib/dataentity.py @@ -104,10 +104,14 @@ class DataEntity(object): return Constraint.validate_string(value) elif type == Schema.INTEGER: return Constraint.validate_integer(value) + elif type == Schema.FLOAT: + return Constraint.validate_float(value) elif type == Schema.NUMBER: return Constraint.validate_number(value) elif type == Schema.BOOLEAN: return Constraint.validate_boolean(value) + elif type == Schema.TIMESTAMP: + return Constraint.validate_timestamp(value) elif type == Schema.LIST: Constraint.validate_list(value) if entry_schema: diff --git a/translator/toscalib/elements/constraints.py b/translator/toscalib/elements/constraints.py index 4e9d4bd0..b60bed58 100644 --- a/translator/toscalib/elements/constraints.py +++ b/translator/toscalib/elements/constraints.py @@ -12,6 +12,7 @@ import collections import datetime +import dateutil.parser import math import numbers import re @@ -177,6 +178,12 @@ class Constraint(object): raise ValueError(_('"%s" is not an integer') % value) return Constraint.validate_number(value) + @staticmethod + def validate_float(value): + if not isinstance(value, float): + raise ValueError(_('"%s" is not a float') % value) + return Constraint.validate_number(value) + @staticmethod def validate_number(value): return Constraint.str_to_num(value) @@ -240,6 +247,10 @@ class Constraint(object): [unit.upper()], -1)) return converted + @staticmethod + def validate_timestamp(value): + return dateutil.parser.parse(value) + @staticmethod def str_to_num(value): '''Convert a string representation of a number into a numeric type.''' diff --git a/translator/toscalib/tests/test_properties.py b/translator/toscalib/tests/test_properties.py index 6c4640c9..e8b158e2 100644 --- a/translator/toscalib/tests/test_properties.py +++ b/translator/toscalib/tests/test_properties.py @@ -125,3 +125,60 @@ class PropertyTest(TestCase): test_property_schema) error = self.assertRaises(ValueError, propertyInstance.validate) self.assertEqual('"12" is not a boolean', str(error)) + + def test_float(self): + test_property_schema = {'type': 'float'} + propertyInstance = Property('test_property', 0.1, + test_property_schema) + self.assertIsNone(propertyInstance.validate()) + self.assertEqual(0.1, propertyInstance.value) + + def test_float_invalid(self): + test_property_schema = {'type': 'float'} + propertyInstance = Property('test_property', 12, + test_property_schema) + error = self.assertRaises(ValueError, propertyInstance.validate) + self.assertEqual('"12" is not a float', str(error)) + + def test_timestamp(self): + test_property_schema = {'type': 'timestamp'} + #canonical timestamp + propertyInstance = Property('test_property', '2015-04-01T02:59:43.1Z', + test_property_schema) + self.assertIsNone(propertyInstance.validate()) + self.assertEqual("2015-04-01T02:59:43.1Z", propertyInstance.value) + + #iso8601 timestamp + propertyInstance = Property('test_property', + '2015-04-01t21:59:43.10-05:00', + test_property_schema) + self.assertIsNone(propertyInstance.validate()) + self.assertEqual("2015-04-01t21:59:43.10-05:00", + propertyInstance.value) + + #space separated timestamp + propertyInstance = Property('test_property', + '2015-04-01 21:59:43.10 -5', + test_property_schema) + self.assertIsNone(propertyInstance.validate()) + self.assertEqual("2015-04-01 21:59:43.10 -5", propertyInstance.value) + + #no time zone timestamp + propertyInstance = Property('test_property', '2015-04-01 21:59:43.10', + test_property_schema) + self.assertIsNone(propertyInstance.validate()) + self.assertEqual("2015-04-01 21:59:43.10", propertyInstance.value) + + #date (00:00:00Z) + propertyInstance = Property('test_property', '2015-04-01', + test_property_schema) + self.assertIsNone(propertyInstance.validate()) + self.assertEqual("2015-04-01", propertyInstance.value) + + def test_timestamp_invalid(self): + test_property_schema = {'type': 'timestamp'} + #invalid timestamp - day out of range + propertyInstance = Property('test_property', '2015-04-115T02:59:43.1Z', + test_property_schema) + error = self.assertRaises(ValueError, propertyInstance.validate) + self.assertEqual('day is out of range for month', str(error))