1 # Licensed under the Apache License, Version 2.0 (the "License"); you may
2 # not use this file except in compliance with the License. You may obtain
3 # a copy of the License at
5 # http://www.apache.org/licenses/LICENSE-2.0
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 # License for the specific language governing permissions and limitations
14 import dateutil.parser
20 from toscaparser.common.exception import ExceptionCollector
21 from toscaparser.common.exception import InvalidTOSCAVersionPropertyException
22 from toscaparser.utils.gettextutils import _
23 log = logging.getLogger('tosca')
26 def str_to_num(value):
27 '''Convert a string representation of a number into a numeric type.'''
28 if isinstance(value, numbers.Number):
36 def validate_number(value):
37 return str_to_num(value)
40 def validate_integer(value):
41 if not isinstance(value, int):
45 ExceptionCollector.appendException(
46 ValueError(_('"%s" is not an integer.') % value))
50 def validate_float(value):
51 if not isinstance(value, float):
52 ExceptionCollector.appendException(
53 ValueError(_('"%s" is not a float.') % value))
54 return validate_number(value)
57 def validate_string(value):
58 if not isinstance(value, six.string_types):
59 ExceptionCollector.appendException(
60 ValueError(_('"%s" is not a string.') % value))
64 def validate_list(value):
65 if not isinstance(value, list):
66 ExceptionCollector.appendException(
67 ValueError(_('"%s" is not a list.') % value))
71 def validate_range(value):
73 if isinstance(value, list):
74 if len(value) != 2 or not (value[0] <= value[1]):
75 ExceptionCollector.appendException(
76 ValueError(_('"%s" is not a valid range.') % value))
77 validate_integer(value[0])
78 if not value[1] == "UNBOUNDED":
79 validate_integer(value[1])
83 def validate_map(value):
84 if not isinstance(value, collections.Mapping):
85 ExceptionCollector.appendException(
86 ValueError(_('"%s" is not a map.') % value))
90 def validate_boolean(value):
91 if isinstance(value, bool):
94 if isinstance(value, str):
95 normalised = value.lower()
96 if normalised in ['true', 'false']:
97 return normalised == 'true'
99 ExceptionCollector.appendException(
100 ValueError(_('"%s" is not a boolean.') % value))
103 def validate_timestamp(value):
105 # Note: we must return our own exception message
106 # as dateutil's parser returns different types / values on
107 # different systems. OSX, for example, returns a tuple
108 # containing a different error message than Linux
109 dateutil.parser.parse(value)
110 except Exception as e:
111 original_err_msg = str(e)
112 log.error(original_err_msg)
113 ExceptionCollector.appendException(
114 ValueError(_('"%(val)s" is not a valid timestamp. "%(msg)s"') %
115 {'val': value, 'msg': original_err_msg}))
119 class TOSCAVersionProperty(object):
121 VERSION_RE = re.compile('^(?P<major_version>([0-9][0-9]*))'
122 '(\.(?P<minor_version>([0-9][0-9]*)))?'
123 '(\.(?P<fix_version>([0-9][0-9]*)))?'
124 '(\.(?P<qualifier>([0-9A-Za-z]+)))?'
125 '(\-(?P<build_version>[0-9])*)?$')
127 def __init__(self, version):
128 self.version = str(version)
129 match = self.VERSION_RE.match(self.version)
131 ExceptionCollector.appendException(
132 InvalidTOSCAVersionPropertyException(what=(self.version)))
134 ver = match.groupdict()
135 if self.version in ['0', '0.0', '0.0.0']:
136 log.warning(_('Version assumed as not provided'))
138 self.minor_version = ver['minor_version']
139 self.major_version = ver['major_version']
140 self.fix_version = ver['fix_version']
141 self.qualifier = self._validate_qualifier(ver['qualifier'])
142 self.build_version = self._validate_build(ver['build_version'])
143 self._validate_major_version(self.major_version)
145 def _validate_major_version(self, value):
146 """Validate major version
148 Checks if only major version is provided and assumes
150 Eg: If version = 18, then it returns version = '18.0'
153 if self.minor_version is None and self.build_version is None and \
155 log.warning(_('Minor version assumed "0".'))
156 self.version = '.'.join([value, '0'])
159 def _validate_qualifier(self, value):
160 """Validate qualifier
162 TOSCA version is invalid if a qualifier is present without the
163 fix version or with all of major, minor and fix version 0s.
165 For example, the following versions are invalid
169 if (self.fix_version is None and value) or \
170 (self.minor_version == self.major_version ==
171 self.fix_version == '0' and value):
172 ExceptionCollector.appendException(
173 InvalidTOSCAVersionPropertyException(what=(self.version)))
176 def _validate_build(self, value):
177 """Validate build version
179 TOSCA version is invalid if build version is present without the
181 Eg: version = 18.0.0-1 is invalid.
183 if not self.qualifier and value:
184 ExceptionCollector.appendException(
185 InvalidTOSCAVersionPropertyException(what=(self.version)))
188 def get_version(self):