Fix translation issue with interface inputs and functions
Fix the issue with interface inputs described using intrinsic functions, that produces an invalid HOT output. Also, include necessary unit tests, and revert templates that were simplified due to this issue.. This patch includes changes required in tosca-parser for resolving the issue. Change-Id: Iefde09d4633a1cadfe2c6b9ac28c58d2da79a37d Partial-Bug: #1440247
This commit is contained in:
parent
6a9483180d
commit
a80b6893c2
@ -14,10 +14,10 @@ import collections
|
||||
import datetime
|
||||
import re
|
||||
|
||||
import toscaparser
|
||||
from toscaparser.common.exception import InvalidSchemaError
|
||||
from toscaparser.common.exception import ValidationError
|
||||
from toscaparser.elements import scalarunit
|
||||
from toscaparser.functions import is_function
|
||||
from toscaparser.utils.gettextutils import _
|
||||
|
||||
|
||||
@ -262,7 +262,8 @@ class GreaterOrEqual(Constraint):
|
||||
'be comparable.'))
|
||||
|
||||
def _is_valid(self, value):
|
||||
if is_function(value) or value >= self.constraint_value:
|
||||
if toscaparser.functions.is_function(value) or \
|
||||
value >= self.constraint_value:
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -417,8 +418,8 @@ class ValidValues(Constraint):
|
||||
|
||||
def _err_msg(self, value):
|
||||
allowed = '[%s]' % ', '.join(str(a) for a in self.constraint_value)
|
||||
return (_('%(pname)s: %(pvalue)s is not an valid '
|
||||
'value "%(cvalue)s".') %
|
||||
return (_('%(pname)s: %(pvalue)s is not a valid value. Expected a '
|
||||
'value from "%(cvalue)s".') %
|
||||
dict(pname=self.property_name,
|
||||
pvalue=value,
|
||||
cvalue=allowed))
|
||||
|
@ -16,6 +16,7 @@ import abc
|
||||
import six
|
||||
|
||||
from toscaparser.common.exception import UnknownInputError
|
||||
from toscaparser.dataentity import DataEntity
|
||||
from toscaparser.utils.gettextutils import _
|
||||
|
||||
|
||||
@ -80,9 +81,15 @@ class GetInput(Function):
|
||||
raise UnknownInputError(input_name=self.args[0])
|
||||
|
||||
def result(self):
|
||||
found_input = [input_def for input_def in self.tosca_tpl.inputs
|
||||
if self.input_name == input_def.name][0]
|
||||
return found_input.default
|
||||
if self.tosca_tpl.parsed_params and \
|
||||
self.input_name in self.tosca_tpl.parsed_params:
|
||||
return DataEntity.validate_datatype(
|
||||
self.tosca_tpl.tpl['inputs'][self.input_name]['type'],
|
||||
self.tosca_tpl.parsed_params[self.input_name])
|
||||
|
||||
input = [input_def for input_def in self.tosca_tpl.inputs
|
||||
if self.input_name == input_def.name][0]
|
||||
return input.default
|
||||
|
||||
@property
|
||||
def input_name(self):
|
||||
@ -307,7 +314,7 @@ class GetProperty(Function):
|
||||
else:
|
||||
property_value = self._find_property(self.args[1]).value
|
||||
if isinstance(property_value, Function):
|
||||
return property_value
|
||||
return property_value.result()
|
||||
return get_function(self.tosca_tpl,
|
||||
self.context,
|
||||
property_value)
|
||||
|
@ -43,16 +43,14 @@ topology_template:
|
||||
properties:
|
||||
github_url: { get_input: github_url }
|
||||
requirements:
|
||||
- host:
|
||||
node: nodejs
|
||||
- database_connection:
|
||||
node: mongo_db
|
||||
- host: nodejs
|
||||
- database_connection: mongo_db
|
||||
interfaces:
|
||||
Standard:
|
||||
configure:
|
||||
implementation: ../Scripts/nodejs/config.sh
|
||||
inputs:
|
||||
github_url: http://github.com/paypal/rest-api-sample-app-nodejs.git
|
||||
github_url: { get_property: [ SELF, github_url ] }
|
||||
mongodb_ip: { get_attribute: [mongo_server, private_address] }
|
||||
start: ../Scripts/nodejs/start.sh
|
||||
nodejs:
|
||||
@ -66,16 +64,14 @@ topology_template:
|
||||
mongo_db:
|
||||
type: tosca.nodes.Database
|
||||
requirements:
|
||||
- host:
|
||||
node: mongo_dbms
|
||||
- host: mongo_dbms
|
||||
interfaces:
|
||||
Standard:
|
||||
create: ../Scripts/mongodb/create_database.sh
|
||||
mongo_dbms:
|
||||
type: tosca.nodes.DBMS
|
||||
requirements:
|
||||
- host:
|
||||
node: mongo_server
|
||||
- host: mongo_server
|
||||
interfaces:
|
||||
Standard:
|
||||
create: ../Scripts/mongodb/create.sh
|
||||
@ -87,8 +83,7 @@ topology_template:
|
||||
elasticsearch:
|
||||
type: tosca.nodes.SoftwareComponent.Elasticsearch
|
||||
requirements:
|
||||
- host:
|
||||
node: elasticsearch_server
|
||||
- host: elasticsearch_server
|
||||
interfaces:
|
||||
Standard:
|
||||
create: ../Scripts/elasticsearch/create.sh
|
||||
@ -96,8 +91,7 @@ topology_template:
|
||||
logstash:
|
||||
type: tosca.nodes.SoftwareComponent.Logstash
|
||||
requirements:
|
||||
- host:
|
||||
node: logstash_server
|
||||
- host: logstash_server
|
||||
- search_endpoint:
|
||||
node: elasticsearch
|
||||
capability: search_endpoint
|
||||
@ -116,11 +110,8 @@ topology_template:
|
||||
kibana:
|
||||
type: tosca.nodes.SoftwareComponent.Kibana
|
||||
requirements:
|
||||
- host:
|
||||
node: kibana_server
|
||||
- search_endpoint:
|
||||
node: elasticsearch
|
||||
capability: search_endpoint
|
||||
- host: kibana_server
|
||||
- search_endpoint: elasticsearch
|
||||
interfaces:
|
||||
Standard:
|
||||
create: ../Scripts/kibana/create.sh
|
||||
@ -133,8 +124,7 @@ topology_template:
|
||||
app_collectd:
|
||||
type: tosca.nodes.SoftwareComponent.Collectd
|
||||
requirements:
|
||||
- host:
|
||||
node: app_server
|
||||
- host: app_server
|
||||
- log_endpoint:
|
||||
node: logstash
|
||||
capability: log_endpoint
|
||||
@ -155,8 +145,7 @@ topology_template:
|
||||
app_rsyslog:
|
||||
type: tosca.nodes.SoftwareComponent.Rsyslog
|
||||
requirements:
|
||||
- host:
|
||||
node: app_server
|
||||
- host: app_server
|
||||
- log_endpoint:
|
||||
node: logstash
|
||||
capability: log_endpoint
|
||||
|
@ -33,10 +33,8 @@ topology_template:
|
||||
wordpress:
|
||||
type: tosca.nodes.WebApplication.WordPress
|
||||
requirements:
|
||||
- host:
|
||||
node: webserver
|
||||
- database_endpoint:
|
||||
node: mysql_database
|
||||
- host: webserver
|
||||
- database_endpoint: mysql_database
|
||||
interfaces:
|
||||
Standard:
|
||||
create: Scripts/WordPress/install.sh
|
||||
@ -54,8 +52,7 @@ topology_template:
|
||||
user: { get_input: db_user }
|
||||
password: { get_input: db_pwd }
|
||||
requirements:
|
||||
- host:
|
||||
node: mysql_dbms
|
||||
- host: mysql_dbms
|
||||
interfaces:
|
||||
Standard:
|
||||
configure:
|
||||
@ -72,8 +69,7 @@ topology_template:
|
||||
root_password: { get_input: db_root_pwd }
|
||||
port: { get_input: db_port }
|
||||
requirements:
|
||||
- host:
|
||||
node: server
|
||||
- host: server
|
||||
interfaces:
|
||||
Standard:
|
||||
create: Scripts/MYSQLDBMS/install.sh
|
||||
@ -86,8 +82,7 @@ topology_template:
|
||||
webserver:
|
||||
type: tosca.nodes.WebServer
|
||||
requirements:
|
||||
- host:
|
||||
node: server
|
||||
- host: server
|
||||
interfaces:
|
||||
Standard:
|
||||
create: Scripts/WebServer/install.sh
|
||||
|
@ -51,7 +51,7 @@ topology_template:
|
||||
configure:
|
||||
implementation: nodejs/config.sh
|
||||
inputs:
|
||||
github_url: http://github.com/paypal/rest-api-sample-app-nodejs.git
|
||||
github_url: { get_property: [ SELF, github_url ] }
|
||||
mongodb_ip: { get_attribute: [mongo_server, private_address] }
|
||||
start: nodejs/start.sh
|
||||
nodejs:
|
||||
@ -111,9 +111,7 @@ topology_template:
|
||||
type: tosca.nodes.SoftwareComponent.Kibana
|
||||
requirements:
|
||||
- host: kibana_server
|
||||
- search_endpoint:
|
||||
node: elasticsearch
|
||||
capability: search_endpoint
|
||||
- search_endpoint: elasticsearch
|
||||
interfaces:
|
||||
Standard:
|
||||
create: kibana/create.sh
|
||||
|
@ -46,9 +46,9 @@ topology_template:
|
||||
configure:
|
||||
implementation: wordpress/wordpress_configure.sh
|
||||
inputs:
|
||||
wp_db_name: wordpress
|
||||
wp_db_user: wp_user
|
||||
wp_db_password: wp_pass
|
||||
wp_db_name: { get_property: [ mysql_database, name ] }
|
||||
wp_db_user: { get_property: [ mysql_database, user ] }
|
||||
wp_db_password: { get_property: [ mysql_database, password ] }
|
||||
|
||||
mysql_database:
|
||||
type: tosca.nodes.Database
|
||||
@ -61,17 +61,17 @@ topology_template:
|
||||
properties:
|
||||
port: { get_input: db_port }
|
||||
requirements:
|
||||
- host:
|
||||
node: mysql_dbms
|
||||
- host: mysql_dbms
|
||||
interfaces:
|
||||
Standard:
|
||||
configure:
|
||||
implementation: mysql/mysql_database_configure.sh
|
||||
inputs:
|
||||
db_name: wordpress
|
||||
db_user: wp_user
|
||||
db_password: wp_pass
|
||||
db_root_password: passw0rd
|
||||
db_name: { get_property: [ SELF, name ] }
|
||||
db_user: { get_property: [ SELF, user ] }
|
||||
db_password: { get_property: [ SELF, password ] }
|
||||
db_root_password: { get_property: [ mysql_dbms, root_password ] }
|
||||
|
||||
mysql_dbms:
|
||||
type: tosca.nodes.DBMS
|
||||
properties:
|
||||
@ -84,12 +84,12 @@ topology_template:
|
||||
create:
|
||||
implementation: mysql/mysql_dbms_install.sh
|
||||
inputs:
|
||||
db_root_password: passw0rd
|
||||
db_root_password: { get_property: [ mysql_dbms, root_password ] }
|
||||
start: mysql/mysql_dbms_start.sh
|
||||
configure:
|
||||
implementation: mysql/mysql_dbms_configure.sh
|
||||
inputs:
|
||||
db_port: 3366
|
||||
db_port: { get_property: [ mysql_dbms, port ] }
|
||||
|
||||
webserver:
|
||||
type: tosca.nodes.WebServer
|
||||
@ -99,6 +99,7 @@ topology_template:
|
||||
Standard:
|
||||
create: webserver/webserver_install.sh
|
||||
start: webserver/webserver_start.sh
|
||||
|
||||
server:
|
||||
type: tosca.nodes.Compute
|
||||
capabilities:
|
||||
|
@ -100,8 +100,8 @@ class ConstraintTest(TestCase):
|
||||
constraint = Constraint('prop', Schema.INTEGER, schema)
|
||||
error = self.assertRaises(exception.ValidationError,
|
||||
constraint.validate, 5)
|
||||
self.assertEqual('prop: 5 is not an valid value "[2, 4, 6, 8]".',
|
||||
str(error))
|
||||
self.assertEqual('prop: 5 is not a valid value. Expected a value from '
|
||||
'"[2, 4, 6, 8]".', str(error))
|
||||
|
||||
def test_invalid_in_range(self):
|
||||
snippet = 'in_range: {2, 6}'
|
||||
|
@ -221,7 +221,7 @@ class DataTypeTest(TestCase):
|
||||
data = DataEntity('tosca.my.datatypes.PeopleBase', value,
|
||||
DataTypeTest.custom_type_def)
|
||||
error = self.assertRaises(ValueError, data.validate)
|
||||
self.assertEqual('"123" is not a string', error.__str__())
|
||||
self.assertEqual('"123" is not a string.', error.__str__())
|
||||
|
||||
# the value of name doesn't meet the defined constraint
|
||||
def test_value_error_in_dataentity(self):
|
||||
@ -247,7 +247,7 @@ class DataTypeTest(TestCase):
|
||||
data = DataEntity('tosca.my.datatypes.People', value,
|
||||
DataTypeTest.custom_type_def)
|
||||
error = self.assertRaises(ValueError, data.validate)
|
||||
self.assertEqual('"1" is not a string', error.__str__())
|
||||
self.assertEqual('"1" is not a string.', error.__str__())
|
||||
|
||||
# contact_pone is an invalid field name in nested datatype
|
||||
def test_validation_in_nested_datatype(self):
|
||||
@ -289,11 +289,11 @@ class DataTypeTest(TestCase):
|
||||
"data/datatypes/test_custom_datatypes_value_error.yaml")
|
||||
error = self.assertRaises(ValueError, ToscaTemplate, tpl_path)
|
||||
self.assertEqual('"[\'1 foo street\', \'9 bar avenue\']" '
|
||||
'is not a map', error.__str__())
|
||||
'is not a map.', error.__str__())
|
||||
|
||||
def test_datatype_in_template_nested_datatype_error(self):
|
||||
tpl_path = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"data/datatypes/test_custom_datatypes_nested_datatype_error.yaml")
|
||||
error = self.assertRaises(ValueError, ToscaTemplate, tpl_path)
|
||||
self.assertEqual('"123456789" is not a string', error.__str__())
|
||||
self.assertEqual('"123456789" is not a string.', error.__str__())
|
||||
|
@ -23,7 +23,8 @@ class IntrinsicFunctionsTest(TestCase):
|
||||
tosca_tpl = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"data/tosca_single_instance_wordpress.yaml")
|
||||
tosca = ToscaTemplate(tosca_tpl)
|
||||
params = {'db_name': 'my_wordpress', 'db_user': 'my_db_user'}
|
||||
tosca = ToscaTemplate(tosca_tpl, parsed_params=params)
|
||||
|
||||
def _get_node(self, node_name):
|
||||
return [
|
||||
@ -39,34 +40,30 @@ class IntrinsicFunctionsTest(TestCase):
|
||||
return [prop.value for prop in node_template.get_properties_objects()
|
||||
if prop.name == property_name][0]
|
||||
|
||||
def test_get_property(self):
|
||||
TestCase.skip(self, 'bug #1440247')
|
||||
mysql_dbms = self._get_node('mysql_dbms')
|
||||
operation = self._get_operation(mysql_dbms.interfaces, 'configure')
|
||||
db_root_password = operation.inputs['db_root_password']
|
||||
self.assertTrue(isinstance(db_root_password, functions.GetProperty))
|
||||
result = db_root_password.result()
|
||||
self.assertTrue(isinstance(result, functions.GetInput))
|
||||
def _get_inputs_dict(self):
|
||||
inputs = {}
|
||||
for input in self.tosca.inputs:
|
||||
inputs[input.name] = input.default
|
||||
return inputs
|
||||
|
||||
def test_get_requirement_property(self):
|
||||
TestCase.skip(self, 'bug #1440247')
|
||||
def _get_input(self, name):
|
||||
self._get_inputs_dict()[name]
|
||||
|
||||
def test_get_property(self):
|
||||
wordpress = self._get_node('wordpress')
|
||||
operation = self._get_operation(wordpress.interfaces, 'configure')
|
||||
wp_db_port = operation.inputs['wp_db_port']
|
||||
self.assertTrue(isinstance(wp_db_port, functions.GetProperty))
|
||||
result = wp_db_port.result()
|
||||
self.assertTrue(isinstance(result, functions.GetInput))
|
||||
self.assertEqual('db_port', result.input_name)
|
||||
wp_db_password = operation.inputs['wp_db_password']
|
||||
self.assertTrue(isinstance(wp_db_password, functions.GetProperty))
|
||||
result = wp_db_password.result()
|
||||
self.assertEqual('wp_pass', result)
|
||||
|
||||
def test_get_capability_property(self):
|
||||
TestCase.skip(self, 'bug #1440247')
|
||||
mysql_database = self._get_node('mysql_database')
|
||||
operation = self._get_operation(mysql_database.interfaces, 'configure')
|
||||
db_port = operation.inputs['db_port']
|
||||
self.assertTrue(isinstance(db_port, functions.GetProperty))
|
||||
result = db_port.result()
|
||||
self.assertTrue(isinstance(result, functions.GetInput))
|
||||
self.assertEqual('db_port', result.input_name)
|
||||
def test_get_property_with_input_param(self):
|
||||
wordpress = self._get_node('wordpress')
|
||||
operation = self._get_operation(wordpress.interfaces, 'configure')
|
||||
wp_db_user = operation.inputs['wp_db_user']
|
||||
self.assertTrue(isinstance(wp_db_user, functions.GetProperty))
|
||||
result = wp_db_user.result()
|
||||
self.assertEqual('my_db_user', result)
|
||||
|
||||
def test_unknown_capability_property(self):
|
||||
err = self.assertRaises(
|
||||
@ -87,13 +84,6 @@ class IntrinsicFunctionsTest(TestCase):
|
||||
expected_inputs.remove(prop.value.input_name)
|
||||
self.assertListEqual(expected_inputs, [])
|
||||
|
||||
def test_get_input_in_interface(self):
|
||||
TestCase.skip(self, 'bug #1440247')
|
||||
mysql_dbms = self._get_node('mysql_dbms')
|
||||
operation = self._get_operation(mysql_dbms.interfaces, 'configure')
|
||||
db_user = operation.inputs['db_user']
|
||||
self.assertTrue(isinstance(db_user, functions.GetInput))
|
||||
|
||||
def test_get_input_validation(self):
|
||||
self.assertRaises(exception.UnknownInputError,
|
||||
self._load_template,
|
||||
|
@ -44,7 +44,7 @@ class PropertyTest(TestCase):
|
||||
propertyInstance = Property('test_property', 'a',
|
||||
test_property_schema)
|
||||
error = self.assertRaises(ValueError, propertyInstance.validate)
|
||||
self.assertEqual('"a" is not a list', str(error))
|
||||
self.assertEqual('"a" is not a list.', str(error))
|
||||
|
||||
def test_list_entry_schema(self):
|
||||
test_property_schema = {'type': 'list',
|
||||
@ -73,8 +73,7 @@ class PropertyTest(TestCase):
|
||||
propertyInstance = Property('test_property', [1, 'b'],
|
||||
test_property_schema)
|
||||
error = self.assertRaises(ValueError, propertyInstance.validate)
|
||||
self.assertEqual('"b" is not an integer',
|
||||
str(error))
|
||||
self.assertEqual('"b" is not an integer.', str(error))
|
||||
|
||||
def test_map(self):
|
||||
test_property_schema = {'type': 'map'}
|
||||
@ -88,7 +87,7 @@ class PropertyTest(TestCase):
|
||||
propertyInstance = Property('test_property', 12,
|
||||
test_property_schema)
|
||||
error = self.assertRaises(ValueError, propertyInstance.validate)
|
||||
self.assertEqual('"12" is not a map', str(error))
|
||||
self.assertEqual('"12" is not a map.', str(error))
|
||||
|
||||
def test_map_entry_schema(self):
|
||||
test_property_schema = {'type': 'map',
|
||||
@ -107,7 +106,7 @@ class PropertyTest(TestCase):
|
||||
{'valid': True, 'contact_name': 123},
|
||||
test_property_schema)
|
||||
error = self.assertRaises(ValueError, propertyInstance.validate)
|
||||
self.assertEqual('"123" is not a boolean', str(error))
|
||||
self.assertEqual('"123" is not a boolean.', str(error))
|
||||
|
||||
def test_boolean(self):
|
||||
test_property_schema = {'type': 'boolean'}
|
||||
@ -124,7 +123,7 @@ class PropertyTest(TestCase):
|
||||
propertyInstance = Property('test_property', 12,
|
||||
test_property_schema)
|
||||
error = self.assertRaises(ValueError, propertyInstance.validate)
|
||||
self.assertEqual('"12" is not a boolean', str(error))
|
||||
self.assertEqual('"12" is not a boolean.', str(error))
|
||||
|
||||
def test_float(self):
|
||||
test_property_schema = {'type': 'float'}
|
||||
@ -138,7 +137,7 @@ class PropertyTest(TestCase):
|
||||
propertyInstance = Property('test_property', 12,
|
||||
test_property_schema)
|
||||
error = self.assertRaises(ValueError, propertyInstance.validate)
|
||||
self.assertEqual('"12" is not a float', str(error))
|
||||
self.assertEqual('"12" is not a float.', str(error))
|
||||
|
||||
def test_timestamp(self):
|
||||
test_property_schema = {'type': 'timestamp'}
|
||||
|
@ -68,7 +68,7 @@ class ToscaTemplateTest(TestCase):
|
||||
expected_type = "tosca.nodes.Database"
|
||||
expected_properties = ['name', 'password', 'user']
|
||||
expected_capabilities = ['database_endpoint']
|
||||
expected_requirements = [{'host': {'node': 'mysql_dbms'}}]
|
||||
expected_requirements = [{'host': 'mysql_dbms'}]
|
||||
''' TODO: needs enhancement in tosca_elk.yaml..
|
||||
expected_relationshp = ['tosca.relationships.HostedOn']
|
||||
expected_host = ['mysql_dbms']
|
||||
|
@ -730,7 +730,7 @@ custom_types/wordpress.yaml
|
||||
capability: log_endpoint
|
||||
occurrences: [a, w]
|
||||
'''
|
||||
expectedmessage = ('"a" is not an integer')
|
||||
expectedmessage = ('"a" is not an integer.')
|
||||
err = self.assertRaises(
|
||||
ValueError,
|
||||
lambda: self._single_node_template_content_test(tpl_snippet))
|
||||
@ -745,7 +745,7 @@ custom_types/wordpress.yaml
|
||||
capability: log_endpoint
|
||||
occurrences: -1
|
||||
'''
|
||||
expectedmessage = ('"-1" is not a list')
|
||||
expectedmessage = ('"-1" is not a list.')
|
||||
err = self.assertRaises(
|
||||
ValueError,
|
||||
lambda: self._single_node_template_content_test(tpl_snippet))
|
||||
@ -1000,7 +1000,7 @@ custom_types/wordpress.yaml
|
||||
lambda: self._single_node_template_content_test(tpl_snippet))
|
||||
self.assertEqual(expectedmessage, err.__str__())
|
||||
|
||||
# validatating capability property values
|
||||
# validating capability property values
|
||||
tpl_snippet = '''
|
||||
node_templates:
|
||||
server:
|
||||
@ -1010,8 +1010,8 @@ custom_types/wordpress.yaml
|
||||
properties:
|
||||
initiator: test
|
||||
'''
|
||||
expectedmessage = ('initiator: test is not an valid value '
|
||||
'"[source, target, peer]".')
|
||||
expectedmessage = ('initiator: test is not a valid value. Expected a '
|
||||
'value from "[source, target, peer]".')
|
||||
|
||||
err = self.assertRaises(
|
||||
exception.ValidationError,
|
||||
|
@ -42,31 +42,31 @@ def validate_integer(value):
|
||||
try:
|
||||
value = int(value)
|
||||
except Exception:
|
||||
raise ValueError(_('"%s" is not an integer') % value)
|
||||
raise ValueError(_('"%s" is not an integer.') % value)
|
||||
return value
|
||||
|
||||
|
||||
def validate_float(value):
|
||||
if not isinstance(value, float):
|
||||
raise ValueError(_('"%s" is not a float') % value)
|
||||
raise ValueError(_('"%s" is not a float.') % value)
|
||||
return validate_number(value)
|
||||
|
||||
|
||||
def validate_string(value):
|
||||
if not isinstance(value, six.string_types):
|
||||
raise ValueError(_('"%s" is not a string') % value)
|
||||
raise ValueError(_('"%s" is not a string.') % value)
|
||||
return value
|
||||
|
||||
|
||||
def validate_list(value):
|
||||
if not isinstance(value, list):
|
||||
raise ValueError(_('"%s" is not a list') % value)
|
||||
raise ValueError(_('"%s" is not a list.') % value)
|
||||
return value
|
||||
|
||||
|
||||
def validate_map(value):
|
||||
if not isinstance(value, collections.Mapping):
|
||||
raise ValueError(_('"%s" is not a map') % value)
|
||||
raise ValueError(_('"%s" is not a map.') % value)
|
||||
return value
|
||||
|
||||
|
||||
@ -78,7 +78,7 @@ def validate_boolean(value):
|
||||
normalised = value.lower()
|
||||
if normalised in ['true', 'false']:
|
||||
return normalised == 'true'
|
||||
raise ValueError(_('"%s" is not a boolean') % value)
|
||||
raise ValueError(_('"%s" is not a boolean.') % value)
|
||||
|
||||
|
||||
def validate_timestamp(value):
|
||||
|
Loading…
x
Reference in New Issue
Block a user