Add Schema parent class for Property, Input, Output

Add a Schema class that handle all schema-related information
(description, type, constraints, required etc) of Property,
Input, Output.

Change-Id: Ic4e4e5e1a5fa29fc3d668c295d6b2ea85eecb0cd
Closes-Bug:#1349457
This commit is contained in:
Yaoguo Jiang 2014-07-29 08:26:27 +00:00
parent ccefa3514e
commit 853fb5c2b6
7 changed files with 253 additions and 169 deletions

View File

@ -65,11 +65,8 @@ class TranslateInputs():
hot_constraints = []
if input.constraints:
for constraint in input.constraints:
for name, value in constraint.items():
constraint_name = name
value = value
hc, hvalue = self._translate_constraints(constraint_name,
value)
hc, hvalue = self._translate_constraints(
constraint.constraint_key, constraint.constraint_value)
hot_constraints.append({hc: hvalue})
cli_value = self.parsed_params[input.name]
hot_inputs.append(HotParameter(name=input.name,

View File

@ -72,3 +72,11 @@ class TypeMismatchError(TOSCAException):
class InvalidNodeTypeError(TOSCAException):
msg_fmt = _('Node type "%(what)s" is not a valid type.')
class InvalidSchemaError(TOSCAException):
msg_fmt = _("%(message)s")
class ValidationError(TOSCAException):
msg_fmt = _("%(message)s")

View File

@ -18,16 +18,86 @@ import datetime
import numbers
import re
from translator.toscalib.common.exception import InvalidSchemaError
from translator.toscalib.common.exception import ValidationError
from translator.toscalib.utils.gettextutils import _
class ValidationError(Exception):
class Schema(collections.Mapping):
def __init__(self, message):
self.message = message
KEYS = (
TYPE, REQUIRED, DESCRIPTION, DEFAULT, CONSTRAINTS,
) = (
'type', 'required', 'description', 'default', 'constraints'
)
def __str__(self):
return str(self.message)
PROPERTY_TYPES = (
INTEGER, STRING, BOOLEAN,
FLOAT, TIMESTAMP
) = (
'integer', 'string', 'boolean',
'float', 'timestamp'
)
def __init__(self, name, schema_dict):
self.name = name
if not isinstance(schema_dict, collections.Mapping):
msg = _("Schema %(pname)s must be a dict.") % dict(pname=name)
raise InvalidSchemaError(message=msg)
try:
schema_dict['type']
except KeyError:
msg = _("Schema %(pname)s must have type.") % dict(pname=name)
raise InvalidSchemaError(message=msg)
self.schema = schema_dict
self._len = None
self.constraints_list = []
@property
def type(self):
return self.schema[self.TYPE]
@property
def required(self):
return self.schema.get(self.REQUIRED, False)
@property
def description(self):
return self.schema.get(self.DESCRIPTION, '')
@property
def default(self):
return self.schema.get(self.DEFAULT)
@property
def constraints(self):
if not self.constraints_list:
constraint_schemata = self.schema.get(self.CONSTRAINTS)
if constraint_schemata:
self.constraints_list = [Constraint(self.name,
self.type,
cschema)
for cschema in constraint_schemata]
return self.constraints_list
def __getitem__(self, key):
return self.schema[key]
def __iter__(self):
for k in self.KEYS:
try:
self.schema[k]
except KeyError:
pass
else:
yield k
def __len__(self):
if self._len is None:
self._len = len(list(iter(self)))
return self._len
class Constraint(object):
@ -40,27 +110,19 @@ class Constraint(object):
'less_or_equal', 'in_range', 'valid_values', 'length',
'min_length', 'max_length', 'pattern')
PROPERTY_TYPES = (
INTEGER, STRING, BOOLEAN,
FLOAT, TIMESTAMP
) = (
'integer', 'string', 'boolean',
'float', 'timestamp'
)
def __new__(cls, property_name, property_type, constraint):
if cls is not Constraint:
return super(Constraint, cls).__new__(cls)
if(not isinstance(constraint, collections.Mapping) or
len(constraint) != 1):
raise ValidationError(_('Invalid constraint schema.'))
raise InvalidSchemaError(message=_('Invalid constraint schema.'))
for type in constraint.keys():
ConstraintClass = get_constraint_class(type)
if not ConstraintClass:
raise ValidationError(_('Invalid constraint type "%s".') %
type)
msg = _('Invalid constraint type "%s".') % type
raise InvalidSchemaError(message=msg)
return ConstraintClass(property_name, property_type, constraint)
@ -70,10 +132,11 @@ class Constraint(object):
self.constraint_value = constraint[self.constraint_key]
# check if constraint is valid for property type
if property_type not in self.valid_prop_types:
raise ValidationError(_('Constraint type "%(ctype)s" is not valid '
'for data type "%(dtype)s".') %
{'ctype': self.constraint_key,
'dtype': property_type})
msg = _('Constraint type "%(ctype)s" is not valid '
'for data type "%(dtype)s".') % dict(
ctype=self.constraint_key,
dtype=property_type)
raise InvalidSchemaError(message=msg)
def _err_msg(self, value):
return _('Property %s could not be validated.') % self.property_name
@ -81,7 +144,7 @@ class Constraint(object):
def validate(self, value):
if not self._is_valid(value):
err_msg = self._err_msg(value)
raise ValidationError(err_msg)
raise ValidationError(message=err_msg)
@staticmethod
def validate_integer(value):
@ -125,7 +188,7 @@ class Equal(Constraint):
constraint_key = Constraint.EQUAL
valid_prop_types = Constraint.PROPERTY_TYPES
valid_prop_types = Schema.PROPERTY_TYPES
def _is_valid(self, value):
if value == self.constraint_value:
@ -152,14 +215,15 @@ class GreaterThan(Constraint):
valid_types = (int, float, datetime.date,
datetime.time, datetime.datetime)
valid_prop_types = (Constraint.INTEGER, Constraint.FLOAT,
Constraint.TIMESTAMP)
valid_prop_types = (Schema.INTEGER, Schema.FLOAT,
Schema.TIMESTAMP)
def __init__(self, property_name, property_type, constraint):
super(GreaterThan, self).__init__(property_name, property_type,
constraint)
if not isinstance(constraint[self.GREATER_THAN], self.valid_types):
raise ValidationError(_('greater_than must be comparable.'))
raise InvalidSchemaError(message=_('greater_than must '
'be comparable.'))
def _is_valid(self, value):
if value > self.constraint_value:
@ -186,14 +250,15 @@ class GreaterOrEqual(Constraint):
valid_types = (int, float, datetime.date,
datetime.time, datetime.datetime)
valid_prop_types = (Constraint.INTEGER, Constraint.FLOAT,
Constraint.TIMESTAMP)
valid_prop_types = (Schema.INTEGER, Schema.FLOAT,
Schema.TIMESTAMP)
def __init__(self, property_name, property_type, constraint):
super(GreaterOrEqual, self).__init__(property_name, property_type,
constraint)
if not isinstance(self.constraint_value, self.valid_types):
raise ValidationError(_('greater_or_equal must be comparable.'))
raise InvalidSchemaError(message=_('greater_or_equal must '
'be comparable.'))
def _is_valid(self, value):
if value >= self.constraint_value:
@ -221,14 +286,15 @@ class LessThan(Constraint):
valid_types = (int, float, datetime.date,
datetime.time, datetime.datetime)
valid_prop_types = (Constraint.INTEGER, Constraint.FLOAT,
Constraint.TIMESTAMP)
valid_prop_types = (Schema.INTEGER, Schema.FLOAT,
Schema.TIMESTAMP)
def __init__(self, property_name, property_type, constraint):
super(LessThan, self).__init__(property_name, property_type,
constraint)
if not isinstance(self.constraint_value, self.valid_types):
raise ValidationError(_('less_than must be comparable.'))
raise InvalidSchemaError(message=_('less_than must '
'be comparable.'))
def _is_valid(self, value):
if value < self.constraint_value:
@ -255,14 +321,15 @@ class LessOrEqual(Constraint):
valid_types = (int, float, datetime.date,
datetime.time, datetime.datetime)
valid_prop_types = (Constraint.INTEGER, Constraint.FLOAT,
Constraint.TIMESTAMP)
valid_prop_types = (Schema.INTEGER, Schema.FLOAT,
Schema.TIMESTAMP)
def __init__(self, property_name, property_type, constraint):
super(LessOrEqual, self).__init__(property_name, property_type,
constraint)
if not isinstance(self.constraint_value, self.valid_types):
raise ValidationError(_('less_or_equal must be comparable.'))
raise InvalidSchemaError(message=_('less_or_equal must '
'be comparable.'))
def _is_valid(self, value):
if value <= self.constraint_value:
@ -290,18 +357,19 @@ class InRange(Constraint):
valid_types = (int, float, datetime.date,
datetime.time, datetime.datetime)
valid_prop_types = (Constraint.INTEGER, Constraint.FLOAT,
Constraint.TIMESTAMP)
valid_prop_types = (Schema.INTEGER, Schema.FLOAT,
Schema.TIMESTAMP)
def __init__(self, property_name, property_type, constraint):
super(InRange, self).__init__(property_name, property_type, constraint)
if(not isinstance(self.constraint_value, collections.Sequence) or
(len(constraint[self.IN_RANGE]) != 2)):
raise ValidationError(_('in_range must be a list.'))
raise InvalidSchemaError(message=_('in_range must be a list.'))
for value in self.constraint_value:
if not isinstance(value, self.valid_types):
raise ValidationError(_('in_range value must be comparable.'))
raise InvalidSchemaError(_('in_range value must '
'be comparable.'))
self.min = self.constraint_value[0]
self.max = self.constraint_value[1]
@ -331,13 +399,13 @@ class ValidValues(Constraint):
"""
constraint_key = Constraint.VALID_VALUES
valid_prop_types = Constraint.PROPERTY_TYPES
valid_prop_types = Schema.PROPERTY_TYPES
def __init__(self, property_name, property_type, constraint):
super(ValidValues, self).__init__(property_name, property_type,
constraint)
if not isinstance(self.constraint_value, collections.Sequence):
raise ValidationError(_('valid_values must be a list.'))
raise InvalidSchemaError(message=_('valid_values must be a list.'))
def _is_valid(self, value):
if isinstance(value, collections.Sequence):
@ -363,12 +431,12 @@ class Length(Constraint):
valid_types = (int, )
valid_prop_types = (Constraint.STRING, )
valid_prop_types = (Schema.STRING, )
def __init__(self, property_name, property_type, constraint):
super(Length, self).__init__(property_name, property_type, constraint)
if not isinstance(self.constraint_value, self.valid_types):
raise ValidationError(_('length must be integer.'))
raise InvalidSchemaError(message=_('length must be integer.'))
def _is_valid(self, value):
if isinstance(value, str) and len(value) == self.constraint_value:
@ -394,13 +462,13 @@ class MinLength(Constraint):
valid_types = (int, )
valid_prop_types = (Constraint.STRING, )
valid_prop_types = (Schema.STRING, )
def __init__(self, property_name, property_type, constraint):
super(MinLength, self).__init__(property_name, property_type,
constraint)
if not isinstance(self.constraint_value, self.valid_types):
raise ValidationError(_('min_length must be integer.'))
raise InvalidSchemaError(message=_('min_length must be integer.'))
def _is_valid(self, value):
if isinstance(value, str) and len(value) >= self.constraint_value:
@ -426,13 +494,13 @@ class MaxLength(Constraint):
valid_types = (int, )
valid_prop_types = (Constraint.STRING, )
valid_prop_types = (Schema.STRING, )
def __init__(self, property_name, property_type, constraint):
super(MaxLength, self).__init__(property_name, property_type,
constraint)
if not isinstance(self.constraint_value, self.valid_types):
raise ValidationError(_('max_length must be integer.'))
raise InvalidSchemaError(message=_('max_length must be integer.'))
def _is_valid(self, value):
if isinstance(value, str) and len(value) <= self.constraint_value:
@ -459,12 +527,12 @@ class Pattern(Constraint):
valid_types = (str, )
valid_prop_types = (Constraint.STRING, )
valid_prop_types = (Schema.STRING, )
def __init__(self, property_name, property_type, constraint):
super(Pattern, self).__init__(property_name, property_type, constraint)
if not isinstance(self.constraint_value, self.valid_types):
raise ValidationError(_('pattern must be string.'))
raise InvalidSchemaError(message=_('pattern must be string.'))
self.match = re.compile(self.constraint_value).match
def _is_valid(self, value):

View File

@ -18,8 +18,7 @@ import logging
from translator.toscalib.common.exception import MissingRequiredFieldError
from translator.toscalib.common.exception import UnknownFieldError
from translator.toscalib.elements.constraints import Constraint
from translator.toscalib.properties import Property
from translator.toscalib.elements.constraints import Schema
log = logging.getLogger('tosca')
@ -30,57 +29,40 @@ class Input(object):
INPUTFIELD = (TYPE, DESCRIPTION, DEFAULT, CONSTRAINTS) = \
('type', 'description', 'default', 'constraints')
def __init__(self, name, schema):
def __init__(self, name, schema_dict):
self.name = name
self.schema = schema
self.schema = Schema(name, schema_dict)
@property
def type(self):
return self.schema[self.TYPE]
return self.schema.type
@property
def description(self):
if Property.DESCRIPTION in self.schema:
return self.schema[self.DESCRIPTION]
return self.schema.description
@property
def default(self):
if self.Property.DEFAULT in self.schema:
return self.schema[self.DEFAULT]
return self.schema.default
@property
def constraints(self):
if Property.CONSTRAINTS in self.schema:
return self.schema[self.CONSTRAINTS]
return self.schema.constraints
def validate(self):
self._validate_field()
self.validate_type(self.type)
if self.constraints:
self.validate_constraints(self.constraints)
def _validate_field(self):
if not isinstance(self.schema, dict):
raise MissingRequiredFieldError(what='Input %s' % self.name,
required=self.TYPE)
try:
self.type
except KeyError:
raise MissingRequiredFieldError(what='Input %s' % self.name,
required=self.TYPE)
for name in self.schema:
if name not in self.INPUTFIELD:
raise UnknownFieldError(what='Input %s' % self.name,
field=name)
def validate_type(self, input_type):
if input_type not in Constraint.PROPERTY_TYPES:
if input_type not in Schema.PROPERTY_TYPES:
raise ValueError(_('Invalid type %s') % type)
def validate_constraints(self, constraints):
for constraint in constraints:
Constraint(self.name, self.type, constraint)
class Output(object):

View File

@ -14,6 +14,7 @@
# under the License.
from translator.toscalib.elements.constraints import Constraint
from translator.toscalib.elements.constraints import Schema
class Property(object):
@ -25,29 +26,30 @@ class Property(object):
'type', 'required', 'description', 'default', 'constraints'
)
def __init__(self, property_name, value, schema=None):
def __init__(self, property_name, value, schema_dict):
self.name = property_name
self.value = value
self.schema = schema
self.schema = Schema(property_name, schema_dict)
@property
def constraints(self):
try:
if self.CONSTRAINTS in self.schema:
return self.schema[self.CONSTRAINTS]
except Exception:
#Simply passing the exception to ignore Node Type in-line value.
#Exception will not be needed when Node Type and Node Template
#properties are separated.
#TODO(spzala)
pass
def type(self):
return self.schema.type
@property
def required(self):
return self.schema.required
@property
def description(self):
if self.schema:
if self.DESCRIPTION in self.schema:
return self.schema[self.DESCRIPTION]
return ''
return self.schema.description
@property
def default(self):
return self.schema.default
@property
def constraints(self):
return self.schema.constraints
def validate(self):
'''Validate if not a reference property.'''
@ -57,23 +59,19 @@ class Property(object):
def _validate_datatype(self):
try:
if self.TYPE in self.schema:
dtype = self.schema[self.TYPE]
if dtype == Constraint.STRING:
return Constraint.validate_string(self.value)
elif dtype == Constraint.INTEGER:
return Constraint.validate_integer(self.value)
elif dtype == Constraint.NUMBER:
return Constraint.validate_number(self.value)
elif dtype == Constraint.LIST:
return Constraint.validate_list(self.value)
dtype = self.type
if dtype == Schema.STRING:
return Constraint.validate_string(self.value)
elif dtype == Schema.INTEGER:
return Constraint.validate_integer(self.value)
elif dtype == Schema.NUMBER:
return Constraint.validate_number(self.value)
elif dtype == Schema.LIST:
return Constraint.validate_list(self.value)
except Exception:
pass
def _validate_constraints(self):
constraints = self.constraints
dtype = self.schema[self.TYPE]
if constraints:
for constraint in constraints:
Constraint(self.name, dtype,
constraint).validate(self.value)
if self.constraints:
for constraint in self.constraints:
constraint.validate(self.value)

View File

@ -16,43 +16,92 @@
import datetime
import yaml
from translator.toscalib.common.exception import InvalidSchemaError
from translator.toscalib.common.exception import ValidationError
from translator.toscalib.elements.constraints import Constraint
from translator.toscalib.elements.constraints import ValidationError
from translator.toscalib.elements.constraints import Schema
from translator.toscalib.tests.base import TestCase
from translator.toscalib.utils import yamlparser
class ConstraintTest(TestCase):
def test_schema_dict(self):
tpl_snippet = '''
cpus:
type: integer
description: Number of CPUs for the server.
'''
schema = yamlparser.simple_parse(tpl_snippet)
cpus_schema = Schema('cpus', schema['cpus'])
self.assertEqual(len(cpus_schema), 2)
self.assertEqual('integer', cpus_schema.type)
self.assertEqual('Number of CPUs for the server.',
cpus_schema.description)
self.assertEqual(False, cpus_schema.required)
self.assertIsNone(cpus_schema.default)
def test_schema_not_dict(self):
tpl_snippet = '''
cpus:
- type: integer
- description: Number of CPUs for the server.
'''
schema = yamlparser.simple_parse(tpl_snippet)
error = self.assertRaises(InvalidSchemaError, Schema,
'cpus', schema['cpus'])
self.assertEqual('Schema cpus must be a dict.', str(error))
def test_schema_miss_type(self):
tpl_snippet = '''
cpus:
description: Number of CPUs for the server.
'''
schema = yamlparser.simple_parse(tpl_snippet)
error = self.assertRaises(InvalidSchemaError, Schema,
'cpus', schema['cpus'])
self.assertEqual('Schema cpus must have type.', str(error))
def test_schema_none_description(self):
tpl_snippet = '''
cpus:
type: integer
'''
schema = yamlparser.simple_parse(tpl_snippet)
cpus_schema = Schema('cpus', schema['cpus'])
self.assertEqual('', cpus_schema.description)
def test_invalid_constraint_type(self):
schema = {'invalid_type': 2}
error = self.assertRaises(ValidationError, Constraint,
'prop', Constraint.INTEGER,
error = self.assertRaises(InvalidSchemaError, Constraint,
'prop', Schema.INTEGER,
schema)
self.assertEqual('Invalid constraint type "invalid_type".',
str(error))
def test_invalid_prop_type(self):
schema = {'length': 5}
error = self.assertRaises(ValidationError, Constraint,
'prop', Constraint.INTEGER,
error = self.assertRaises(InvalidSchemaError, Constraint,
'prop', Schema.INTEGER,
schema)
self.assertEqual('Constraint type "length" is not valid for '
'data type "integer".', str(error))
def test_invalid_validvalues(self):
schema = {'valid_values': 2}
error = self.assertRaises(ValidationError, Constraint,
'prop', Constraint.INTEGER,
error = self.assertRaises(InvalidSchemaError, Constraint,
'prop', Schema.INTEGER,
schema)
self.assertEqual('valid_values must be a list.', str(error))
def test_validvalues_validate(self):
schema = {'valid_values': [2, 4, 6, 8]}
constraint = Constraint('prop', Constraint.INTEGER, schema)
constraint = Constraint('prop', Schema.INTEGER, schema)
self.assertIsNone(constraint.validate(4))
def test_validvalues_validate_fail(self):
schema = {'valid_values': [2, 4, 6, 8]}
constraint = Constraint('prop', Constraint.INTEGER, schema)
constraint = Constraint('prop', Schema.INTEGER, schema)
error = self.assertRaises(ValidationError, constraint.validate, 5)
self.assertEqual('prop: 5 is not an valid value "[2, 4, 6, 8]".',
str(error))
@ -60,50 +109,50 @@ class ConstraintTest(TestCase):
def test_invalid_in_range(self):
snippet = 'in_range: {2, 6}'
schema = yaml.load(snippet)
error = self.assertRaises(ValidationError, Constraint,
'prop', Constraint.INTEGER,
error = self.assertRaises(InvalidSchemaError, Constraint,
'prop', Schema.INTEGER,
schema)
self.assertEqual('in_range must be a list.', str(error))
def test_in_range_min_max(self):
schema = {'in_range': [2, 6]}
constraint = Constraint('prop', Constraint.INTEGER, schema)
constraint = Constraint('prop', Schema.INTEGER, schema)
self.assertEqual(2, constraint.min)
self.assertEqual(6, constraint.max)
def test_in_range_validate(self):
schema = {'in_range': [2, 6]}
constraint = Constraint('prop', Constraint.INTEGER, schema)
constraint = Constraint('prop', Schema.INTEGER, schema)
self.assertIsNone(constraint.validate(2))
self.assertIsNone(constraint.validate(4))
self.assertIsNone(constraint.validate(6))
def test_in_range_validate_fail(self):
schema = {'in_range': [2, 6]}
constraint = Constraint('prop', Constraint.INTEGER, schema)
constraint = Constraint('prop', Schema.INTEGER, schema)
error = self.assertRaises(ValidationError, constraint.validate, 8)
self.assertEqual('prop: 8 is out of range (min:2, max:6).',
str(error))
def test_equal_validate(self):
schema = {'equal': 4}
constraint = Constraint('prop', Constraint.INTEGER, schema)
constraint = Constraint('prop', Schema.INTEGER, schema)
self.assertIsNone(constraint.validate(4))
def test_equal_validate_fail(self):
schema = {'equal': 4}
constraint = Constraint('prop', Constraint.INTEGER, schema)
constraint = Constraint('prop', Schema.INTEGER, schema)
error = self.assertRaises(ValidationError, constraint.validate, 8)
self.assertEqual('prop: 8 is not equal to "4".', str(error))
def test_greater_than_validate(self):
schema = {'greater_than': 4}
constraint = Constraint('prop', Constraint.INTEGER, schema)
constraint = Constraint('prop', Schema.INTEGER, schema)
self.assertIsNone(constraint.validate(6))
def test_greater_than_validate_fail(self):
schema = {'greater_than': 4}
constraint = Constraint('prop', Constraint.INTEGER, schema)
constraint = Constraint('prop', Schema.INTEGER, schema)
error = self.assertRaises(ValidationError, constraint.validate, 3)
self.assertEqual('prop: 3 must be greater than "4".', str(error))
@ -112,13 +161,13 @@ class ConstraintTest(TestCase):
def test_greater_or_equal_validate(self):
schema = {'greater_or_equal': 3.9}
constraint = Constraint('prop', Constraint.FLOAT, schema)
constraint = Constraint('prop', Schema.FLOAT, schema)
self.assertIsNone(constraint.validate(3.9))
self.assertIsNone(constraint.validate(4.0))
def test_greater_or_equal_validate_fail(self):
schema = {'greater_or_equal': 3.9}
constraint = Constraint('prop', Constraint.FLOAT, schema)
constraint = Constraint('prop', Schema.FLOAT, schema)
error = self.assertRaises(ValidationError, constraint.validate, 3.0)
self.assertEqual('prop: 3.0 must be greater or equal to "3.9".',
str(error))
@ -129,13 +178,13 @@ class ConstraintTest(TestCase):
def test_less_than_validate(self):
schema = {'less_than': datetime.date(2014, 0o7, 25)}
constraint = Constraint('prop', Constraint.TIMESTAMP, schema)
constraint = Constraint('prop', Schema.TIMESTAMP, schema)
self.assertIsNone(constraint.validate(datetime.date(2014, 0o7, 20)))
self.assertIsNone(constraint.validate(datetime.date(2014, 0o7, 24)))
def test_less_than_validate_fail(self):
schema = {'less_than': datetime.date(2014, 0o7, 25)}
constraint = Constraint('prop', Constraint.TIMESTAMP, schema)
constraint = Constraint('prop', Schema.TIMESTAMP, schema)
error = self.assertRaises(ValidationError,
constraint.validate,
datetime.date(2014, 0o7, 25))
@ -152,37 +201,37 @@ class ConstraintTest(TestCase):
def test_less_or_equal_validate(self):
schema = {'less_or_equal': 4}
constraint = Constraint('prop', Constraint.INTEGER, schema)
constraint = Constraint('prop', Schema.INTEGER, schema)
self.assertIsNone(constraint.validate(4))
self.assertIsNone(constraint.validate(3))
def test_less_or_equal_validate_fail(self):
schema = {'less_or_equal': 4}
constraint = Constraint('prop', Constraint.INTEGER, schema)
constraint = Constraint('prop', Schema.INTEGER, schema)
error = self.assertRaises(ValidationError, constraint.validate, 5)
self.assertEqual('prop: 5 must be less or equal to "4".', str(error))
def test_invalid_length(self):
schema = {'length': 'four'}
error = self.assertRaises(ValidationError, Constraint,
'prop', Constraint.STRING,
error = self.assertRaises(InvalidSchemaError, Constraint,
'prop', Schema.STRING,
schema)
self.assertEqual('length must be integer.', str(error))
schema = {'length': 4.5}
error = self.assertRaises(ValidationError, Constraint,
'prop', Constraint.STRING,
error = self.assertRaises(InvalidSchemaError, Constraint,
'prop', Schema.STRING,
schema)
self.assertEqual('length must be integer.', str(error))
def test_length_validate(self):
schema = {'length': 4}
constraint = Constraint('prop', Constraint.STRING, schema)
constraint = Constraint('prop', Schema.STRING, schema)
self.assertIsNone(constraint.validate('abcd'))
def test_length_validate_fail(self):
schema = {'length': 4}
constraint = Constraint('prop', Constraint.STRING, schema)
constraint = Constraint('prop', Schema.STRING, schema)
error = self.assertRaises(ValidationError, constraint.validate, 'abc')
self.assertEqual('length of prop: abc must be equal to "4".',
str(error))
@ -195,40 +244,40 @@ class ConstraintTest(TestCase):
def test_invalid_min_length(self):
schema = {'min_length': 'four'}
error = self.assertRaises(ValidationError, Constraint,
'prop', Constraint.STRING,
error = self.assertRaises(InvalidSchemaError, Constraint,
'prop', Schema.STRING,
schema)
self.assertEqual('min_length must be integer.', str(error))
def test_min_length_validate(self):
schema = {'min_length': 4}
constraint = Constraint('prop', Constraint.STRING, schema)
constraint = Constraint('prop', Schema.STRING, schema)
self.assertIsNone(constraint.validate('abcd'))
self.assertIsNone(constraint.validate('abcde'))
def test_min_length_validate_fail(self):
schema = {'min_length': 4}
constraint = Constraint('prop', Constraint.STRING, schema)
constraint = Constraint('prop', Schema.STRING, schema)
error = self.assertRaises(ValidationError, constraint.validate, 'abc')
self.assertEqual('length of prop: abc must be at least "4".',
str(error))
def test_invalid_max_length(self):
schema = {'max_length': 'four'}
error = self.assertRaises(ValidationError, Constraint,
'prop', Constraint.STRING,
error = self.assertRaises(InvalidSchemaError, Constraint,
'prop', Schema.STRING,
schema)
self.assertEqual('max_length must be integer.', str(error))
def test_max_length_validate(self):
schema = {'max_length': 4}
constraint = Constraint('prop', Constraint.STRING, schema)
constraint = Constraint('prop', Schema.STRING, schema)
self.assertIsNone(constraint.validate('abcd'))
self.assertIsNone(constraint.validate('abc'))
def test_max_length_validate_fail(self):
schema = {'max_length': 4}
constraint = Constraint('prop', Constraint.STRING, schema)
constraint = Constraint('prop', Schema.STRING, schema)
error = self.assertRaises(ValidationError,
constraint.validate,
'abcde')
@ -237,12 +286,12 @@ class ConstraintTest(TestCase):
def test_pattern_validate(self):
schema = {'pattern': '[0-9]*'}
constraint = Constraint('prop', Constraint.STRING, schema)
constraint = Constraint('prop', Schema.STRING, schema)
self.assertIsNone(constraint.validate('123'))
def test_pattern_validate_fail(self):
schema = {'pattern': '[0-9]*'}
constraint = Constraint('prop', Constraint.STRING, schema)
constraint = Constraint('prop', Schema.STRING, schema)
error = self.assertRaises(ValidationError, constraint.validate, 'abc')
self.assertEqual('prop: "abc" does not match pattern "[0-9]*".',
str(error))

View File

@ -59,24 +59,6 @@ class ToscaTemplateValidationTest(TestCase):
'to verify valid values.', err.__str__())
def test_inputs(self):
tpl_snippet = '''
inputs:
cpus:
description: Number of CPUs for the server.
constraints:
- valid_values: [ 1, 2, 4, 8 ]
'''
inputs = (translator.toscalib.utils.yamlparser.
simple_parse(tpl_snippet)['inputs'])
name, attrs = list(inputs.items())[0]
input = Input(name, attrs)
try:
input.validate()
except Exception as err:
self.assertTrue(isinstance(err, MissingRequiredFieldError))
self.assertEqual('Input cpus is missing required field: '
'"type".', err.__str__())
tpl_snippet = '''
inputs:
cpus: