From 80bc4fbebd02961decc4e58bbc149a8614c18b92 Mon Sep 17 00:00:00 2001 From: rabi Date: Fri, 26 Aug 2016 17:05:54 +0530 Subject: [PATCH] Convert props form delimited params to lists Use allow_conversion flag to convert comma_delimited_list to list before validation when using from_parameter. Change-Id: Id144aade23eee13df227acdb728906c8dd345337 Closes-Bug: #1617019 --- heat/common/param_utils.py | 10 ++++++++++ heat/engine/parameters.py | 6 ++---- heat/engine/properties.py | 7 ++++++- heat/tests/test_properties.py | 9 ++++++++- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/heat/common/param_utils.py b/heat/common/param_utils.py index 8c835d1069..f3655a1303 100644 --- a/heat/common/param_utils.py +++ b/heat/common/param_utils.py @@ -28,6 +28,16 @@ def extract_bool(name, value): return strutils.bool_from_string(value, strict=True) +def delim_string_to_list(value): + if value is None: + return None + + if value == '': + return [] + + return value.split(',') + + def extract_int(name, value, allow_zero=True, allow_negative=False): if value is None: return None diff --git a/heat/engine/parameters.py b/heat/engine/parameters.py index bc524b53fe..a110babc6b 100644 --- a/heat/engine/parameters.py +++ b/heat/engine/parameters.py @@ -21,6 +21,7 @@ import six from heat.common import exception from heat.common.i18n import _ +from heat.common import param_utils from heat.engine import constraints as constr @@ -376,10 +377,7 @@ class CommaDelimitedListParam(ParsedParameter, collections.Sequence): if isinstance(value, list): return [(six.text_type(x)) for x in value] try: - if value is not None: - if value == '': - return [] - return value.split(',') + return param_utils.delim_string_to_list(value) except (KeyError, AttributeError) as err: message = _('Value must be a comma-delimited list string: %s') raise ValueError(message % six.text_type(err)) diff --git a/heat/engine/properties.py b/heat/engine/properties.py index 674248f477..92d4ac4da6 100644 --- a/heat/engine/properties.py +++ b/heat/engine/properties.py @@ -18,6 +18,7 @@ import six from heat.common import exception from heat.common.i18n import _ +from heat.common import param_utils from heat.engine import constraints as constr from heat.engine import function from heat.engine.hot import parameters as hot_param @@ -162,7 +163,8 @@ class Schema(constr.Schema): # a json parameter value is passed via a Map property, which requires # some coercion to pass strings or lists (which are both valid for # Json parameters but not for Map properties). - allow_conversion = param.type == param.MAP + allow_conversion = (param.type == param.MAP + or param.type == param.LIST) # make update_allowed true by default on TemplateResources # as the template should deal with this. @@ -299,6 +301,9 @@ class Property(object): def _get_list(self, value, validate=False): if value is None: value = self.has_default() and self.default() or [] + if self.schema.allow_conversion and isinstance(value, + six.string_types): + value = param_utils.delim_string_to_list(value) if (not isinstance(value, collections.Sequence) or isinstance(value, six.string_types)): raise TypeError(_('"%s" is not a list') % repr(value)) diff --git a/heat/tests/test_properties.py b/heat/tests/test_properties.py index 8380a00a6d..2276da5238 100644 --- a/heat/tests/test_properties.py +++ b/heat/tests/test_properties.py @@ -598,7 +598,7 @@ class PropertySchemaTest(common.HeatTestCase): self.assertEqual(properties.Schema.LIST, schema.type) self.assertIsNone(schema.default) self.assertFalse(schema.required) - self.assertFalse(schema.allow_conversion) + self.assertTrue(schema.allow_conversion) props = properties.Properties({'test': schema}, {}) props.validate() @@ -903,6 +903,13 @@ class PropertyTest(common.HeatTestCase): p = properties.Property({'Type': 'List'}) self.assertRaises(TypeError, p.get_value, {'foo': 'bar'}) + def test_list_is_delimited(self): + p = properties.Property({'Type': 'List'}) + self.assertRaises(TypeError, p.get_value, 'foo,bar') + p.schema.allow_conversion = True + self.assertEqual(['foo', 'bar'], p.get_value('foo,bar')) + self.assertEqual(['foo'], p.get_value('foo')) + def test_list_maxlength_good(self): schema = {'Type': 'List', 'MaxLength': '3'}